diff options
103 files changed, 4332 insertions, 273 deletions
diff --git a/build/phone-hdpi-2048-dalvik-heap.mk b/build/phone-hdpi-2048-dalvik-heap.mk new file mode 100644 index 0000000..2f0bbd2 --- /dev/null +++ b/build/phone-hdpi-2048-dalvik-heap.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the Dalvik heap for a 2G phone +# 192m of RAM gives enough space for 5 8 megapixel camera bitmaps in RAM. + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=12m \ + dalvik.vm.heapgrowthlimit=128m \ + dalvik.vm.heapsize=256m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=4m diff --git a/build/phone-xhdpi-1024-dalvik-heap.mk b/build/phone-xhdpi-1024-dalvik-heap.mk index 221227d..20f365f 100644 --- a/build/phone-xhdpi-1024-dalvik-heap.mk +++ b/build/phone-xhdpi-1024-dalvik-heap.mk @@ -21,5 +21,5 @@ PRODUCT_PROPERTY_OVERRIDES += \ dalvik.vm.heapgrowthlimit=96m \ dalvik.vm.heapsize=256m \ dalvik.vm.heaptargetutilization=0.75 \ - dalvik.vm.heapminfree=512k \ + dalvik.vm.heapminfree=2m \ dalvik.vm.heapmaxfree=8m diff --git a/build/phone-xxhdpi-2048-dalvik-heap.mk b/build/phone-xxhdpi-2048-dalvik-heap.mk new file mode 100644 index 0000000..9489593 --- /dev/null +++ b/build/phone-xxhdpi-2048-dalvik-heap.mk @@ -0,0 +1,26 @@ +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the Dalvik heap for a 2G phone +# 192m of RAM gives enough space for 5 8 megapixel camera bitmaps in RAM. + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=16m \ + dalvik.vm.heapgrowthlimit=192m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=2m \ + dalvik.vm.heapmaxfree=8m diff --git a/build/phone-xxhdpi-2048-hwui-memory.mk b/build/phone-xxhdpi-2048-hwui-memory.mk new file mode 100644 index 0000000..b4226bc --- /dev/null +++ b/build/phone-xxhdpi-2048-hwui-memory.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2013 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the HWUI memory limits + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.hwui.texture_cache_size=72 \ + ro.hwui.layer_cache_size=48 \ + ro.hwui.r_buffer_cache_size=8 \ + ro.hwui.path_cache_size=32 \ + ro.hwui.gradient_cache_size=1 \ + ro.hwui.drop_shadow_cache_size=6 \ + ro.hwui.texture_cache_flushrate=0.4 \ + ro.hwui.text_small_cache_width=1024 \ + ro.hwui.text_small_cache_height=1024 \ + ro.hwui.text_large_cache_width=2048 \ + ro.hwui.text_large_cache_height=1024 diff --git a/build/phone-xxhdpi-3072-dalvik-heap.mk b/build/phone-xxhdpi-3072-dalvik-heap.mk new file mode 100644 index 0000000..450f4e1 --- /dev/null +++ b/build/phone-xxhdpi-3072-dalvik-heap.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the Dalvik heap for a 3G phone + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=8m \ + dalvik.vm.heapgrowthlimit=256m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=512k \ + dalvik.vm.heapmaxfree=8m diff --git a/build/phone-xxhdpi-3072-hwui-memory.mk b/build/phone-xxhdpi-3072-hwui-memory.mk new file mode 100644 index 0000000..217bfb8 --- /dev/null +++ b/build/phone-xxhdpi-3072-hwui-memory.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the HWUI memory limits + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.hwui.texture_cache_size=72 \ + ro.hwui.layer_cache_size=48 \ + ro.hwui.path_cache_size=32 \ + ro.hwui.gradient_cache_size=1 \ + ro.hwui.drop_shadow_cache_size=6 \ + ro.hwui.r_buffer_cache_size=8 \ + ro.hwui.texture_cache_flushrate=0.4 \ + ro.hwui.text_small_cache_width=1024 \ + ro.hwui.text_small_cache_height=1024 \ + ro.hwui.text_large_cache_width=2048 \ + ro.hwui.text_large_cache_height=1024 diff --git a/build/phone-xxxhdpi-3072-dalvik-heap.mk b/build/phone-xxxhdpi-3072-dalvik-heap.mk new file mode 100644 index 0000000..3bf65a7 --- /dev/null +++ b/build/phone-xxxhdpi-3072-dalvik-heap.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2015 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the Dalvik heap for a 3G phone + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=8m \ + dalvik.vm.heapgrowthlimit=256m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=2m \ + dalvik.vm.heapmaxfree=8m diff --git a/build/phone-xxxhdpi-3072-hwui-memory.mk b/build/phone-xxxhdpi-3072-hwui-memory.mk new file mode 100644 index 0000000..8123fa0 --- /dev/null +++ b/build/phone-xxxhdpi-3072-hwui-memory.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2015 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the HWUI memory limits + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.hwui.texture_cache_size=88 \ + ro.hwui.layer_cache_size=58 \ + ro.hwui.path_cache_size=32 \ + ro.hwui.shape_cache_size=4 \ + ro.hwui.gradient_cache_size=2 \ + ro.hwui.drop_shadow_cache_size=8 \ + ro.hwui.r_buffer_cache_size=8 \ + ro.hwui.text_small_cache_width=2048 \ + ro.hwui.text_small_cache_height=2048 \ + ro.hwui.text_large_cache_width=4096 \ + ro.hwui.text_large_cache_height=4096 diff --git a/build/phone-xxxhdpi-4096-dalvik-heap.mk b/build/phone-xxxhdpi-4096-dalvik-heap.mk new file mode 100644 index 0000000..67f94f4 --- /dev/null +++ b/build/phone-xxxhdpi-4096-dalvik-heap.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the Dalvik heap for a 4G phone + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=8m \ + dalvik.vm.heapgrowthlimit=256m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.25 \ + dalvik.vm.heapminfree=4m \ + dalvik.vm.heapmaxfree=16m diff --git a/build/phone-xxxhdpi-4096-hwui-memory.mk b/build/phone-xxxhdpi-4096-hwui-memory.mk new file mode 100644 index 0000000..98cef64 --- /dev/null +++ b/build/phone-xxxhdpi-4096-hwui-memory.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2015 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides overrides to configure the HWUI memory limits + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.hwui.texture_cache_size=72 \ + ro.hwui.layer_cache_size=48 \ + ro.hwui.r_buffer_cache_size=8 \ + ro.hwui.path_cache_size=32 \ + ro.hwui.gradient_cache_size=1 \ + ro.hwui.drop_shadow_cache_size=6 \ + ro.hwui.texture_cache_flushrate=0.4 \ + ro.hwui.text_small_cache_width=1024 \ + ro.hwui.text_small_cache_height=1024 \ + ro.hwui.text_large_cache_width=2048 \ + ro.hwui.text_large_cache_height=1024 diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 26c5b4a..7201e77 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -93,6 +93,7 @@ static const TracingCategory k_categories[] = { { "sched", "CPU Scheduling", 0, { { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, { REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" }, + { OPT, "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" }, } }, { "irq", "IRQ Events", 0, { { REQ, "/sys/kernel/debug/tracing/events/irq/enable" }, diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index 792f015..5b9a42f 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -47,6 +47,7 @@ static char screenshot_path[PATH_MAX] = ""; #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" +#define RAFT_DIR "/data/misc/raft/" #define TOMBSTONE_DIR "/data/tombstones" #define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_" /* Can accomodate a tombstone number up to 9999. */ @@ -261,6 +262,8 @@ static unsigned long logcat_timeout(char *name) { /* End copy from system/core/logd/LogBuffer.cpp */ +static const unsigned long logcat_min_timeout = 40000; /* ms */ + /* dumps the current system state to stdout */ static void dumpstate() { unsigned long timeout; @@ -269,7 +272,9 @@ static void dumpstate() { char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX]; char network[PROPERTY_VALUE_MAX], date[80]; char build_type[PROPERTY_VALUE_MAX]; + char cm_version[PROPERTY_VALUE_MAX]; + property_get("ro.cm.version", cm_version, "(unknown)"); property_get("ro.build.display.id", build, "(unknown)"); property_get("ro.build.fingerprint", fingerprint, "(unknown)"); property_get("ro.build.type", build_type, "(unknown)"); @@ -283,6 +288,7 @@ static void dumpstate() { printf("========================================================\n"); printf("\n"); + printf("CM Version: %s\n", cm_version); printf("Build: %s\n", build); printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */ printf("Bootloader: %s\n", bootloader); @@ -333,23 +339,25 @@ static void dumpstate() { // dump_file("EVENT LOG TAGS", "/etc/event-log-tags"); // calculate timeout timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash"); - if (timeout < 20000) { - timeout = 20000; + if (timeout < logcat_min_timeout) { + timeout = logcat_min_timeout; } run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL); timeout = logcat_timeout("events"); - if (timeout < 20000) { - timeout = 20000; + if (timeout < logcat_min_timeout) { + timeout = logcat_min_timeout; } run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL); timeout = logcat_timeout("radio"); - if (timeout < 20000) { - timeout = 20000; + if (timeout < logcat_min_timeout) { + timeout = logcat_min_timeout; } run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL); run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL); + run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL); + /* show the traces we collected in main(), if that was done */ if (dump_traces_path != NULL) { dump_file("VM TRACES JUST NOW", dump_traces_path); diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp index d4aa7d3..09369ce 100644 --- a/cmds/installd/commands.cpp +++ b/cmds/installd/commands.cpp @@ -39,6 +39,7 @@ dir_rec_t android_app_private_dir; dir_rec_t android_app_lib_dir; dir_rec_t android_media_dir; dir_rec_t android_mnt_expand_dir; +dir_rec_t android_prebundled_dir; dir_rec_array_t android_system_dirs; static const char* kCpPath = "/system/bin/cp"; @@ -770,24 +771,11 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, dex2oat_compiler_filter_flag, NULL) > 0; char dex2oat_threads_buf[PROPERTY_VALUE_MAX]; - bool have_dex2oat_threads_flag = false; - if (!post_bootcomplete) { - have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads", - dex2oat_threads_buf, - NULL) > 0; - // If there's no boot property, fall back to the image property. - if (!have_dex2oat_threads_flag) { - have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads", - dex2oat_threads_buf, - NULL) > 0; - } - // If there's neither, fall back to the default property. - } - if (!have_dex2oat_threads_flag) { - have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", - dex2oat_threads_buf, - NULL) > 0; - } + bool have_dex2oat_threads_flag = property_get(post_bootcomplete + ? "dalvik.vm.dex2oat-threads" + : "dalvik.vm.boot-dex2oat-threads", + dex2oat_threads_buf, + NULL) > 0; char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2]; if (have_dex2oat_threads_flag) { sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); @@ -1623,62 +1611,46 @@ out: return rc; } -static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) +static void run_idmap(const char *target_apk, const char *overlay_apk, const char *cache_path, + int idmap_fd, uint32_t target_hash, uint32_t overlay_hash) { static const char *IDMAP_BIN = "/system/bin/idmap"; static const size_t MAX_INT_LEN = 32; char idmap_str[MAX_INT_LEN]; + char target_hash_str[MAX_INT_LEN]; + char overlay_hash_str[MAX_INT_LEN]; snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); + snprintf(target_hash_str, sizeof(target_hash_str), "%d", target_hash); + snprintf(overlay_hash_str, sizeof(overlay_hash_str), "%d", overlay_hash); - execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); + execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, cache_path, idmap_str, + target_hash_str, overlay_hash_str, (char*)NULL); ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); } -// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) -// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap -static int flatten_path(const char *prefix, const char *suffix, - const char *overlay_path, char *idmap_path, size_t N) +static int get_idmap_path(const char *prefix, const char *suffix, char *idmap_path, size_t N) { - if (overlay_path == NULL || idmap_path == NULL) { - return -1; - } - const size_t len_overlay_path = strlen(overlay_path); - // will access overlay_path + 1 further below; requires absolute path - if (len_overlay_path < 2 || *overlay_path != '/') { - return -1; - } - const size_t len_idmap_root = strlen(prefix); - const size_t len_suffix = strlen(suffix); - if (SIZE_MAX - len_idmap_root < len_overlay_path || - SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { - // additions below would cause overflow - return -1; - } - if (N < len_idmap_root + len_overlay_path + len_suffix) { - return -1; - } + if (idmap_path == NULL) return -1; + memset(idmap_path, 0, N); - snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); - char *ch = idmap_path + len_idmap_root; - while (*ch != '\0') { - if (*ch == '/') { - *ch = '@'; - } - ++ch; + int len = snprintf(idmap_path, N, "%s/%s", prefix, suffix); + if (len < 0 || (size_t)len >= N) { + return -1; // error or truncated } return 0; } -int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) +int idmap(const char *target_apk, const char *overlay_apk, const char *cache_path, + uid_t uid, uint32_t target_hash, uint32_t overlay_hash) { - ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); + ALOGD("idmap target_apk=%s overlay_apk=%s cache_path=%s uid=%d\n", target_apk, overlay_apk, + cache_path, uid); int idmap_fd = -1; char idmap_path[PATH_MAX]; - if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, - idmap_path, sizeof(idmap_path)) == -1) { + if (get_idmap_path(cache_path, IDMAP_SUFFIX, idmap_path, sizeof(idmap_path)) == -1) { ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); goto fail; } @@ -1715,7 +1687,7 @@ int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) exit(1); } - run_idmap(target_apk, overlay_apk, idmap_fd); + run_idmap(target_apk, overlay_apk, cache_path, idmap_fd, target_hash, overlay_hash); exit(1); /* only if exec call to idmap failed */ } else { int status = wait_child(pid); @@ -1735,6 +1707,174 @@ fail: return -1; } +static void run_aapt(const char *source_apk, const char *internal_path, + int resapk_fd, int pkgId, int min_sdk_version, + const char *app_res_path, const char *common_res_path) +{ + static const char *AAPT_BIN = "/system/bin/aapt"; + static const char *MANIFEST = "/data/app/AndroidManifest.xml"; + static const char *FRAMEWORK_RES = "/system/framework/framework-res.apk"; + + static const size_t MAX_INT_LEN = 32; + char resapk_str[MAX_INT_LEN]; + char pkgId_str[MAX_INT_LEN]; + char minSdkVersion_str[MAX_INT_LEN]; + + snprintf(resapk_str, sizeof(resapk_str), "%d", resapk_fd); + snprintf(pkgId_str, sizeof(pkgId_str), "%d", pkgId); + snprintf(minSdkVersion_str, sizeof(minSdkVersion_str), "%d", min_sdk_version); + + bool hasCommonResources = (common_res_path != NULL && common_res_path[0] != '\0'); + bool hasAppResources = (app_res_path != NULL && app_res_path[0] != '\0'); + + if (hasCommonResources) { + execl(AAPT_BIN, AAPT_BIN, "package", + "--min-sdk-version", minSdkVersion_str, + "-M", MANIFEST, + "-S", source_apk, + "-X", internal_path, + "-I", FRAMEWORK_RES, + "-r", resapk_str, + "-x", pkgId_str, + "-f", + "-I", common_res_path, + hasAppResources ? "-I" : (char*)NULL, + hasAppResources ? app_res_path : (char*) NULL, + (char*)NULL); + } else { + execl(AAPT_BIN, AAPT_BIN, "package", + "--min-sdk-version", minSdkVersion_str, + "-M", MANIFEST, + "-S", source_apk, + "-X", internal_path, + "-I", FRAMEWORK_RES, + "-r", resapk_str, + "-x", pkgId_str, + "-f", + hasAppResources ? "-I" : (char*)NULL, + hasAppResources ? app_res_path : (char*) NULL, + (char*)NULL); + } + ALOGE("execl(%s) failed: %s\n", AAPT_BIN, strerror(errno)); +} + +int aapt(const char *source_apk, const char *internal_path, const char *out_restable, uid_t uid, + int pkgId, int min_sdk_version, const char *app_res_path, const char *common_res_path) +{ + ALOGD("aapt source_apk=%s internal_path=%s out_restable=%s uid=%d, pkgId=%d,min_sdk_version=%d,\ + app_res_path=%s, common_res_path=%s", + source_apk, internal_path, out_restable, uid, pkgId, min_sdk_version, app_res_path, + common_res_path); + static const int PARENT_READ_PIPE = 0; + static const int CHILD_WRITE_PIPE = 1; + + int resapk_fd = -1; + char restable_path[PATH_MAX]; + char resapk_path[PATH_MAX]; + + // create pipes for redirecting STDERR to a buffer that can be displayed in logcat + int pipefd[2]; + if (pipe(pipefd) != 0) { + pipefd[0] = pipefd[1] = -1; + } + + pid_t pid = fork(); + + if (pid == 0) { + // get file descriptor for resources.arsc + snprintf(restable_path, PATH_MAX, "%s/resources.arsc", out_restable); + unlink(restable_path); + + // get file descriptor for resources.apk + snprintf(resapk_path, PATH_MAX, "%s/resources.apk", out_restable); + unlink(resapk_path); + resapk_fd = open(resapk_path, O_RDWR | O_CREAT | O_EXCL, 0644); + if (resapk_fd < 0) { + ALOGE("aapt cannot open '%s' for output: %s\n", resapk_path, strerror(errno)); + goto fail; + } + if (fchown(resapk_fd, AID_SYSTEM, uid) < 0) { + ALOGE("aapt cannot chown '%s'\n", resapk_path); + goto fail; + } + if (fchmod(resapk_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { + ALOGE("aapt cannot chmod '%s'\n", resapk_path); + goto fail; + } + + /* child -- drop privileges before continuing */ + if (setgid(uid) != 0) { + ALOGE("setgid(%d) failed during aapt\n", uid); + exit(1); + } + if (setuid(uid) != 0) { + ALOGE("setuid(%d) failed during aapt\n", uid); + exit(1); + } + + if (flock(resapk_fd, LOCK_EX | LOCK_NB) != 0) { + ALOGE("flock(%s) failed during aapt: %s\n", out_restable, strerror(errno)); + exit(1); + } + + if (pipefd[PARENT_READ_PIPE] > 0 && pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[PARENT_READ_PIPE]); // close unused read end + if (dup2(pipefd[CHILD_WRITE_PIPE], STDERR_FILENO) != STDERR_FILENO) { + pipefd[CHILD_WRITE_PIPE] = -1; + } + } + + run_aapt(source_apk, internal_path, resapk_fd, pkgId, min_sdk_version, app_res_path, + common_res_path); + + close(resapk_fd); + if (pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[CHILD_WRITE_PIPE]); + } + exit(1); /* only if exec call to idmap failed */ + } else { + int status, i; + char buffer[1024]; + ssize_t readlen; + + if (pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[CHILD_WRITE_PIPE]); // close unused write end + } + + if (pipefd[PARENT_READ_PIPE] > 0) { + while ((readlen = read(pipefd[PARENT_READ_PIPE], buffer, sizeof(buffer) - 1)) > 0) { + // in case buffer has more than one string in it, replace '\0' with '\n' + for (i = 0; i < readlen; i++) { + if (buffer[i] == '\0') buffer[i] = '\n'; + } + // null terminate buffer at readlen + buffer[readlen] = '\0'; + ALOG(LOG_ERROR, "InstallTheme", "%s", buffer); + } + waitpid(pid, &status, 0); + + if (pipefd[PARENT_READ_PIPE] > 0) { + close(pipefd[PARENT_READ_PIPE]); + } + } else { + status = wait_child(pid); + } + + if (status != 0) { + ALOGE("aapt failed, status=0x%04x\n", status); + goto fail; + } + } + + return 0; +fail: + if (resapk_fd >= 0) { + close(resapk_fd); + unlink(resapk_path); + } + return -1; +} + int restorecon_data(const char* uuid, const char* pkgName, const char* seinfo, uid_t uid) { diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp index f67e838..df159e3 100644 --- a/cmds/installd/installd.cpp +++ b/cmds/installd/installd.cpp @@ -158,7 +158,17 @@ static int do_linklib(char **arg, char reply[REPLY_MAX] __unused) static int do_idmap(char **arg, char reply[REPLY_MAX] __unused) { - return idmap(arg[0], arg[1], atoi(arg[2])); + return idmap(arg[0], arg[1], arg[2], atoi(arg[3]), atoi(arg[4]), atoi(arg[5])); +} + +static int do_aapt(char **arg, char reply[REPLY_MAX] __unused) +{ + return aapt(arg[0], arg[1], arg[2], atoi(arg[3]), atoi(arg[4]), atoi(arg[5]), arg[6], ""); +} + +static int do_aapt_with_common(char **arg, char reply[REPLY_MAX] __unused) +{ + return aapt(arg[0], arg[1], arg[2], atoi(arg[3]), atoi(arg[4]), atoi(arg[5]), arg[6], arg[7]); } static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused))) @@ -212,7 +222,9 @@ struct cmdinfo cmds[] = { { "mkuserdata", 5, do_mk_user_data }, { "mkuserconfig", 1, do_mk_user_config }, { "rmuser", 2, do_rm_user }, - { "idmap", 3, do_idmap }, + { "idmap", 6, do_idmap }, + { "aapt", 7, do_aapt }, + { "aapt_with_common", 8, do_aapt_with_common }, { "restorecondata", 4, do_restorecon_data }, { "createoatdir", 2, do_create_oat_dir }, { "rmpackagedir", 1, do_rm_package_dir }, @@ -373,6 +385,12 @@ int initialize_globals() { return -1; } + // Get the android external app directory. + if (get_path_from_string(&android_prebundled_dir, PREBUNDLED_APP_PREFIX) < 0) { + return -1; + } + + // Take note of the system and vendor directories. android_system_dirs.count = 4; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 24b9084..b4c5961 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -80,7 +80,7 @@ #define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/" #define IDMAP_PREFIX "/data/resource-cache/" -#define IDMAP_SUFFIX "@idmap" +#define IDMAP_SUFFIX "idmap" #define PKG_NAME_MAX 128 /* largest allowed package name */ #define PKG_PATH_MAX 256 /* max size of any path we use */ @@ -92,6 +92,8 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) +#define PREBUNDLED_APP_PREFIX "/vendor/bundled-app/" + /* data structures */ typedef struct { @@ -111,6 +113,7 @@ extern dir_rec_t android_data_dir; extern dir_rec_t android_asec_dir; extern dir_rec_t android_media_dir; extern dir_rec_t android_mnt_expand_dir; +extern dir_rec_t android_prebundled_dir; extern dir_rec_array_t android_system_dirs; typedef struct cache_dir_struct { @@ -247,7 +250,10 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, int mark_boot_complete(const char *instruction_set); int movefiles(); int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId); -int idmap(const char *target_path, const char *overlay_path, uid_t uid); +int idmap(const char *target_path, const char *overlay_path, const char *cache_path, uid_t uid, + uint32_t target_hash, uint32_t overlay_hash); +int aapt(const char *source_apk, const char *internal_path, const char *out_restable, uid_t uid, + int pkgId, int min_sdk_version, const char *app_res_path, const char *common_res_path); int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid); int create_oat_dir(const char* oat_dir, const char *instruction_set); int rm_package_dir(const char* apk_path); diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 7db3fb9..a32d1a0 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -1061,6 +1061,8 @@ static int validate_apk_path_internal(const char *path, int maxSubdirs) { if (maxSubdirs < 2) { maxSubdirs = 2; } + } else if (!strncmp(path, android_prebundled_dir.path, android_prebundled_dir.len)) { + dir = &android_prebundled_dir; } else { return -1; } diff --git a/data/etc/android.hardware.sensor.ambient_temperature.xml b/data/etc/android.hardware.sensor.ambient_temperature.xml new file mode 100644 index 0000000..ffb105d --- /dev/null +++ b/data/etc/android.hardware.sensor.ambient_temperature.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + +Copyright (c) 2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--> + +<!-- Feature for devices with an ambient temperature sensor. --> +<permissions> + <feature name="android.hardware.sensor.ambient_temperature" /> +</permissions> diff --git a/data/etc/android.hardware.sensor.relative_humidity.xml b/data/etc/android.hardware.sensor.relative_humidity.xml new file mode 100644 index 0000000..0710079 --- /dev/null +++ b/data/etc/android.hardware.sensor.relative_humidity.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + +Copyright (c) 2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--> + +<!-- Feature for devices with relative humidity sensor. --> +<permissions> + <feature name="android.hardware.sensor.relative_humidity" /> +</permissions> diff --git a/include/android/input.h b/include/android/input.h index 5ab4e29..46cf89c 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -815,6 +815,8 @@ enum { AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION, /** navigation */ AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, + /** gesture sensor (?) */ + AINPUT_SOURCE_GESTURE_SENSOR = 0x00400000 | AINPUT_SOURCE_CLASS_NONE, /** joystick */ AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, diff --git a/include/android/keycodes.h b/include/android/keycodes.h index 15bb786..421abe5 100644 --- a/include/android/keycodes.h +++ b/include/android/keycodes.h @@ -722,7 +722,22 @@ enum { AKEYCODE_NAVIGATE_PREVIOUS = 260, AKEYCODE_NAVIGATE_NEXT = 261, AKEYCODE_NAVIGATE_IN = 262, - AKEYCODE_NAVIGATE_OUT = 263 + AKEYCODE_NAVIGATE_OUT = 263, + /** Primary stem key for Wear + * Main power/reset button on watch. */ + AKEYCODE_STEM_PRIMARY = 264, + /** Generic stem key 1 for Wear */ + AKEYCODE_STEM_1 = 265, + /** Generic stem key 2 for Wear */ + AKEYCODE_STEM_2 = 266, + /** Generic stem key 3 for Wear */ + AKEYCODE_STEM_3 = 267, + AKEYCODE_MEDIA_SKIP_FORWARD = 272, + AKEYCODE_MEDIA_SKIP_BACKWARD = 273, + AKEYCODE_MEDIA_STEP_FORWARD = 274, + AKEYCODE_MEDIA_STEP_BACKWARD = 275, + /** Put device to sleep unless a wakelock is held. */ + AKEYCODE_SOFT_SLEEP = 276 // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h index f0a2790..3e6bfb8 100644 --- a/include/batteryservice/BatteryService.h +++ b/include/batteryservice/BatteryService.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +67,16 @@ struct BatteryProperties { int batteryTemperature; String8 batteryTechnology; + bool dockBatterySupported; + bool chargerDockAcOnline; + int dockBatteryStatus; + int dockBatteryHealth; + bool dockBatteryPresent; + int dockBatteryLevel; + int dockBatteryVoltage; + int dockBatteryTemperature; + String8 dockBatteryTechnology; + status_t writeToParcel(Parcel* parcel) const; status_t readFromParcel(Parcel* parcel); }; diff --git a/include/batteryservice/IBatteryPropertiesRegistrar.h b/include/batteryservice/IBatteryPropertiesRegistrar.h index eca075d..f6a7981 100644 --- a/include/batteryservice/IBatteryPropertiesRegistrar.h +++ b/include/batteryservice/IBatteryPropertiesRegistrar.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +28,7 @@ enum { REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION, UNREGISTER_LISTENER, GET_PROPERTY, + GET_DOCK_PROPERTY, }; class IBatteryPropertiesRegistrar : public IInterface { @@ -36,6 +38,7 @@ public: virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0; virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0; virtual status_t getProperty(int id, struct BatteryProperty *val) = 0; + virtual status_t getDockProperty(int id, struct BatteryProperty *val) = 0; }; class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> { diff --git a/include/binder/AppOpsManager.h b/include/binder/AppOpsManager.h index 042927c..1d0e968 100644 --- a/include/binder/AppOpsManager.h +++ b/include/binder/AppOpsManager.h @@ -91,7 +91,19 @@ public: OP_USE_SIP = 53, OP_PROCESS_OUTGOING_CALLS = 54, OP_USE_FINGERPRINT = 55, - OP_BODY_SENSORS = 56 + OP_BODY_SENSORS = 56, + OP_READ_CELL_BROADCASTS = 57, + OP_MOCK_LOCATION = 58, + OP_READ_EXTERNAL_STORAGE = 59, + OP_WRITE_EXTERNAL_STORAGE = 60, + OP_TURN_SCREEN_ON = 61, + OP_GET_ACCOUNTS = 62, + OP_WIFI_CHANGE = 63, + OP_BLUETOOTH_CHANGE = 64, + OP_BOOT_COMPLETED = 65, + OP_NFC_CHANGE = 66, + OP_DATA_CONNECT_CHANGE = 67, + OP_SU = 68 }; AppOpsManager(); diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h index 2d0db00..178ef85 100644 --- a/include/binder/IMemory.h +++ b/include/binder/IMemory.h @@ -36,7 +36,12 @@ public: // flags returned by getFlags() enum { - READ_ONLY = 0x00000001 + READ_ONLY = 0x00000001, +#ifdef USE_MEMORY_HEAP_ION + USE_ION_FD = 0x00008000 +#else + USE_ION_FD = 0x00000008 +#endif }; virtual int getHeapID() const = 0; diff --git a/include/binder/MemoryHeapIon.h b/include/binder/MemoryHeapIon.h new file mode 100644 index 0000000..7e059f4 --- /dev/null +++ b/include/binder/MemoryHeapIon.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright 2011, Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*! + * \file MemoryHeapIon.h + * \brief header file for MemoryHeapIon + * \author MinGu, Jeon(mingu85.jeon) + * \date 2011/11/20 + * + * <b>Revision History: </b> + * - 2011/11/21 : MinGu, Jeon(mingu85.jeon)) \n + * Initial version + * - 2012/11/29 : MinGu, Jeon(mingu85.jeon)) \n + * Change name + */ + +#ifndef ANDROID_MEMORY_HEAP_ION_H +#define ANDROID_MEMORY_HEAP_ION_H + +#include <binder/IMemory.h> +#include <binder/MemoryHeapBase.h> +#include <stdlib.h> + +#define MHB_ION_HEAP_SYSTEM_CONTIG_MASK (1 << 1) +#define MHB_ION_HEAP_EXYNOS_CONTIG_MASK (1 << 4) +#define MHB_ION_HEAP_EXYNOS_MASK (1 << 5) +#define MHB_ION_HEAP_SYSTEM_MASK (1 << 6) + +#define MHB_ION_FLAG_CACHED (1 << 16) +#define MHB_ION_FLAG_CACHED_NEEDS_SYNC (1 << 17) +#define MHB_ION_FLAG_PRESERVE_KMAP (1 << 18) + +#define MHB_ION_EXYNOS_VIDEO_MASK (1 << 21) +#define MHB_ION_EXYNOS_MFC_INPUT_MASK (1 << 25) +#define MHB_ION_EXYNOS_MFC_OUTPUT_MASK (1 << 26) +#define MHB_ION_EXYNOS_GSC_MASK (1 << 27) +#define MHB_ION_EXYNOS_FIMD_VIDEO_MASK (1 << 28) + +namespace android { + +class MemoryHeapIon : public MemoryHeapBase +{ +public: + enum { + USE_ION_FD = IMemoryHeap::USE_ION_FD + }; + MemoryHeapIon(size_t size, uint32_t flags = 0, char const* name = NULL); + MemoryHeapIon(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0); + ~MemoryHeapIon(); +private: + int mIonClient; +}; + +}; +#endif diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index 16cd6cf..91ffae0 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -340,8 +340,10 @@ public: inline void* data() { return mData; } }; +#ifndef DISABLE_ASHMEM_TRACKING private: size_t mOpenAshmemSize; +#endif public: // TODO: Remove once ABI can be changed. diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 8c3d49e..6e3fc5a 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -59,7 +59,10 @@ public: enum { eDisplayIdMain = 0, - eDisplayIdHdmi = 1 + eDisplayIdHdmi = 1, +#ifdef QTI_BSP + eDisplayIdTertiary = 2 +#endif }; enum Rotation { @@ -144,7 +147,8 @@ public: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + Rotation rotation = eRotateNone, + bool isCpuConsumer = false) = 0; /* Clears the frame statistics for animations. * diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h index bb79bd0..d3e8b8b 100644 --- a/include/gui/ISurfaceComposerClient.h +++ b/include/gui/ISurfaceComposerClient.h @@ -50,6 +50,7 @@ public: eCursorWindow = 0x00002000, eFXSurfaceNormal = 0x00000000, + eFXSurfaceBlur = 0x00010000, eFXSurfaceDim = 0x00020000, eFXSurfaceMask = 0x000F0000, }; diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 37d953e..9ec3f23 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -163,6 +163,11 @@ public: const Rect& layerStackRect, const Rect& displayRect); + status_t setBlur(const sp<IBinder>& id, float blur); + status_t setBlurMaskSurface(const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId); + status_t setBlurMaskSampling(const sp<IBinder>& id, uint32_t blurMaskSampling); + status_t setBlurMaskAlphaThreshold(const sp<IBinder>& id, float alpha); + private: virtual void onFirstRef(); Composer& getComposer(); diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index 9f62f7c..5fa45d1 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -77,6 +77,11 @@ public: status_t clearLayerFrameStats() const; status_t getLayerFrameStats(FrameStats* outStats) const; + status_t setBlur(float blur = 0); + status_t setBlurMaskSurface(const sp<SurfaceControl>& maskSurface); + status_t setBlurMaskSampling(uint32_t blurMaskSampling); + status_t setBlurMaskAlphaThreshold(float alpha); + private: // can't be copied SurfaceControl& operator = (SurfaceControl& rhs); diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index 3962001..c03c0f2 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -303,6 +303,15 @@ static const InputEventLabel KEYCODES[] = { DEFINE_KEYCODE(NAVIGATE_NEXT), DEFINE_KEYCODE(NAVIGATE_IN), DEFINE_KEYCODE(NAVIGATE_OUT), + DEFINE_KEYCODE(STEM_PRIMARY), + DEFINE_KEYCODE(STEM_1), + DEFINE_KEYCODE(STEM_2), + DEFINE_KEYCODE(STEM_3), + DEFINE_KEYCODE(MEDIA_SKIP_FORWARD), + DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD), + DEFINE_KEYCODE(MEDIA_STEP_FORWARD), + DEFINE_KEYCODE(MEDIA_STEP_BACKWARD), + DEFINE_KEYCODE(SOFT_SLEEP), { NULL, 0 } }; @@ -378,6 +387,7 @@ static const InputEventLabel LEDS[] = { }; static const InputEventLabel FLAGS[] = { + DEFINE_FLAG(WAKE), DEFINE_FLAG(VIRTUAL), DEFINE_FLAG(FUNCTION), DEFINE_FLAG(GESTURE), diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h index 521c223..f746a69 100644 --- a/include/media/openmax/OMX_Core.h +++ b/include/media/openmax/OMX_Core.h @@ -509,7 +509,7 @@ typedef enum OMX_EVENTTYPE OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ - /** Event when tunneled decoder has rendered an output + /** Event when tunneled decoder has rendered an output or reached EOS * nData1 must contain the number of timestamps returned * pEventData must point to an array of the OMX_VIDEO_RENDEREVENTTYPE structs containing the * render-timestamps of each frame. Component may batch rendered timestamps using this event, @@ -518,6 +518,10 @@ typedef enum OMX_EVENTTYPE * * If component is doing frame-rate conversion, it must signal the render time of each * converted frame, and must interpolate media timestamps for in-between frames. + * + * When the component reached EOS, it must signal an EOS timestamp using the same mechanism. + * This is in addition to the timestamp of the last rendered frame, and should follow that + * frame. */ OMX_EventOutputRendered = 0x7F000001, OMX_EventMax = 0x7FFFFFFF diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h index 34c0405..3971bc5 100644 --- a/include/media/openmax/OMX_VideoExt.h +++ b/include/media/openmax/OMX_VideoExt.h @@ -203,10 +203,17 @@ typedef struct OMX_VIDEO_SLICESEGMENTSTYPE { OMX_BOOL bEnableLoopFilterAcrossSlices; } OMX_VIDEO_SLICESEGMENTSTYPE; -/** Structure to return timestamps of rendered output frames for tunneled components */ +/** Structure to return timestamps of rendered output frames as well as EOS + * for tunneled components. + */ typedef struct OMX_VIDEO_RENDEREVENTTYPE { OMX_S64 nMediaTimeUs; // timestamp of rendered video frame OMX_S64 nSystemTimeNs; // system monotonic time at the time frame was rendered + // Use INT64_MAX for nMediaTimeUs to signal that the EOS + // has been reached. In this case, nSystemTimeNs MUST be + // the system time when the last frame was rendered. + // This MUST be done in addition to returning (and + // following) the render information for the last frame. } OMX_VIDEO_RENDEREVENTTYPE; #ifdef __cplusplus diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index cbe8733..9ff8409 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -52,12 +52,16 @@ struct layer_state_t { eFlagsChanged = 0x00000040, eLayerStackChanged = 0x00000080, eCropChanged = 0x00000100, + eBlurChanged = 0x00400000, + eBlurMaskSurfaceChanged = 0x00800000, + eBlurMaskSamplingChanged = 0x01000000, + eBlurMaskAlphaThresholdChanged = 0x02000000, }; layer_state_t() : what(0), - x(0), y(0), z(0), w(0), h(0), layerStack(0), - alpha(0), flags(0), mask(0), + x(0), y(0), z(0), w(0), h(0), layerStack(0), blur(0), + blurMaskSampling(0), blurMaskAlphaThreshold(0), alpha(0), flags(0), mask(0), reserved(0) { matrix.dsdx = matrix.dtdy = 1.0f; @@ -82,6 +86,10 @@ struct layer_state_t { uint32_t w; uint32_t h; uint32_t layerStack; + float blur; + sp<IBinder> blurMaskSurface; + uint32_t blurMaskSampling; + float blurMaskAlphaThreshold; float alpha; uint8_t flags; uint8_t mask; diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h index 6099548..9900624 100644 --- a/include/ui/GraphicBufferMapper.h +++ b/include/ui/GraphicBufferMapper.h @@ -59,6 +59,10 @@ public: status_t unlockAsync(buffer_handle_t handle, int *fenceFd); +#ifdef EXYNOS4_ENHANCEMENTS + status_t getphys(buffer_handle_t handle, void** paddr); +#endif + // dumps information about the mapping of this handle void dump(buffer_handle_t handle); diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index d5860ef..b12eda8 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -38,11 +38,31 @@ sources := \ Static.cpp \ TextOutput.cpp \ +ifeq ($(BOARD_NEEDS_MEMORYHEAPION),true) +sources += \ + MemoryHeapIon.cpp +endif + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) + +ifeq ($(BOARD_NEEDS_MEMORYHEAPION),true) +LOCAL_SHARED_LIBRARIES += libion_exynos +LOCAL_CFLAGS += -DUSE_MEMORY_HEAP_ION + +ifeq ($(TARGET_SLSI_VARIANT),cm) +SLSI_DIR := samsung_slsi-cm +PLATFORM_DIR := $(TARGET_BOARD_PLATFORM) +else +SLSI_DIR := samsung_slsi +PLATFORM_DIR := $(TARGET_BOARD_PLATFORM)-$(TARGET_SLSI_VARIANT) +endif +LOCAL_C_INCLUDES += hardware/$(SLSI_DIR)/$(PLATFORM_DIR)/include +endif + LOCAL_MODULE := libbinder -LOCAL_SHARED_LIBRARIES := liblog libcutils libutils +LOCAL_SHARED_LIBRARIES += liblog libcutils libutils LOCAL_SRC_FILES := $(sources) ifneq ($(TARGET_USES_64_BIT_BINDER),true) ifneq ($(TARGET_IS_64_BIT),true) @@ -53,9 +73,30 @@ LOCAL_CFLAGS += -Werror include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) + +ifeq ($(BOARD_NEEDS_MEMORYHEAPION),true) +LOCAL_SHARED_LIBRARIES += libion_exynos +LOCAL_CFLAGS += -DUSE_MEMORY_HEAP_ION + +ifeq ($(TARGET_SLSI_VARIANT),cm) +SLSI_DIR := samsung_slsi-cm +PLATFORM_DIR := $(TARGET_BOARD_PLATFORM) +else +SLSI_DIR := samsung_slsi +PLATFORM_DIR := $(TARGET_BOARD_PLATFORM)-$(TARGET_SLSI_VARIANT) +endif +LOCAL_C_INCLUDES += hardware/$(SLSI_DIR)/$(PLATFORM_DIR)/include +endif + LOCAL_MODULE := libbinder LOCAL_STATIC_LIBRARIES += libutils LOCAL_SRC_FILES := $(sources) +ifeq ($(BOARD_NEEDS_MEMORYHEAPPMEM),true) +LOCAL_C_INCLUDES += \ + $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := \ + $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +endif ifneq ($(TARGET_USES_64_BIT_BINDER),true) ifneq ($(TARGET_IS_64_BIT),true) LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1 diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp index fb8d620..f59867a 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -33,6 +33,10 @@ #include <binder/Parcel.h> #include <utils/CallStack.h> +#ifdef USE_MEMORY_HEAP_ION +#include "ion.h" +#endif + #define VERBOSE 0 namespace android { @@ -312,6 +316,14 @@ void BpMemoryHeap::assertReallyMapped() const IInterface::asBinder(this).get(), parcel_fd, size, err, strerror(-err)); +#ifdef USE_MEMORY_HEAP_ION + ion_client ion_client_num = -1; + if (flags & USE_ION_FD) { + ion_client_num = ion_client_create(); + ALOGE_IF(ion_client_num < 0, "BpMemoryHeap : ion client creation error"); + } +#endif + int fd = dup( parcel_fd ); ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)", parcel_fd, size, err, strerror(errno)); @@ -324,7 +336,16 @@ void BpMemoryHeap::assertReallyMapped() const Mutex::Autolock _l(mLock); if (mHeapId == -1) { mRealHeap = true; - mBase = mmap(0, size, access, MAP_SHARED, fd, offset); + +#ifdef USE_MEMORY_HEAP_ION + if (flags & USE_ION_FD) { + if (ion_client_num < 0) + mBase = MAP_FAILED; + else + mBase = ion_map(fd, size, offset); + } else +#endif + mBase = mmap(0, size, access, MAP_SHARED, fd, offset); if (mBase == MAP_FAILED) { ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)", IInterface::asBinder(this).get(), size, fd, strerror(errno)); @@ -336,6 +357,12 @@ void BpMemoryHeap::assertReallyMapped() const android_atomic_write(fd, &mHeapId); } } +#ifdef USE_MEMORY_HEAP_ION + if (ion_client_num < 0) + ion_client_num = -1; + else + ion_client_destroy(ion_client_num); +#endif } } diff --git a/libs/binder/MemoryHeapIon.cpp b/libs/binder/MemoryHeapIon.cpp new file mode 100644 index 0000000..26c5566 --- /dev/null +++ b/libs/binder/MemoryHeapIon.cpp @@ -0,0 +1,191 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*! + * \file MemoryHeapIon.cpp + * \brief source file for MemoryHeapIon + * \author MinGu, Jeon(mingu85.jeon) + * \date 2011/11/20 + * + * <b>Revision History: </b> + * - 2011/11/20 : MinGu, Jeon(mingu85.jeon)) \n + * Initial version + * - 2012/11/29 : MinGu, Jeon(mingu85.jeon)) \n + * Change name + */ + +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <cutils/log.h> +#include <binder/MemoryHeapBase.h> +#include <binder/IMemory.h> +#include <binder/MemoryHeapIon.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/mman.h> +#include "ion.h" + +#define HEAP_MASK_FILTER ((1 << 16) - (2)) +#define FLAG_MASK_FILTER (~(HEAP_MASK_FILTER) - (1)) + +namespace android { + +uint32_t ion_HeapMask_valid_check(uint32_t flags) +{ + uint32_t heap_mask, result; + result = 0; + + heap_mask = flags & HEAP_MASK_FILTER; + + switch(heap_mask) { + case MHB_ION_HEAP_SYSTEM_MASK: + return ION_HEAP_SYSTEM_MASK; + case MHB_ION_HEAP_SYSTEM_CONTIG_MASK: + return ION_HEAP_SYSTEM_CONTIG_MASK; + case MHB_ION_HEAP_EXYNOS_CONTIG_MASK: + return ION_HEAP_EXYNOS_CONTIG_MASK; + case MHB_ION_HEAP_EXYNOS_MASK: + return ION_HEAP_EXYNOS_MASK; + default: + ALOGE("MemoryHeapIon : Heap Mask flag is default (flags:%x)", flags); + return 0; + break; + } + ALOGE("MemoryHeapIon : Heap Mask flag is wrong (flags:%x)", flags); + return 0; +} + +uint32_t ion_FlagMask_valid_check(uint32_t flags) +{ + uint32_t flag_mask, result; + result = 0; + + flag_mask = flags & FLAG_MASK_FILTER; + + if (flag_mask & MHB_ION_FLAG_CACHED) + result |= ION_FLAG_CACHED; + if (flag_mask & MHB_ION_FLAG_CACHED_NEEDS_SYNC) + result |= ION_FLAG_CACHED_NEEDS_SYNC; + if (flag_mask & MHB_ION_FLAG_PRESERVE_KMAP) + result |= ION_FLAG_PRESERVE_KMAP; + if (flag_mask & MHB_ION_EXYNOS_VIDEO_MASK) + result |= ION_EXYNOS_VIDEO_MASK; + if (flag_mask & MHB_ION_EXYNOS_MFC_INPUT_MASK) + result |= ION_EXYNOS_MFC_INPUT_MASK; + if (flag_mask & MHB_ION_EXYNOS_MFC_OUTPUT_MASK) + result |= ION_EXYNOS_MFC_OUTPUT_MASK; + if (flag_mask & MHB_ION_EXYNOS_GSC_MASK) + result |= ION_EXYNOS_GSC_MASK; + if (flag_mask & MHB_ION_EXYNOS_FIMD_VIDEO_MASK) + result |= ION_EXYNOS_FIMD_VIDEO_MASK; + + return result; +} + +MemoryHeapIon::MemoryHeapIon(size_t size, uint32_t flags, + __attribute__((unused))char const *name):MemoryHeapBase() +{ + void* base = NULL; + int fd = -1; + uint32_t isReadOnly, heapMask, flagMask; + + mIonClient = ion_client_create(); + + if (mIonClient < 0) { + ALOGE("MemoryHeapIon : ION client creation failed : %s", strerror(errno)); + mIonClient = -1; + } else { + isReadOnly = flags & (IMemoryHeap::READ_ONLY); + heapMask = ion_HeapMask_valid_check(flags); + flagMask = ion_FlagMask_valid_check(flags); + + if (heapMask) { + ALOGD("MemoryHeapIon : Allocated with size:%zu, heap:0x%X , flag:0x%X", size, heapMask, flagMask); + fd = ion_alloc(mIonClient, size, 0, heapMask, flagMask); + if (fd < 0) { + ALOGE("MemoryHeapIon : ION Reserve memory allocation failed(size[%zu]) : %s", size, strerror(errno)); + if (errno == ENOMEM) { // Out of reserve memory. So re-try allocating in system heap + ALOGD("MemoryHeapIon : Re-try Allocating in default heap - SYSTEM heap"); + fd = ion_alloc(mIonClient, size, 0, ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC | ION_FLAG_PRESERVE_KMAP); + } + } + } else { + fd = ion_alloc(mIonClient, size, 0, ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC | ION_FLAG_PRESERVE_KMAP); + ALOGD("MemoryHeapIon : Allocated with default heap - SYSTEM heap"); + } + + flags = isReadOnly | heapMask | flagMask; + + if (fd < 0) { + ALOGE("MemoryHeapIon : ION memory allocation failed(size[%zu]) : %s", size, strerror(errno)); + } else { + flags |= USE_ION_FD; + base = ion_map(fd, size, 0); + if (base != MAP_FAILED) { + init(fd, base, size, flags, NULL); + } else { + ALOGE("MemoryHeapIon : ION mmap failed(size[%zu], fd[%d]) : %s", size, fd, strerror(errno)); + ion_free(fd); + } + } + } +} + +MemoryHeapIon::MemoryHeapIon(int fd, size_t size, uint32_t flags, + __attribute__((unused))uint32_t offset):MemoryHeapBase() +{ + void* base = NULL; + int dup_fd = -1; + + mIonClient = ion_client_create(); + + if (mIonClient < 0) { + ALOGE("MemoryHeapIon : ION client creation failed : %s", strerror(errno)); + mIonClient = -1; + } else { + if (fd >= 0) { + dup_fd = dup(fd); + if (dup_fd == -1) { + ALOGE("MemoryHeapIon : cannot dup fd (size[%zu], fd[%d]) : %s", size, fd, strerror(errno)); + } else { + flags |= USE_ION_FD; + base = ion_map(dup_fd, size, 0); + if (base != MAP_FAILED) { + init(dup_fd, base, size, flags, NULL); + } else { + ALOGE("MemoryHeapIon : ION mmap failed(size[%zu], fd[%d]): %s", size, fd, strerror(errno)); + ion_free(dup_fd); + } + } + } else { + ALOGE("MemoryHeapIon : fd parameter error(fd : %d)", fd); + } + } +} + +MemoryHeapIon::~MemoryHeapIon() +{ + if (mIonClient != -1) { + ion_unmap(getBase(), getSize()); + ion_client_destroy(mIonClient); + mIonClient = -1; + } +} + +}; diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 22d7ef3..4f539a8 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -182,6 +182,10 @@ static void release_object(const sp<ProcessState>& proc, close(obj.handle); } +#ifdef DISABLE_ASHMEM_TRACKING + } else if (obj.cookie != 0) { + close(obj.handle); +#endif } return; } @@ -532,7 +536,11 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(mData + off); +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(proc, *flat, this, &mOpenAshmemSize); +#else + acquire_object(proc, *flat, this); +#endif if (flat->type == BINDER_TYPE_FD) { // If this is a file descriptor, we need to dup it so the @@ -1052,7 +1060,11 @@ restart_write: // Need to write meta-data? if (nullMetaData || val.binder != 0) { mObjects[mObjectsSize] = mDataPos; +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize); +#else + acquire_object(ProcessState::self(), val, this); +#endif mObjectsSize++; } @@ -1635,7 +1647,11 @@ void Parcel::releaseObjects() i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data+objects[i]); +#ifndef DISABLE_ASHMEM_TRACKING release_object(proc, *flat, this, &mOpenAshmemSize); +#else + release_object(proc, *flat, this); +#endif } } @@ -1649,7 +1665,11 @@ void Parcel::acquireObjects() i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data+objects[i]); +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(proc, *flat, this, &mOpenAshmemSize); +#else + acquire_object(proc, *flat, this); +#endif } } @@ -1831,7 +1851,11 @@ status_t Parcel::continueWrite(size_t desired) // will need to rescan because we may have lopped off the only FDs mFdsKnown = false; } +#ifndef DISABLE_ASHMEM_TRACKING release_object(proc, *flat, this, &mOpenAshmemSize); +#else + release_object(proc, *flat, this); +#endif } binder_size_t* objects = (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t)); @@ -1916,7 +1940,9 @@ void Parcel::initState() mFdsKnown = true; mAllowFds = true; mOwner = NULL; +#ifndef DISABLE_ASHMEM_TRACKING mOpenAshmemSize = 0; +#endif } void Parcel::scanForFds() const @@ -1939,12 +1965,20 @@ size_t Parcel::getBlobAshmemSize() const // This used to return the size of all blobs that were written to ashmem, now we're returning // the ashmem currently referenced by this Parcel, which should be equivalent. // TODO: Remove method once ABI can be changed. +#ifndef DISABLE_ASHMEM_TRACKING return mOpenAshmemSize; +#else + return 0; +#endif } size_t Parcel::getOpenAshmemSize() const { +#ifndef DISABLE_ASHMEM_TRACKING return mOpenAshmemSize; +#else + return 0; +#endif } // --- Parcel::Blob --- diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 8a965dd..76aec6e 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -91,6 +91,10 @@ ifeq ($(TARGET_BOARD_PLATFORM), tegra3) LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC endif +ifeq ($(TARGET_NO_SENSOR_PERMISSION_CHECK),true) +LOCAL_CPPFLAGS += -DNO_SENSOR_PERMISSION_CHECK +endif + include $(BUILD_SHARED_LIBRARY) ifeq (,$(ONE_SHOT_MAKEFILE)) diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 87e5b4d..a941e2d 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -696,15 +696,6 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->validateConsistencyLocked(); } // Autolock scope - // Wait without lock held - if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { - // Waiting here allows for two full buffers to be queued but not a - // third. In the event that frames take varying time, this makes a - // small trade-off in favor of latency rather than throughput. - mLastQueueBufferFence->waitForever("Throttling EGL Production"); - mLastQueueBufferFence = fence; - } - // Don't send the GraphicBuffer through the callback, and don't send // the slot number, since the consumer shouldn't need it item.mGraphicBuffer.clear(); @@ -728,6 +719,15 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCallbackCondition.broadcast(); } + // Wait without lock held + if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { + // Waiting here allows for two full buffers to be queued but not a + // third. In the event that frames take varying time, this makes a + // small trade-off in favor of latency rather than throughput. + mLastQueueBufferFence->waitForever("Throttling EGL Production"); + mLastQueueBufferFence = fence; + } + return NO_ERROR; } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 78886d5..0ad6339 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -103,7 +103,8 @@ public: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) + ISurfaceComposer::Rotation rotation, + bool isCpuConsumer) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -116,6 +117,7 @@ public: data.writeUint32(maxLayerZ); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); + data.writeInt32(isCpuConsumer); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); return reply.readInt32(); } @@ -361,11 +363,13 @@ status_t BnSurfaceComposer::onTransact( uint32_t maxLayerZ = data.readUint32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); int32_t rotation = data.readInt32(); + bool isCpuConsumer = data.readInt32(); status_t res = captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast<ISurfaceComposer::Rotation>(rotation)); + static_cast<ISurfaceComposer::Rotation>(rotation), + isCpuConsumer); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 00323dc..85452e6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -32,6 +32,10 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(w); output.writeUint32(h); output.writeUint32(layerStack); + output.writeFloat(blur); + output.writeStrongBinder(blurMaskSurface); + output.writeUint32(blurMaskSampling); + output.writeFloat(blurMaskAlphaThreshold); output.writeFloat(alpha); output.writeUint32(flags); output.writeUint32(mask); @@ -52,6 +56,10 @@ status_t layer_state_t::read(const Parcel& input) w = input.readUint32(); h = input.readUint32(); layerStack = input.readUint32(); + blur = input.readFloat(); + blurMaskSurface = input.readStrongBinder(); + blurMaskSampling = input.readUint32(); + blurMaskAlphaThreshold = input.readFloat(); alpha = input.readFloat(); flags = static_cast<uint8_t>(input.readUint32()); mask = static_cast<uint8_t>(input.readUint32()); diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 235cbbd..e423a8e 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -118,9 +118,11 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) break; case SENSOR_TYPE_HEART_RATE: { mStringType = SENSOR_STRING_TYPE_HEART_RATE; +#ifndef NO_SENSOR_PERMISSION_CHECK mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS; AppOpsManager appOps; mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS)); +#endif mFlags |= SENSOR_FLAG_ON_CHANGE_MODE; } break; case SENSOR_TYPE_LIGHT: @@ -221,6 +223,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) { mStringType = hwSensor->stringType; } +#ifndef NO_SENSOR_PERMISSION_CHECK if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) { mRequiredPermission = hwSensor->requiredPermission; if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) { @@ -228,6 +231,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS)); } } +#endif if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) { mFlags = static_cast<uint32_t>(hwSensor->flags); @@ -267,6 +271,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) } } +#ifndef NO_SENSOR_PERMISSION_CHECK if (mRequiredPermission.length() > 0) { // If the sensor is protected by a permission we need to know if it is // a runtime one to determine whether we can use the permission cache. @@ -277,6 +282,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) String16(mRequiredPermission)); } } +#endif } Sensor::~Sensor() diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 4b76f98..1abb6c3 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1023,6 +1023,7 @@ status_t Surface::lock( } // figure out if we can copy the frontbuffer back + int backBufferSlot(getSlotFromBufferLocked(backBuffer.get())); const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); const bool canCopyBack = (frontBuffer != 0 && backBuffer->width == frontBuffer->width && @@ -1030,15 +1031,23 @@ status_t Surface::lock( backBuffer->format == frontBuffer->format); if (canCopyBack) { - // copy the area that is invalid and not repainted this round - const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); + Mutex::Autolock lock(mMutex); + Region oldDirtyRegion; + if(mSlots[backBufferSlot].dirtyRegion.isEmpty()) { + oldDirtyRegion.set(bounds); + } else { + for(int i = 0 ; i < NUM_BUFFER_SLOTS; i++ ) { + if(i != backBufferSlot && !mSlots[i].dirtyRegion.isEmpty()) + oldDirtyRegion.orSelf(mSlots[i].dirtyRegion); + } + } + const Region copyback(oldDirtyRegion.subtract(newDirtyRegion)); if (!copyback.isEmpty()) copyBlt(backBuffer, frontBuffer, copyback); } else { // if we can't copy-back anything, modify the user's dirty // region to make sure they redraw the whole buffer newDirtyRegion.set(bounds); - mDirtyRegion.clear(); Mutex::Autolock lock(mMutex); for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) { mSlots[i].dirtyRegion.clear(); @@ -1048,15 +1057,9 @@ status_t Surface::lock( { // scope for the lock Mutex::Autolock lock(mMutex); - int backBufferSlot(getSlotFromBufferLocked(backBuffer.get())); - if (backBufferSlot >= 0) { - Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); - mDirtyRegion.subtract(dirtyRegion); - dirtyRegion = newDirtyRegion; - } + mSlots[backBufferSlot].dirtyRegion = newDirtyRegion; } - mDirtyRegion.orSelf(newDirtyRegion); if (inOutDirtyBounds) { *inOutDirtyBounds = newDirtyRegion.getBounds(); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6ad47d8..82bdd6b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -144,6 +144,14 @@ public: uint32_t w, uint32_t h); status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t z); + status_t setBlur(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + float blur); + status_t setBlurMaskSurface(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + const sp<IBinder>& maskSurfaceId); + status_t setBlurMaskSampling(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + uint32_t blurMaskSampling); + status_t setBlurMaskAlphaThreshold(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + float alpha); status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t flags, uint32_t mask); status_t setTransparentRegionHint( @@ -303,6 +311,50 @@ status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, return NO_ERROR; } +status_t Composer::setBlur(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, float blur) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eBlurChanged; + s->blur = blur; + return NO_ERROR; +} + +status_t Composer::setBlurMaskSurface(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eBlurMaskSurfaceChanged; + s->blurMaskSurface = maskSurfaceId; + return NO_ERROR; +} + +status_t Composer::setBlurMaskSampling(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, uint32_t blurMaskSampling) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eBlurMaskSamplingChanged; + s->blurMaskSampling = blurMaskSampling; + return NO_ERROR; +} + +status_t Composer::setBlurMaskAlphaThreshold(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, float alpha) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eBlurMaskAlphaThresholdChanged; + s->blurMaskAlphaThreshold = alpha; + return NO_ERROR; +} + status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t flags, uint32_t mask) { @@ -574,6 +626,22 @@ status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, uint32_t z) { return getComposer().setLayer(this, id, z); } +status_t SurfaceComposerClient::setBlur(const sp<IBinder>& id, float blur) { + return getComposer().setBlur(this, id, blur); +} + +status_t SurfaceComposerClient::setBlurMaskSurface(const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId) { + return getComposer().setBlurMaskSurface(this, id, maskSurfaceId); +} + +status_t SurfaceComposerClient::setBlurMaskSampling(const sp<IBinder>& id, uint32_t blurMaskSampling) { + return getComposer().setBlurMaskSampling(this, id, blurMaskSampling); +} + +status_t SurfaceComposerClient::setBlurMaskAlphaThreshold(const sp<IBinder>& id, float alpha) { + return getComposer().setBlurMaskAlphaThreshold(this, id, alpha); +} + status_t SurfaceComposerClient::hide(const sp<IBinder>& id) { return getComposer().setFlags(this, id, layer_state_t::eLayerHidden, @@ -683,6 +751,12 @@ status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) { // ---------------------------------------------------------------------------- +#ifndef FORCE_SCREENSHOT_CPU_PATH +#define SS_CPU_CONSUMER false +#else +#define SS_CPU_CONSUMER true +#endif + status_t ScreenshotClient::capture( const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, @@ -691,7 +765,8 @@ status_t ScreenshotClient::capture( sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, + ISurfaceComposer::eRotateNone, SS_CPU_CONSUMER); } ScreenshotClient::ScreenshotClient() @@ -729,7 +804,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, status_t err = s->captureScreen(display, mProducer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast<ISurfaceComposer::Rotation>(rotation)); + static_cast<ISurfaceComposer::Rotation>(rotation), true); if (err == NO_ERROR) { err = mCpuConsumer->lockNextBuffer(&mBuffer); diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 1983027..8212b90 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -99,6 +99,26 @@ status_t SurfaceControl::setLayer(uint32_t layer) { if (err < 0) return err; return mClient->setLayer(mHandle, layer); } +status_t SurfaceControl::setBlur(float blur) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setBlur(mHandle, blur); +} +status_t SurfaceControl::setBlurMaskSurface(const sp<SurfaceControl>& maskSurface) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setBlurMaskSurface(mHandle, maskSurface != 0 ? maskSurface->mHandle : 0); +} +status_t SurfaceControl::setBlurMaskSampling(uint32_t blurMaskSampling) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setBlurMaskSampling(mHandle, blurMaskSampling); +} +status_t SurfaceControl::setBlurMaskAlphaThreshold(float alpha) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setBlurMaskAlphaThreshold(mHandle, alpha); +} status_t SurfaceControl::setPosition(float x, float y) { status_t err = validate(); if (err < 0) return err; diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 1ce8626..a8eb67b 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -56,6 +56,10 @@ ifneq ($(BOARD_FRAMEBUFFER_FORCE_FORMAT),) LOCAL_CFLAGS += -DFRAMEBUFFER_FORCE_FORMAT=$(BOARD_FRAMEBUFFER_FORCE_FORMAT) endif +ifeq ($(BOARD_EGL_NEEDS_HANDLE_VALUE),true) +LOCAL_CFLAGS += -DEGL_NEEDS_HANDLE +endif + LOCAL_MODULE := libui include $(BUILD_SHARED_LIBRARY) diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index e55db30..992c1fe 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -112,6 +112,11 @@ void GraphicBuffer::free_handle() GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); } + +#ifndef EGL_NEEDS_HANDLE + handle = NULL; +#endif + mWrappedBuffer = 0; } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 90a1c11..0580e16 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -190,5 +190,18 @@ status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd) return err; } +#ifdef EXYNOS4_ENHANCEMENTS +status_t GraphicBufferMapper::getphys(buffer_handle_t handle, void** paddr) +{ + status_t err; + + err = mAllocMod->getphys(mAllocMod, handle, paddr); + + ALOGW_IF(err, "getphys(%p) fail %d(%s)", handle, err, strerror(-err)); + return err; +} +#endif + + // --------------------------------------------------------------------------- }; // namespace android diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 18ad300..870c2bd 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -47,6 +47,12 @@ LOCAL_CFLAGS += -DEGL_TRACE=1 ifeq ($(BOARD_ALLOW_EGL_HIBERNATION),true) LOCAL_CFLAGS += -DBOARD_ALLOW_EGL_HIBERNATION endif +ifeq ($(TARGET_BOARD_PLATFORM), omap4) + LOCAL_CFLAGS += -DWORKAROUND_BUG_10194508=1 +endif +ifeq ($(BOARD_EGL_WORKAROUND_BUG_10194508),true) + LOCAL_CFLAGS += -DWORKAROUND_BUG_10194508=1 +endif ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),) LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE) endif @@ -59,6 +65,10 @@ ifneq ($(MAX_EGL_CACHE_SIZE),) LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE) endif +ifeq ($(BOARD_USE_BGRA_8888), true) + LOCAL_CFLAGS += -DUSE_BGRA_8888 +endif + LOCAL_REQUIRED_MODULES := $(egl.cfg_config_module) egl.cfg_config_module := diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index cdec565..2f6bc79 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -462,15 +462,32 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, // modify the EGLconfig's format before setting the native window's // format. +#ifdef USE_BGRA_8888 + // by default, just pick BGRA_8888 + EGLint format = HAL_PIXEL_FORMAT_BGRA_8888; +#else // by default, just pick RGBA_8888 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; +#if WORKAROUND_BUG_10194508 + if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID, + &format)) { + ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x", + eglGetError()); + format = 0; + } +#else EGLint a = 0; cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); if (a > 0) { // alpha-channel requested, there's really only one suitable format +#ifdef USE_BGRA_8888 + format = HAL_PIXEL_FORMAT_BGRA_8888; +#else format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif } else { EGLint r, g, b; r = g = b = 0; @@ -484,6 +501,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, format = HAL_PIXEL_FORMAT_RGBX_8888; } } +#endif // now select a corresponding sRGB format if needed if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp index f13d6e8..55c7813 100644 --- a/services/batteryservice/BatteryProperties.cpp +++ b/services/batteryservice/BatteryProperties.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +42,27 @@ status_t BatteryProperties::readFromParcel(Parcel* p) { batteryVoltage = p->readInt32(); batteryTemperature = p->readInt32(); batteryTechnology = String8((p->readString16()).string()); + + dockBatterySupported = p->readInt32() == 1 ? true : false; + if (dockBatterySupported) { + chargerDockAcOnline = p->readInt32() == 1 ? true : false; + dockBatteryStatus = p->readInt32(); + dockBatteryHealth = p->readInt32(); + dockBatteryPresent = p->readInt32() == 1 ? true : false; + dockBatteryLevel = p->readInt32(); + dockBatteryVoltage = p->readInt32(); + dockBatteryTemperature = p->readInt32(); + dockBatteryTechnology = String8((p->readString16()).string()); + } else { + chargerDockAcOnline = false; + dockBatteryStatus = BATTERY_STATUS_UNKNOWN; + dockBatteryHealth = BATTERY_HEALTH_UNKNOWN; + dockBatteryPresent = false; + dockBatteryLevel = 0; + dockBatteryVoltage = 0; + dockBatteryTemperature = 0; + dockBatteryTechnology = String8(String8::kEmptyString); + } return OK; } @@ -56,6 +78,18 @@ status_t BatteryProperties::writeToParcel(Parcel* p) const { p->writeInt32(batteryVoltage); p->writeInt32(batteryTemperature); p->writeString16(String16(batteryTechnology)); + + p->writeInt32(dockBatterySupported ? 1 : 0); + if (dockBatterySupported) { + p->writeInt32(chargerDockAcOnline ? 1 : 0); + p->writeInt32(dockBatteryStatus); + p->writeInt32(dockBatteryHealth); + p->writeInt32(dockBatteryPresent ? 1 : 0); + p->writeInt32(dockBatteryLevel); + p->writeInt32(dockBatteryVoltage); + p->writeInt32(dockBatteryTemperature); + p->writeString16(String16(dockBatteryTechnology)); + } return OK; } diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp index 46934e0..e18e39c 100644 --- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp +++ b/services/batteryservice/IBatteryPropertiesRegistrar.cpp @@ -60,6 +60,22 @@ public: val->readFromParcel(&reply); return ret; } + + status_t getDockProperty(int id, struct BatteryProperty *val) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor()); + data.writeInt32(id); + remote()->transact(GET_DOCK_PROPERTY, data, &reply); + int32_t ret = reply.readExceptionCode(); + if (ret != 0) { + return ret; + } + ret = reply.readInt32(); + int parcelpresent = reply.readInt32(); + if (parcelpresent) + val->readFromParcel(&reply); + return ret; + } }; IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar"); @@ -97,6 +113,18 @@ status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code, val.writeToParcel(reply); return OK; } + + case GET_DOCK_PROPERTY: { + CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply); + int id = data.readInt32(); + struct BatteryProperty val; + status_t result = getDockProperty(id, &val); + reply->writeNoException(); + reply->writeInt32(result); + reply->writeInt32(1); + val.writeToParcel(reply); + return OK; + } } return BBinder::onTransact(code, data, reply, flags); }; diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 6a6547b..4f28840 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -21,6 +21,7 @@ #include "InputManager.h" #include <cutils/log.h> +#include <cutils/iosched_policy.h> namespace android { @@ -51,13 +52,15 @@ void InputManager::initialize() { } status_t InputManager::start() { - status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); + status_t result = mDispatcherThread->run("InputDispatcher", + PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); if (result) { ALOGE("Could not start InputDispatcher thread due to error %d.", result); return result; } - result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); + result = mReaderThread->run("InputReader", + PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); if (result) { ALOGE("Could not start InputReader thread due to error %d.", result); @@ -65,6 +68,9 @@ status_t InputManager::start() { return result; } + android_set_rt_ioprio(mDispatcherThread->getTid(), 1); + android_set_rt_ioprio(mReaderThread->getTid(), 1); + return OK; } diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index b2cbfe8..53ff155 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -116,9 +116,9 @@ static inline const char* toString(bool value) { } static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, - const int32_t map[][4], size_t mapSize) { + const int32_t map[][4], size_t mapSize, int32_t rotationMapOffset) { if (orientation != DISPLAY_ORIENTATION_0) { - for (size_t i = 0; i < mapSize; i++) { + for (size_t i = rotationMapOffset; i < mapSize; i++) { if (value == map[i][0]) { return map[i][orientation]; } @@ -130,6 +130,16 @@ static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, static const int32_t keyCodeRotationMap[][4] = { // key codes enumerated counter-clockwise with the original (unrotated) key first // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation + + // volume keys - tablet + { AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_DOWN }, + { AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_UP }, + + // volume keys - phone or hybrid + { AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_UP }, + { AKEYCODE_VOLUME_DOWN, AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_UP, AKEYCODE_VOLUME_DOWN }, + + // dpad keys - common { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT }, { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN }, { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT }, @@ -138,9 +148,9 @@ static const int32_t keyCodeRotationMap[][4] = { static const size_t keyCodeRotationMapSize = sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); -static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { +static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation, int32_t rotationMapOffset) { return rotateValueUsingRotationMap(keyCode, orientation, - keyCodeRotationMap, keyCodeRotationMapSize); + keyCodeRotationMap, keyCodeRotationMapSize, rotationMapOffset); } static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) { @@ -2131,10 +2141,16 @@ void KeyboardInputMapper::configure(nsecs_t when, mOrientation = DISPLAY_ORIENTATION_0; } } + if (!changes || (changes & InputReaderConfiguration::CHANGE_VOLUME_KEYS_ROTATION)) { + // mode 0 (disabled) ~ offset 4 + // mode 1 (phone) ~ offset 2 + // mode 2 (tablet) ~ offset 0 + mRotationMapOffset = 4 - 2 * config->volumeKeysRotationMode; + } } void KeyboardInputMapper::configureParameters() { - mParameters.orientationAware = false; + mParameters.orientationAware = !getDevice()->isExternal(); getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware); @@ -2218,7 +2234,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, if (down) { // Rotate key codes according to orientation if needed. if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - keyCode = rotateKeyCode(keyCode, mOrientation); + keyCode = rotateKeyCode(keyCode, mOrientation, mRotationMapOffset); } // Add key down. @@ -2934,7 +2950,8 @@ void TouchInputMapper::configure(nsecs_t when, if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT | InputReaderConfiguration::CHANGE_SHOW_TOUCHES - | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) { + | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE + | InputReaderConfiguration::CHANGE_STYLUS_ICON_ENABLED))) { // Configure device sources, surface dimensions, orientation and // scaling factors. configureSurface(when, &resetNeeded); @@ -3006,6 +3023,8 @@ void TouchInputMapper::configureParameters() { mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION; } else if (deviceTypeString == "pointer") { mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; + } else if (deviceTypeString == "gesture") { + mParameters.deviceType = Parameters::DEVICE_TYPE_GESTURE_SENSOR; } else if (deviceTypeString != "default") { ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); } @@ -3061,6 +3080,9 @@ void TouchInputMapper::dumpParameters(String8& dump) { case Parameters::DEVICE_TYPE_POINTER: dump.append(INDENT4 "DeviceType: pointer\n"); break; + case Parameters::DEVICE_TYPE_GESTURE_SENSOR: + dump.append(INDENT4 "DeviceType: gesture\n"); + break; default: ALOG_ASSERT(false); } @@ -3123,6 +3145,9 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) { mSource = AINPUT_SOURCE_TOUCH_NAVIGATION; mDeviceMode = DEVICE_MODE_NAVIGATION; + } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_GESTURE_SENSOR) { + mSource = AINPUT_SOURCE_GESTURE_SENSOR; + mDeviceMode = DEVICE_MODE_UNSCALED; } else { mSource = AINPUT_SOURCE_TOUCHPAD; mDeviceMode = DEVICE_MODE_UNSCALED; @@ -4858,7 +4883,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) { // Remind the user of where the pointer is after finishing a gesture with spots. - mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL); + unfadePointer(PointerControllerInterface::TRANSITION_GRADUAL); } break; case PointerGesture::TAP: @@ -5847,6 +5872,7 @@ void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) mPointerSimple.currentProperties.id = 0; mPointerSimple.currentProperties.toolType = mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType; + mLastStylusTime = when; } else { down = false; hovering = false; @@ -5923,11 +5949,16 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); mPointerController->clearSpots(); mPointerController->setButtonState(mCurrentRawState.buttonState); - mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); + unfadePointer(PointerControllerInterface::TRANSITION_IMMEDIATE); } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); } } + + if (rejectPalm(when)) { // stylus is currently active + mPointerSimple.reset(); + return; + } if (mPointerSimple.down && !down) { mPointerSimple.down = false; @@ -6049,6 +6080,9 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { + + if (rejectPalm(when)) return; + PointerCoords pointerCoords[MAX_POINTERS]; PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0; @@ -6122,6 +6156,20 @@ void TouchInputMapper::fadePointer() { } } +void TouchInputMapper::unfadePointer(PointerControllerInterface::Transition transition) { + if (mPointerController != NULL && + !(mPointerUsage == POINTER_USAGE_STYLUS && !mConfig.stylusIconEnabled)) { + mPointerController->unfade(transition); + } +} + +nsecs_t TouchInputMapper::mLastStylusTime = 0; + +bool TouchInputMapper::rejectPalm(nsecs_t when) { + return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) && + mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS; +} + void TouchInputMapper::cancelTouch(nsecs_t when) { abortPointerUsage(when, 0 /*policyFlags*/); abortTouches(when, 0 /* policyFlags*/); diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 30c84b1..e480350 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -144,6 +144,12 @@ struct InputReaderConfiguration { // The presence of an external stylus has changed. CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7, + // Volume keys rotation option changed. + CHANGE_VOLUME_KEYS_ROTATION = 1 << 8, + + // Stylus icon option changed. + CHANGE_STYLUS_ICON_ENABLED = 1 << 9, + // All devices must be reopened. CHANGE_MUST_REOPEN = 1 << 31, }; @@ -231,6 +237,16 @@ struct InputReaderConfiguration { // True to show the location of touches on the touch screen as spots. bool showTouches; + // True to show the pointer icon when a stylus is used. + bool stylusIconEnabled; + + // Ignore finger touches this long after the stylus has been used (including hover) + nsecs_t stylusPalmRejectionTime; + + // Remap volume keys according to display rotation + // 0 - disabled, 1 - phone or hybrid rotation mode, 2 - tablet rotation mode + int volumeKeysRotationMode; + InputReaderConfiguration() : virtualKeyQuietTime(0), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), @@ -247,7 +263,11 @@ struct InputReaderConfiguration { pointerGestureSwipeMaxWidthRatio(0.25f), pointerGestureMovementSpeedRatio(0.8f), pointerGestureZoomSpeedRatio(0.3f), - showTouches(false) { } + showTouches(false), + stylusIconEnabled(false), + stylusPalmRejectionTime(50 * 10000000LL), // 50 ms + volumeKeysRotationMode(0) + { } bool getDisplayInfo(bool external, DisplayViewport* outViewport) const; void setDisplayInfo(bool external, const DisplayViewport& viewport); @@ -1126,7 +1146,8 @@ private: uint32_t mSource; int32_t mKeyboardType; - int32_t mOrientation; // orientation for dpad keys + int32_t mRotationMapOffset; // determines if and how volume keys rotate + int32_t mOrientation; // orientation for dpad and volume keys Vector<KeyDown> mKeyDowns; // keys that are down int32_t mMetaState; @@ -1295,6 +1316,7 @@ protected: DEVICE_TYPE_TOUCH_SCREEN, DEVICE_TYPE_TOUCH_PAD, DEVICE_TYPE_TOUCH_NAVIGATION, + DEVICE_TYPE_GESTURE_SENSOR, DEVICE_TYPE_POINTER, }; @@ -1785,6 +1807,9 @@ private: VelocityControl mPointerVelocityControl; VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + + // The time the stylus event was processed by any TouchInputMapper + static nsecs_t mLastStylusTime; void resetExternalStylus(); void clearStylusDataPendingFlags(); @@ -1851,6 +1876,10 @@ private: const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); static void assignPointerIds(const RawState* last, RawState* current); + + void unfadePointer(PointerControllerInterface::Transition transition); + + bool rejectPalm(nsecs_t when); }; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index fd72b23..3d9dcd0 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -146,9 +146,10 @@ void SensorService::onFirstRef() aSensor = registerVirtualSensor( new OrientationSensor() ); if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { - // if we are doing our own rotation-vector, also add - // the orientation sensor and remove the HAL provided one. - mUserSensorList.replaceAt(aSensor, orientationIndex); + if (orientationIndex == -1) { + // some sensor HALs don't provide an orientation sensor. + mUserSensorList.add(aSensor); + } } // virtual debugging sensors are not added to mUserSensorList @@ -358,6 +359,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) result.appendFormat("non-wakeUp | "); } + result.appendFormat("%.4f mA | ", s.getPowerUsage()); + int bufIndex = mLastEventSeen.indexOfKey(s.getHandle()); if (bufIndex >= 0) { const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex); @@ -918,17 +921,20 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, // to maintain the on-change logic (any on-change events except the initial // one should be trigger by a change in value). Also if this sensor isn't // already active, don't call flush(). + const SensorDevice& device(SensorDevice::getInstance()); if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ON_CHANGE && rec->getNumConnections() > 1) { - connection->setFirstFlushPending(handle, true); - status_t err_flush = sensor->flush(connection.get(), handle); - // Flush may return error if the underlying h/w sensor uses an older HAL. - if (err_flush == NO_ERROR) { - rec->addPendingFlushConnection(connection.get()); - } else { - connection->setFirstFlushPending(handle, false); + if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) { + connection->setFirstFlushPending(handle, true); + status_t err_flush = sensor->flush(connection.get(), handle); + // Flush may return error if the underlying h/w sensor uses an older HAL. + if (err_flush == NO_ERROR) { + rec->addPendingFlushConnection(connection.get()); + } else { + connection->setFirstFlushPending(handle, false); + } } } @@ -954,6 +960,11 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE; } + if (device.getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { + // Pre-1.1 sensor HALs had no flush method, and relied on setDelay at init + sensor->setDelay(connection.get(), handle, samplingPeriodNs); + } + if (err != NO_ERROR) { // batch/activate has failed, reset our state. cleanupWithoutDisableLocked(connection, handle); @@ -1109,7 +1120,7 @@ bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation, AppOpsManager appOps; if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName) != AppOpsManager::MODE_ALLOWED) { - ALOGE("%s a sensor (%s) without enabled required app op: %D", + ALOGE("%s a sensor (%s) without enabled required app op: %d", operation, sensor.getName().string(), opCode); return false; } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1eb2361..6a90083 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -13,6 +13,7 @@ LOCAL_SRC_FILES := \ FrameTracker.cpp \ Layer.cpp \ LayerDim.cpp \ + LayerBlur.cpp \ MessageQueue.cpp \ MonitoredProducer.cpp \ SurfaceFlinger.cpp \ @@ -34,10 +35,15 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES10RenderEngine.cpp \ RenderEngine/GLES11RenderEngine.cpp \ - RenderEngine/GLES20RenderEngine.cpp - + RenderEngine/GLES20RenderEngine.cpp \ + DisplayUtils.cpp LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" + +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +LOCAL_CFLAGS += -DDEBUG_CONT_DUMPSYS +endif + LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES ifeq ($(TARGET_BOARD_PLATFORM),omap4) @@ -89,6 +95,10 @@ else LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0 endif +ifeq ($(BOARD_USE_BGRA_8888),true) + LOCAL_CFLAGS += -DUSE_BGRA_8888 +endif + LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_CFLAGS += -std=c++11 @@ -106,6 +116,24 @@ LOCAL_SHARED_LIBRARIES := \ libgui \ libpowermanager +ifeq ($(TARGET_USES_QCOM_BSP), true) + LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libgralloc + LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libqdutils + LOCAL_SHARED_LIBRARIES += libqdutils + LOCAL_CFLAGS += -DQTI_BSP + LOCAL_SRC_FILES += \ + ExSurfaceFlinger/ExLayer.cpp \ + ExSurfaceFlinger/ExSurfaceFlinger.cpp \ + ExSurfaceFlinger/ExVirtualDisplaySurface.cpp \ + ExSurfaceFlinger/ExHWComposer.cpp +endif + +ifeq ($(TARGET_HAVE_UI_BLUR),true) + LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/ui + LOCAL_SHARED_LIBRARIES += libuiblur + LOCAL_CFLAGS += -DUI_BLUR +endif + LOCAL_MODULE := libsurfaceflinger LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code @@ -122,6 +150,10 @@ LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--e LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CPPFLAGS := -std=c++11 +ifneq ($(ENABLE_CPUSETS),) + LOCAL_CFLAGS += -DENABLE_CPUSETS +endif + LOCAL_SRC_FILES := \ main_surfaceflinger.cpp diff --git a/services/surfaceflinger/CleanSpec.mk b/services/surfaceflinger/CleanSpec.mk new file mode 100644 index 0000000..c46eaeb --- /dev/null +++ b/services/surfaceflinger/CleanSpec.mk @@ -0,0 +1,51 @@ +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libsurfaceflinger_ddmconnection_intermediates) diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 3738a55..73b3897 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -21,6 +21,7 @@ #include <math.h> +#include <cutils/iosched_policy.h> #include <cutils/log.h> #include <ui/Fence.h> @@ -292,6 +293,7 @@ DispSync::DispSync() : mThread(new DispSyncThread()) { mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); + android_set_rt_ioprio(mThread->getTid(), 1); reset(); beginResync(); diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 67142b6..ebe19a5 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -26,11 +26,8 @@ namespace android { // Ignore present (retire) fences if the device doesn't have support for the -// sync framework, or if all phase offsets are zero. The latter is useful -// because it allows us to avoid resync bursts on devices that don't need -// phase-offset VSYNC events. -#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \ - (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0) +// sync framework. +#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) static const bool kIgnorePresentFences = true; #else static const bool kIgnorePresentFences = false; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 13d44f3..f597b73 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -88,21 +88,23 @@ DisplayDevice::DisplayDevice( mPowerMode(HWC_POWER_MODE_OFF), mActiveConfig(0) { - mNativeWindow = new Surface(producer, false); + Surface* surface; + mNativeWindow = surface = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); + char property[PROPERTY_VALUE_MAX]; /* * Create our display's surface */ - EGLSurface surface; + EGLSurface eglSurface; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (config == EGL_NO_CONFIG) { config = RenderEngine::chooseEglConfig(display, format); } - surface = eglCreateWindowSurface(display, config, window, NULL); - eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); - eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); + eglSurface = eglCreateWindowSurface(display, config, window, NULL); + eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth); + eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight); // Make sure that composition can never be stalled by a virtual display // consumer that isn't processing buffers fast enough. We have to do this @@ -116,7 +118,7 @@ DisplayDevice::DisplayDevice( mConfig = config; mDisplay = display; - mSurface = surface; + mSurface = eglSurface; mFormat = format; mPageFlipCount = 0; mViewport.makeInvalid(); @@ -140,8 +142,17 @@ DisplayDevice::DisplayDevice( break; } + mPanelInverseMounted = false; + // Check if panel is inverse mounted (contents show up HV flipped) + property_get("persist.panel.inversemounted", property, "0"); + mPanelInverseMounted = !!atoi(property); + // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); + +#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS + surface->allocateBuffers(); +#endif } DisplayDevice::~DisplayDevice() { @@ -386,6 +397,20 @@ status_t DisplayDevice::orientationToTransfrom( int orientation, int w, int h, Transform* tr) { uint32_t flags = 0; + char value[PROPERTY_VALUE_MAX]; + property_get("ro.sf.hwrotation", value, "0"); + int additionalRot = atoi(value); + + if (additionalRot) { + additionalRot /= 90; + if (orientation == DisplayState::eOrientationUnchanged) { + orientation = additionalRot; + } else { + orientation += additionalRot; + orientation %= 4; + } + } + switch (orientation) { case DisplayState::eOrientationDefault: flags = Transform::ROT_0; @@ -402,6 +427,11 @@ status_t DisplayDevice::orientationToTransfrom( default: return BAD_VALUE; } + + if (DISPLAY_PRIMARY == mHwcDisplayId && isPanelInverseMounted()) { + flags = flags ^ Transform::ROT_180; + } + tr->set(flags, w, h); return NO_ERROR; } @@ -441,7 +471,15 @@ void DisplayDevice::setProjection(int orientation, if (!frame.isValid()) { // the destination frame can be invalid if it has never been set, // in that case we assume the whole display frame. - frame = Rect(w, h); + char value[PROPERTY_VALUE_MAX]; + property_get("ro.sf.hwrotation", value, "0"); + int additionalRot = atoi(value); + + if (additionalRot == 90 || additionalRot == 270) { + frame = Rect(h, w); + } else { + frame = Rect(w, h); + } } if (viewport.isEmpty()) { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8695a44..f492a42 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -126,6 +126,10 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } + bool isPanelInverseMounted() const { + return mPanelInverseMounted; + } + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; @@ -209,7 +213,7 @@ private: /* * Transaction state */ - static status_t orientationToTransfrom(int orientation, + status_t orientationToTransfrom(int orientation, int w, int h, Transform* tr); uint32_t mLayerStack; @@ -226,6 +230,8 @@ private: int mPowerMode; // Current active config int mActiveConfig; + // Panel is inverse mounted + int mPanelInverseMounted; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 6ef3295..70af656 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -67,6 +67,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp)); mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp)); mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); + mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1); } status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 0859149..17e91d9 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -36,6 +36,9 @@ #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#ifdef QTI_BSP +#include <hardware/display_defs.h> +#endif #include <android/configuration.h> @@ -190,6 +193,11 @@ HWComposer::HWComposer( // we don't have VSYNC support, we need to fake it mVSyncThread = new VSyncThread(*this); } + + mDimComp = 0; + if (mHwc) { + mHwc->query(mHwc, HWC_BACKGROUND_LAYER_SUPPORTED, &mDimComp); + } } HWComposer::~HWComposer() { @@ -368,7 +376,12 @@ status_t HWComposer::queryDisplayProperties(int disp) { return err; } - mDisplayData[disp].currentConfig = 0; + int currentConfig = getActiveConfig(disp); + if (currentConfig < 0 || currentConfig > static_cast<int>((numConfigs-1))) { + ALOGE("%s: Invalid display config! %d", __FUNCTION__, currentConfig); + currentConfig = 0; + } + mDisplayData[disp].currentConfig = currentConfig; for (size_t c = 0; c < numConfigs; ++c) { err = mHwc->getDisplayAttributes(mHwc, disp, configs[c], DISPLAY_ATTRIBUTES, values); @@ -422,7 +435,11 @@ status_t HWComposer::queryDisplayProperties(int disp) { } // FIXME: what should we set the format to? +#ifdef USE_BGRA_8888 + mDisplayData[disp].format = HAL_PIXEL_FORMAT_BGRA_8888; +#else mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif mDisplayData[disp].connected = true; return NO_ERROR; } @@ -484,7 +501,11 @@ sp<Fence> HWComposer::getDisplayFence(int disp) const { uint32_t HWComposer::getFormat(int disp) const { if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) { +#ifdef USE_BGRA_8888 + return HAL_PIXEL_FORMAT_BGRA_8888; +#else return HAL_PIXEL_FORMAT_RGBA_8888; +#endif } else { return mDisplayData[disp].format; } @@ -701,13 +722,14 @@ status_t HWComposer::prepare() { disp.hasFbComp = false; disp.hasOvComp = false; if (disp.list) { - for (size_t i=0 ; i<disp.list->numHwLayers ; i++) { - hwc_layer_1_t& l = disp.list->hwLayers[i]; + for (size_t j=0 ; j<disp.list->numHwLayers ; j++) { + hwc_layer_1_t& l = disp.list->hwLayers[j]; //ALOGD("prepare: %d, type=%d, handle=%p", // i, l.compositionType, l.handle); - if (l.flags & HWC_SKIP_LAYER) { + if ((i == DisplayDevice::DISPLAY_PRIMARY) && + l.flags & HWC_SKIP_LAYER) { l.compositionType = HWC_FRAMEBUFFER; } if (l.compositionType == HWC_FRAMEBUFFER) { @@ -716,6 +738,9 @@ status_t HWComposer::prepare() { if (l.compositionType == HWC_OVERLAY) { disp.hasOvComp = true; } + if (isCompositionTypeBlit(l.compositionType)) { + disp.hasFbComp = true; + } if (l.compositionType == HWC_CURSOR_OVERLAY) { disp.hasOvComp = true; } @@ -816,15 +841,31 @@ status_t HWComposer::setPowerMode(int disp, int mode) { status_t HWComposer::setActiveConfig(int disp, int mode) { LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); DisplayData& dd(mDisplayData[disp]); - dd.currentConfig = mode; if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { - return (status_t)mHwc->setActiveConfig(mHwc, disp, mode); + status_t status = static_cast<status_t>( + mHwc->setActiveConfig(mHwc, disp, mode)); + if (status == NO_ERROR) { + dd.currentConfig = mode; + } else { + ALOGE("%s Failed to set new config (%d) for display (%d)", + __FUNCTION__, mode, disp); + } + return status; } else { LOG_FATAL_IF(mode != 0); } return NO_ERROR; } +int HWComposer::getActiveConfig(int disp) const { + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); + if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { + return mHwc->getActiveConfig(mHwc, disp); + } else { + return 0; + } +} + void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); DisplayData& dd(mDisplayData[disp]); @@ -846,7 +887,11 @@ int HWComposer::getVisualID() const { // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED // is supported by the implementation. we can only be in this case // if we have HWC 1.1 +#ifdef USE_BGRA_8888 + return HAL_PIXEL_FORMAT_BGRA_8888; +#else return HAL_PIXEL_FORMAT_RGBA_8888; +#endif //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } else { return mFbDev->format; @@ -977,6 +1022,17 @@ public: } } } + virtual void setAnimating(bool animating) { + if (animating) { +#ifdef QTI_BSP + getLayer()->flags |= HWC_SCREENSHOT_ANIMATOR_LAYER; +#endif + } else { +#ifdef QTI_BSP + getLayer()->flags &= ~HWC_SCREENSHOT_ANIMATOR_LAYER; +#endif + } + } virtual void setDefaultState() { hwc_layer_1_t* const l = getLayer(); l->compositionType = HWC_FRAMEBUFFER; @@ -998,6 +1054,10 @@ public: getLayer()->flags &= ~HWC_SKIP_LAYER; } } + virtual void setDim() { + setSkip(false); + getLayer()->flags |= 0x80000000; + } virtual void setIsCursorLayerHint(bool isCursor) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { if (isCursor) { @@ -1233,7 +1293,7 @@ void HWComposer::dump(String8& result) const { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) { result.appendFormat( " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n", - compositionTypeName[type], + (isCompositionTypeBlit(l.compositionType)) ? "HWC_BLIT" : compositionTypeName[type], intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(), l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, @@ -1241,7 +1301,7 @@ void HWComposer::dump(String8& result) const { } else { result.appendFormat( " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n", - compositionTypeName[type], + (isCompositionTypeBlit(l.compositionType)) ? "HWC_BLIT" : compositionTypeName[type], intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(), l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, @@ -1319,7 +1379,11 @@ bool HWComposer::VSyncThread::threadLoop() { HWComposer::DisplayData::DisplayData() : configs(), currentConfig(0), +#ifdef USE_BGRA_8888 + format(HAL_PIXEL_FORMAT_BGRA_8888), +#else format(HAL_PIXEL_FORMAT_RGBA_8888), +#endif connected(false), hasFbComp(false), hasOvComp(false), capacity(0), list(NULL), diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 5e0b3d8..9bdb7de 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -74,7 +74,7 @@ public: const sp<SurfaceFlinger>& flinger, EventHandler& handler); - ~HWComposer(); + virtual ~HWComposer(); status_t initCheck() const; @@ -103,6 +103,9 @@ public: // set active config status_t setActiveConfig(int disp, int mode); + // get active config + int getActiveConfig(int disp) const; + // reset state when an external, non-virtual display is disconnected void disconnectDisplay(int disp); @@ -117,6 +120,9 @@ public: // does this display have layers handled by GLES bool hasGlesComposition(int32_t id) const; + // does this display support dim layer composition + bool hasDimComposition() const { return (mDimComp == 1); } + // get the releaseFence file descriptor for a display's framebuffer layer. // the release fence is only valid after commit() sp<Fence> getAndResetReleaseFence(int32_t id); @@ -162,6 +168,7 @@ public: virtual sp<Fence> getAndResetReleaseFence() = 0; virtual void setDefaultState() = 0; virtual void setSkip(bool skip) = 0; + virtual void setDim() = 0; virtual void setIsCursorLayerHint(bool isCursor = true) = 0; virtual void setBlending(uint32_t blending) = 0; virtual void setTransform(uint32_t transform) = 0; @@ -174,6 +181,7 @@ public: virtual void setAcquireFenceFd(int fenceFd) = 0; virtual void setPlaneAlpha(uint8_t alpha) = 0; virtual void onDisplayed() = 0; + virtual void setAnimating(bool animating)= 0; }; /* @@ -302,6 +310,14 @@ public: // for debugging ---------------------------------------------------------- void dump(String8& out) const; + /* ------------------------------------------------------------------------ + * Extensions + */ + virtual inline bool isVDSEnabled() const { return true; }; + virtual inline bool isCompositionTypeBlit(const int32_t /*compType*/) const { + return false; + }; + private: void loadHwcModule(); int loadFbHalModule(); @@ -372,6 +388,8 @@ private: // thread-safe mutable Mutex mEventControlLock; + + int mDimComp; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index ba4c198..5fd2136 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -19,6 +19,7 @@ #include "HWComposer.h" #include <gui/BufferItem.h> +#include <gui/Surface.h> // --------------------------------------------------------------------------- namespace android { @@ -30,6 +31,10 @@ static const bool sForceHwcCopy = true; static const bool sForceHwcCopy = false; #endif +#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS +#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2) +#endif + #define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \ mDisplayName.string(), ##__VA_ARGS__) #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \ @@ -64,6 +69,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bqProducer; + sp<Surface> surface(new Surface(bqProducer, false)); resetPerFrameState(); @@ -92,7 +98,9 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, mConsumer->setConsumerName(ConsumerBase::mName); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER); mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight); - mConsumer->setDefaultMaxBufferCount(2); + mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); + + surface->allocateBuffers(); } VirtualDisplaySurface::~VirtualDisplaySurface() { @@ -152,7 +160,7 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { // format/usage and get a new buffer when the GLES driver calls // dequeueBuffer(). mOutputFormat = mDefaultOutputFormat; - mOutputUsage = GRALLOC_USAGE_HW_COMPOSER; + setOutputUsage(GRALLOC_USAGE_HW_COMPOSER); refreshOutputBuffer(); } @@ -377,7 +385,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool mSinkBufferWidth, mSinkBufferHeight, buf->getPixelFormat(), buf->getUsage()); mOutputFormat = format; - mOutputUsage = usage; + setOutputUsage(usage); result = refreshOutputBuffer(); if (result < 0) return result; @@ -616,6 +624,10 @@ const char* VirtualDisplaySurface::dbgSourceStr(Source s) { } } +void VirtualDisplaySurface::setOutputUsage(uint32_t usage) { + mOutputUsage = usage; +} + // --------------------------------------------------------------------------- } // namespace android // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 6298751..3d0e412 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -72,6 +72,10 @@ class VirtualDisplaySurface : public DisplaySurface, public BnGraphicBufferProducer, private ConsumerBase { public: +#ifdef QTI_BSP + friend class ExVirtualDisplaySurface; +#endif + VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, @@ -118,6 +122,7 @@ private: virtual status_t allowAllocation(bool allow); virtual status_t setGenerationNumber(uint32_t generationNumber); virtual String8 getConsumerName() const override; + virtual void setOutputUsage(uint32_t flag); // // Utility methods diff --git a/services/surfaceflinger/DisplayUtils.cpp b/services/surfaceflinger/DisplayUtils.cpp new file mode 100644 index 0000000..a07e69e --- /dev/null +++ b/services/surfaceflinger/DisplayUtils.cpp @@ -0,0 +1,192 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <gui/Surface.h> +#include <ui/GraphicBuffer.h> + +#include "RenderEngine/RenderEngine.h" +#include "DisplayHardware/FramebufferSurface.h" +#include "DisplayUtils.h" +#ifdef QTI_BSP +#include <ExSurfaceFlinger/ExSurfaceFlinger.h> +#include <ExSurfaceFlinger/ExLayer.h> +#include <ExSurfaceFlinger/ExHWComposer.h> +#include <ExSurfaceFlinger/ExVirtualDisplaySurface.h> +#include <gralloc_priv.h> +#endif +#include <dlfcn.h> +#include <cutils/properties.h> + +namespace android { + +DisplayUtils* DisplayUtils::sDisplayUtils = NULL; +bool DisplayUtils::sUseExtendedImpls = false; + +DisplayUtils::DisplayUtils() { +#ifdef QTI_BSP + sUseExtendedImpls = true; +#endif +} + +DisplayUtils* DisplayUtils::getInstance() { + if(sDisplayUtils == NULL) { + sDisplayUtils = new DisplayUtils(); + } + return sDisplayUtils; +} + +SurfaceFlinger* DisplayUtils::getSFInstance() { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExSurfaceFlinger(); + } +#endif + return new SurfaceFlinger(); +} + +Layer* DisplayUtils::getLayerInstance(SurfaceFlinger* flinger, + const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags) { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExLayer(flinger, client, name, w, h, flags); + } +#endif + return new Layer(flinger, client, name, w, h, flags); +} + +HWComposer* DisplayUtils::getHWCInstance( + const sp<SurfaceFlinger>& flinger, + HWComposer::EventHandler& handler) { +#ifdef QTI_BSP + if(sUseExtendedImpls) { + return new ExHWComposer(flinger, handler); + } +#endif + return new HWComposer(flinger,handler); +} + +void DisplayUtils::initVDSInstance(HWComposer* hwc, int32_t hwcDisplayId, + sp<IGraphicBufferProducer> currentStateSurface, sp<DisplaySurface> &dispSurface, + sp<IGraphicBufferProducer> &producer, sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, String8 currentStateDisplayName, + bool currentStateIsSecure, int currentStateType) +{ +#ifdef QTI_BSP + if(sUseExtendedImpls) { + if(hwc->isVDSEnabled()) { + VirtualDisplaySurface* vds = new ExVirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName, + currentStateIsSecure); + dispSurface = vds; + producer = vds; + } else if(!createV4L2BasedVirtualDisplay(hwc, hwcDisplayId, dispSurface, producer, + currentStateSurface, bqProducer, bqConsumer, currentStateType)) { + VirtualDisplaySurface* vds = new VirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName); + dispSurface = vds; + producer = vds; + } + } else { +#endif + (void)currentStateIsSecure; + (void)currentStateType; + VirtualDisplaySurface* vds = new VirtualDisplaySurface(*hwc, hwcDisplayId, + currentStateSurface, bqProducer, bqConsumer, currentStateDisplayName); + dispSurface = vds; + producer = vds; +#ifdef QTI_BSP + } +#endif +} + +bool DisplayUtils::createV4L2BasedVirtualDisplay(HWComposer* hwc, int32_t &hwcDisplayId, + sp<DisplaySurface> &dispSurface, sp<IGraphicBufferProducer> &producer, + sp<IGraphicBufferProducer> currentStateSurface, + sp<IGraphicBufferProducer> bqProducer, sp<IGraphicBufferConsumer> bqConsumer, + int currentStateType) { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.sys.wfd.virtual", value, "0"); + int wfdVirtual = atoi(value); + if(wfdVirtual && hwcDisplayId > 0) { + //Read virtual display properties and create a + //rendering surface for it inorder to be handled + //by hwc. + + sp<ANativeWindow> mNativeWindow = new Surface(currentStateSurface); + ANativeWindow* const window = mNativeWindow.get(); + + int format; + window->query(window, NATIVE_WINDOW_FORMAT, &format); + EGLSurface surface; + EGLint w, h; + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + // In M AOSP getEGLConfig() always returns EGL_NO_CONFIG as + // EGL_ANDROIDX_no_config_context active now. + EGLConfig config = RenderEngine::chooseEglConfig(display, format); + + surface = eglCreateWindowSurface(display, config, window, NULL); + eglQuerySurface(display, surface, EGL_WIDTH, &w); + eglQuerySurface(display, surface, EGL_HEIGHT, &h); + if(hwc->setVirtualDisplayProperties(hwcDisplayId, w, h, format) != NO_ERROR) + return false; + + dispSurface = new FramebufferSurface(*hwc, currentStateType, bqConsumer); + producer = bqProducer; + return true; + } + return false; +} + +bool DisplayUtils::canAllocateHwcDisplayIdForVDS(int usage) { + // on AOSP builds with QTI_BSP disabled, we should allocate hwc display id for virtual display + int flag_mask = 0xffffffff; + +#ifdef QTI_BSP +#ifdef FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS + // Reserve hardware acceleration for WFD use-case + flag_mask = GRALLOC_USAGE_PRIVATE_WFD; +#else + // Don't allocate HWC display unless we force HWC copy, otherwise + // incompatible buffers are sent to the media stack + flag_mask = 0; +#endif +#endif + + return (usage & flag_mask); +} + +}; // namespace android + diff --git a/services/surfaceflinger/DisplayUtils.h b/services/surfaceflinger/DisplayUtils.h new file mode 100644 index 0000000..bb3d16b --- /dev/null +++ b/services/surfaceflinger/DisplayUtils.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_DISPLAY_UTILS_H +#define ANDROID_DISPLAY_UTILS_H + +#include <stdint.h> +#include <sys/types.h> + +#include "Layer.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/VirtualDisplaySurface.h" + +// --------------------------------------------------------------------------- + +namespace android { + +class IGraphicBufferProducer; +class IGraphicBufferConsumer; +class DisplaySurface; + +/* Factory Classes */ + +class DisplayUtils { + public: + static DisplayUtils* getInstance() ANDROID_API; + SurfaceFlinger* getSFInstance() ANDROID_API; + Layer* getLayerInstance(SurfaceFlinger*, const sp<Client>&, + const String8&, uint32_t, + uint32_t, uint32_t); + HWComposer* getHWCInstance(const sp<SurfaceFlinger>& flinger, + HWComposer::EventHandler& handler); + void initVDSInstance(HWComposer* hwc, int32_t hwcDisplayId, + sp<IGraphicBufferProducer> currentStateSurface, sp<DisplaySurface> &dispSurface, + sp<IGraphicBufferProducer> &producer, sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, String8 currentStateDisplayName, + bool currentStateIsSecure, int currentStateType); + bool canAllocateHwcDisplayIdForVDS(int usage); + DisplayUtils(); + private: + static DisplayUtils* sDisplayUtils; + static bool sUseExtendedImpls; + + bool createV4L2BasedVirtualDisplay(HWComposer* hwc, int32_t &hwcDisplayId, + sp<DisplaySurface> &dispSurface, sp<IGraphicBufferProducer> &producer, + sp<IGraphicBufferProducer> currentStateSurface, + sp<IGraphicBufferProducer> bqProducer, + sp<IGraphicBufferConsumer> bqConsumer, int currentStateType); +}; + +}; // namespace android + +#endif // ANDROID_DISPLAY_UTILS_H diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index f760200..973a8bc 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -20,6 +20,7 @@ #include <sys/types.h> #include <cutils/compiler.h> +#include <cutils/iosched_policy.h> #include <gui/BitTube.h> #include <gui/IDisplayEventConnection.h> @@ -91,6 +92,7 @@ void EventThread::sendVsyncHintOnLocked() { void EventThread::onFirstRef() { run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); + android_set_rt_ioprio(getTid(), 1); } sp<EventThread::Connection> EventThread::createEventConnection() const { diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp new file mode 100644 index 0000000..2b41098 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ExSurfaceFlinger.h" +#include "ExLayer.h" +#include "ExHWComposer.h" +#ifdef QTI_BSP +#include <hardware/display_defs.h> +#endif + +namespace android { + +ExHWComposer::ExHWComposer(const sp<SurfaceFlinger>& flinger, + EventHandler& handler) + : HWComposer(flinger, handler) { + + mVDSEnabled = false; + char property[PROPERTY_VALUE_MAX] = {0}; + + /* Read system property for VDS solution. + * This property is expected to be setup once during bootup + */ + if( (property_get("persist.hwc.enable_vds", property, NULL) > 0) && + ((!strncmp(property, "1", strlen("1"))) || + !strncasecmp(property, "true", strlen("true")))) { + /* HAL virtual display is using VDS based implementation */ + mVDSEnabled = true; + } + + mDebugLogs = false; + if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) && + (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || + (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { + mDebugLogs = true; + } + + ALOGD_IF(isDebug(),"Creating custom HWC %s",__FUNCTION__); +} + +ExHWComposer::~ExHWComposer() { +} + +bool ExHWComposer::isCompositionTypeBlit(const int32_t compType) const { +#ifdef QTI_BSP + return (compType == HWC_BLIT); +#else + ALOGD_IF(mDebugLogs, "%s: compType = %d", __FUNCTION__, compType); +#endif + return false; +} + +}; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h new file mode 100644 index 0000000..2016ff0 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_EX_HWCOMPOSER_H +#define ANDROID_EX_HWCOMPOSER_H + +#include <DisplayHardware/HWComposer.h> + +namespace android { + +class ExHWComposer : public HWComposer +{ +public: + + ExHWComposer( + const sp<SurfaceFlinger>& flinger, + EventHandler& handler); + + virtual ~ExHWComposer(); + +protected: + bool mVDSEnabled; + inline bool isVDSEnabled() const { return mVDSEnabled; }; + bool mDebugLogs; + bool isDebug() { return mDebugLogs; } + bool isCompositionTypeBlit(const int32_t compType) const; +}; + + +}; //namespace android + +#endif //ANDROID_EX_HWCOMPOSER_H diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp new file mode 100644 index 0000000..fa45579 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp @@ -0,0 +1,207 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/GraphicBuffer.h> +#ifdef QTI_BSP +#include <gralloc_priv.h> +#include <hardware/display_defs.h> +#endif + +#include "ExLayer.h" + +namespace android { + +/* Calculates the aspect ratio for external display based on the video w/h */ +static Rect getAspectRatio(const sp<const DisplayDevice>& hw, + const int& srcWidth, const int& srcHeight) { + Rect outRect; + int fbWidth = hw->getWidth(); + int fbHeight = hw->getHeight(); + int x , y = 0; + int w = fbWidth, h = fbHeight; + if (srcWidth * fbHeight > fbWidth * srcHeight) { + h = fbWidth * srcHeight / srcWidth; + w = fbWidth; + } else if (srcWidth * fbHeight < fbWidth * srcHeight) { + w = fbHeight * srcWidth / srcHeight; + h = fbHeight; + } + x = (fbWidth - w) / 2; + y = (fbHeight - h) / 2; + outRect.left = x; + outRect.top = y; + outRect.right = x + w; + outRect.bottom = y + h; + + return outRect; +} + +ExLayer::ExLayer(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags) { + + char property[PROPERTY_VALUE_MAX] = {0}; + + mDebugLogs = false; + mIsGPUAllowedForProtected = false; + if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) && + (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || + (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { + mDebugLogs = true; + } + + ALOGD_IF(isDebug(),"Creating custom Layer %s",__FUNCTION__); + + if ((property_get("persist.gralloc.cp.level3", property, NULL) > 0) && + (atoi(property) == 1)) { + mIsGPUAllowedForProtected = true; + } +} + +ExLayer::~ExLayer() { +} + +bool ExLayer::isExtOnly() const { + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); + if (activeBuffer != 0) { +#ifdef QTI_BSP + ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer(); + if(buffer) { + private_handle_t* hnd = static_cast<private_handle_t*> + (const_cast<native_handle_t*>(buffer->handle)); + /* return true if layer is EXT_ONLY */ + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY)); + } +#endif + } + return false; +} + +bool ExLayer::isIntOnly() const { + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); + if (activeBuffer != 0) { +#ifdef QTI_BSP + ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer(); + if(buffer) { + private_handle_t* hnd = static_cast<private_handle_t*> + (const_cast<native_handle_t*>(buffer->handle)); + /* return true if layer is INT_ONLY */ + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_INTERNAL_ONLY)); + } +#endif + } + return false; +} + +bool ExLayer::isSecureDisplay() const { + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); + if (activeBuffer != 0) { +#ifdef QTI_BSP + ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer(); + if(buffer) { + private_handle_t* hnd = static_cast<private_handle_t*> + (const_cast<native_handle_t*>(buffer->handle)); + /* return true if layer is SECURE_DISPLAY */ + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY)); + } +#endif + } + return false; +} + +bool ExLayer::isYuvLayer() const { + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); + if(activeBuffer != 0) { +#ifdef QTI_BSP + ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer(); + if(buffer) { + private_handle_t* hnd = static_cast<private_handle_t*> + (const_cast<native_handle_t*>(buffer->handle)); + /* return true if layer is YUV */ + return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)); + } +#endif + } + return false; +} + +void ExLayer::setPosition(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer, const State& state) { + /* Set dest_rect to display width and height, if external_only flag + * for the layer is enabled or if its yuvLayer in extended mode. + */ + uint32_t w = hw->getWidth(); + uint32_t h = hw->getHeight(); + bool extendedMode = ExSurfaceFlinger::isExtendedMode(); + if(isExtOnly()) { + /* Position: fullscreen for ext_only */ + Rect r(0, 0, w, h); + layer.setFrame(r); + } else if(hw->getDisplayType() > 0 && (extendedMode && isYuvLayer())) { + /* Need to position the video full screen on external with aspect ratio */ + Rect r = getAspectRatio(hw, state.active.w, state.active.h); + layer.setFrame(r); + } + return; +} + +void ExLayer::setAcquiredFenceIfBlit(int &fenceFd, + HWComposer::HWCLayerInterface& layer) { +#ifdef QTI_BSP + if (layer.getCompositionType() == HWC_BLIT) { + sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); + if (fence->isValid()) { + fenceFd = fence->dup(); + if (fenceFd == -1) { + ALOGW("%s: failed to dup layer fence, skipping sync: %d", + __FUNCTION__,errno); + } + } + } +#else + ALOGD_IF(isDebug(),"Not a BLIT Layer, compType = %d fencefd = %d", + layer.getCompositionType(), fenceFd); +#endif +} + +bool ExLayer::canAllowGPUForProtected() const { + if(isProtected()) { + return mIsGPUAllowedForProtected; + } else { + return false; + } +} + +}; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h new file mode 100644 index 0000000..01c74a8 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_EX_LAYER_H +#define ANDROID_EX_LAYER_H + +#include <stdint.h> +#include <sys/types.h> +#include <cutils/properties.h> + +#include <Layer.h> +#include "ExSurfaceFlinger.h" + +namespace android { + +class ExSurfaceFlinger; + +class ExLayer : public Layer +{ +public: + ExLayer(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); + virtual ~ExLayer(); + + virtual bool isExtOnly() const; + virtual bool isIntOnly() const; + virtual bool isSecureDisplay() const; + virtual bool isYuvLayer() const; + virtual void setPosition(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer, const State& state); + virtual void setAcquiredFenceIfBlit(int &fenceFd, + HWComposer::HWCLayerInterface& layer); + virtual bool canAllowGPUForProtected() const; + +protected: + bool mDebugLogs; + bool isDebug() { return mDebugLogs; } + bool mIsGPUAllowedForProtected; +}; + +}; // namespace android + +#endif // ANDROID_EX_LAYER_H diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp new file mode 100644 index 0000000..96d4b1d --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp @@ -0,0 +1,376 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ExSurfaceFlinger.h" +#include "ExLayer.h" +#include <fstream> +#include <cutils/properties.h> +#ifdef QTI_BSP +#include <hardware/display_defs.h> +#endif +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +namespace android { + +bool ExSurfaceFlinger::sExtendedMode = false; + +ExSurfaceFlinger::ExSurfaceFlinger() { + char property[PROPERTY_VALUE_MAX] = {0}; + + mDebugLogs = false; + if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) && + (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || + (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { + mDebugLogs = true; + } + + ALOGD_IF(isDebug(),"Creating custom SurfaceFlinger %s",__FUNCTION__); + + mDisableExtAnimation = false; + if((property_get("sys.disable_ext_animation", property, "0") > 0) && + (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || + (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { + mDisableExtAnimation = true; + } + + ALOGD_IF(isDebug(),"Animation on external is %s in %s", + mDisableExtAnimation ? "disabled" : "not disabled", __FUNCTION__); +} + +ExSurfaceFlinger::~ExSurfaceFlinger() { } + +void ExSurfaceFlinger::updateExtendedMode() { + char prop[PROPERTY_VALUE_MAX]; + property_get("sys.extended_mode", prop, "0"); + sExtendedMode = atoi(prop) ? true : false; +} + +void ExSurfaceFlinger::getIndexLOI(size_t dpy, + const LayerVector& currentLayers, + bool& bIgnoreLayers, + int& indexLOI ) { + size_t i = currentLayers.size(); + while(i--) { + const sp<Layer>& layer = currentLayers[i]; + /* iterate through the layer list to find ext_only layers and store + * the index + */ + if (layer->isSecureDisplay()) { + bIgnoreLayers = true; + indexLOI = -1; + if(!dpy) + indexLOI = i; + break; + } + /* iterate through the layer list to find ext_only layers or yuv + * layer(extended_mode) and store the index + */ + if ((dpy && (layer->isExtOnly() || + (isExtendedMode() && layer->isYuvLayer())))) { + bIgnoreLayers= true; + indexLOI = i; + } + } + return; +} + +bool ExSurfaceFlinger::updateLayerVisibleNonTransparentRegion( + const int& dpy, const sp<Layer>& layer, + bool& bIgnoreLayers, int& indexLOI, + uint32_t layerStack, const int& i) { + + const Layer::State& s(layer->getDrawingState()); + + /* Only add the layer marked as "external_only" or yuvLayer + * (extended_mode) to external list and + * only remove the layer marked as "external_only" or yuvLayer in + * extended_mode from primary list + * and do not add the layer marked as "internal_only" to external list + * Add secure UI layers to primary and remove other layers from internal + * and external list + */ + if(((bIgnoreLayers && indexLOI != (int)i) || + (!dpy && layer->isExtOnly()) || + (!dpy && isExtendedMode() && layer->isYuvLayer()))|| + (dpy && layer->isIntOnly())) { + /* Ignore all other layers except the layers marked as ext_only + * by setting visible non transparent region empty + */ + Region visibleNonTransRegion; + visibleNonTransRegion.set(Rect(0,0)); + layer->setVisibleNonTransparentRegion(visibleNonTransRegion); + return true; + } + /* only consider the layers on the given later stack + * Override layers created using presentation class by the layers having + * ext_only flag enabled + */ + if(s.layerStack != layerStack && !bIgnoreLayers) { + /* set the visible region as empty since we have removed the + * layerstack check in rebuildLayerStack() function + */ + Region visibleNonTransRegion; + visibleNonTransRegion.set(Rect(0,0)); + layer->setVisibleNonTransparentRegion(visibleNonTransRegion); + return true; + } + + if (mDisableExtAnimation) { + /* Remove screenShotSurface from secondary displays when ext animation disabled */ + const int screenShotLen = strlen("ScreenshotSurface"); + if (dpy && !strncmp(layer->getName(), "ScreenshotSurface", screenShotLen) ) { + Region visibleNonTransRegion; + visibleNonTransRegion.set(Rect(0, 0)); + layer->setVisibleNonTransparentRegion(visibleNonTransRegion); + return true; + } + } + + return false; +} + +void ExSurfaceFlinger::delayDPTransactionIfNeeded( + const Vector<DisplayState>& displays) { + /* Delay the display projection transaction by 50ms only when the disable + * external rotation animation feature is enabled + */ + if(mDisableExtAnimation) { + size_t count = displays.size(); + for (size_t i=0 ; i<count ; i++) { + const DisplayState& s(displays[i]); + if((mDisplays.indexOfKey(s.token) >= 0) && (s.token != + mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])) { + const uint32_t what = s.what; + /* Invalidate and Delay the binder thread by 50 ms on + * eDisplayProjectionChanged to trigger a draw cycle so that + * it can fix one incorrect frame on the External, when we + * disable external animation + */ + if (what & DisplayState::eDisplayProjectionChanged) { + invalidateHwcGeometry(); + repaintEverything(); + usleep(50000); + } + } + } + } +} + +bool ExSurfaceFlinger::canDrawLayerinScreenShot( + const sp<const DisplayDevice>& hw, + const sp<Layer>& layer) { + int dispType = hw->getDisplayType(); + /* a) Don't draw SecureDisplayLayer or ProtectedLayer. + * b) Don't let ext_only and extended_mode to be captured + * If not, we would see incorrect image during rotation + * on primary. + */ + if(!layer->isSecureDisplay() + && !layer->isProtected() + && !(!dispType && (layer->isExtOnly() || + (isExtendedMode() && layer->isYuvLayer()))) + && !(layer->isIntOnly() && dispType) + && layer->isVisible()){ + return true; + } + return false; +} + +void ExSurfaceFlinger::isfreezeSurfacePresent(bool& freezeSurfacePresent, + const sp<const DisplayDevice>& hw, + const int32_t& id) { + freezeSurfacePresent = false; + /* Get the layers in the current drawing state */ + const LayerVector& layers(mDrawingState.layersSortedByZ); + const size_t layerCount = layers.size(); + /* Look for ScreenShotSurface in external layer list, only when + * disable external rotation animation feature is enabled + */ + if(mDisableExtAnimation && (id != HWC_DISPLAY_PRIMARY)) { + for (size_t i = 0 ; i < layerCount ; ++i) { + static int screenShotLen = strlen("ScreenshotSurface"); + const sp<Layer>& layer(layers[i]); + const Layer::State& s(layer->getDrawingState()); + /* check the layers associated with external display */ + if(s.layerStack == hw->getLayerStack()) { + if(!strncmp(layer->getName(), "ScreenshotSurface", + screenShotLen)) { + /* Screenshot layer is present, and animation in + * progress + */ + freezeSurfacePresent = true; + break; + } + } + } + } +} + +void ExSurfaceFlinger::setOrientationEventControl(bool& freezeSurfacePresent, + const int32_t& id) { + HWComposer& hwc(getHwComposer()); + HWComposer::LayerListIterator cur = hwc.begin(id); + + if(freezeSurfacePresent) { + /* If freezeSurfacePresent, set ANIMATING flag + * which is used to support disable animation on external + */ + cur->setAnimating(true); + } +} + +void ExSurfaceFlinger::updateVisibleRegionsDirty() { + /* If extended_mode is set, and set mVisibleRegionsDirty + * as we need to rebuildLayerStack + */ + if(isExtendedMode()) { + mVisibleRegionsDirty = true; + } +} + +void ExSurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& cur, + const HWComposer::LayerListIterator& end, + const sp<const DisplayDevice>& hw, + const Region& region) { + if (cur != end) { +#ifdef QTI_BSP + if (cur->getCompositionType() != HWC_BLIT) + drawWormhole(hw, region); +#endif + } else { + drawWormhole(hw, region); + } +} + +#ifdef DEBUG_CONT_DUMPSYS +status_t ExSurfaceFlinger::dump(int fd, const Vector<String16>& args) { + // Format: adb shell dumpsys SurfaceFlinger --file --no-limit + size_t numArgs = args.size(); + status_t err = NO_ERROR; + + if (!numArgs || (args[0] != String16("--file"))) { + return SurfaceFlinger::dump(fd, args); + } + + Mutex::Autolock _l(mFileDump.lock); + + // Same command is used to start and end dump. + mFileDump.running = !mFileDump.running; + + if (mFileDump.running) { + // Create an empty file or erase existing file. + std::fstream fs; + fs.open(mFileDump.name, std::ios::out); + if (!fs) { + mFileDump.running = false; + err = UNKNOWN_ERROR; + } else { + mFileDump.position = 0; + if (numArgs >= 2 && (args[1] == String16("--nolimit"))) { + mFileDump.noLimit = true; + } else { + mFileDump.noLimit = false; + } + } + } + + String8 result; + result += mFileDump.running ? "Start" : "End"; + result += mFileDump.noLimit ? " unlimited" : " fixed limit"; + result += " dumpsys to file : "; + result += mFileDump.name; + result += "\n"; + + write(fd, result.string(), result.size()); + + return NO_ERROR; +} + +void ExSurfaceFlinger::dumpDrawCycle(bool prePrepare) { + Mutex::Autolock _l(mFileDump.lock); + + // User might stop dump collection in middle of prepare & commit. + // Collect dumpsys again after commit and replace. + if (!mFileDump.running && !mFileDump.replaceAfterCommit) { + return; + } + + Vector<String16> args; + size_t index = 0; + String8 dumpsys; + + dumpAllLocked(args, index, dumpsys); + + char timeStamp[32]; + char dataSize[32]; + char hms[32]; + long millis; + struct timeval tv; + struct tm *ptm; + + gettimeofday(&tv, NULL); + ptm = localtime(&tv.tv_sec); + strftime (hms, sizeof (hms), "%H:%M:%S", ptm); + millis = tv.tv_usec / 1000; + snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03ld", hms, millis); + snprintf(dataSize, sizeof(dataSize), "Size: %8zu", dumpsys.size()); + + std::fstream fs; + fs.open(mFileDump.name, std::ios::in | std::ios::out); + if (!fs) { + ALOGE("Failed to open %s file for dumpsys", mFileDump.name); + return; + } + + // Format: + // | start code | after commit? | time stamp | dump size | dump data | + fs.seekp(mFileDump.position, std::ios::beg); + + fs << "#@#@-- DUMPSYS START --@#@#" << std::endl; + fs << "PostCommit: " << ( prePrepare ? "false" : "true" ) << std::endl; + fs << timeStamp << std::endl; + fs << dataSize << std::endl; + fs << dumpsys << std::endl; + + if (prePrepare) { + mFileDump.replaceAfterCommit = true; + } else { + mFileDump.replaceAfterCommit = false; + // Reposition only after commit. + // Keem file size to appx 20 MB limit by default, wrap around if exceeds. + mFileDump.position = fs.tellp(); + if (!mFileDump.noLimit && (mFileDump.position > (20 * 1024 * 1024))) { + mFileDump.position = 0; + } + } + + fs.close(); +} +#endif + +}; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h new file mode 100644 index 0000000..068f2b9 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_EX_SURFACE_FLINGER_H +#define ANDROID_EX_SURFACE_FLINGER_H + +#include "SurfaceFlinger.h" + +namespace android { + +class ExSurfaceFlinger : public SurfaceFlinger +{ +public: + + ExSurfaceFlinger(); + +protected: + friend class ExLayer; + + virtual void updateExtendedMode(); + virtual void getIndexLOI(size_t dpy, + const LayerVector& currentLayers, + bool& bIgnoreLayers, + int& indexLOI); + virtual bool updateLayerVisibleNonTransparentRegion( + const int& dpy, const sp<Layer>& layer, + bool& bIgnoreLayers, int& indexLOI, + uint32_t layerStack, const int& i); + virtual void delayDPTransactionIfNeeded( + const Vector<DisplayState>& displays); + virtual bool canDrawLayerinScreenShot( + const sp<const DisplayDevice>& hw, + const sp<Layer>& layer); + virtual void isfreezeSurfacePresent( + bool& freezeSurfacePresent, + const sp<const DisplayDevice>& hw, + const int32_t& id); + virtual void setOrientationEventControl( + bool& freezeSurfacePresent, + const int32_t& id); + virtual void updateVisibleRegionsDirty(); + virtual void drawWormHoleIfRequired(HWComposer::LayerListIterator& /*cur*/, + const HWComposer::LayerListIterator& /*end*/, + const sp<const DisplayDevice>& hw, + const Region& region); + virtual ~ExSurfaceFlinger(); + + /* Extended Mode + * No video on primary but video will be shown full + * screen on External + */ + static bool sExtendedMode; + static bool isExtendedMode() { return sExtendedMode; } + bool mDebugLogs; + bool isDebug() { return mDebugLogs; } + bool mDisableExtAnimation; + +#ifdef DEBUG_CONT_DUMPSYS + virtual status_t dump(int fd, const Vector<String16>& args); + virtual void dumpDrawCycle(bool prePrepare ); + + struct { + Mutex lock; + const char *name = "/data/misc/display/dumpsys.txt"; + bool running = false; + bool noLimit = false; + bool replaceAfterCommit = false; + long int position = 0; + } mFileDump; +#endif +}; + +}; //namespace android + +#endif //ANDROID_EX_SURFACE_FLINGER_H diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.cpp new file mode 100644 index 0000000..e4ad758 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.cpp @@ -0,0 +1,93 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ExVirtualDisplaySurface.h" +#ifdef QTI_BSP +#include <gralloc_priv.h> +#endif + +namespace android { + +#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \ + mDisplayName.string(), ##__VA_ARGS__) +#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \ + mDisplayName.string(), ##__VA_ARGS__) +#define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \ + mDisplayName.string(), ##__VA_ARGS__) + +ExVirtualDisplaySurface::ExVirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, + const sp<IGraphicBufferProducer>& bqProducer, + const sp<IGraphicBufferConsumer>& bqConsumer, + const String8& name, + bool secure) +: VirtualDisplaySurface(hwc, dispId, sink, bqProducer, bqConsumer, name), + mSecure(secure) { + sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mSinkUsage); + mSinkUsage |= GRALLOC_USAGE_HW_COMPOSER; + setOutputUsage(mSinkUsage); +} + +status_t ExVirtualDisplaySurface::beginFrame(bool mustRecompose) { + if (mDisplayId < 0) + return NO_ERROR; + + mMustRecompose = mustRecompose; + /* For WFD use cases we must always set the recompose flag in order + * to support pause/resume functionality + */ + if (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { + mMustRecompose = true; + } + + VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, + "Unexpected beginFrame() in %s state", dbgStateStr()); + mDbgState = DBG_STATE_BEGUN; + + return refreshOutputBuffer(); + +} + +/* Helper to update the output usage when the display is secure */ +void ExVirtualDisplaySurface::setOutputUsage(uint32_t /*flag*/) { + mOutputUsage = mSinkUsage; + if (mSecure && (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) { + /* TODO: Currently, the framework can only say whether the display + * and its subsequent session are secure or not. However, there is + * no mechanism to distinguish the different levels of security. + * The current solution assumes WV L3 protection. + */ + mOutputUsage |= GRALLOC_USAGE_PROTECTED; +#ifdef QTI_BSP + mOutputUsage |= GRALLOC_USAGE_PRIVATE_MM_HEAP | + GRALLOC_USAGE_PRIVATE_UNCACHED; +#endif + } +} + +}; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.h b/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.h new file mode 100644 index 0000000..ab71594 --- /dev/null +++ b/services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_EX_VIRTUAL_DISPLAY_SURFACE_H +#define ANDROID_EX_VIRTUAL_DISPLAY_SURFACE_H + +#include <DisplayHardware/VirtualDisplaySurface.h> + +namespace android { + +class ExVirtualDisplaySurface : public VirtualDisplaySurface { +public: + ExVirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, + const sp<IGraphicBufferProducer>& bqProducer, + const sp<IGraphicBufferConsumer>& bqConsumer, + const String8& name, + bool secure); + +private: + virtual status_t beginFrame(bool mustRecompose); + virtual void setOutputUsage(uint32_t flag); + bool mSecure; + int mSinkUsage; +}; + +}; // namespace android + +#endif // ANDROID_EX_VIRTUAL_DISPLAY_SURFACE_H + diff --git a/services/surfaceflinger/FrameRateHelper.h b/services/surfaceflinger/FrameRateHelper.h new file mode 100644 index 0000000..1a69fed --- /dev/null +++ b/services/surfaceflinger/FrameRateHelper.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_SF_FRAME_RATE_HELPER_H +#define ANDROID_SF_FRAME_RATE_HELPER_H + +#include <utils/Timers.h> + +namespace android { + +class FrameRateHelper { +public: + FrameRateHelper() : mTime(0), mFps(0), mFpsCount(0) {} + ~FrameRateHelper() {} + + bool update() { + mFpsCount++; + + nsecs_t now = systemTime(); + if (ns2ms(now - mTime) > 1000) { + mFps = mFpsCount; + mFpsCount = 0; + mTime = now; + return true; + } + + return false; + } + + unsigned int get() const { + return mFps; + } + +private: + nsecs_t mTime; + unsigned int mFps; + unsigned int mFpsCount; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_SF_FRAME_RATE_HELPER_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5ff79a9..c346a2f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -84,7 +84,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mQueueItemCondition(), mQueueItems(), mLastFrameNumberReceived(0), - mUpdateTexImageFailed(false) + mUpdateTexImageFailed(false), + mTransformHint(0) { mCurrentCrop.makeInvalid(); mFlinger->getRenderEngine().genTextures(1, &mTextureName); @@ -103,11 +104,15 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mName = name; + mCurrentState.active.x = 0; + mCurrentState.active.y = 0; mCurrentState.active.w = w; mCurrentState.active.h = h; mCurrentState.active.crop.makeInvalid(); + mCurrentState.active.isPositionPending = false; mCurrentState.z = 0; mCurrentState.alpha = 0xFF; + mCurrentState.blur = 0xFF; mCurrentState.layerStack = 0; mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; @@ -320,11 +325,13 @@ Rect Layer::getContentCrop() const { return crop; } -static Rect reduce(const Rect& win, const Region& exclude) { +Rect Layer::reduce(const Rect& win, const Region& exclude) const{ if (CC_LIKELY(exclude.isEmpty())) { return win; } - if (exclude.isRect()) { + Rect tmp; + win.intersect(exclude.getBounds(), &tmp); + if (exclude.isRect() && !tmp.isEmpty()) { return win.reduce(exclude.getBounds()); } return Region(win).subtract(exclude).getBounds(); @@ -494,6 +501,7 @@ void Layer::setGeometry( frame.intersect(hw->getViewport(), &frame); const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); + setPosition(hw, layer, s); layer.setCrop(computeCrop(hw)); layer.setPlaneAlpha(s.alpha); @@ -578,6 +586,7 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, } } } + setAcquiredFenceIfBlit(fenceFd, layer); layer.setAcquireFenceFd(fenceFd); } @@ -605,21 +614,21 @@ Rect Layer::getPosition( // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const { +void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) { onDraw(hw, clip, false); } void Layer::draw(const sp<const DisplayDevice>& hw, - bool useIdentityTransform) const { + bool useIdentityTransform) { onDraw(hw, Region(hw->bounds()), useIdentityTransform); } -void Layer::draw(const sp<const DisplayDevice>& hw) const { +void Layer::draw(const sp<const DisplayDevice>& hw) { onDraw(hw, Region(hw->bounds()), false); } void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, - bool useIdentityTransform) const + bool useIdentityTransform) { ATRACE_CALL(); @@ -663,8 +672,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); RenderEngine& engine(mFlinger->getRenderEngine()); - - if (!blackOutLayer) { + if (!blackOutLayer || + ((hw->getDisplayType() == HWC_DISPLAY_PRIMARY) && canAllowGPUForProtected())) { // TODO: we could be more subtle with isFixedSize() const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); @@ -750,8 +759,19 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, * minimal value)? Or, we could make GL behave like HWC -- but this feel * like more of a hack. */ - const Rect win(computeBounds()); - + Rect win(s.active.w, s.active.h); + if(!s.active.crop.isEmpty()) { + win = s.active.crop; + } +#ifdef QTI_BSP + win = s.transform.transform(win); + win.intersect(hw->getViewport(), &win); + win = s.transform.inverse().transform(win); + win.intersect(Rect(s.active.w, s.active.h), &win); + win = reduce(win, s.activeTransparentRegion); +#else + win = reduce(win, s.activeTransparentRegion); +#endif float left = float(win.left) / float(s.active.w); float top = float(win.top) / float(s.active.h); float right = float(win.right) / float(s.active.w); @@ -818,16 +838,49 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform tr(useIdentityTransform ? + Transform tr(useIdentityTransform ? hw->getTransform() : hw->getTransform() * s.transform); const uint32_t hw_h = hw->getHeight(); Rect win(s.active.w, s.active.h); if (!s.active.crop.isEmpty()) { win.intersect(s.active.crop, &win); } - // subtract the transparent region and snap to the bounds +#ifdef QTI_BSP + win = s.transform.transform(win); + win.intersect(hw->getViewport(), &win); + win = s.transform.inverse().transform(win); + win.intersect(Rect(s.active.w, s.active.h), &win); win = reduce(win, s.activeTransparentRegion); - + const Transform bufferOrientation(mCurrentTransform); + Transform transform(tr * s.transform * bufferOrientation); + if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { + uint32_t invTransform = hw->getOrientationTransform(); + uint32_t t_orientation = transform.getOrientation(); + if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | + NATIVE_WINDOW_TRANSFORM_FLIP_H; + bool is_h_flipped = (t_orientation & + NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; + bool is_v_flipped = (t_orientation & + NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; + if (is_h_flipped != is_v_flipped) { + t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | + NATIVE_WINDOW_TRANSFORM_FLIP_H; + } + transform = Transform(t_orientation) * Transform(invTransform); + } + } + const uint32_t orientation = transform.getOrientation(); + if (!(mTransformHint | mCurrentTransform | orientation)) { + tr = hw->getTransform(); + if (!useIdentityTransform) { + win = s.transform.transform(win); + win.intersect(hw->getViewport(), &win); + } + } +#else + win = reduce(win, s.activeTransparentRegion); +#endif Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); position[0] = tr.transform(win.left, win.top); position[1] = tr.transform(win.left, win.bottom); @@ -977,6 +1030,17 @@ uint32_t Layer::doTransaction(uint32_t flags) { if (flags & eDontUpdateGeometryState) { } else { Layer::State& editCurrentState(getCurrentState()); + // If a position change was requested, and we have the correct + // buffer size, no need to delay, update state now. + if (editCurrentState.requested.isPositionPending) { + float requestedX = editCurrentState.requested.x; + float requestedY = editCurrentState.requested.y; + if (requestedX != editCurrentState.active.x || + requestedY != editCurrentState.active.y) { + editCurrentState.requested.isPositionPending = false; + editCurrentState.transform.set(requestedX, requestedY); + } + } editCurrentState.active = c.requested; } @@ -1014,10 +1078,15 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { } bool Layer::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) + if ((mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y + && !mCurrentState.requested.isPositionPending) || + (mCurrentState.requested.isPositionPending && mCurrentState.requested.x == x + && mCurrentState.requested.y == y)) return false; mCurrentState.sequence++; - mCurrentState.transform.set(x, y); + mCurrentState.requested.x = x; + mCurrentState.requested.y = y; + mCurrentState.requested.isPositionPending = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1029,6 +1098,14 @@ bool Layer::setLayer(uint32_t z) { setTransactionFlags(eTransactionNeeded); return true; } +bool Layer::setBlur(uint8_t blur) { + if (mCurrentState.blur == blur) + return false; + mCurrentState.sequence++; + mCurrentState.blur = blur; + setTransactionFlags(eTransactionNeeded); + return true; +} bool Layer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; @@ -1232,6 +1309,19 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) (bufWidth == front.requested.w && bufHeight == front.requested.h)) { + + // If a position change was requested along with a resize. + // Now that we have the correct buffer size, update the position as well. + if (current.requested.isPositionPending) { + float requestedX = current.requested.x; + float requestedY = current.requested.y; + if (requestedX != current.active.x || requestedY != current.active.y) { + front.transform.set(requestedX, requestedY); + current.transform.set(requestedX, requestedY); + current.requested.isPositionPending = false; + } + } + // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked @@ -1440,7 +1530,7 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const return usage; } -void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { +void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { // The transform hint is used to improve performance, but we can @@ -1453,6 +1543,7 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { } } mSurfaceFlingerConsumer->setTransformHint(orientation); + mTransformHint = orientation; } // ---------------------------------------------------------------------------- @@ -1477,13 +1568,13 @@ void Layer::dump(String8& result, Colorizer& colorizer) const result.appendFormat( " " "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " "isOpaque=%1d, invalidate=%1d, " - "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" + "alpha=0x%02x, blur=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" " client=%p\n", s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, s.active.crop.left, s.active.crop.top, s.active.crop.right, s.active.crop.bottom, isOpaque(s), contentDirty, - s.alpha, s.flags, + s.alpha, s.blur, s.flags, s.transform[0][0], s.transform[0][1], s.transform[1][0], s.transform[1][1], client.get()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c1e5e9f..02d6f16 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -57,6 +57,7 @@ class Colorizer; class DisplayDevice; class GraphicBuffer; class SurfaceFlinger; +class LayerBlur; // --------------------------------------------------------------------------- @@ -70,7 +71,12 @@ class SurfaceFlinger; class Layer : public SurfaceFlingerConsumer::ContentsChangedListener { static int32_t sSequence; + friend class LayerBlur; + public: +#ifdef QTI_BSP + friend class ExLayer; +#endif mutable bool contentDirty; // regions below are in window-manager space Region visibleRegion; @@ -89,11 +95,15 @@ public: }; struct Geometry { + float x; + float y; uint32_t w; uint32_t h; + bool isPositionPending; Rect crop; inline bool operator ==(const Geometry& rhs) const { - return (w == rhs.w && h == rhs.h && crop == rhs.crop); + return (w == rhs.w && h == rhs.h && crop == rhs.crop && x == rhs.x && y == rhs.y + && isPositionPending == rhs.isPositionPending); } inline bool operator !=(const Geometry& rhs) const { return !operator ==(rhs); @@ -105,6 +115,7 @@ public: Geometry requested; uint32_t z; uint32_t layerStack; + uint8_t blur; uint8_t alpha; uint8_t flags; uint8_t reserved[2]; @@ -130,6 +141,10 @@ public: // modify current state bool setPosition(float x, float y); bool setLayer(uint32_t z); + bool setBlur(uint8_t blur); + virtual bool setBlurMaskLayer(sp<Layer>& /*maskLayer*/) { return false; } + virtual bool setBlurMaskSampling(int32_t /*sampling*/) { return false; } + virtual bool setBlurMaskAlphaThreshold(float /*alpha*/) { return false; } bool setSize(uint32_t w, uint32_t h); bool setAlpha(uint8_t alpha); bool setMatrix(const layer_state_t::matrix22_t& matrix); @@ -192,19 +207,24 @@ public: */ virtual bool isFixedSize() const; + /* + * isBlurLayer - true if this is a LayerBlur instance + */ + virtual bool isBlurLayer() const { return false; } + protected: /* * onDraw - draws the surface. */ virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform); public: // ----------------------------------------------------------------------- void setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); - void setPerFrameData(const sp<const DisplayDevice>& hw, + virtual void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); void setAcquireFence(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); @@ -234,9 +254,9 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const sp<const DisplayDevice>& hw, const Region& clip) const; - void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform) const; - void draw(const sp<const DisplayDevice>& hw) const; + void draw(const sp<const DisplayDevice>& hw, const Region& clip); + void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform); + void draw(const sp<const DisplayDevice>& hw); /* * doTransaction - process the transaction. This is a good place to figure @@ -283,7 +303,22 @@ public: // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. - void updateTransformHint(const sp<const DisplayDevice>& hw) const; + void updateTransformHint(const sp<const DisplayDevice>& hw) ; + + /* ------------------------------------------------------------------------ + * Extensions + */ + virtual bool isExtOnly() const { return false; } + virtual bool isIntOnly() const { return false; } + virtual bool isSecureDisplay() const { return false; } + virtual bool isYuvLayer() const { return false; } + virtual void setPosition(const sp<const DisplayDevice>& /*hw*/, + HWComposer::HWCLayerInterface& /*layer*/, + const State& /*state*/) { } + virtual void setAcquiredFenceIfBlit(int& /*fenceFd */, + HWComposer::HWCLayerInterface& /*layer */) { } + virtual bool canAllowGPUForProtected() const { return false; } + /* * returns the rectangle that crops the content of the layer and scales it @@ -336,6 +371,7 @@ protected: LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer); }; + Rect reduce(const Rect& win, const Region& exclude) const; private: // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener @@ -419,6 +455,7 @@ private: Vector<BufferItem> mQueueItems; uint64_t mLastFrameNumberReceived; bool mUpdateTexImageFailed; // This is only modified from the main thread + uint32_t mTransformHint; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp new file mode 100644 index 0000000..021978d --- /dev/null +++ b/services/surfaceflinger/LayerBlur.cpp @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +//#define LOG_NDEBUG 0 + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> +#include <time.h> + +#include <utils/Errors.h> +#include <utils/Log.h> +#include <utils/Trace.h> +#include <GLES/gl.h> +#include <GLES2/gl2.h> + +#include "LayerBlur.h" +#include "SurfaceFlinger.h" +#include "DisplayDevice.h" +#include "RenderEngine/RenderEngine.h" + +namespace android { +// --------------------------------------------------------------------------- + +// Automatically disables scissor test and restores it when destroyed +class ScopedScissorDisabler { + bool scissorEnabled; +public: + ScopedScissorDisabler(bool enabled) : scissorEnabled(enabled) { + if(scissorEnabled) { + glDisable(GL_SCISSOR_TEST); + } + } + ~ScopedScissorDisabler() { + if(scissorEnabled) { + glEnable(GL_SCISSOR_TEST); + } + }; +}; + +static void setupMeshPartial(Mesh& mesh, Rect rcDraw, Rect rcTexture, int texWidth, int texHeight, int viewportHeight) { + Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); + position[0] = vec2(rcDraw.left, rcDraw.top); + position[1] = vec2(rcDraw.left, rcDraw.bottom); + position[2] = vec2(rcDraw.right, rcDraw.bottom); + position[3] = vec2(rcDraw.right, rcDraw.top); + for(size_t i=0; i<4; ++i) { + position[i].y = viewportHeight - position[i].y; + } + + Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>()); + texCoords[0] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight); + texCoords[1] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight); + texCoords[2] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight); + texCoords[3] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight); +} + +static void setupMesh(Mesh& mesh, int width, int height, int viewportHeight) { + Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); + position[0] = vec2(0, 0); + position[1] = vec2(0, height); + position[2] = vec2(width, height); + position[3] = vec2(width, 0); + for(size_t i=0; i<4; ++i) { + position[i].y = viewportHeight - position[i].y; + } + + Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>()); + texCoords[0] = vec2(0, 1.0f); + texCoords[1] = vec2(0, 0); + texCoords[2] = vec2(1.0f, 0); + texCoords[3] = vec2(1.0f, 1.0f); +} + + +LayerBlur::LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags), mBlurMaskSampling(1), mBlurMaskAlphaThreshold(0.0f) + ,mLastFrameSequence(0) +{ +#ifdef UI_BLUR + mBlurToken = qtiblur::initBlurToken(); +#endif + + GLuint texnames[3]; + mFlinger->getRenderEngine().genTextures(3, texnames); + mTextureCapture.init(Texture::TEXTURE_2D, texnames[0]); + mTextureBlur.init(Texture::TEXTURE_2D, texnames[1]); + mTextureMasking.init(Texture::TEXTURE_2D, texnames[2]); +} + +LayerBlur::~LayerBlur() { +#ifdef UI_BLUR + qtiblur::releaseBlurToken(mBlurToken); +#endif + + releaseFbo(mFboCapture); + releaseFbo(mFboMasking); + mFlinger->deleteTextureAsync(mTextureCapture.getTextureName()); + mFlinger->deleteTextureAsync(mTextureBlur.getTextureName()); + mFlinger->deleteTextureAsync(mTextureMasking.getTextureName()); +} + +void LayerBlur::onDraw(const sp<const DisplayDevice>& hw, const Region& /*clip*/, + bool useIdentityTransform) +{ + clock_t t1 = clock(); + const ScopedTrace traceTotal(ATRACE_TAG, "Blur.onDraw"); + + const Layer::State& s(getDrawingState()); + + if (s.alpha==0) { + return; + } + + ///// + // NOTE: + // + // Scissor test has been turned on by SurfaceFlinger for NON-primary display + // We need to turn off the scissor test during our fbo drawing + GLboolean isScissorEnabled = false; + glGetBooleanv(GL_SCISSOR_TEST, &isScissorEnabled); + ScopedScissorDisabler _(isScissorEnabled); + // + ///// + + + int hwWidth = hw->getWidth(); + int hwHeight = hw->getHeight(); + + RenderEngine& engine(mFlinger->getRenderEngine()); + + bool savedProjectionYSwap = engine.getProjectionYSwap(); + Rect savedProjectionSourceCrop = engine.getProjectionSourceCrop(); + Transform::orientation_flags savedProjectionRotation = engine.getProjectionRotation(); + size_t savedViewportWidth = engine.getViewportWidth(); + size_t savedViewportHeight = engine.getViewportHeight(); + + + if (mLastFrameSequence != mFlinger->mActiveFrameSequence || + mTextureBlur.getWidth() == 0 || mTextureBlur.getHeight() == 0) { + // full drawing needed. + + + // capture + if (!captureScreen(hw, mFboCapture, mTextureCapture, hwWidth, hwHeight)) { + return; + } + + // blur + size_t outTexWidth = mTextureBlur.getWidth(); + size_t outTexHeight = mTextureBlur.getHeight(); +#ifdef UI_BLUR + if (!qtiblur::blur(mBlurToken, + s.blur, + mTextureCapture.getTextureName(), + mTextureCapture.getWidth(), + mTextureCapture.getHeight(), + mTextureBlur.getTextureName(), + &outTexWidth, + &outTexHeight)) { + return; + } +#endif + + // mTextureBlur now has "Blurred image" + mTextureBlur.setDimensions(outTexWidth, outTexHeight); + + } else { + // We can just re-use mTextureBlur. + // SurfaceFlinger or other LayerBlur object called my draw() multiple times + // while making one frame. + // + // Fall through + } + + // masking + bool masking = false; + sp<Layer> maskLayer = mBlurMaskLayer.promote(); + if (maskLayer != 0) { + // The larger sampling, the faster drawing. + // The smaller sampling, the prettier out line. + int sampling = mBlurMaskSampling >= 1 ? mBlurMaskSampling : 1; + //ALOGV("maskLayer available, sampling:%d", sampling); + masking = drawMaskLayer(maskLayer, hw, mFboMasking, hwWidth, hwHeight, sampling, mTextureMasking); + } + + + // final draw + doDrawFinal(hw, + savedViewportWidth, savedViewportHeight, + savedProjectionSourceCrop, + savedProjectionYSwap, + savedProjectionRotation, + useIdentityTransform, + masking ? &mTextureMasking : 0 + ); + + mLastFrameSequence = mFlinger->mActiveFrameSequence; + + clock_t t2 = clock(); + ALOGV("onDraw took %d ms", (int)(1000*(t2-t1)/CLOCKS_PER_SEC)); +} + + +bool LayerBlur::captureScreen(const sp<const DisplayDevice>& hw, FBO& fbo, Texture& texture, int width, int height) { + ATRACE_CALL(); + ensureFbo(fbo, width, height, texture.getTextureName()); + Transform::orientation_flags rotation = Transform::ROT_0; + if(fbo.fbo == 0) { + ALOGE("captureScreen(). fbo.fbo == 0"); + return false; + } + + GLint savedFramebuffer = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + texture.getTextureTarget(), + texture.getTextureName(), 0); + + mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 1.0f); + if (hw->isPanelInverseMounted()) + rotation = Transform::ROT_180; + mFlinger->renderScreenImplLocked( + hw, + Rect(0,0,width,height), + width, height, + 0, getDrawingState().z-1, + false, + false, + rotation); + + glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer); + + texture.setDimensions(width, height); + + return true; +} + +bool LayerBlur::drawMaskLayer(sp<Layer>& maskLayer, const sp<const DisplayDevice>& hw, + FBO& fbo, int width, int height, int sampling, Texture& texture) { + // Draw maskLayer into fbo + ATRACE_CALL(); + + int maskWidth = width/sampling; + int maskHeight = height/sampling; + + ensureFbo(fbo, maskWidth, maskHeight, texture.getTextureName()); + if(fbo.fbo == 0) { + ALOGE("drawMaskLayer(). fbo.fbo == 0"); + return false; + } + + GLint savedFramebuffer = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + texture.getTextureTarget(), + texture.getTextureName(), 0); + + mFlinger->getRenderEngine().setViewportAndProjection( + maskWidth, maskHeight, + Rect(0,0,width,height), + height, + false, + Transform::ROT_0 + ); + setupMesh(mMesh, width, height, height); + mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 0.0f); // alpha must be ZERO + maskLayer->draw(hw); + glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer); + + texture.setDimensions(maskWidth, maskHeight); + + return true; +} + +/* + * draw final texture into outer framebuffer + */ +void LayerBlur::doDrawFinal(const sp<const DisplayDevice>& hw, + int savedViewportWidth, int savedViewportHeight, + Rect savedProjectionSourceCrop, + bool savedProjectionYSwap, + Transform::orientation_flags savedRotation, + bool useIdentityTransform, + Texture* maskTexture + ) { + ATRACE_CALL(); + + int hwWidth = hw->getWidth(); + int hwHeight = hw->getHeight(); + + RenderEngine& engine(mFlinger->getRenderEngine()); + const Layer::State& s(getDrawingState()); + + Transform trToDraw(useIdentityTransform ? hw->getTransform() : hw->getTransform() * s.transform); + Transform trToMapTexture(hw->getTransform() * s.transform); + + Rect frameToDraw(trToDraw.transform(Rect(s.active.w, s.active.h))); + Rect frameToMapTexture(trToMapTexture.transform(Rect(s.active.w, s.active.h))); + + engine.setViewportAndProjection( + savedViewportWidth, savedViewportHeight, + savedProjectionSourceCrop, + hwHeight, + savedProjectionYSwap, + savedRotation + ); + + + const mat4 identity; + float textureMatrix[16]; + memcpy(textureMatrix, identity.asArray(), sizeof(textureMatrix)); + + //mTextureBlur.setDimensions(hwWidth, hwHeight); + mTextureBlur.setFiltering(true); + mTextureBlur.setMatrix(textureMatrix); + + if (maskTexture != 0) { + maskTexture->setFiltering(false); + maskTexture->setMatrix(textureMatrix); + } + + setupMeshPartial(mMesh, frameToDraw, frameToMapTexture, hwWidth, hwHeight, + savedProjectionSourceCrop.height()); + + engine.setupLayerTexturing(mTextureBlur); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); + if (maskTexture) { + engine.setupLayerMasking(*maskTexture, mBlurMaskAlphaThreshold); + } + engine.drawMesh(mMesh); + engine.disableLayerMasking(); + engine.disableBlending(); + engine.disableTexturing(); + +} + +bool LayerBlur::isVisible() const { + const Layer::State& s(getDrawingState()); + return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; +} + +bool LayerBlur::setBlurMaskLayer(sp<Layer>& maskLayer) { + if (maskLayer == mBlurMaskLayer) { + return false; + } + mBlurMaskLayer = maskLayer; + return true; +} + + +void LayerBlur::initFbo(FBO& fbobj, int width, int height, int textureName) { + GLuint fbo=0; + + glGenFramebuffers(1, &fbo); + glBindTexture(GL_TEXTURE_2D, textureName); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + GLint savedFramebuffer = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, textureName, 0); + glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer); + + fbobj.fbo = fbo; + fbobj.width = width; + fbobj.height = height; +} + +void LayerBlur::releaseFbo(FBO& fbo) { + if(fbo.fbo != 0) { + glDeleteFramebuffers(1, (GLuint*)&fbo.fbo); + } + fbo.fbo = 0; + fbo.width = 0; + fbo.height = 0; +} + +void LayerBlur::ensureFbo(FBO& fbo, int width, int height, int textureName) { + if(fbo.fbo != 0) { + if(fbo.width != width || fbo.height != height) { + releaseFbo(fbo); + } + } + if(fbo.fbo == 0) { + initFbo(fbo, width, height, textureName); + } +} + + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/services/surfaceflinger/LayerBlur.h b/services/surfaceflinger/LayerBlur.h new file mode 100644 index 0000000..251423e --- /dev/null +++ b/services/surfaceflinger/LayerBlur.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_LAYER_BLUR_H +#define ANDROID_LAYER_BLUR_H + +#include <stdint.h> +#include <sys/types.h> + +#include "Layer.h" + +#ifdef UI_BLUR +#include "Blur.h" // libuiblur.so +#endif + +// --------------------------------------------------------------------------- + +namespace android { + +/** + * Blur layer object. + * Actual blurring logics are capsulated in libuiblur.so + */ +class LayerBlur : public Layer +{ +public: + LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); + virtual ~LayerBlur(); + + virtual const char* getTypeId() const { return "LayerBlur"; } + virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip, + bool useIdentityTransform); + virtual bool isOpaque(const Layer::State& /*s*/) const { return false; } + virtual bool isSecure() const { return false; } + virtual bool isFixedSize() const { return true; } + virtual bool isVisible() const; + + virtual bool isBlurLayer() const { return true; } + virtual bool setBlurMaskLayer(sp<Layer>& maskLayer); + virtual bool setBlurMaskSampling(int32_t sampling) { mBlurMaskSampling = sampling; return true; } + virtual bool setBlurMaskAlphaThreshold(float alpha) { mBlurMaskAlphaThreshold = alpha; return true; } + +private: +#ifdef UI_BLUR + qtiblur::BLUR_TOKEN mBlurToken; +#endif + wp<Layer> mBlurMaskLayer; + int32_t mBlurMaskSampling; + float mBlurMaskAlphaThreshold; + uint32_t mLastFrameSequence; + + class FBO { + public: + FBO() : fbo(0), width(0), height(0) {} + int fbo; + int width; + int height; + }; + + void initFbo(FBO& fbo, int width, int height, int textureName); + void releaseFbo(FBO& fbo); + void ensureFbo(FBO& fbo, int width, int height, int textureName); + + + FBO mFboCapture; + Texture mTextureCapture; + + Texture mTextureBlur; + + FBO mFboMasking; + Texture mTextureMasking; + + bool captureScreen(const sp<const DisplayDevice>& hw, + FBO& fbo, Texture& texture, int width, int height); + void doDrawFinal(const sp<const DisplayDevice>& hw, + int savedViewportWidth, int savedViewportHeight, + Rect savedProjectionSourceCrop, bool savedProjectionYSwap, + Transform::orientation_flags savedRotation, bool useIdentityTransform, + Texture* maskTexture); + bool drawMaskLayer(sp<Layer>& maskLayer, const sp<const DisplayDevice>& hw, + FBO& fbo, int width, int height, int sampling, Texture& texture); + +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_LAYER_BLUR_H diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index 14aa328..5afd291 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -40,7 +40,7 @@ LayerDim::~LayerDim() { } void LayerDim::onDraw(const sp<const DisplayDevice>& hw, - const Region& /* clip */, bool useIdentityTransform) const + const Region& /* clip */, bool useIdentityTransform) { const State& s(getDrawingState()); if (s.alpha>0) { @@ -58,6 +58,15 @@ bool LayerDim::isVisible() const { return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; } +void LayerDim::setPerFrameData(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer) { + HWComposer& hwc = mFlinger->getHwComposer(); + + Layer::setPerFrameData(hw, layer); + if (hwc.hasDimComposition()) { + layer.setDim(); + } +} // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index a0cfca9..01f71cc 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -35,11 +35,13 @@ public: virtual const char* getTypeId() const { return "LayerDim"; } virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform); virtual bool isOpaque(const Layer::State&) const { return false; } virtual bool isSecure() const { return false; } virtual bool isFixedSize() const { return true; } virtual bool isVisible() const; + virtual void setPerFrameData(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index 0dab872..14607ca 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -33,6 +33,8 @@ Description::Description() : mOpaque = true; mTextureEnabled = false; mColorMatrixEnabled = false; + mMaskTextureEnabled = false; + mMaskAlphaThreshold = 0.0f; memset(mColor, 0, sizeof(mColor)); } @@ -92,5 +94,14 @@ const mat4& Description::getColorMatrix() const { return mColorMatrix; } +void Description::setMasking(const Texture& maskTexture, float alphaThreshold) { + mMaskTexture = maskTexture; + mMaskTextureEnabled = true; + mMaskAlphaThreshold = alphaThreshold; +} + +void Description::disableMasking() { + mMaskTextureEnabled = false; +} } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 8a3447c..2bfb632 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -53,6 +53,9 @@ class Description { bool mColorMatrixEnabled; mat4 mColorMatrix; + Texture mMaskTexture; + bool mMaskTextureEnabled; + GLclampf mMaskAlphaThreshold; public: Description(); @@ -67,6 +70,8 @@ public: void setProjectionMatrix(const mat4& mtx); void setColorMatrix(const mat4& mtx); const mat4& getColorMatrix() const; + void setMasking(const Texture& maskTexture, float alphaThreshold); + void disableMasking(); private: bool mUniformsDirty; diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp index 1a9f59b..853a4eb 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp @@ -92,14 +92,29 @@ void GLES11RenderEngine::setViewportAndProjection( case Transform::ROT_0: break; case Transform::ROT_90: - glRotatef(90, 0, 0, 1); + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1-y1, x1+y1, 0); + glRotatef(270, 0, 0, 1); break; + } case Transform::ROT_180: + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1*2, y1*2, 0); glRotatef(180, 0, 0, 1); break; + } case Transform::ROT_270: - glRotatef(270, 0, 0, 1); + { + float x1 = (l+r)/2; + float y1 = (t+b)/2; + glTranslatef(x1+y1, y1-x1, 0); + glRotatef(90, 0, 0, 1); break; + } default: break; } @@ -210,28 +225,46 @@ void GLES11RenderEngine::disableBlending() { } void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status) { + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight) { GLuint tname, name; - // turn our EGLImage into a texture - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - - // create a Framebuffer Object to render into - glGenFramebuffersOES(1, &name); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); - glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, - GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + if (!useReadPixels) { + // turn our EGLImage into a texture + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + + // create a Framebuffer Object to render into + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, + GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + } else { + // since we're going to use glReadPixels() anyways, + // use an intermediate renderbuffer instead + glGenRenderbuffersOES(1, &tname); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight); + // create a FBO to render into + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, + GL_RENDERBUFFER_OES, tname); + } *status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); *texName = tname; *fbName = name; } -void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { +void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) { glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteFramebuffersOES(1, &fbName); - glDeleteTextures(1, &texName); + if (!useReadPixels) + glDeleteTextures(1, &texName); + else + glDeleteRenderbuffersOES(1, &texName); } void GLES11RenderEngine::setupFillWithColor(float r, float g, float b, float a) { diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h index 08de646..cb13ee0 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h @@ -40,8 +40,9 @@ class GLES11RenderEngine : public RenderEngine { GLint mMaxTextureSize; virtual void bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + uint32_t* texName, uint32_t* fbName, uint32_t* status, bool useReadPixels, + int reqWidth, int reqHeight); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels); public: GLES11RenderEngine(); @@ -59,6 +60,8 @@ protected: virtual void setupFillWithColor(float r, float g, float b, float a) ; virtual void disableTexturing(); virtual void disableBlending(); + virtual void setupLayerMasking(const Texture& /*maskTexture*/, float /*alphaThreshold*/) {} + virtual void disableLayerMasking() {} virtual void drawMesh(const Mesh& mesh); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 1fabaf5..6333a41 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -40,7 +40,7 @@ namespace android { // --------------------------------------------------------------------------- GLES20RenderEngine::GLES20RenderEngine() : - mVpWidth(0), mVpHeight(0) { + mVpWidth(0), mVpHeight(0), mProjectionRotation(Transform::ROT_0) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); @@ -115,6 +115,9 @@ void GLES20RenderEngine::setViewportAndProjection( mState.setProjectionMatrix(m); mVpWidth = vpw; mVpHeight = vph; + mProjectionSourceCrop = sourceCrop; + mProjectionYSwap = yswap; + mProjectionRotation = rotation; } void GLES20RenderEngine::setupLayerBlending( @@ -185,27 +188,44 @@ void GLES20RenderEngine::disableBlending() { void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status) { + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight) { GLuint tname, name; - // turn our EGLImage into a texture - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - - // create a Framebuffer Object to render into - glGenFramebuffers(1, &name); - glBindFramebuffer(GL_FRAMEBUFFER, name); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + if (!useReadPixels) { + // turn our EGLImage into a texture + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + + // create a Framebuffer Object to render into + glGenFramebuffers(1, &name); + glBindFramebuffer(GL_FRAMEBUFFER, name); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + } else { + // since we're going to use glReadPixels() anyways, + // use an intermediate renderbuffer instead + glGenRenderbuffers(1, &tname); + glBindRenderbuffer(GL_RENDERBUFFER, tname); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, reqWidth, reqHeight); + // create a FBO to render into + glGenFramebuffers(1, &name); + glBindFramebuffer(GL_FRAMEBUFFER, name); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, tname); + } *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); *texName = tname; *fbName = name; } -void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { +void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) { glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbName); - glDeleteTextures(1, &texName); + if (!useReadPixels) + glDeleteTextures(1, &texName); + else + glDeleteRenderbuffers(1, &texName); } void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { @@ -247,6 +267,30 @@ void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); } +void GLES20RenderEngine::setupLayerMasking(const Texture& maskTexture, float alphaThreshold) { + glActiveTexture(GL_TEXTURE0 + 1); + GLuint target = maskTexture.getTextureTarget(); + glBindTexture(target, maskTexture.getTextureName()); + GLenum filter = GL_NEAREST; + if (maskTexture.getFiltering()) { + filter = GL_LINEAR; + } + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); + + if (alphaThreshold < 0) alphaThreshold = 0; + if (alphaThreshold > 1.0f) alphaThreshold = 1.0f; + + mState.setMasking(maskTexture, alphaThreshold); + glActiveTexture(GL_TEXTURE0); +} + +void GLES20RenderEngine::disableLayerMasking() { + mState.disableMasking(); +} + // --------------------------------------------------------------------------- }; // namespace android // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 819356a..414a999 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -42,6 +42,9 @@ class GLES20RenderEngine : public RenderEngine { GLint mMaxTextureSize; GLuint mVpWidth; GLuint mVpHeight; + Rect mProjectionSourceCrop; + bool mProjectionYSwap; + Transform::orientation_flags mProjectionRotation; struct Group { GLuint texture; @@ -55,8 +58,9 @@ class GLES20RenderEngine : public RenderEngine { Vector<Group> mGroupStack; virtual void bindImageAsFramebuffer(EGLImageKHR image, - uint32_t* texName, uint32_t* fbName, uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + uint32_t* texName, uint32_t* fbName, uint32_t* status, + bool useReadPixels, int reqWidth, int reqHeight); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels); public: GLES20RenderEngine(); @@ -75,11 +79,18 @@ protected: virtual mat4 setupColorTransform(const mat4& colorTransform); virtual void disableTexturing(); virtual void disableBlending(); + virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold); + virtual void disableLayerMasking(); virtual void drawMesh(const Mesh& mesh); virtual size_t getMaxTextureSize() const; virtual size_t getMaxViewportDims() const; + virtual bool getProjectionYSwap() { return mProjectionYSwap; } + virtual size_t getViewportWidth() const { return mVpWidth; } + virtual size_t getViewportHeight() const { return mVpHeight; } + virtual Rect getProjectionSourceCrop() const { return mProjectionSourceCrop; } + virtual Transform::orientation_flags getProjectionRotation() const { return mProjectionRotation; } }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 0424e0c..936cb1b 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -64,6 +64,8 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane"); + mSamplerMaskLoc = glGetUniformLocation(programId, "samplerMask"); + mMaskAlphaThresholdLoc = glGetUniformLocation(programId, "maskAlphaThreshold"); // set-up the default values for our uniforms glUseProgram(programId); @@ -143,6 +145,12 @@ void Program::setUniforms(const Description& desc) { } // these uniforms are always present glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); + if (mSamplerMaskLoc >= 0) { + glUniform1i(mSamplerMaskLoc, 1); + } + if (mMaskAlphaThresholdLoc >= 0) { + glUniform1f(mMaskAlphaThresholdLoc, desc.mMaskAlphaThreshold); + } } } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h index 36bd120..08dee59 100644 --- a/services/surfaceflinger/RenderEngine/Program.h +++ b/services/surfaceflinger/RenderEngine/Program.h @@ -84,6 +84,9 @@ private: /* location of the color uniform */ GLint mColorLoc; + + GLint mSamplerMaskLoc; + GLint mMaskAlphaThresholdLoc; }; diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index ba11259..33ff7d0 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 + #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> @@ -110,9 +112,27 @@ void ProgramCache::primeCache() { shaderCount++; } } + + // Keys that are actually used by blurring. + // This is obtained by log msg from useProgram() + uint32_t blurringKeys[] = { + 0x01000015, + 0x01000011, + }; + for (size_t i=0; i<sizeof(blurringKeys)/sizeof(blurringKeys[0]); ++i) { + Key shaderKey; + shaderKey.set(blurringKeys[i], blurringKeys[i]); + Program* program = mCache.valueFor(shaderKey); + if (program == NULL) { + program = generateProgram(shaderKey); + mCache.add(shaderKey, program); + shaderCount++; + } + } + nsecs_t timeAfter = systemTime(); float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6; - ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs); + ALOGD("SF. shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs); } ProgramCache::Key ProgramCache::computeKey(const Description& description) { @@ -129,15 +149,20 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { .set(Key::OPACITY_MASK, description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT) .set(Key::COLOR_MATRIX_MASK, - description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF); + description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF) + .set(Key::TEXTURE_MASKING_MASK, + !description.mMaskTextureEnabled ? Key::TEXTURE_MASKING_OFF : + description.mMaskTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_MASKING_EXT : + description.mMaskTexture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_MASKING_2D : + Key::TEXTURE_MASKING_OFF); return needs; } String8 ProgramCache::generateVertexShader(const Key& needs) { Formatter vs; if (needs.isTexturing()) { - vs << "attribute vec4 texCoords;" - << "varying vec2 outTexCoords;"; + vs << "attribute vec4 texCoords;" + << "varying vec2 outTexCoords;"; } vs << "attribute vec4 position;" << "uniform mat4 projection;" @@ -145,7 +170,7 @@ String8 ProgramCache::generateVertexShader(const Key& needs) { << "void main(void) {" << indent << "gl_Position = projection * position;"; if (needs.isTexturing()) { - vs << "outTexCoords = (texture * texCoords).st;"; + vs << "outTexCoords = (texture * texCoords).st;"; } vs << dedent << "}"; return vs.getString(); @@ -169,6 +194,14 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) { fs << "uniform vec4 color;"; } + if (needs.getTextureMaskingTarget() == Key::TEXTURE_MASKING_EXT) { + fs << "uniform samplerExternalOES samplerMask;"; + } else if (needs.getTextureMaskingTarget() == Key::TEXTURE_MASKING_2D) { + fs << "uniform sampler2D samplerMask;"; + } + if (needs.getTextureMaskingTarget() != Key::TEXTURE_MASKING_OFF) { + fs << "uniform float maskAlphaThreshold;"; + } if (needs.hasPlaneAlpha()) { fs << "uniform float alphaPlane;"; } @@ -177,7 +210,12 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } fs << "void main(void) {" << indent; if (needs.isTexturing()) { - fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; + if (needs.getTextureMaskingTarget() != Key::TEXTURE_MASKING_OFF) { + fs << "if (texture2D(samplerMask, outTexCoords).a <= maskAlphaThreshold) discard;" + << "gl_FragColor = texture2D(sampler, outTexCoords);"; + } else { + fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; + } } else { fs << "gl_FragColor = color;"; } @@ -235,9 +273,6 @@ void ProgramCache::useProgram(const Description& description) { program = generateProgram(needs); mCache.add(needs, program); time += systemTime(); - - //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)", - // needs.mNeeds, uint32_t(ns2ms(time)), mCache.size()); } // here we have a suitable program for this description diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h index 1fa53d3..3824e73 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.h +++ b/services/surfaceflinger/RenderEngine/ProgramCache.h @@ -69,6 +69,11 @@ public: COLOR_MATRIX_OFF = 0x00000000, COLOR_MATRIX_ON = 0x00000020, COLOR_MATRIX_MASK = 0x00000020, + + TEXTURE_MASKING_OFF = 0x00000000, + TEXTURE_MASKING_EXT = 0x00800000, + TEXTURE_MASKING_2D = 0x01000000, + TEXTURE_MASKING_MASK = 0x01800000, }; inline Key() : mKey(0) { } @@ -97,6 +102,12 @@ public: inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; } + inline bool isTextureMasking() const { + return (mKey & TEXTURE_MASKING_MASK) != TEXTURE_MASKING_OFF; + } + inline int getTextureMaskingTarget() const { + return (mKey & TEXTURE_MASKING_MASK); + } // this is the definition of a friend function -- not a method of class Needs friend inline int strictly_order_type(const Key& lhs, const Key& rhs) { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 7cd42e4..cb1d14c 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -83,7 +83,6 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { EGL_CONTEXT_CLIENT_VERSION, contextClientVersion, // MUST be first #ifdef EGL_IMG_context_priority #ifdef HAS_CONTEXT_PRIORITY -#warning "using EGL_IMG_context_priority" EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, #endif #endif @@ -262,9 +261,11 @@ void RenderEngine::dump(String8& result) { // --------------------------------------------------------------------------- RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( - RenderEngine& engine, EGLImageKHR image) : mEngine(engine) + RenderEngine& engine, EGLImageKHR image, bool useReadPixels, + int reqWidth, int reqHeight) : mEngine(engine), mUseReadPixels(useReadPixels) { - mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus); + mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus, + useReadPixels, reqWidth, reqHeight); ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", mStatus); @@ -272,7 +273,7 @@ RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { // back to main framebuffer - mEngine.unbindFramebuffer(mTexName, mFbName); + mEngine.unbindFramebuffer(mTexName, mFbName, mUseReadPixels); } status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 31a961e..a669fdd 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -51,8 +51,11 @@ class RenderEngine { EGLContext mEGLContext; void setEGLHandles(EGLConfig config, EGLContext ctxt); - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0; - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, + uint32_t* fbName, uint32_t* status, bool useReadPixels, int reqWidth, + int reqHeight) = 0; + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, + bool useReadPixels) = 0; protected: RenderEngine(); @@ -83,8 +86,10 @@ public: RenderEngine& mEngine; uint32_t mTexName, mFbName; uint32_t mStatus; + bool mUseReadPixels; public: - BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image); + BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image, + bool useReadPixels, int reqWidth, int reqHeight); ~BindImageAsFramebuffer(); int getStatus() const; }; @@ -105,6 +110,8 @@ public: virtual void disableTexturing() = 0; virtual void disableBlending() = 0; + virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold) = 0; + virtual void disableLayerMasking() = 0; // drawing virtual void drawMesh(const Mesh& mesh) = 0; @@ -112,6 +119,11 @@ public: // queries virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; + virtual bool getProjectionYSwap() { return 0; } + virtual size_t getViewportWidth() const { return 1; } + virtual size_t getViewportHeight() const { return 1; } + virtual Rect getProjectionSourceCrop() const { return Rect(0, 0, 1, 1); } + virtual Transform::orientation_flags getProjectionRotation() const { return Transform::ROT_0; } EGLConfig getEGLConfig() const; EGLContext getEGLContext() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fdc3650..40e5da1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <stdint.h> @@ -27,6 +28,7 @@ #include <EGL/egl.h> #include <cutils/log.h> +#include <cutils/iosched_policy.h> #include <cutils/properties.h> #include <binder/IPCThreadState.h> @@ -67,6 +69,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerDim.h" +#include "LayerBlur.h" #include "SurfaceFlinger.h" #include "DisplayHardware/FramebufferSurface.h" @@ -77,6 +80,7 @@ #include "RenderEngine/RenderEngine.h" #include <cutils/compiler.h> +#include "DisplayUtils.h" #define DISPLAY_COUNT 1 @@ -122,6 +126,8 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER" const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sDump("android.permission.DUMP"); +static sp<Layer> lastSurfaceViewLayer; + // --------------------------------------------------------------------------- SurfaceFlinger::SurfaceFlinger() @@ -150,10 +156,12 @@ SurfaceFlinger::SurfaceFlinger() mHWVsyncAvailable(false), mDaltonize(false), mHasColorMatrix(false), + mHasSecondaryColorMatrix(false), mHasPoweredOff(false), mFrameBuckets(), mTotalTime(0), - mLastSwapTime(0) + mLastSwapTime(0), + mActiveFrameSequence(0) { ALOGI("SurfaceFlinger is starting"); @@ -446,17 +454,24 @@ void SurfaceFlinger::init() { eglInitialize(mEGLDisplay, NULL, NULL); // start the EventThread - sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc); - sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, - sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = new EventThread(sfVsyncSrc); - mEventQueue.setEventThread(mSFEventThread); + if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) { + sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "app"); + mEventThread = new EventThread(vsyncSrc); + sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, + sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = new EventThread(sfVsyncSrc); + mEventQueue.setEventThread(mSFEventThread); + } else { + sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "sf-app"); + mEventThread = new EventThread(vsyncSrc); + mEventQueue.setEventThread(mEventThread); + } // Initialize the H/W composer object. There may or may not be an // actual hardware composer underneath. - mHwc = new HWComposer(this, + mHwc = DisplayUtils::getInstance()->getHWCInstance(this, *static_cast<HWComposer::EventHandler *>(this)); // get a RenderEngine for the given display / config (can't fail) @@ -497,6 +512,13 @@ void SurfaceFlinger::init() { ALOGD("marking display %zu as acquired/unblanked", i); hw->setPowerMode(HWC_POWER_MODE_NORMAL); } + // When a non-virtual display device is added at boot time, + // update the active config by querying HWC otherwise the + // default config (config 0) will be used. + int activeConfig = mHwc->getActiveConfig(hwcId); + if (activeConfig >= 0) { + hw->setActiveConfig(activeConfig); + } mDisplays.add(token, hw); } } @@ -507,6 +529,7 @@ void SurfaceFlinger::init() { mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); + android_set_rt_ioprio(mEventControlThread->getTid(), 1); // set a fake vsync period if there is no HWComposer if (mHwc->initCheck() != NO_ERROR) { @@ -626,10 +649,21 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, info.orientation = 0; } - info.w = hwConfig.width; - info.h = hwConfig.height; - info.xdpi = xdpi; - info.ydpi = ydpi; + char value[PROPERTY_VALUE_MAX]; + property_get("ro.sf.hwrotation", value, "0"); + int additionalRot = atoi(value) / 90; + if ((type == DisplayDevice::DISPLAY_PRIMARY) && (additionalRot & DisplayState::eOrientationSwapMask)) { + info.h = hwConfig.width; + info.w = hwConfig.height; + info.xdpi = ydpi; + info.ydpi = xdpi; + } + else { + info.w = hwConfig.width; + info.h = hwConfig.height; + info.xdpi = xdpi; + info.ydpi = ydpi; + } info.fps = float(1e9 / hwConfig.refresh); info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS; info.colorTransform = hwConfig.colorTransform; @@ -695,8 +729,10 @@ void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mo return; } - hw->setActiveConfig(mode); - getHwComposer().setActiveConfig(type, mode); + status_t status = getHwComposer().setActiveConfig(type, mode); + if (status == NO_ERROR) { + hw->setActiveConfig(mode); + } } status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) { @@ -869,6 +905,7 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) { } else { mCurrentState.displays.removeItem(mBuiltinDisplays[type]); mBuiltinDisplays[type].clear(); + updateVisibleRegionsDirty(); } setTransactionFlags(eDisplayTransactionNeeded); @@ -1045,6 +1082,8 @@ void SurfaceFlinger::postComposition() mAnimFrameTracker.advanceFrame(); } + dumpDrawCycle(false); + if (hw->getPowerMode() == HWC_POWER_MODE_OFF) { return; } @@ -1067,6 +1106,7 @@ void SurfaceFlinger::postComposition() } void SurfaceFlinger::rebuildLayerStacks() { + updateExtendedMode(); // rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_CALL(); @@ -1082,14 +1122,13 @@ void SurfaceFlinger::rebuildLayerStacks() { const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); if (hw->isDisplayOn()) { - SurfaceFlinger::computeVisibleRegions(layers, + computeVisibleRegions(hw->getHwcDisplayId(), layers, hw->getLayerStack(), dirtyRegion, opaqueRegion); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { const sp<Layer>& layer(layers[i]); - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == hw->getLayerStack()) { + { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1155,7 +1194,7 @@ void SurfaceFlinger::setUpHWComposer() { for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<Layer>& layer(currentLayers[i]); layer->setGeometry(hw, *cur); - if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) { + if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix || mHasSecondaryColorMatrix) { cur->setSkip(true); } } @@ -1169,6 +1208,8 @@ void SurfaceFlinger::setUpHWComposer() { sp<const DisplayDevice> hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { + bool freezeSurfacePresent = false; + isfreezeSurfacePresent(freezeSurfacePresent, hw, id); const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); @@ -1181,6 +1222,11 @@ void SurfaceFlinger::setUpHWComposer() { */ const sp<Layer>& layer(currentLayers[i]); layer->setPerFrameData(hw, *cur); + setOrientationEventControl(freezeSurfacePresent,id); + if(!strncmp(layer->getName(), "SurfaceView", + 11)) { + lastSurfaceViewLayer = layer; + } } } } @@ -1205,6 +1251,8 @@ void SurfaceFlinger::setUpHWComposer() { } } + dumpDrawCycle(true); + status_t err = hwc.prepare(); ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); @@ -1227,6 +1275,8 @@ void SurfaceFlinger::doComposition() { // repaint the framebuffer (if needed) doDisplayComposition(hw, dirtyRegion); + ++mActiveFrameSequence; + hw->dirtyRegion.clear(); hw->flip(hw->swapRegion); hw->swapRegion.clear(); @@ -1287,6 +1337,7 @@ void SurfaceFlinger::postFramebuffer() if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { logFrameStats(); } + ALOGV_IF(mFrameRateHelper.update(), "FPS: %d", mFrameRateHelper.get()); } void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) @@ -1439,6 +1490,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (state.surface != NULL) { int width = 0; + DisplayUtils* displayUtils = DisplayUtils::getInstance(); int status = state.surface->query( NATIVE_WINDOW_WIDTH, &width); ALOGE_IF(status != NO_ERROR, @@ -1451,15 +1503,21 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 || (width <= MAX_VIRTUAL_DISPLAY_DIMENSION && height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) { - hwcDisplayId = allocateHwcDisplayId(state.type); + int usage = 0; + status = state.surface->query( + NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); + ALOGW_IF(status != NO_ERROR, + "Unable to query usage (%d)", status); + if ( (status == NO_ERROR) && + displayUtils->canAllocateHwcDisplayIdForVDS(usage)) { + hwcDisplayId = allocateHwcDisplayId(state.type); + } } - sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface( - *mHwc, hwcDisplayId, state.surface, - bqProducer, bqConsumer, state.displayName); + displayUtils->initVDSInstance(mHwc, hwcDisplayId, state.surface, + dispSurface, producer, bqProducer, bqConsumer, + state.displayName, state.isSecure, state.type); - dispSurface = vds; - producer = vds; } } else { ALOGE_IF(state.surface!=NULL, @@ -1475,7 +1533,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } const wp<IBinder>& display(curr.keyAt(i)); - if (dispSurface != NULL) { + if (dispSurface != NULL && producer != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, state.type, hwcDisplayId, mHwc->getFormat(hwcDisplayId), state.isSecure, @@ -1485,6 +1543,16 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); + // When a new display device is added update the active + // config by querying HWC otherwise the default config + // (config 0) will be used. + if (hwcDisplayId >= DisplayDevice::DISPLAY_PRIMARY && + hwcDisplayId < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + int activeConfig = mHwc->getActiveConfig(hwcDisplayId); + if (activeConfig >= 0) { + hw->setActiveConfig(activeConfig); + } + } mDisplays.add(display, hw); if (state.isVirtualDisplay()) { if (hwcDisplayId >= 0) { @@ -1643,7 +1711,7 @@ void SurfaceFlinger::commitTransaction() mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions( +void SurfaceFlinger::computeVisibleRegions(size_t dpy, const LayerVector& currentLayers, uint32_t layerStack, Region& outDirtyRegion, Region& outOpaqueRegion) { @@ -1654,6 +1722,9 @@ void SurfaceFlinger::computeVisibleRegions( Region dirty; outDirtyRegion.clear(); + bool bIgnoreLayers = false; + int indexLOI = -1; + getIndexLOI(dpy, currentLayers, bIgnoreLayers, indexLOI); size_t i = currentLayers.size(); while (i--) { @@ -1662,8 +1733,9 @@ void SurfaceFlinger::computeVisibleRegions( // start with the whole surface at its current location const Layer::State& s(layer->getDrawingState()); - // only consider the layers on the given layer stack - if (s.layerStack != layerStack) + if(updateLayerVisibleNonTransparentRegion(dpy, layer, + bIgnoreLayers, indexLOI, + layerStack, i)) continue; /* @@ -1887,11 +1959,14 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, } } - if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) { + if (CC_LIKELY(!mDaltonize && !mHasColorMatrix && !mHasSecondaryColorMatrix)) { if (!doComposeSurfaces(hw, dirtyRegion)) return; } else { RenderEngine& engine(getRenderEngine()); mat4 colorMatrix = mColorMatrix; + if (mHasSecondaryColorMatrix) { + colorMatrix = mHasColorMatrix ? (colorMatrix * mSecondaryColorMatrix) : mSecondaryColorMatrix; + } if (mDaltonize) { colorMatrix = colorMatrix * mDaltonizer(); } @@ -1954,7 +2029,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView - drawWormhole(hw, region); + drawWormHoleIfRequired(cur, end, hw, region); } } @@ -2096,6 +2171,8 @@ void SurfaceFlinger::setTransactionState( uint32_t flags) { ATRACE_CALL(); + + delayDPTransactionIfNeeded(displays); Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; @@ -2241,6 +2318,41 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & layer_state_t::eBlurChanged) { + ALOGV("eBlurChanged"); + if (layer->setBlur(uint8_t(255.0f*s.blur+0.5f))) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskSurfaceChanged) { + ALOGV("eBlurMaskSurfaceChanged"); + sp<Layer> maskLayer = 0; + if (s.blurMaskSurface != 0) { + maskLayer = client->getLayerUser(s.blurMaskSurface); + } + if (maskLayer == 0) { + ALOGV("eBlurMaskSurfaceChanged. maskLayer == 0"); + } else { + ALOGV("eBlurMaskSurfaceChagned. maskLayer.z == %d", maskLayer->getCurrentState().z); + if (maskLayer->isBlurLayer()) { + ALOGE("Blur layer can not be used as blur mask surface"); + maskLayer = 0; + } + } + if (layer->setBlurMaskLayer(maskLayer)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskSamplingChanged) { + if (layer->setBlurMaskSampling(s.blurMaskSampling)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eBlurMaskAlphaThresholdChanged) { + if (layer->setBlurMaskAlphaThreshold(s.blurMaskAlphaThreshold)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eSizeChanged) { if (layer->setSize(s.w, s.h)) { flags |= eTraversalNeeded; @@ -2309,6 +2421,11 @@ status_t SurfaceFlinger::createLayer( name, w, h, flags, handle, gbp, &layer); break; + case ISurfaceComposerClient::eFXSurfaceBlur: + result = createBlurLayer(client, + name, w, h, flags, + handle, gbp, &layer); + break; default: result = BAD_VALUE; break; @@ -2342,7 +2459,7 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); + *outLayer = DisplayUtils::getInstance()->getLayerInstance(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = (*outLayer)->getHandle(); @@ -2363,6 +2480,16 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, return NO_ERROR; } +status_t SurfaceFlinger::createBlurLayer(const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) +{ + *outLayer = new LayerBlur(this, client, name, w, h, flags); + *handle = (*outLayer)->getHandle(); + *gbp = (*outLayer)->getProducer(); + return NO_ERROR; +} + status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle) { // called by the window manager when it wants to remove a Layer @@ -2605,14 +2732,19 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index if (name.isEmpty()) { mAnimFrameTracker.dumpStats(result); } else { + bool found = false; const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { const sp<Layer>& layer(currentLayers[i]); if (name == layer->getName()) { + found = true; layer->dumpFrameStats(result); } } + if (!found && !strncmp(name.string(), "SurfaceView", 11)) { + lastSurfaceViewLayer->dumpFrameStats(result); + } } } @@ -2820,7 +2952,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.appendFormat(" h/w composer %s and %s\n", hwc.initCheck()==NO_ERROR ? "present" : "not present", (mDebugDisableHWC || mDebugRegion || mDaltonize - || mHasColorMatrix) ? "disabled" : "enabled"); + || mHasColorMatrix + || mHasSecondaryColorMatrix) ? "disabled" : "enabled"); hwc.dump(result); /* @@ -2841,7 +2974,7 @@ SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { } } if (dpy == NULL) { - ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); + ALOGW("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); // Just use the primary display so we have something to return dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); } @@ -3020,14 +3153,38 @@ status_t SurfaceFlinger::onTransact( } case 1018: { // Modify Choreographer's phase offset n = data.readInt32(); - mEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); + if (mEventThread != NULL) + mEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); return NO_ERROR; } case 1019: { // Modify SurfaceFlinger's phase offset n = data.readInt32(); - mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); + if (mSFEventThread != NULL) + mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n)); return NO_ERROR; } + case 1030: { + // apply a secondary color matrix + // this will be combined with any other transformations + n = data.readInt32(); + mHasSecondaryColorMatrix = n ? 1 : 0; + if (n) { + // color matrix is sent as mat3 matrix followed by vec3 + // offset, then packed into a mat4 where the last row is + // the offset and extra values are 0 + for (size_t i = 0 ; i < 4; i++) { + for (size_t j = 0; j < 4; j++) { + mSecondaryColorMatrix[i][j] = data.readFloat(); + } + } + } else { + mSecondaryColorMatrix = mat4(); + } + invalidateHwcGeometry(); + repaintEverything(); + return NO_ERROR; + } + } } return err; @@ -3155,7 +3312,8 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + bool useIdentityTransform, ISurfaceComposer::Rotation rotation, + bool useReadPixels) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; @@ -3205,6 +3363,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, uint32_t minLayerZ,maxLayerZ; bool useIdentityTransform; Transform::orientation_flags rotation; + bool useReadPixels; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, @@ -3212,12 +3371,14 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) : flinger(flinger), display(display), producer(producer), sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), useIdentityTransform(useIdentityTransform), rotation(rotation), + useReadPixels(useReadPixels), result(PERMISSION_DENIED) { } @@ -3227,9 +3388,10 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); + bool useReadPixels = this->useReadPixels && !flinger->mGpuToCpuSupported; result = flinger->captureScreenImplLocked(hw, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotation); + useIdentityTransform, rotation, useReadPixels); static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result); return true; } @@ -3252,7 +3414,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<MessageBase> msg = new MessageCaptureScreen(this, display, IGraphicBufferProducer::asInterface( wrapper ), sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotationFlags); + useIdentityTransform, rotationFlags, useReadPixels); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3301,6 +3463,12 @@ void SurfaceFlinger::renderScreenImplLocked( // make sure to clear all GL error flags engine.checkErrors(); + if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType() && + hw->isPanelInverseMounted()) { + rotation = (Transform::orientation_flags) + (rotation ^ Transform::ROT_180); + } + // set-up our viewport engine.setViewportAndProjection( reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); @@ -3316,7 +3484,7 @@ void SurfaceFlinger::renderScreenImplLocked( const Layer::State& state(layer->getDrawingState()); if (state.layerStack == hw->getLayerStack()) { if (state.z >= minLayerZ && state.z <= maxLayerZ) { - if (layer->isVisible()) { + if (canDrawLayerinScreenShot(hw,layer)) { if (filtering) layer->setFiltering(true); layer->draw(hw, useIdentityTransform); if (filtering) layer->setFiltering(false); @@ -3336,7 +3504,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) { ATRACE_CALL(); @@ -3354,6 +3523,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( return BAD_VALUE; } + ++mActiveFrameSequence; + reqWidth = (!reqWidth) ? hw_w : reqWidth; reqHeight = (!reqHeight) ? hw_h : reqHeight; @@ -3388,7 +3559,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( if (image != EGL_NO_IMAGE_KHR) { // this binds the given EGLImage as a framebuffer for the // duration of this scope. - RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image); + RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image, + useReadPixels, reqWidth, reqHeight); if (imageBond.getStatus() == NO_ERROR) { // this will in fact render into our dequeued buffer // via an FBO, which means we didn't have to create @@ -3435,6 +3607,15 @@ status_t SurfaceFlinger::captureScreenImplLocked( ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError()); } } + if (useReadPixels) { + sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer); + void* vaddr; + if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) { + getRenderEngine().readPixels(0, 0, buffer->stride, reqHeight, + (uint32_t *)vaddr); + buf->unlock(); + } + } if (DEBUG_SCREENSHOTS) { uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); @@ -3492,6 +3673,44 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v } } +/* ------------------------------------------------------------------------ + * Extensions + */ + +bool SurfaceFlinger::updateLayerVisibleNonTransparentRegion(const int& /*dpy*/, + const sp<Layer>& layer, bool& /*bIgnoreLayers*/, int& /*indexLOI*/, + uint32_t layerStack, const int& /*i*/) { + + const Layer::State& s(layer->getDrawingState()); + + // only consider the layers on the given layer stack + if (s.layerStack != layerStack) { + /* set the visible region as empty since we have removed the + * layerstack check in rebuildLayerStack() function + */ + Region visibleNonTransRegion; + visibleNonTransRegion.set(Rect(0,0)); + layer->setVisibleNonTransparentRegion(visibleNonTransRegion); + + return true; + } + + return false; +} + +bool SurfaceFlinger::canDrawLayerinScreenShot( + const sp<const DisplayDevice>& /*hw*/, + const sp<Layer>& layer) { + return layer->isVisible(); +} + +void SurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& /*cur*/, + const HWComposer::LayerListIterator& /*end*/, + const sp<const DisplayDevice>& hw, + const Region& region) { + drawWormhole(hw, region); +} + // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b3baadd..20d65c1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -56,6 +56,8 @@ #include "DisplayHardware/HWComposer.h" #include "Effects/Daltonizer.h" +#include "FrameRateHelper.h" + namespace android { // --------------------------------------------------------------------------- @@ -66,6 +68,7 @@ class EventThread; class IGraphicBufferAlloc; class Layer; class LayerDim; +class LayerBlur; class Surface; class RenderEngine; class EventControlThread; @@ -84,6 +87,10 @@ class SurfaceFlinger : public BnSurfaceComposer, private HWComposer::EventHandler { public: +#ifdef QTI_BSP + friend class ExSurfaceFlinger; +#endif + static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } @@ -138,7 +145,9 @@ private: friend class Client; friend class DisplayEventConnection; friend class Layer; + friend class LayerDim; friend class MonitoredProducer; + friend class LayerBlur; // This value is specified in number of frames. Log frame stats at most // every half hour. @@ -207,7 +216,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + bool useIdentityTransform, ISurfaceComposer::Rotation rotation, + bool isCpuConsumer); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp<IBinder>& display, @@ -235,6 +245,43 @@ private: virtual void onHotplugReceived(int disp, bool connected); /* ------------------------------------------------------------------------ + * Extensions + */ + virtual void updateExtendedMode() { } + + virtual void getIndexLOI(size_t /*dpy*/, + const LayerVector& /*currentLayers*/, + bool& /*bIgnoreLayers*/, + int& /*indexLOI*/) { } + + virtual bool updateLayerVisibleNonTransparentRegion( + const int& dpy, const sp<Layer>& layer, + bool& bIgnoreLayers, int& indexLOI, + uint32_t layerStack, const int& i); + + virtual void delayDPTransactionIfNeeded( + const Vector<DisplayState>& /*displays*/) { } + + virtual bool canDrawLayerinScreenShot( + const sp<const DisplayDevice>& hw, + const sp<Layer>& layer); + + virtual void isfreezeSurfacePresent( + bool& freezeSurfacePresent, + const sp<const DisplayDevice>& /*hw*/, + const int32_t& /*id*/) { freezeSurfacePresent = false; } + + virtual void setOrientationEventControl( + bool& /*freezeSurfacePresent*/, + const int32_t& /*id*/) { } + + virtual void updateVisibleRegionsDirty() { } + + virtual void drawWormHoleIfRequired(HWComposer::LayerListIterator &cur, + const HWComposer::LayerListIterator &end, + const sp<const DisplayDevice>& hw, + const Region& region); + /* ------------------------------------------------------------------------ * Message handling */ void waitForEvent(); @@ -294,6 +341,10 @@ private: uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer); + status_t createBlurLayer(const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle, + sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer); + // called in response to the window-manager calling // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle); @@ -329,7 +380,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation); + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels); /* ------------------------------------------------------------------------ * EGL @@ -373,7 +425,7 @@ private: * Compositing */ void invalidateHwcGeometry(); - static void computeVisibleRegions( + void computeVisibleRegions(size_t dpy, const LayerVector& currentLayers, uint32_t layerStack, Region& dirtyRegion, Region& opaqueRegion); @@ -419,6 +471,7 @@ private: void logFrameStats(); void dumpStaticScreenStats(String8& result) const; + virtual void dumpDrawCycle(bool /* prePrepare */ ) { } /* ------------------------------------------------------------------------ * Attributes @@ -500,12 +553,26 @@ private: mat4 mColorMatrix; bool mHasColorMatrix; + mat4 mSecondaryColorMatrix; + bool mHasSecondaryColorMatrix; + // Static screen stats bool mHasPoweredOff; static const size_t NUM_BUCKETS = 8; // < 1-7, 7+ nsecs_t mFrameBuckets[NUM_BUCKETS]; nsecs_t mTotalTime; nsecs_t mLastSwapTime; + + FrameRateHelper mFrameRateHelper; + + /* + * A number that increases on every new frame composition and screen capture. + * LayerBlur can speed up it's drawing by caching texture using this variable + * if multiple LayerBlur objects draw in one frame composition. + * In case of display mirroring, this variable should be increased on every display. + */ + uint32_t mActiveFrameSequence; + }; }; // namespace android diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index a74bc4c..e8464a3 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -22,6 +22,7 @@ #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include "SurfaceFlinger.h" +#include "DisplayUtils.h" using namespace android; @@ -35,12 +36,19 @@ int main(int, char**) { ps->startThreadPool(); // instantiate surfaceflinger - sp<SurfaceFlinger> flinger = new SurfaceFlinger(); + sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance(); setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); +#ifdef ENABLE_CPUSETS + // Put most SurfaceFlinger threads in the system-background cpuset + // Keeps us from unnecessarily using big cores + // Do this after the binder thread pool init + set_cpuset_policy(0, SP_SYSTEM); +#endif + // initialize before clients can connect flinger->init(); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index dcde512..2ef2a50 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -249,4 +249,50 @@ TEST_F(LayerUpdateTest, LayerResizeWorks) { } } +// Ensure that if we move and resize a surface in the same +// transaction, we don't reposition the surface and draw +// using the incorrect buffer size +TEST_F(LayerUpdateTest, LayerMoveAndResizeWorks) { + sp<ScreenCapture> sc; + { + SCOPED_TRACE("before resize and reposition"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel( 0, 12, 63, 63, 195); + sc->checkPixel( 75, 75, 195, 63, 63); + sc->checkPixel(145, 145, 63, 63, 195); + } + + ALOGD("resizing and repositioning"); + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 0)); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(64, 128)); + SurfaceComposerClient::closeGlobalTransaction(true); + + ALOGD("resized and repositioned"); + { + // This should not reflect the new size, position or color because SurfaceFlinger + // has not yet received a buffer of the correct size. + SCOPED_TRACE("after resize, before redraw"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel( 0, 12, 63, 63, 195); + sc->checkPixel( 75, 75, 195, 63, 63); + sc->checkPixel(145, 145, 63, 63, 195); + } + + ALOGD("drawing"); + fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63); + waitForPostedBuffers(); + ALOGD("drawn"); + { + // This should reflect the new size, position and the new color. + SCOPED_TRACE("after redraw"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel( 64, 0, 63, 195, 63); + // This should pass to imply that we didn't have a frame where the + // surface was moved but not yet resized even though the operations + // were part of the same transaction + sc->checkPixel( 64, 75, 63, 195, 63); + sc->checkPixel(145, 145, 63, 63, 195); + } +} } |