summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/phone-hdpi-2048-dalvik-heap.mk25
-rw-r--r--build/phone-xhdpi-1024-dalvik-heap.mk2
-rw-r--r--build/phone-xxhdpi-2048-dalvik-heap.mk26
-rw-r--r--build/phone-xxhdpi-2048-hwui-memory.mk30
-rw-r--r--build/phone-xxhdpi-3072-dalvik-heap.mk25
-rw-r--r--build/phone-xxhdpi-3072-hwui-memory.mk30
-rw-r--r--build/phone-xxxhdpi-3072-dalvik-heap.mk25
-rw-r--r--build/phone-xxxhdpi-3072-hwui-memory.mk30
-rw-r--r--build/phone-xxxhdpi-4096-dalvik-heap.mk25
-rw-r--r--build/phone-xxxhdpi-4096-hwui-memory.mk30
-rw-r--r--cmds/atrace/atrace.cpp1
-rw-r--r--cmds/dumpstate/dumpstate.c20
-rw-r--r--cmds/installd/commands.cpp248
-rw-r--r--cmds/installd/installd.cpp22
-rw-r--r--cmds/installd/installd.h10
-rw-r--r--cmds/installd/utils.cpp2
-rw-r--r--data/etc/android.hardware.sensor.ambient_temperature.xml36
-rw-r--r--data/etc/android.hardware.sensor.relative_humidity.xml36
-rw-r--r--include/android/input.h2
-rw-r--r--include/android/keycodes.h17
-rw-r--r--include/batteryservice/BatteryService.h11
-rw-r--r--include/batteryservice/IBatteryPropertiesRegistrar.h3
-rw-r--r--include/binder/AppOpsManager.h14
-rw-r--r--include/binder/IMemory.h7
-rw-r--r--include/binder/MemoryHeapIon.h68
-rw-r--r--include/binder/Parcel.h2
-rw-r--r--include/gui/ISurfaceComposer.h8
-rw-r--r--include/gui/ISurfaceComposerClient.h1
-rw-r--r--include/gui/SurfaceComposerClient.h5
-rw-r--r--include/gui/SurfaceControl.h5
-rw-r--r--include/input/InputEventLabels.h10
-rw-r--r--include/media/openmax/OMX_Core.h6
-rw-r--r--include/media/openmax/OMX_VideoExt.h9
-rw-r--r--include/private/gui/LayerState.h12
-rw-r--r--include/ui/GraphicBufferMapper.h4
-rw-r--r--libs/binder/Android.mk43
-rw-r--r--libs/binder/IMemory.cpp29
-rw-r--r--libs/binder/MemoryHeapIon.cpp191
-rw-r--r--libs/binder/Parcel.cpp34
-rw-r--r--libs/gui/Android.mk4
-rw-r--r--libs/gui/BufferQueueProducer.cpp18
-rw-r--r--libs/gui/ISurfaceComposer.cpp8
-rw-r--r--libs/gui/LayerState.cpp8
-rw-r--r--libs/gui/Sensor.cpp6
-rw-r--r--libs/gui/Surface.cpp23
-rw-r--r--libs/gui/SurfaceComposerClient.cpp79
-rw-r--r--libs/gui/SurfaceControl.cpp20
-rw-r--r--libs/ui/Android.mk4
-rw-r--r--libs/ui/GraphicBuffer.cpp5
-rw-r--r--libs/ui/GraphicBufferMapper.cpp13
-rw-r--r--opengl/libs/Android.mk10
-rw-r--r--opengl/libs/EGL/eglApi.cpp18
-rw-r--r--services/batteryservice/BatteryProperties.cpp34
-rw-r--r--services/batteryservice/IBatteryPropertiesRegistrar.cpp28
-rw-r--r--services/inputflinger/InputManager.cpp10
-rw-r--r--services/inputflinger/InputReader.cpp66
-rw-r--r--services/inputflinger/InputReader.h33
-rw-r--r--services/sensorservice/SensorService.cpp33
-rw-r--r--services/surfaceflinger/Android.mk36
-rw-r--r--services/surfaceflinger/CleanSpec.mk51
-rw-r--r--services/surfaceflinger/DispSync.cpp2
-rw-r--r--services/surfaceflinger/DispSync.h7
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp52
-rw-r--r--services/surfaceflinger/DisplayDevice.h8
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp1
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp80
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h20
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp18
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h5
-rw-r--r--services/surfaceflinger/DisplayUtils.cpp192
-rw-r--r--services/surfaceflinger/DisplayUtils.h79
-rw-r--r--services/surfaceflinger/EventThread.cpp2
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp77
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h57
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp207
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExLayer.h68
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp376
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h100
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.cpp93
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExVirtualDisplaySurface.h55
-rw-r--r--services/surfaceflinger/FrameRateHelper.h69
-rw-r--r--services/surfaceflinger/Layer.cpp129
-rw-r--r--services/surfaceflinger/Layer.h51
-rw-r--r--services/surfaceflinger/LayerBlur.cpp418
-rw-r--r--services/surfaceflinger/LayerBlur.h106
-rw-r--r--services/surfaceflinger/LayerDim.cpp11
-rw-r--r--services/surfaceflinger/LayerDim.h4
-rw-r--r--services/surfaceflinger/RenderEngine/Description.cpp11
-rw-r--r--services/surfaceflinger/RenderEngine/Description.h5
-rw-r--r--services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp63
-rw-r--r--services/surfaceflinger/RenderEngine/GLES11RenderEngine.h7
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp70
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.h15
-rw-r--r--services/surfaceflinger/RenderEngine/Program.cpp8
-rw-r--r--services/surfaceflinger/RenderEngine/Program.h3
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.cpp53
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.h11
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.cpp9
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.h18
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp305
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h73
-rw-r--r--services/surfaceflinger/main_surfaceflinger.cpp10
-rw-r--r--services/surfaceflinger/tests/Transaction_test.cpp46
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);
+ }
+}
}