diff options
72 files changed, 1265 insertions, 383 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index 3c79ae9..220af47 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -43,6 +43,8 @@ static const char *dump_traces_path = NULL; static char screenshot_path[PATH_MAX] = ""; +#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" + /* dumps the current system state to stdout */ static void dumpstate() { time_t now = time(NULL); @@ -161,8 +163,14 @@ static void dumpstate() { dump_file("NETWORK ROUTES", "/proc/net/route"); dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route"); - /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ - dump_file("LAST KMSG", "/proc/last_kmsg"); + if (!stat(PSTORE_LAST_KMSG, &st)) { + /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */ + dump_file("LAST KMSG", PSTORE_LAST_KMSG); + } else { + /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ + dump_file("LAST KMSG", "/proc/last_kmsg"); + } + dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console"); dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads"); @@ -321,7 +329,7 @@ static void usage() { " -e: play sound file instead of vibrate, at end of job\n" " -q: disable vibrate\n" " -B: send broadcast when finished (requires -o and -p)\n" - ); + ); } static void sigpipe_handler(int n) { diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index fe716ac..dbf0877 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -548,7 +548,7 @@ const char *dump_traces() { /* wait for the writable-close notification from inotify */ struct pollfd pfd = { ifd, POLLIN, 0 }; - int ret = poll(&pfd, 1, 200); /* 200 msec timeout */ + int ret = poll(&pfd, 1, 5000); /* 5 sec timeout */ if (ret < 0) { fprintf(stderr, "poll: %s\n", strerror(errno)); } else if (ret == 0) { diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 84ad204..e9d6b15 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -184,7 +184,7 @@ int delete_user_data(const char *pkgname, userid_t userid) return delete_dir_contents(pkgdir, 0, "lib"); } -int make_user_data(const char *pkgname, uid_t uid, userid_t userid) +int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) { char pkgdir[PKG_PATH_MAX]; char applibdir[PKG_PATH_MAX]; @@ -245,7 +245,7 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid) return -1; } - if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { + if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 1904408..0c80dac 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -16,6 +16,8 @@ #include <sys/capability.h> #include <linux/prctl.h> +#include <selinux/android.h> +#include <selinux/avc.h> #include "installd.h" @@ -103,7 +105,8 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) static int do_mk_user_data(char **arg, char reply[REPLY_MAX]) { - return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */ + return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); + /* pkgname, uid, userid, seinfo */ } static int do_rm_user(char **arg, char reply[REPLY_MAX]) @@ -142,7 +145,7 @@ struct cmdinfo cmds[] = { { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 3, do_linklib }, - { "mkuserdata", 3, do_mk_user_data }, + { "mkuserdata", 4, do_mk_user_data }, { "rmuser", 1, do_rm_user }, }; @@ -389,6 +392,10 @@ int initialize_directories() { goto fail; } + if (selinux_android_restorecon(android_media_dir.path)) { + goto fail; + } + // /data/media/0 char owner_media_dir[PATH_MAX]; snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path); @@ -525,6 +532,7 @@ int main(const int argc, const char *argv[]) { struct sockaddr addr; socklen_t alen; int lsocket, s, count; + int selinux_enabled = (is_selinux_enabled() > 0); ALOGI("installd firing up\n"); @@ -538,6 +546,11 @@ int main(const int argc, const char *argv[]) { exit(1); } + if (selinux_enabled && selinux_status_open(true) < 0) { + ALOGE("Could not open selinux status; exiting.\n"); + exit(1); + } + drop_privileges(); lsocket = android_get_control_socket(SOCKET_PATH); @@ -576,6 +589,9 @@ int main(const int argc, const char *argv[]) { break; } buf[count] = 0; + if (selinux_enabled && selinux_status_updated() > 0) { + selinux_android_seapp_context_reload(); + } if (execute(s, buf)) break; } ALOGI("closing connection\n"); diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 635b07c..9ca2f86 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -194,7 +194,7 @@ int uninstall(const char *pkgname, userid_t userid); int renamepkg(const char *oldpkgname, const char *newpkgname); int fix_uid(const char *pkgname, uid_t uid, gid_t gid); int delete_user_data(const char *pkgname, userid_t userid); -int make_user_data(const char *pkgname, uid_t uid, userid_t userid); +int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo); int delete_user(userid_t userid); int delete_cache(const char *pkgname, userid_t userid); int move_dex(const char *src, const char *dst); diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk index 0afb2c5..1ee7807 100644 --- a/cmds/screenshot/Android.mk +++ b/cmds/screenshot/Android.mk @@ -7,6 +7,6 @@ LOCAL_MODULE := screenshot LOCAL_SHARED_LIBRARIES := libcutils libz liblog LOCAL_STATIC_LIBRARIES := libpng -LOCAL_C_INCLUDES += external/zlib +LOCAL_C_INCLUDES += external/zlib external/libpng include $(BUILD_EXECUTABLE) diff --git a/cmds/screenshot/screenshot.c b/cmds/screenshot/screenshot.c index cca80c3..be1ecd4 100644 --- a/cmds/screenshot/screenshot.c +++ b/cmds/screenshot/screenshot.c @@ -8,7 +8,7 @@ #include <linux/fb.h> #include <zlib.h> -#include <libpng/png.h> +#include <png.h> #include "private/android_filesystem_config.h" diff --git a/data/etc/android.hardware.camera.external.xml b/data/etc/android.hardware.camera.external.xml new file mode 100644 index 0000000..a138bcd --- /dev/null +++ b/data/etc/android.hardware.camera.external.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- This is the standard set of features for a Android device that can support +an external camera being connected to it. --> +<permissions> + <feature name="android.hardware.camera.any" /> + <feature name="android.hardware.camera.external" /> +</permissions> diff --git a/data/etc/android.hardware.screen.landscape.xml b/data/etc/android.hardware.screen.landscape.xml new file mode 100644 index 0000000..07bcd0a --- /dev/null +++ b/data/etc/android.hardware.screen.landscape.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Standard feature indicating that the device supports landscape mode. --> +<permissions> + <feature name="android.hardware.screen.landscape" /> +</permissions> diff --git a/data/etc/android.hardware.screen.portrait.xml b/data/etc/android.hardware.screen.portrait.xml new file mode 100644 index 0000000..530c6c6 --- /dev/null +++ b/data/etc/android.hardware.screen.portrait.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Standard feature indicating that the device supports portrait mode. --> +<permissions> + <feature name="android.hardware.screen.portrait" /> +</permissions> diff --git a/data/etc/android.hardware.sensor.heartrate.xml b/data/etc/android.hardware.sensor.heartrate.xml new file mode 100644 index 0000000..c49bfc0 --- /dev/null +++ b/data/etc/android.hardware.sensor.heartrate.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Feature for devices with a hardware heart rate monitor. --> +<permissions> + <feature name="android.hardware.sensor.heartrate" /> +</permissions> diff --git a/data/etc/android.software.app_widgets.xml b/data/etc/android.software.app_widgets.xml new file mode 100644 index 0000000..9a51b24 --- /dev/null +++ b/data/etc/android.software.app_widgets.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<permissions> + <feature name="android.software.app_widgets" /> +</permissions> diff --git a/data/etc/android.software.backup.xml b/data/etc/android.software.backup.xml new file mode 100644 index 0000000..1ab4603 --- /dev/null +++ b/data/etc/android.software.backup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<permissions> + <feature name="android.software.backup" /> +</permissions> diff --git a/data/etc/android.software.device_admin.xml b/data/etc/android.software.device_admin.xml new file mode 100644 index 0000000..7d14dc6 --- /dev/null +++ b/data/etc/android.software.device_admin.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<permissions> + <feature name="android.software.device_admin" /> +</permissions> diff --git a/data/etc/android.software.print.xml b/data/etc/android.software.print.xml new file mode 100644 index 0000000..713a7f7 --- /dev/null +++ b/data/etc/android.software.print.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<permissions> + <feature name="android.software.print" /> +</permissions> diff --git a/data/etc/android.software.webview.xml b/data/etc/android.software.webview.xml new file mode 100644 index 0000000..d843209 --- /dev/null +++ b/data/etc/android.software.webview.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<permissions> + <feature name="android.software.webview" /> +</permissions> diff --git a/data/etc/com.google.android.hardware.sensor.heartrate.ecg.xml b/data/etc/com.google.android.hardware.sensor.heartrate.ecg.xml new file mode 100644 index 0000000..a4c6176 --- /dev/null +++ b/data/etc/com.google.android.hardware.sensor.heartrate.ecg.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Feature for devices with a hardware electrocardiography(ECG) sensor. --> +<permissions> + <feature name="com.google.android.hardware.sensor.heartrate.ecg" /> +</permissions> diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml index 4a9f2dd..4d81fb6 100644 --- a/data/etc/handheld_core_hardware.xml +++ b/data/etc/handheld_core_hardware.xml @@ -33,11 +33,17 @@ <feature name="android.hardware.microphone" /> <feature name="android.hardware.screen.portrait" /> <feature name="android.hardware.screen.landscape" /> + + <!-- basic system services --> <feature name="android.software.app_widgets" /> + <feature name="android.software.backup" /> <feature name="android.software.home_screen" /> <feature name="android.software.input_methods" /> + <feature name="android.software.print" /> + <!-- Feature to specify if the device supports adding device admins. --> <feature name="android.software.device_admin" /> + <!-- devices with GPS must include android.hardware.location.gps.xml --> <!-- devices with an autofocus camera and/or flash must include either android.hardware.camera.autofocus.xml or diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml index 78b9736..2a74b0f 100644 --- a/data/etc/tablet_core_hardware.xml +++ b/data/etc/tablet_core_hardware.xml @@ -34,11 +34,17 @@ <feature name="android.hardware.microphone" /> <feature name="android.hardware.screen.portrait" /> <feature name="android.hardware.screen.landscape" /> + + <!-- basic system services --> <feature name="android.software.app_widgets" /> + <feature name="android.software.backup" /> <feature name="android.software.home_screen" /> <feature name="android.software.input_methods" /> + <feature name="android.software.print" /> + <!-- Feature to specify if the device supports adding device admins. --> <feature name="android.software.device_admin" /> + <!-- devices with GPS must include android.hardware.location.gps.xml --> <!-- devices with a rear-facing camera must include one of these as appropriate: android.hardware.camera.xml or diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml new file mode 100644 index 0000000..ae1d73a --- /dev/null +++ b/data/etc/wearable_core_hardware.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- These are the hardware and software components that all wearable devices + must include. Devices with optional hardware/software must also include + extra hardware/software files, per the comments below. + + Wearable devices include watches, glasses, backpacks, and sweaters. +--> +<permissions> + <feature name="android.hardware.location" /> + <feature name="android.hardware.sensor.compass" /> + <feature name="android.hardware.sensor.accelerometer" /> + <feature name="android.hardware.bluetooth" /> + <feature name="android.hardware.touchscreen" /> + <feature name="android.hardware.microphone" /> + + <!-- basic system services --> + <feature name="android.software.home_screen" /> + + <!-- devices that support a device administrator policy must include + android.software.device_admin.xml --> + <!-- devices with GPS must include device/google/clockwork/gps.xml --> + <!-- devices with an autofocus camera and/or flash must include either + android.hardware.camera.autofocus.xml or + android.hardware.camera.autofocus-flash.xml --> + <!-- devices with a front facing camera must include + android.hardware.camera.front.xml --> + <!-- devices with WiFi must also include android.hardware.wifi.xml --> + <!-- devices that support multitouch must include the most appropriate one + of these files: + + If only partial (non-independent) pointers are supported: + android.hardware.touchscreen.multitouch.xml + + If up to 4 independently tracked pointers are supported: + include android.hardware.touchscreen.multitouch.distinct.xml + + If 5 or more independently tracked pointers are supported: + include android.hardware.touchscreen.multitouch.jazzhand.xml + + ONLY ONE of the above should be included. --> + <!-- devices with an ambient light sensor must also include + android.hardware.sensor.light.xml --> + <!-- devices with a proximity sensor must also include + android.hardware.sensor.proximity.xml --> + <!-- Devices that have low-latency audio stacks suitable for apps like + VoIP may include android.hardware.audio.low_latency.xml. ONLY apps + that meet the requirements specified in the CDD may include this. --> +</permissions> diff --git a/include/android/configuration.h b/include/android/configuration.h index 6d8784d..97d4c42 100644 --- a/include/android/configuration.h +++ b/include/android/configuration.h @@ -83,6 +83,7 @@ enum { ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03, ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04, ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05, + ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06, ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00, ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1, diff --git a/include/android/keycodes.h b/include/android/keycodes.h index 1ca1332..b6a5f4c 100644 --- a/include/android/keycodes.h +++ b/include/android/keycodes.h @@ -266,6 +266,8 @@ enum { AKEYCODE_BRIGHTNESS_DOWN = 220, AKEYCODE_BRIGHTNESS_UP = 221, AKEYCODE_MEDIA_AUDIO_TRACK = 222, + AKEYCODE_SLEEP = 223, + AKEYCODE_WAKEUP = 224, // 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/android/looper.h b/include/android/looper.h index 24e3967..74c0383 100644 --- a/include/android/looper.h +++ b/include/android/looper.h @@ -253,4 +253,4 @@ int ALooper_removeFd(ALooper* looper, int fd); }; #endif -#endif // ANDROID_NATIVE_WINDOW_H +#endif // ANDROID_LOOPER_H diff --git a/include/android/sensor.h b/include/android/sensor.h index 129ea3e..b71bccb 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -66,6 +66,7 @@ enum { * Sensor accuracy measure */ enum { + ASENSOR_STATUS_NO_CONTACT = -1, ASENSOR_STATUS_UNRELIABLE = 0, ASENSOR_STATUS_ACCURACY_LOW = 1, ASENSOR_STATUS_ACCURACY_MEDIUM = 2, @@ -130,6 +131,11 @@ typedef struct AUncalibratedEvent { }; } AUncalibratedEvent; +typedef struct AHeartRateEvent { + float bpm; + int8_t status; +} AHeartRateEvent; + /* NOTE: Must match hardware/sensors.h */ typedef struct ASensorEvent { int32_t version; /* sizeof(struct ASensorEvent) */ @@ -151,6 +157,7 @@ typedef struct ASensorEvent { AUncalibratedEvent uncalibrated_gyro; AUncalibratedEvent uncalibrated_magnetic; AMetaDataEvent meta_data; + AHeartRateEvent heart_rate; }; union { uint64_t data[8]; @@ -281,6 +288,21 @@ float ASensor_getResolution(ASensor const* sensor); */ int ASensor_getMinDelay(ASensor const* sensor); +/* + * Returns the maximum size of batches for this sensor. Batches will often be + * smaller, as the hardware fifo might be used for other sensors. + */ +int ASensor_getFifoMaxEventCount(ASensor const* sensor); + +/* + * Returns the hardware batch fifo size reserved to this sensor. + */ +int ASensor_getFifoReservedEventCount(ASensor const* sensor); + +/* + * Returns this sensor's string type. + */ +const char* ASensor_getStringType(ASensor const* sensor); #ifdef __cplusplus }; diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index 0c81426..033b262 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -69,6 +69,8 @@ public: int32_t getVersion() const; int32_t getFifoReservedEventCount() const; int32_t getFifoMaxEventCount() const; + const String8& getStringType() const; + const String8& getRequiredPermission() const; // LightFlattenable protocol inline bool isFixedSize() const { return false; } @@ -89,6 +91,10 @@ private: int32_t mVersion; int32_t mFifoReservedEventCount; int32_t mFifoMaxEventCount; + String8 mStringType; + String8 mRequiredPermission; + static void flattenString8(void*& buffer, size_t& size, const String8& string8); + static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8); }; // ---------------------------------------------------------------------------- diff --git a/include/input/Input.h b/include/input/Input.h index 44e4027..235813e 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -22,11 +22,12 @@ */ #include <android/input.h> -#include <utils/Vector.h> +#include <utils/BitSet.h> #include <utils/KeyedVector.h> -#include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> +#include <utils/Timers.h> +#include <utils/Vector.h> #include <stdint.h> /* @@ -66,6 +67,34 @@ enum { AINPUT_SOURCE_SWITCH = 0x80000000, }; +enum { + /** + * Constants for LEDs. Hidden from the API since we don't actually expose a way to interact + * with LEDs to developers + * + * NOTE: If you add LEDs here, you must also add them to KeycodeLabels.h + */ + + ALED_NUM_LOCK = 0x00, + ALED_CAPS_LOCK = 0x01, + ALED_SCROLL_LOCK = 0x02, + ALED_COMPOSE = 0x03, + ALED_KANA = 0x04, + ALED_SLEEP = 0x05, + ALED_SUSPEND = 0x06, + ALED_MUTE = 0x07, + ALED_MISC = 0x08, + ALED_MAIL = 0x09, + ALED_CHARGING = 0x0a, + ALED_CONTROLLER_1 = 0x10, + ALED_CONTROLLER_2 = 0x11, + ALED_CONTROLLER_3 = 0x12, + ALED_CONTROLLER_4 = 0x13, +}; + +/* Maximum number of controller LEDs we support */ +#define MAX_CONTROLLER_LEDS 4 + /* * SystemUiVisibility constants from View. */ @@ -155,13 +184,9 @@ enum { /* These flags are set by the input reader policy as it intercepts each event. */ - // Indicates that the screen was off when the event was received and the event - // should wake the device. - POLICY_FLAG_WOKE_HERE = 0x10000000, - - // Indicates that the screen was dim when the event was received and the event - // should brighten the device. - POLICY_FLAG_BRIGHT_HERE = 0x20000000, + // Indicates that the device was in an interactive state when the + // event was intercepted. + POLICY_FLAG_INTERACTIVE = 0x20000000, // Indicates that the event should be dispatched to applications. // The input event should still be sent to the InputDispatcher so that it can see all @@ -183,13 +208,18 @@ struct PointerCoords { float values[MAX_AXES]; inline void clear() { - bits = 0; + BitSet64::clear(bits); + } + + bool isEmpty() const { + return BitSet64::isEmpty(bits); } float getAxisValue(int32_t axis) const; status_t setAxisValue(int32_t axis, float value); void scale(float scale); + void applyOffset(float xOffset, float yOffset); inline float getX() const { return getAxisValue(AMOTION_EVENT_AXIS_X); diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 1419b45..adf9fb9 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -46,6 +46,11 @@ struct InputDeviceIdentifier { // Ideally, the way this value is computed should not change between Android releases // because that would invalidate persistent settings that rely on it. String8 descriptor; + + // A value added to uniquely identify a device in the absence of a unique id. This + // is intended to be a minimum way to distinguish from other active devices and may + // reuse values that are not associated with an input anymore. + uint16_t nonce; }; /* diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h index eec11cf..1e8de71 100644 --- a/include/input/KeyLayoutMap.h +++ b/include/input/KeyLayoutMap.h @@ -67,6 +67,8 @@ public: status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode, uint32_t* outFlags) const; status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const; + status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const; + status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const; status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; @@ -79,9 +81,16 @@ private: uint32_t flags; }; + struct Led { + int32_t ledCode; + }; + + KeyedVector<int32_t, Key> mKeysByScanCode; KeyedVector<int32_t, Key> mKeysByUsageCode; KeyedVector<int32_t, AxisInfo> mAxes; + KeyedVector<int32_t, Led> mLedsByScanCode; + KeyedVector<int32_t, Led> mLedsByUsageCode; KeyLayoutMap(); @@ -99,6 +108,7 @@ private: private: status_t parseKey(); status_t parseAxis(); + status_t parseLed(); }; }; diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h index 846cb0c..25b2f07 100644 --- a/include/input/Keyboard.h +++ b/include/input/Keyboard.h @@ -94,18 +94,24 @@ extern int32_t getKeyCodeByLabel(const char* label); extern uint32_t getKeyFlagByLabel(const char* label); /** - * Gets a axis by its short form label, eg. "X". + * Gets an axis by its short form label, eg. "X". * Returns -1 if unknown. */ extern int32_t getAxisByLabel(const char* label); /** - * Gets a axis label by its id. + * Gets an axis label by its id. * Returns NULL if unknown. */ extern const char* getAxisLabel(int32_t axisId); /** + * Gets an LED by its short form label, eg. "CAPS_LOCK". + * Returns -1 if unknown. + */ +extern int32_t getLedByLabel(const char* label); + +/** * Updates a meta state field when a key is pressed or released. */ extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState); diff --git a/include/input/KeycodeLabels.h b/include/input/KeycodeLabels.h index c64c5d8..a8d63da 100644 --- a/include/input/KeycodeLabels.h +++ b/include/input/KeycodeLabels.h @@ -247,6 +247,8 @@ static const KeycodeLabel KEYCODES[] = { { "BRIGHTNESS_DOWN", 220 }, { "BRIGHTNESS_UP", 221 }, { "MEDIA_AUDIO_TRACK", 222 }, + { "SLEEP", 223 }, + { "WAKEUP", 224 }, // 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. @@ -319,4 +321,26 @@ static const KeycodeLabel AXES[] = { { NULL, -1 } }; +static const KeycodeLabel LEDS[] = { + { "NUM_LOCK", 0x00 }, + { "CAPS_LOCK", 0x01 }, + { "SCROLL_LOCK", 0x02 }, + { "COMPOSE", 0x03 }, + { "KANA", 0x04 }, + { "SLEEP", 0x05 }, + { "SUSPEND", 0x06 }, + { "MUTE", 0x07 }, + { "MISC", 0x08 }, + { "MAIL", 0x09 }, + { "CHARGING", 0x0a }, + { "CONTROLLER_1", 0x10 }, + { "CONTROLLER_2", 0x11 }, + { "CONTROLLER_3", 0x12 }, + { "CONTROLLER_4", 0x13 }, + + // NOTE: If you add new LEDs here, you must also add them to Input.h + + { NULL, -1 } +}; + #endif // _LIBINPUT_KEYCODE_LABELS_H diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h index 95bdf77..fc6b49c 100644 --- a/include/media/drm/DrmAPI.h +++ b/include/media/drm/DrmAPI.h @@ -178,12 +178,16 @@ namespace android { // provisioning server. // // If successful, the opaque provision request blob is returned to the caller. - virtual status_t getProvisionRequest(Vector<uint8_t> &request, + virtual status_t getProvisionRequest(String8 const &cert_type, + String8 const &cert_authority, + Vector<uint8_t> &request, String8 &defaultUrl) = 0; // After a provision response is received by the app, it is provided to the // Drm plugin using provideProvisionResponse. - virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) = 0; + virtual status_t provideProvisionResponse(Vector<uint8_t> const &response, + Vector<uint8_t> &certificate, + Vector<uint8_t> &wrapped_key) = 0; // A means of enforcing the contractual requirement for a concurrent stream // limit per subscriber across devices is provided via SecureStop. SecureStop @@ -290,6 +294,15 @@ namespace android { bool &match) = 0; + // Compute an RSA signature on the provided message using the algorithm + // specified by algorithm. + virtual status_t signRSA(Vector<uint8_t> const &sessionId, + String8 const &algorithm, + Vector<uint8_t> const &message, + Vector<uint8_t> const &wrapped_key, + Vector<uint8_t> &signature) = 0; + + status_t setListener(const sp<DrmPluginListener>& listener) { Mutex::Autolock lock(mEventLock); mListener = listener; diff --git a/include/media/openmax/OMX_AudioExt.h b/include/media/openmax/OMX_AudioExt.h new file mode 100644 index 0000000..aa6e6d0 --- /dev/null +++ b/include/media/openmax/OMX_AudioExt.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_AudioExt.h - OpenMax IL version 1.1.2 + * The OMX_AudioExt header file contains extensions to the + * definitions used by both the application and the component to + * access video items. + */ + +#ifndef OMX_AudioExt_h +#define OMX_AudioExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include <OMX_Core.h> + +typedef enum OMX_AUDIO_CODINGEXTTYPE { + OMX_AUDIO_CodingAndroidUnused = OMX_AUDIO_CodingKhronosExtensions + 0x00100000, + OMX_AUDIO_CodingAndroidAC3, /**< AC3 encoded data */ +} OMX_AUDIO_CODINGEXTTYPE; + +typedef struct OMX_AUDIO_PARAM_ANDROID_AC3TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ +} OMX_AUDIO_PARAM_ANDROID_AC3TYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_AudioExt_h */ +/* File EOF */ diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h index d22df56..c47a885 100644 --- a/include/media/openmax/OMX_IndexExt.h +++ b/include/media/openmax/OMX_IndexExt.h @@ -57,6 +57,7 @@ typedef enum OMX_INDEXEXTTYPE { /* Audio parameters and configurations */ OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000, + OMX_IndexParamAudioAndroidAc3, /**< reference: OMX_AUDIO_PARAM_ANDROID_AC3TYPE */ /* Image parameters and configurations */ OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000, diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index bf4bf03..5584fb1 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -30,11 +30,15 @@ namespace android { class Parcel; class ISurfaceComposerClient; +/* + * Used to communicate layer information between SurfaceFlinger and its clients. + */ struct layer_state_t { enum { - eLayerHidden = 0x01, + eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java + eLayerOpaque = 0x02, // SURFACE_OPAQUE }; enum { @@ -47,6 +51,7 @@ struct layer_state_t { eVisibilityChanged = 0x00000040, eLayerStackChanged = 0x00000080, eCropChanged = 0x00000100, + eOpacityChanged = 0x00000200, }; layer_state_t() diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp index d1cbf1c..43a01e4 100644 --- a/libs/binder/MemoryHeapBase.cpp +++ b/libs/binder/MemoryHeapBase.cpp @@ -31,11 +31,6 @@ #include <binder/MemoryHeapBase.h> -#ifdef HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - - namespace android { // --------------------------------------------------------------------------- @@ -108,18 +103,9 @@ status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset) { if (size == 0) { // try to figure out the size automatically -#ifdef HAVE_ANDROID_OS - // first try the PMEM ioctl - pmem_region reg; - int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®); - if (err == 0) - size = reg.len; -#endif - if (size == 0) { // try fstat - struct stat sb; - if (fstat(fd, &sb) == 0) - size = sb.st_size; - } + struct stat sb; + if (fstat(fd, &sb) == 0) + size = sb.st_size; // if it didn't work, let mmap() fail. } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 7ee3081..3215b2f 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -350,20 +350,24 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) { status_t err = NO_ERROR; + int buf = item.mBuf; + if (!mAttached) { ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " "ES context"); + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return INVALID_OPERATION; } // Confirm state. err = checkAndUpdateEglStateLocked(); if (err != NO_ERROR) { + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return err; } - int buf = item.mBuf; - // If the mEglSlot entry is empty, create an EGLImage for the gralloc // buffer currently in the slot in ConsumerBase. // @@ -377,6 +381,12 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) if (image == EGL_NO_IMAGE_KHR) { ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, buf); + const sp<GraphicBuffer>& gb = mSlots[buf].mGraphicBuffer; + ST_LOGW("buffer size=%ux%u st=%u usage=0x%x fmt=%d", + gb->getWidth(), gb->getHeight(), gb->getStride(), + gb->getUsage(), gb->getPixelFormat()); + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return UNKNOWN_ERROR; } mEglSlots[buf].mEglImage = image; diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index e713c04..3171b65 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -60,7 +60,11 @@ public: bool nonNull = reply.readInt32(); if (nonNull) { *buf = new GraphicBuffer(); - reply.read(**buf); + result = reply.read(**buf); + if(result != NO_ERROR) { + (*buf).clear(); + return result; + } } result = reply.readInt32(); return result; diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index da6b0f9..8f63870 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -48,6 +48,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mResolution = hwSensor->resolution; mPower = hwSensor->power; mMinDelay = hwSensor->minDelay; + // Set fifo event count zero for older devices which do not support batching. Fused // sensors also have their fifo counts set to zero. if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) { @@ -57,6 +58,84 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mFifoReservedEventCount = 0; mFifoMaxEventCount = 0; } + + // Ensure existing sensors have correct string type and required + // permissions. + switch (mType) { + case SENSOR_TYPE_ACCELEROMETER: + mStringType = SENSOR_STRING_TYPE_ACCELEROMETER; + break; + case SENSOR_TYPE_AMBIENT_TEMPERATURE: + mStringType = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE; + break; + case SENSOR_TYPE_GAME_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR; + break; + case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR; + break; + case SENSOR_TYPE_GRAVITY: + mStringType = SENSOR_STRING_TYPE_GRAVITY; + break; + case SENSOR_TYPE_GYROSCOPE: + mStringType = SENSOR_STRING_TYPE_GYROSCOPE; + break; + case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED; + break; + case SENSOR_TYPE_HEART_RATE: + mStringType = SENSOR_STRING_TYPE_HEART_RATE; + mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS; + break; + case SENSOR_TYPE_LIGHT: + mStringType = SENSOR_STRING_TYPE_LIGHT; + break; + case SENSOR_TYPE_LINEAR_ACCELERATION: + mStringType = SENSOR_STRING_TYPE_LINEAR_ACCELERATION; + break; + case SENSOR_TYPE_MAGNETIC_FIELD: + mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD; + break; + case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED; + break; + case SENSOR_TYPE_ORIENTATION: + mStringType = SENSOR_STRING_TYPE_ORIENTATION; + break; + case SENSOR_TYPE_PRESSURE: + mStringType = SENSOR_STRING_TYPE_PRESSURE; + break; + case SENSOR_TYPE_PROXIMITY: + mStringType = SENSOR_STRING_TYPE_PROXIMITY; + break; + case SENSOR_TYPE_RELATIVE_HUMIDITY: + mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY; + break; + case SENSOR_TYPE_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_ROTATION_VECTOR; + break; + case SENSOR_TYPE_SIGNIFICANT_MOTION: + mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION; + break; + case SENSOR_TYPE_STEP_COUNTER: + mStringType = SENSOR_STRING_TYPE_STEP_COUNTER; + break; + case SENSOR_TYPE_STEP_DETECTOR: + mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR; + break; + case SENSOR_TYPE_TEMPERATURE: + mStringType = SENSOR_STRING_TYPE_TEMPERATURE; + break; + default: + // Only pipe the stringType and requiredPermission for custom sensors. + if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) { + mStringType = hwSensor->stringType; + } + if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) { + mRequiredPermission = hwSensor->requiredPermission; + } + break; + } } Sensor::~Sensor() @@ -115,6 +194,14 @@ int32_t Sensor::getFifoMaxEventCount() const { return mFifoMaxEventCount; } +const String8& Sensor::getStringType() const { + return mStringType; +} + +const String8& Sensor::getRequiredPermission() const { + return mRequiredPermission; +} + size_t Sensor::getFlattenedSize() const { size_t fixedSize = @@ -123,8 +210,10 @@ size_t Sensor::getFlattenedSize() const sizeof(int32_t) * 3; size_t variableSize = - sizeof(int32_t) + FlattenableUtils::align<4>(mName.length()) + - sizeof(int32_t) + FlattenableUtils::align<4>(mVendor.length()); + sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mVendor.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mStringType.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mRequiredPermission.length()); return fixedSize + variableSize; } @@ -134,14 +223,8 @@ status_t Sensor::flatten(void* buffer, size_t size) const { return NO_MEMORY; } - FlattenableUtils::write(buffer, size, mName.length()); - memcpy(static_cast<char*>(buffer), mName.string(), mName.length()); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mName.length())); - - FlattenableUtils::write(buffer, size, mVendor.length()); - memcpy(static_cast<char*>(buffer), mVendor.string(), mVendor.length()); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mVendor.length())); - + flattenString8(buffer, size, mName); + flattenString8(buffer, size, mVendor); FlattenableUtils::write(buffer, size, mVersion); FlattenableUtils::write(buffer, size, mHandle); FlattenableUtils::write(buffer, size, mType); @@ -152,38 +235,23 @@ status_t Sensor::flatten(void* buffer, size_t size) const { FlattenableUtils::write(buffer, size, mMinDelay); FlattenableUtils::write(buffer, size, mFifoReservedEventCount); FlattenableUtils::write(buffer, size, mFifoMaxEventCount); + flattenString8(buffer, size, mStringType); + flattenString8(buffer, size, mRequiredPermission); return NO_ERROR; } status_t Sensor::unflatten(void const* buffer, size_t size) { - size_t len; - - if (size < sizeof(size_t)) { - return NO_MEMORY; - } - FlattenableUtils::read(buffer, size, len); - if (size < len) { - return NO_MEMORY; - } - mName.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); - - - if (size < sizeof(size_t)) { + if (!unflattenString8(buffer, size, mName)) { return NO_MEMORY; } - FlattenableUtils::read(buffer, size, len); - if (size < len) { + if (!unflattenString8(buffer, size, mVendor)) { return NO_MEMORY; } - mVendor.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); size_t fixedSize = sizeof(int32_t) * 3 + sizeof(float) * 4 + sizeof(int32_t) * 3; - if (size < fixedSize) { return NO_MEMORY; } @@ -198,8 +266,37 @@ status_t Sensor::unflatten(void const* buffer, size_t size) { FlattenableUtils::read(buffer, size, mMinDelay); FlattenableUtils::read(buffer, size, mFifoReservedEventCount); FlattenableUtils::read(buffer, size, mFifoMaxEventCount); + + if (!unflattenString8(buffer, size, mStringType)) { + return NO_MEMORY; + } + if (!unflattenString8(buffer, size, mRequiredPermission)) { + return NO_MEMORY; + } return NO_ERROR; } +void Sensor::flattenString8(void*& buffer, size_t& size, + const String8& string8) { + uint32_t len = string8.length(); + FlattenableUtils::write(buffer, size, len); + memcpy(static_cast<char*>(buffer), string8.string(), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); +} + +bool Sensor::unflattenString8(void const*& buffer, size_t& size, String8& outputString8) { + uint32_t len; + if (size < sizeof(len)) { + return false; + } + FlattenableUtils::read(buffer, size, len); + if (size < len) { + return false; + } + outputString8.setTo(static_cast<char const*>(buffer), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); + return true; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index aafc4d2..2246f5f 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -309,7 +309,12 @@ status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= layer_state_t::eVisibilityChanged; + if (mask & layer_state_t::eLayerOpaque) { + s->what |= layer_state_t::eOpacityChanged; + } + if (mask & layer_state_t::eLayerHidden) { + s->what |= layer_state_t::eVisibilityChanged; + } s->flags &= ~mask; s->flags |= (flags & mask); s->mask |= mask; diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index 05b0b67..e4fba15 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -35,7 +35,6 @@ #include <GLES2/gl2ext.h> #include <ui/FramebufferNativeWindow.h> -#include <utils/UniquePtr.h> #include <android/native_window.h> namespace android { diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 83e241c..71b25b7 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -158,16 +158,10 @@ void KeyEvent::initialize(const KeyEvent& from) { // --- PointerCoords --- float PointerCoords::getAxisValue(int32_t axis) const { - if (axis < 0 || axis > 63) { - return 0; - } - - uint64_t axisBit = 1LL << axis; - if (!(bits & axisBit)) { + if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){ return 0; } - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - return values[index]; + return values[BitSet64::getIndexOfBit(bits, axis)]; } status_t PointerCoords::setAxisValue(int32_t axis, float value) { @@ -175,22 +169,23 @@ status_t PointerCoords::setAxisValue(int32_t axis, float value) { return NAME_NOT_FOUND; } - uint64_t axisBit = 1LL << axis; - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - if (!(bits & axisBit)) { + uint32_t index = BitSet64::getIndexOfBit(bits, axis); + if (!BitSet64::hasBit(bits, axis)) { if (value == 0) { return OK; // axes with value 0 do not need to be stored } - uint32_t count = __builtin_popcountll(bits); + + uint32_t count = BitSet64::count(bits); if (count >= MAX_AXES) { tooManyAxes(axis); return NO_MEMORY; } - bits |= axisBit; + BitSet64::markBit(bits, axis); for (uint32_t i = count; i > index; i--) { values[i] = values[i - 1]; } } + values[index] = value; return OK; } @@ -213,11 +208,16 @@ void PointerCoords::scale(float scaleFactor) { scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); } +void PointerCoords::applyOffset(float xOffset, float yOffset) { + setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset); + setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset); +} + #ifdef HAVE_ANDROID_OS status_t PointerCoords::readFromParcel(Parcel* parcel) { bits = parcel->readInt64(); - uint32_t count = __builtin_popcountll(bits); + uint32_t count = BitSet64::count(bits); if (count > MAX_AXES) { return BAD_VALUE; } @@ -231,7 +231,7 @@ status_t PointerCoords::readFromParcel(Parcel* parcel) { status_t PointerCoords::writeToParcel(Parcel* parcel) const { parcel->writeInt64(bits); - uint32_t count = __builtin_popcountll(bits); + uint32_t count = BitSet64::count(bits); for (uint32_t i = 0; i < count; i++) { parcel->writeFloat(values[i]); } @@ -248,7 +248,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const { if (bits != other.bits) { return false; } - uint32_t count = __builtin_popcountll(bits); + uint32_t count = BitSet64::count(bits); for (uint32_t i = 0; i < count; i++) { if (values[i] != other.values[i]) { return false; @@ -259,7 +259,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const { void PointerCoords::copyFrom(const PointerCoords& other) { bits = other.bits; - uint32_t count = __builtin_popcountll(bits); + uint32_t count = BitSet64::count(bits); for (uint32_t i = 0; i < count; i++) { values[i] = other.values[i]; } diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index 2f5494b..0800a31 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -150,6 +150,40 @@ status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { return NO_ERROR; } +status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const { + const size_t N = mLedsByScanCode.size(); + for (size_t i = 0; i < N; i++) { + if (mLedsByScanCode.valueAt(i).ledCode == ledCode) { + *outScanCode = mLedsByScanCode.keyAt(i); +#if DEBUG_MAPPING + ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode); +#endif + return NO_ERROR; + } + } +#if DEBUG_MAPPING + ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode); +#endif + return NAME_NOT_FOUND; +} + +status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const { + const size_t N = mLedsByUsageCode.size(); + for (size_t i = 0; i < N; i++) { + if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) { + *outUsageCode = mLedsByUsageCode.keyAt(i); +#if DEBUG_MAPPING + ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode); +#endif + return NO_ERROR; + } + } +#if DEBUG_MAPPING + ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode); +#endif + return NAME_NOT_FOUND; +} + // --- KeyLayoutMap::Parser --- @@ -179,6 +213,10 @@ status_t KeyLayoutMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseAxis(); if (status) return status; + } else if (keywordToken == "led") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseLed(); + if (status) return status; } else { ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), keywordToken.string()); @@ -215,8 +253,7 @@ status_t KeyLayoutMap::Parser::parseKey() { mapUsage ? "usage" : "scan code", codeToken.string()); return BAD_VALUE; } - KeyedVector<int32_t, Key>& map = - mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; + KeyedVector<int32_t, Key>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; if (map.indexOfKey(code) >= 0) { ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), mapUsage ? "usage" : "scan code", codeToken.string()); @@ -364,4 +401,46 @@ status_t KeyLayoutMap::Parser::parseAxis() { return NO_ERROR; } +status_t KeyLayoutMap::Parser::parseLed() { + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + bool mapUsage = false; + if (codeToken == "usage") { + mapUsage = true; + mTokenizer->skipDelimiters(WHITESPACE); + codeToken = mTokenizer->nextToken(WHITESPACE); + } + char* end; + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); + if (*end) { + ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); + return BAD_VALUE; + } + + KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode; + if (map.indexOfKey(code) >= 0) { + ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE); + int32_t ledCode = getLedByLabel(ledCodeToken.string()); + if (ledCode < 0) { + ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(), + ledCodeToken.string()); + return BAD_VALUE; + } + +#if DEBUG_PARSER + ALOGD("Parsed led %s: code=%d, ledCode=%d.", + mapUsage ? "usage" : "scan code", code, ledCode); +#endif + + Led led; + led.ledCode = ledCode; + map.add(code, led); + return NO_ERROR; +} }; diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp index b6551ee..7d4ac92 100644 --- a/libs/input/Keyboard.cpp +++ b/libs/input/Keyboard.cpp @@ -203,6 +203,10 @@ const char* getAxisLabel(int32_t axisId) { return lookupLabelByValue(axisId, AXES); } +int32_t getLedByLabel(const char* label) { + return int32_t(lookupValueByLabel(label, LEDS)); +} + static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { int32_t newMetaState; if (down) { diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 8c325fd..6c8272d 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -301,6 +301,8 @@ status_t GraphicBuffer::unflatten( if (handle != 0) { status_t err = mBufferMapper.registerBuffer(handle); if (err != NO_ERROR) { + width = height = stride = format = usage = 0; + handle = NULL; ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err); return err; diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 9886bf0..95a8ef2 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -44,7 +44,7 @@ endif # we need to access the private Bionic header <bionic_tls.h> LOCAL_C_INCLUDES += bionic/libc/private -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl +LOCAL_MODULE_RELATIVE_PATH := egl LOCAL_MODULE:= libGLES_android include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libagl/Tokenizer.cpp b/opengl/libagl/Tokenizer.cpp index eac8d6d..ac0a48c 100644 --- a/opengl/libagl/Tokenizer.cpp +++ b/opengl/libagl/Tokenizer.cpp @@ -163,9 +163,9 @@ void Tokenizer::dump() const { const run_t* ranges = mRanges.array(); const size_t c = mRanges.size(); - ALOGD("Tokenizer (%p, size = %u)\n", this, c); + ALOGD("Tokenizer (%p, size = %zu)\n", this, c); for (size_t i=0 ; i<c ; i++) { - ALOGD("%u: (%u, %u)\n", i, ranges[i].first, ranges[i].length); + ALOGD("%zu: (%u, %u)\n", i, ranges[i].first, ranges[i].length); } } diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h index 7065a30..c599a55 100644 --- a/opengl/libagl/context.h +++ b/opengl/libagl/context.h @@ -147,7 +147,11 @@ struct vertex_t { vec4_t color; vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; +#ifdef __LP64__ + uint32_t reserved1[2]; +#else uint32_t reserved1[4]; +#endif inline void clear() { flags = index = locked = mru = 0; @@ -578,10 +582,10 @@ private: #ifdef HAVE_ANDROID_OS // We have a dedicated TLS slot in bionic inline void setGlThreadSpecific(ogles_context_t *value) { - ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value; + __get_tls()[TLS_SLOT_OPENGL] = value; } inline ogles_context_t* getGlThreadSpecific() { - return (ogles_context_t *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]); + return static_cast<ogles_context_t*>(__get_tls()[TLS_SLOT_OPENGL]); } #else extern pthread_key_t gGLKey; diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index bbbda76..f925e7d 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -78,20 +78,20 @@ static T setError(GLint error, T returnValue) { pthread_key_create(&gEGLErrorKey, NULL); pthread_mutex_unlock(&gErrorKeyMutex); } - pthread_setspecific(gEGLErrorKey, (void*)error); + pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)error); return returnValue; } static GLint getError() { if (ggl_unlikely(gEGLErrorKey == -1)) return EGL_SUCCESS; - GLint error = (GLint)pthread_getspecific(gEGLErrorKey); + GLint error = (GLint)(uintptr_t)pthread_getspecific(gEGLErrorKey); if (error == 0) { // The TLS key has been created by another thread, but the value for // this thread has not been initialized. return EGL_SUCCESS; } - pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); + pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)EGL_SUCCESS); return error; } @@ -1201,7 +1201,7 @@ static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) { size_t numConfigs = NELEM(gConfigs); - int index = (int)config; + int index = (int)(uintptr_t)config; if (uint32_t(index) >= numConfigs) return setError(EGL_BAD_CONFIG, EGL_FALSE); @@ -1448,7 +1448,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, } GLint i; for (i=0 ; i<numConfigs && i<config_size ; i++) { - *configs++ = (EGLConfig)i; + *configs++ = (EGLConfig)(uintptr_t)i; } *num_config = i; return EGL_TRUE; @@ -1519,7 +1519,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, if (configs) { for (int i=0 ; config_size && i<numConfigs ; i++) { if (possibleMatch & (1<<i)) { - *configs++ = (EGLConfig)i; + *configs++ = (EGLConfig)(uintptr_t)i; config_size--; n++; } diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index f759e6b..67fbae5 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -27,7 +27,6 @@ #include <cutils/log.h> #include <cutils/atomic.h> #include <cutils/properties.h> -#include <cutils/memory.h> #include <utils/CallStack.h> #include <utils/String8.h> @@ -42,6 +41,8 @@ #include "egl_display.h" #include "egl_object.h" +typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer; + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- @@ -234,11 +235,11 @@ static void early_egl_init(void) pthread_key_create(&gGLTraceKey, NULL); initEglTraceLevel(); #endif - uint32_t addr = (uint32_t)((void*)gl_no_context); - android_memset32( - (uint32_t*)(void*)&gHooksNoContext, - addr, - sizeof(gHooksNoContext)); + int numHooks = sizeof(gHooksNoContext) / sizeof(EGLFuncPointer); + EGLFuncPointer *iter = reinterpret_cast<EGLFuncPointer*>(&gHooksNoContext); + for (int hook = 0; hook < numHooks; ++hook) { + *(iter++) = reinterpret_cast<EGLFuncPointer>(gl_no_context); + } setGLHooksThreadSpecific(&gHooksNoContext); } diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 0cc5265..d96b54f 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -204,7 +204,7 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display) { clearError(); - uint32_t index = uint32_t(display); + uintptr_t index = reinterpret_cast<uintptr_t>(display); if (index >= NUM_DISPLAYS) { return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); } diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java index d5e2d34..b1bd1fd 100644 --- a/opengl/tools/glgen/src/JniCodeEmitter.java +++ b/opengl/tools/glgen/src/JniCodeEmitter.java @@ -1073,6 +1073,7 @@ public class JniCodeEmitter { String decl = type.getDeclaration(); needsExit = true; out.println(indent + "if (!" + cname + ") {"); + out.println(indent + indent + "_exception = 1;"); out.println(indent + indent + "_exceptionType = \"java/lang/IllegalArgumentException\";"); out.println(indent + indent + diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index f6705f6..ca2fdf6 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -205,7 +205,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) String8 result; if (!PermissionCache::checkCallingPermission(sDump)) { result.appendFormat("Permission Denial: " - "can't dump SurfaceFlinger from pid=%d, uid=%d\n", + "can't dump SensorService from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); } else { @@ -215,21 +215,24 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); result.appendFormat( - "%-48s| %-32s | 0x%08x | ", + "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t", s.getName().string(), s.getVendor().string(), - s.getHandle()); + s.getStringType().string(), + s.getHandle(), + s.getRequiredPermission().string()); if (s.getMinDelay() > 0) { result.appendFormat( - "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); + "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); } else { result.append(s.getMinDelay() == 0 ? "on-demand | " : "one-shot | "); } if (s.getFifoMaxEventCount() > 0) { - result.appendFormat("getFifoMaxEventCount=%d events | ", s.getFifoMaxEventCount()); + result.appendFormat("FifoMax=%d events | ", + s.getFifoMaxEventCount()); } else { result.append("no batching support | "); } @@ -490,10 +493,23 @@ Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); - if (atoi(value)) { - return mUserSensorListDebug; + const Vector<Sensor>& initialSensorList = (atoi(value)) ? + mUserSensorListDebug : mUserSensorList; + Vector<Sensor> accessibleSensorList; + for (size_t i = 0; i < initialSensorList.size(); i++) { + Sensor sensor = initialSensorList[i]; + if (canAccessSensor(sensor)) { + accessibleSensorList.add(sensor); + } else { + String8 infoMessage; + infoMessage.appendFormat( + "Skipped sensor %s because it requires permission %s", + sensor.getName().string(), + sensor.getRequiredPermission().string()); + ALOGI(infoMessage.string()); + } } - return mUserSensorList; + return accessibleSensorList; } sp<ISensorEventConnection> SensorService::createSensorEventConnection() @@ -539,6 +555,10 @@ void SensorService::cleanupConnection(SensorEventConnection* c) BatteryService::cleanup(c->getUid()); } +Sensor SensorService::getSensorFromHandle(int handle) const { + return mSensorMap.valueFor(handle)->getSensor(); +} + status_t SensorService::enable(const sp<SensorEventConnection>& connection, int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) { @@ -549,6 +569,11 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (sensor == NULL) { return BAD_VALUE; } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried enabling")) { + return BAD_VALUE; + } + Mutex::Autolock _l(mLock); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { @@ -670,6 +695,10 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection if (!sensor) return BAD_VALUE; + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried configuring")) { + return BAD_VALUE; + } + if (ns < 0) return BAD_VALUE; @@ -683,17 +712,44 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection, int handle) { - if (mInitCheck != NO_ERROR) return mInitCheck; - SensorInterface* sensor = mSensorMap.valueFor(handle); - if (sensor == NULL) { - return BAD_VALUE; - } - if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { - ALOGE("flush called on Significant Motion sensor"); - return INVALID_OPERATION; - } - return sensor->flush(connection.get(), handle); + if (mInitCheck != NO_ERROR) return mInitCheck; + SensorInterface* sensor = mSensorMap.valueFor(handle); + if (sensor == NULL) { + return BAD_VALUE; + } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried flushing")) { + return BAD_VALUE; + } + + if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { + ALOGE("flush called on Significant Motion sensor"); + return INVALID_OPERATION; + } + return sensor->flush(connection.get(), handle); +} + + +bool SensorService::canAccessSensor(const Sensor& sensor) { + String16 permissionString(sensor.getRequiredPermission()); + return permissionString.size() == 0 || + PermissionCache::checkCallingPermission(permissionString); } + +bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* operation) { + if (canAccessSensor(sensor)) { + return true; + } else { + String8 errorMessage; + errorMessage.appendFormat( + "%s a sensor (%s) without holding its required permission: %s", + operation, + sensor.getName().string(), + sensor.getRequiredPermission().string()); + return false; + } +} + // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( @@ -761,6 +817,9 @@ void SensorService::SensorEventConnection::dump(String8& result) { bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); + if (!verifyCanAccessSensor(mService->getSensorFromHandle(handle), "Tried adding")) { + return false; + } if (mSensorInfo.indexOfKey(handle) < 0) { mSensorInfo.add(handle, FlushInfo()); return true; diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 1dc2dd3..e88ffc8 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -131,6 +131,7 @@ class SensorService : String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; + Sensor getSensorFromHandle(int handle) const; void recordLastValue(const sensors_event_t* buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count); Sensor registerSensor(SensorInterface* sensor); @@ -141,7 +142,8 @@ class SensorService : const sp<SensorEventConnection>& connection, int handle); void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count); - + static bool canAccessSensor(const Sensor& sensor); + static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation); // constants Vector<Sensor> mSensorList; Vector<Sensor> mUserSensorListDebug; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index b2bc550..afa680f 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -37,9 +37,6 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -ifeq ($(TARGET_BOARD_PLATFORM),omap3) - LOCAL_CFLAGS += -DNO_RGBX_8888 -endif ifeq ($(TARGET_BOARD_PLATFORM),omap4) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY endif diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index ce07ab5..c51d207 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -20,6 +20,7 @@ #define __STDC_LIMIT_MACROS #include <math.h> +#include <inttypes.h> #include <cutils/log.h> @@ -487,4 +488,49 @@ void DispSync::resetErrorLocked() { } } +void DispSync::dump(String8& result) const { + Mutex::Autolock lock(mMutex); + result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod); + result.appendFormat("mPhase: %"PRId64" ns\n", mPhase); + result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", + mError, sqrt(mError)); + result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n", + mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT); + result.appendFormat("mNumResyncSamples: %d (max %d)\n", + mNumResyncSamples, MAX_RESYNC_SAMPLES); + + result.appendFormat("mResyncSamples:\n"); + nsecs_t previous = -1; + for (size_t i = 0; i < mNumResyncSamples; i++) { + size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; + nsecs_t sampleTime = mResyncSamples[idx]; + if (i == 0) { + result.appendFormat(" %"PRId64"\n", sampleTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64")\n", + sampleTime, sampleTime - previous); + } + previous = sampleTime; + } + + result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", + NUM_PRESENT_SAMPLES); + previous = 0; + for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { + size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; + bool signaled = mPresentFences[idx] == NULL; + nsecs_t presentTime = mPresentTimes[idx]; + if (!signaled) { + result.appendFormat(" [unsignaled fence]\n"); + } else if (previous == 0) { + result.appendFormat(" %"PRId64"\n", presentTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64" / %.3f)\n", + presentTime, presentTime - previous, + (presentTime - previous) / (double) mPeriod); + } + previous = presentTime; + } +} + } // namespace android diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index c4280aa..19eb3e5 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -99,6 +99,9 @@ public: // DispSync object. status_t removeEventListener(const sp<Callback>& callback); + // dump appends human-readable debug info to the result string. + void dump(String8& result) const; + private: void updateModelLocked(); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 800137b..88e0dd7 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -53,12 +53,14 @@ DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, int32_t hwcId, + int format, bool isSecure, const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer, EGLConfig config) - : mFlinger(flinger), + : lastCompositionHadVisibleLayers(false), + mFlinger(flinger), mType(type), mHwcDisplayId(hwcId), mDisplayToken(displayToken), mDisplaySurface(displaySurface), @@ -76,9 +78,6 @@ DisplayDevice::DisplayDevice( mNativeWindow = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); - int format; - window->query(window, NATIVE_WINDOW_FORMAT, &format); - // 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 // in two places: @@ -96,6 +95,9 @@ DisplayDevice::DisplayDevice( EGLSurface surface; EGLint w, h; 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); @@ -198,8 +200,8 @@ void DisplayDevice::flip(const Region& dirty) const mPageFlipCount++; } -status_t DisplayDevice::beginFrame() const { - return mDisplaySurface->beginFrame(); +status_t DisplayDevice::beginFrame(bool mustRecompose) const { + return mDisplaySurface->beginFrame(mustRecompose); } status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index c3abe89..620e598 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -53,6 +53,7 @@ public: mutable Region swapRegion; // region in screen space Region undefinedRegion; + bool lastCompositionHadVisibleLayers; enum DisplayType { DISPLAY_ID_INVALID = -1, @@ -75,6 +76,7 @@ public: const sp<SurfaceFlinger>& flinger, DisplayType type, int32_t hwcId, // negative for non-HWC-composited displays + int format, bool isSecure, const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, @@ -123,7 +125,9 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } - status_t beginFrame() const; + // 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; status_t prepareFrame(const HWComposer& hwc) const; void swapBuffers(HWComposer& hwc) const; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index 48bf3f2..1db3eb8 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -33,7 +33,9 @@ public: // beginFrame is called at the beginning of the composition loop, before // the configuration is known. The DisplaySurface should do anything it // needs to do to enable HWComposer to decide how to compose the frame. - virtual status_t beginFrame() = 0; + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state + // machine happy without actually queueing a buffer if nothing has changed. + virtual status_t beginFrame(bool mustRecompose) = 0; // prepareFrame is called after the composition configuration is known but // before composition takes place. The DisplaySurface can use the diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 8c634ed..0f34764 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -68,7 +68,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); } -status_t FramebufferSurface::beginFrame() { +status_t FramebufferSurface::beginFrame(bool mustRecompose) { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 1d67446..ba72ce3 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -39,7 +39,7 @@ class FramebufferSurface : public ConsumerBase, public: FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer); - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c7d1a90..1b652c3 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -455,7 +455,11 @@ uint32_t HWComposer::getHeight(int disp) const { } uint32_t HWComposer::getFormat(int disp) const { - return mDisplayData[disp].format; + if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) { + return HAL_PIXEL_FORMAT_RGBA_8888; + } else { + return mDisplayData[disp].format; + } } float HWComposer::getDpiX(int disp) const { @@ -1147,7 +1151,7 @@ bool HWComposer::VSyncThread::threadLoop() { } HWComposer::DisplayData::DisplayData() -: width(0), height(0), format(0), +: width(0), height(0), format(HAL_PIXEL_FORMAT_RGBA_8888), xdpi(0.0f), ydpi(0.0f), refresh(0), connected(false), diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index be5cf4a..a1820ab 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -56,7 +56,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), mProducerSlotSource(0), mDbgState(DBG_STATE_IDLE), - mDbgLastCompositionType(COMPOSITION_UNKNOWN) + mDbgLastCompositionType(COMPOSITION_UNKNOWN), + mMustRecompose(false) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bq; @@ -92,10 +93,12 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, VirtualDisplaySurface::~VirtualDisplaySurface() { } -status_t VirtualDisplaySurface::beginFrame() { +status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { if (mDisplayId < 0) return NO_ERROR; + mMustRecompose = mustRecompose; + VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, "Unexpected beginFrame() in %s state", dbgStateStr()); mDbgState = DBG_STATE_BEGUN; @@ -228,16 +231,24 @@ void VirtualDisplaySurface::onFrameCommitted() { QueueBufferOutput qbo; sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); - status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, - QueueBufferInput( - systemTime(), false /* isAutoTimestamp */, - Rect(mSinkBufferWidth, mSinkBufferHeight), - NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, - true /* async*/, - outFence), - &qbo); - if (result == NO_ERROR) { - updateQueueBufferOutput(qbo); + if (mMustRecompose) { + status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, + QueueBufferInput( + systemTime(), false /* isAutoTimestamp */, + Rect(mSinkBufferWidth, mSinkBufferHeight), + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, + true /* async*/, + outFence), + &qbo); + if (result == NO_ERROR) { + updateQueueBufferOutput(qbo); + } + } else { + // If the surface hadn't actually been updated, then we only went + // through the motions of updating the display to keep our state + // machine happy. We cancel the buffer to avoid triggering another + // re-composition and causing an infinite loop. + mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence); } } @@ -458,8 +469,10 @@ void VirtualDisplaySurface::resetPerFrameState() { mCompositionType = COMPOSITION_UNKNOWN; mSinkBufferWidth = 0; mSinkBufferHeight = 0; + mFbFence = Fence::NO_FENCE; mOutputFence = Fence::NO_FENCE; mOutputProducerSlot = -1; + mFbProducerSlot = -1; } status_t VirtualDisplaySurface::refreshOutputBuffer() { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 1e85ac4..6899904 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -79,7 +79,7 @@ public: // // DisplaySurface interface // - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); @@ -222,6 +222,8 @@ private: const char* dbgStateStr() const; static const char* dbgSourceStr(Source s); + + bool mMustRecompose; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 61af51f..fcc9d78 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -64,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mName("unnamed"), mDebug(false), mFormat(PIXEL_FORMAT_NONE), - mOpaqueLayer(true), mTransactionFlags(0), mQueuedFrames(0), mCurrentTransform(0), @@ -86,7 +85,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, uint32_t layerFlags = 0; if (flags & ISurfaceComposerClient::eHidden) - layerFlags = layer_state_t::eLayerHidden; + layerFlags |= layer_state_t::eLayerHidden; + if (flags & ISurfaceComposerClient::eOpaque) + layerFlags |= layer_state_t::eLayerOpaque; if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; @@ -189,7 +190,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); mCurrentOpacity = getOpacityForFormat(format); mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); @@ -352,7 +352,7 @@ void Layer::setGeometry( // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); - if (!isOpaque() || s.alpha != 0xFF) { + if (!isOpaque(s) || s.alpha != 0xFF) { layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); @@ -596,7 +596,7 @@ void Layer::drawWithOpenGL( texCoords[3] = vec2(right, 1.0f - top); RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); engine.drawMesh(mMesh); engine.disableBlending(); } @@ -656,7 +656,7 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh) const } } -bool Layer::isOpaque() const +bool Layer::isOpaque(const Layer::State& s) const { // if we don't have a buffer yet, we're translucent regardless of the // layer's opaque flag. @@ -666,7 +666,7 @@ bool Layer::isOpaque() const // if the layer has the opaque flag, then we're always opaque, // otherwise we use the current buffer's format. - return mOpaqueLayer || mCurrentOpacity; + return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; } bool Layer::isProtected() const @@ -954,7 +954,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } // Capture the old state of the layer for comparisons later - const bool oldOpacity = isOpaque(); + const State& s(getDrawingState()); + const bool oldOpacity = isOpaque(s); sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; struct Reject : public SurfaceFlingerConsumer::BufferRejecter { @@ -1122,12 +1123,11 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); - if (oldOpacity != isOpaque()) { + if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } // FIXME: postedRegion should be dirty & bounds - const Layer::State& s(getDrawingState()); Region dirtyRegion(Rect(s.active.w, s.active.h)); // transform the dirty region to window-manager space @@ -1188,7 +1188,7 @@ void Layer::dump(String8& result, Colorizer& colorizer) const 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(), contentDirty, + isOpaque(s), contentDirty, s.alpha, s.flags, s.transform[0][0], s.transform[0][1], s.transform[1][0], s.transform[1][1], diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ef4a7e9..ea65ded 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -149,8 +149,12 @@ public: /* * isOpaque - true if this surface is opaque + * + * This takes into account the buffer format (i.e. whether or not the + * pixel format includes an alpha channel) and the "opaque" flag set + * on the layer. It does not examine the current plane alpha value. */ - virtual bool isOpaque() const; + virtual bool isOpaque(const Layer::State& s) const; /* * isSecure - true if this surface is secure, that is if it prevents @@ -335,7 +339,6 @@ private: String8 mName; mutable bool mDebug; PixelFormat mFormat; - bool mOpaqueLayer; // these are protected by an external lock State mCurrentState; diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index c9c7b96..cc672b6 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -105,7 +105,7 @@ void MessageQueue::setEventThread(const sp<EventThread>& eventThread) mEventThread = eventThread; mEvents = eventThread->createEventConnection(); mEventTube = mEvents->getDataChannel(); - mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, + mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this); } @@ -114,12 +114,12 @@ void MessageQueue::waitMessage() { IPCThreadState::self()->flushCommands(); int32_t ret = mLooper->pollOnce(-1); switch (ret) { - case ALOOPER_POLL_WAKE: - case ALOOPER_POLL_CALLBACK: + case Looper::POLL_WAKE: + case Looper::POLL_CALLBACK: continue; - case ALOOPER_POLL_ERROR: - ALOGE("ALOOPER_POLL_ERROR"); - case ALOOPER_POLL_TIMEOUT: + case Looper::POLL_ERROR: + ALOGE("Looper::POLL_ERROR"); + case Looper::POLL_TIMEOUT: // timeout (should not happen) continue; default: diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index ba82cad..2871ce9 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -25,19 +25,51 @@ #include "GLExtensions.h" #include "Mesh.h" +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- -RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { - EGLint renderableType = 0; - EGLint contextClientVersion = 0; +static bool findExtension(const char* exts, const char* name) { + if (!exts) + return false; + size_t len = strlen(name); - // query the renderable type, setting the EGL_CONTEXT_CLIENT_VERSION accordingly - if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) { - LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + const char* pos = exts; + while ((pos = strstr(pos, name)) != NULL) { + if (pos[len] == '\0' || pos[len] == ' ') + return true; + pos += len; } + return false; +} + +RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { + // EGL_ANDROIDX_no_config_context is an experimental extension with no + // written specification. It will be replaced by something more formal. + // SurfaceFlinger is using it to allow a single EGLContext to render to + // both a 16-bit primary display framebuffer and a 32-bit virtual display + // framebuffer. + // + // The code assumes that ES2 or later is available if this extension is + // supported. + EGLConfig config = EGL_NO_CONFIG; + if (!findExtension( + eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS), + "EGL_ANDROIDX_no_config_context")) { + config = chooseEglConfig(display, hwcFormat); + } + + EGLint renderableType = 0; + if (config == EGL_NO_CONFIG) { + renderableType = EGL_OPENGL_ES2_BIT; + } else if (!eglGetConfigAttrib(display, config, + EGL_RENDERABLE_TYPE, &renderableType)) { + LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + } + EGLint contextClientVersion = 0; if (renderableType & EGL_OPENGL_ES2_BIT) { contextClientVersion = 2; } else if (renderableType & EGL_OPENGL_ES_BIT) { @@ -66,8 +98,12 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { // now figure out what version of GL did we actually get // NOTE: a dummy surface is not needed if KHR_create_context is supported + EGLConfig dummyConfig = config; + if (dummyConfig == EGL_NO_CONFIG) { + dummyConfig = chooseEglConfig(display, hwcFormat); + } EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; - EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs); + EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs); LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); @@ -96,7 +132,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { engine = new GLES20RenderEngine(); break; } - engine->setEGLContext(ctxt); + engine->setEGLHandles(config, ctxt); ALOGI("OpenGL ES informations:"); ALOGI("vendor : %s", extensions.getVendor()); @@ -118,10 +154,15 @@ RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) { RenderEngine::~RenderEngine() { } -void RenderEngine::setEGLContext(EGLContext ctxt) { +void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) { + mEGLConfig = config; mEGLContext = ctxt; } +EGLContext RenderEngine::getEGLConfig() const { + return mEGLConfig; +} + EGLContext RenderEngine::getEGLContext() const { return mEGLContext; } @@ -235,5 +276,163 @@ status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { } // --------------------------------------------------------------------------- + +static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, + EGLint attribute, EGLint wanted, EGLConfig* outConfig) { + EGLConfig config = NULL; + EGLint numConfigs = -1, n = 0; + eglGetConfigs(dpy, NULL, 0, &numConfigs); + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(dpy, attrs, configs, numConfigs, &n); + + if (n) { + if (attribute != EGL_NONE) { + for (int i=0 ; i<n ; i++) { + EGLint value = 0; + eglGetConfigAttrib(dpy, configs[i], attribute, &value); + if (wanted == value) { + *outConfig = configs[i]; + delete [] configs; + return NO_ERROR; + } + } + } else { + // just pick the first one + *outConfig = configs[0]; + delete [] configs; + return NO_ERROR; + } + } + delete [] configs; + return NAME_NOT_FOUND; +} + +class EGLAttributeVector { + struct Attribute; + class Adder; + friend class Adder; + KeyedVector<Attribute, EGLint> mList; + struct Attribute { + Attribute() {}; + Attribute(EGLint v) : v(v) { } + EGLint v; + bool operator < (const Attribute& other) const { + // this places EGL_NONE at the end + EGLint lhs(v); + EGLint rhs(other.v); + if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; + if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; + return lhs < rhs; + } + }; + class Adder { + friend class EGLAttributeVector; + EGLAttributeVector& v; + EGLint attribute; + Adder(EGLAttributeVector& v, EGLint attribute) + : v(v), attribute(attribute) { + } + public: + void operator = (EGLint value) { + if (attribute != EGL_NONE) { + v.mList.add(attribute, value); + } + } + operator EGLint () const { return v.mList[attribute]; } + }; +public: + EGLAttributeVector() { + mList.add(EGL_NONE, EGL_NONE); + } + void remove(EGLint attribute) { + if (attribute != EGL_NONE) { + mList.removeItem(attribute); + } + } + Adder operator [] (EGLint attribute) { + return Adder(*this, attribute); + } + EGLint operator [] (EGLint attribute) const { + return mList[attribute]; + } + // cast-operator to (EGLint const*) + operator EGLint const* () const { return &mList.keyAt(0).v; } +}; + + +static status_t selectEGLConfig(EGLDisplay display, EGLint format, + EGLint renderableType, EGLConfig* config) { + // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if + // it is to be used with WIFI displays + status_t err; + EGLint wantedAttribute; + EGLint wantedAttributeValue; + + EGLAttributeVector attribs; + if (renderableType) { + attribs[EGL_RENDERABLE_TYPE] = renderableType; + attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; + attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; + attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; + attribs[EGL_RED_SIZE] = 8; + attribs[EGL_GREEN_SIZE] = 8; + attribs[EGL_BLUE_SIZE] = 8; + wantedAttribute = EGL_NONE; + wantedAttributeValue = EGL_NONE; + } else { + // if no renderable type specified, fallback to a simplified query + wantedAttribute = EGL_NATIVE_VISUAL_ID; + wantedAttributeValue = format; + } + + err = selectConfigForAttribute(display, attribs, + wantedAttribute, wantedAttributeValue, config); + if (err == NO_ERROR) { + EGLint caveat; + if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) + ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); + } + + return err; +} + +EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) { + status_t err; + EGLConfig config; + + // First try to get an ES2 config + err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config); + if (err != NO_ERROR) { + // If ES2 fails, try ES1 + err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config); + if (err != NO_ERROR) { + // still didn't work, probably because we're on the emulator... + // try a simplified query + ALOGW("no suitable EGLConfig found, trying a simpler query"); + err = selectEGLConfig(display, format, 0, &config); + if (err != NO_ERROR) { + // this EGL is too lame for android + LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); + } + } + } + + // print some debugging info + EGLint r,g,b,a; + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); + ALOGI("EGL information:"); + ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); + ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); + ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); + ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); + ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); + + return config; +} + +// --------------------------------------------------------------------------- }; // namespace android // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 3c7f9ab..577dc0a 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -25,6 +25,8 @@ #include <EGL/eglext.h> #include <ui/mat4.h> +#define EGL_NO_CONFIG ((EGLConfig)0) + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- @@ -44,8 +46,9 @@ class RenderEngine { }; static GlesVersion parseGlesVersion(const char* str); + EGLConfig mEGLConfig; EGLContext mEGLContext; - void setEGLContext(EGLContext ctxt); + 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; @@ -55,7 +58,9 @@ protected: virtual ~RenderEngine() = 0; public: - static RenderEngine* create(EGLDisplay display, EGLConfig config); + static RenderEngine* create(EGLDisplay display, int hwcFormat); + + static EGLConfig chooseEglConfig(EGLDisplay display, int format); // dump the extension strings. always call the base class. virtual void dump(String8& result); @@ -107,6 +112,7 @@ public: virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; + EGLConfig getEGLConfig() const; EGLContext getEGLContext() const; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9d94c87..13a63c4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -318,128 +318,6 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture)); } -status_t SurfaceFlinger::selectConfigForAttribute( - EGLDisplay dpy, - EGLint const* attrs, - EGLint attribute, EGLint wanted, - EGLConfig* outConfig) -{ - EGLConfig config = NULL; - EGLint numConfigs = -1, n=0; - eglGetConfigs(dpy, NULL, 0, &numConfigs); - EGLConfig* const configs = new EGLConfig[numConfigs]; - eglChooseConfig(dpy, attrs, configs, numConfigs, &n); - - if (n) { - if (attribute != EGL_NONE) { - for (int i=0 ; i<n ; i++) { - EGLint value = 0; - eglGetConfigAttrib(dpy, configs[i], attribute, &value); - if (wanted == value) { - *outConfig = configs[i]; - delete [] configs; - return NO_ERROR; - } - } - } else { - // just pick the first one - *outConfig = configs[0]; - delete [] configs; - return NO_ERROR; - } - } - delete [] configs; - return NAME_NOT_FOUND; -} - -class EGLAttributeVector { - struct Attribute; - class Adder; - friend class Adder; - KeyedVector<Attribute, EGLint> mList; - struct Attribute { - Attribute() {}; - Attribute(EGLint v) : v(v) { } - EGLint v; - bool operator < (const Attribute& other) const { - // this places EGL_NONE at the end - EGLint lhs(v); - EGLint rhs(other.v); - if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; - if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; - return lhs < rhs; - } - }; - class Adder { - friend class EGLAttributeVector; - EGLAttributeVector& v; - EGLint attribute; - Adder(EGLAttributeVector& v, EGLint attribute) - : v(v), attribute(attribute) { - } - public: - void operator = (EGLint value) { - if (attribute != EGL_NONE) { - v.mList.add(attribute, value); - } - } - operator EGLint () const { return v.mList[attribute]; } - }; -public: - EGLAttributeVector() { - mList.add(EGL_NONE, EGL_NONE); - } - void remove(EGLint attribute) { - if (attribute != EGL_NONE) { - mList.removeItem(attribute); - } - } - Adder operator [] (EGLint attribute) { - return Adder(*this, attribute); - } - EGLint operator [] (EGLint attribute) const { - return mList[attribute]; - } - // cast-operator to (EGLint const*) - operator EGLint const* () const { return &mList.keyAt(0).v; } -}; - -status_t SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId, - EGLint renderableType, EGLConfig* config) { - // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if - // it is to be used with WIFI displays - status_t err; - EGLint wantedAttribute; - EGLint wantedAttributeValue; - - EGLAttributeVector attribs; - if (renderableType) { - attribs[EGL_RENDERABLE_TYPE] = renderableType; - attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; - attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; - attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; - attribs[EGL_RED_SIZE] = 8; - attribs[EGL_GREEN_SIZE] = 8; - attribs[EGL_BLUE_SIZE] = 8; - wantedAttribute = EGL_NONE; - wantedAttributeValue = EGL_NONE; - - } else { - // if no renderable type specified, fallback to a simplified query - wantedAttribute = EGL_NATIVE_VISUAL_ID; - wantedAttributeValue = nativeVisualId; - } - - err = selectConfigForAttribute(display, attribs, wantedAttribute, - wantedAttributeValue, config); - if (err == NO_ERROR) { - EGLint caveat; - if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) - ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); - } - return err; -} - class DispSyncSource : public VSyncSource, private DispSync::Callback { public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) : @@ -521,51 +399,12 @@ void SurfaceFlinger::init() { mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this)); - // First try to get an ES2 config - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT, - &mEGLConfig); - - if (err != NO_ERROR) { - // If ES2 fails, try ES1 - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), - EGL_OPENGL_ES_BIT, &mEGLConfig); - } - - if (err != NO_ERROR) { - // still didn't work, probably because we're on the emulator... - // try a simplified query - ALOGW("no suitable EGLConfig found, trying a simpler query"); - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig); - } - - if (err != NO_ERROR) { - // this EGL is too lame for android - LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); - } - - // print some debugging info - EGLint r,g,b,a; - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a); - ALOGI("EGL informations:"); - ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR)); - ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION)); - ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS)); - ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported"); - ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); - // get a RenderEngine for the given display / config (can't fail) - mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig); + mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID()); // retrieve the EGL context that was selected/created mEGLContext = mRenderEngine->getEGLContext(); - // figure out which format we got - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, - EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId); - LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, "couldn't create EGLContext"); @@ -581,10 +420,11 @@ void SurfaceFlinger::init() { sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc()); sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq); + int32_t hwcId = allocateHwcDisplayId(type); sp<DisplayDevice> hw = new DisplayDevice(this, - type, allocateHwcDisplayId(type), isSecure, token, + type, hwcId, mHwc->getFormat(hwcId), isSecure, token, fbs, bq, - mEGLConfig); + mRenderEngine->getEGLConfig()); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always @@ -1041,7 +881,32 @@ void SurfaceFlinger::rebuildLayerStacks() { void SurfaceFlinger::setUpHWComposer() { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - mDisplays[dpy]->beginFrame(); + bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty(); + bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0; + bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers; + + // If nothing has changed (!dirty), don't recompose. + // If something changed, but we don't currently have any visible layers, + // and didn't when we last did a composition, then skip it this time. + // The second rule does two things: + // - When all layers are removed from a display, we'll emit one black + // frame, then nothing more until we get new layers. + // - When a display is created with a private layer stack, we won't + // emit any black frames until a layer is added to the layer stack. + bool mustRecompose = dirty && !(empty && wasEmpty); + + ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL, + "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy, + mustRecompose ? "doing" : "skipping", + dirty ? "+" : "-", + empty ? "+" : "-", + wasEmpty ? "+" : "-"); + + mDisplays[dpy]->beginFrame(mustRecompose); + + if (mustRecompose) { + mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; + } } HWComposer& hwc(getHwComposer()); @@ -1346,8 +1211,10 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const wp<IBinder>& display(curr.keyAt(i)); if (dispSurface != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, - state.type, hwcDisplayId, state.isSecure, - display, dispSurface, producer, mEGLConfig); + state.type, hwcDisplayId, + mHwc->getFormat(hwcDisplayId), state.isSecure, + display, dispSurface, producer, + mRenderEngine->getEGLConfig()); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); @@ -1537,7 +1404,7 @@ void SurfaceFlinger::computeVisibleRegions( // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { - const bool translucent = !layer->isOpaque(); + const bool translucent = !layer->isOpaque(s); Rect bounds(s.transform.transform(layer->computeBounds())); visibleRegion.set(bounds); if (!visibleRegion.isEmpty()) { @@ -1657,6 +1524,15 @@ void SurfaceFlinger::invalidateHwcGeometry() void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, const Region& inDirtyRegion) { + // We only need to actually compose the display if: + // 1) It is being handled by hardware composer, which may need this to + // keep its virtual display state machine in sync, or + // 2) There is work to be done (the dirty region isn't empty) + bool isHwcDisplay = hw->getHwcDisplayId() >= 0; + if (!isHwcDisplay && inDirtyRegion.isEmpty()) { + return; + } + Region dirtyRegion(inDirtyRegion); // compute the invalid region @@ -1782,7 +1658,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const const Layer::State& state(layer->getDrawingState()); if ((cur->getHints() & HWC_HINT_CLEAR_FB) && i - && layer->isOpaque() && (state.alpha == 0xFF) + && layer->isOpaque(state) && (state.alpha == 0xFF) && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -2026,7 +1902,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setTransparentRegionHint(s.transparentRegion)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eVisibilityChanged) { + if ((what & layer_state_t::eVisibilityChanged) || + (what & layer_state_t::eOpacityChanged)) { + // TODO: should we just use an eFlagsChanged for this? if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; } @@ -2100,19 +1978,10 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: -#ifdef NO_RGBX_8888 - format = PIXEL_FORMAT_RGB_565; -#else format = PIXEL_FORMAT_RGBX_8888; -#endif break; } -#ifdef NO_RGBX_8888 - if (format == PIXEL_FORMAT_RGBX_8888) - format = PIXEL_FORMAT_RGBA_8888; -#endif - *outLayer = new Layer(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { @@ -2346,6 +2215,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) clearStatsLocked(args, index, result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--dispsync"))) { + index++; + mPrimaryDispSync.dump(result); + dumpAll = false; + } } if (dumpAll) { @@ -2436,9 +2312,6 @@ void SurfaceFlinger::logFrameStats() { { static const char* config = " [sf" -#ifdef NO_RGBX_8888 - " NO_RGBX_8888" -#endif #ifdef HAS_CONTEXT_PRIORITY " HAS_CONTEXT_PRIORITY" #endif @@ -2544,7 +2417,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, " refresh-rate : %f fps\n" " x-dpi : %f\n" " y-dpi : %f\n" - " EGL_NATIVE_VISUAL_ID : %d\n" " gpu_to_cpu_unsupported : %d\n" , mLastSwapBufferTime/1000.0, @@ -2553,7 +2425,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY), hwc.getDpiX(HWC_DISPLAY_PRIMARY), hwc.getDpiY(HWC_DISPLAY_PRIMARY), - mEGLNativeVisualId, !mGpuToCpuSupported); result.appendFormat(" eglSwapBuffers time: %f us\n", diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f08e66a..80bb619 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -317,10 +317,6 @@ private: /* ------------------------------------------------------------------------ * EGL */ - static status_t selectConfigForAttribute(EGLDisplay dpy, - EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig); - static status_t selectEGLConfig(EGLDisplay disp, EGLint visualId, - EGLint renderableType, EGLConfig* config); size_t getMaxTextureSize() const; size_t getMaxViewportDims() const; @@ -431,9 +427,7 @@ private: sp<EventThread> mSFEventThread; sp<EventControlThread> mEventControlThread; EGLContext mEGLContext; - EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; - EGLint mEGLNativeVisualId; sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; // Can only accessed from the main thread, these members diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index b161480..90e3f7d 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -27,7 +27,7 @@ using namespace android; -int main(int argc, char** argv) { +int main(int, char**) { // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); |