diff options
50 files changed, 923 insertions, 146 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 670e09c..ef5072a 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/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/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..09a064a --- /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 android.hardware.location.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/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 7c662a7..793b414 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> /* * Additional private constants not defined in ndk/ui/input.h. @@ -65,6 +66,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. */ @@ -149,13 +178,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 @@ -177,13 +202,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/Parcel.cpp b/libs/binder/Parcel.cpp index 27a50a6..f943f82 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -1356,7 +1356,7 @@ size_t Parcel::ipcObjectsCount() const void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie) { - size_t minOffset = 0; + binder_size_t minOffset = 0; freeDataNoInit(); mError = NO_ERROR; mData = const_cast<uint8_t*>(data); @@ -1370,10 +1370,10 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, mOwner = relFunc; mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { - size_t offset = mObjects[i]; + binder_size_t offset = mObjects[i]; if (offset < minOffset) { - ALOGE("%s: bad object offset %zu < %zu\n", - __func__, offset, minOffset); + ALOGE("%s: bad object offset %"PRIu64" < %"PRIu64"\n", + __func__, (uint64_t)offset, (uint64_t)minOffset); mObjectsSize = 0; break; } 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/Sensor.cpp b/libs/gui/Sensor.cpp index e8948bb..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, static_cast<uint32_t>(mName.length())); - memcpy(static_cast<char*>(buffer), mName.string(), mName.length()); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mName.length())); - - FlattenableUtils::write(buffer, size, static_cast<uint32_t>(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) { - uint32_t len; - - if (size < sizeof(uint32_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; } - mName.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); - - if (size < sizeof(uint32_t)) { - return NO_MEMORY; - } - FlattenableUtils::read(buffer, size, len); - if (size < len) { - return NO_MEMORY; - } - mVendor.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); - - const size_t fixedSize = + 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/input/Input.cpp b/libs/input/Input.cpp index 6f53996..d9f22e9 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/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index d671951..ba75b6c 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -206,7 +206,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 { @@ -216,21 +216,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 | "); } @@ -491,10 +494,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() @@ -540,6 +556,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) { @@ -550,6 +570,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) { @@ -671,6 +696,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; @@ -684,17 +713,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( @@ -762,6 +818,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 49a017f..5a8efeb 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 602f20a..95839b7 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 a1430b9..f9034a6 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -199,8 +199,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 01a9d2e..f750c6c 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -124,7 +124,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 7d4b196..086ccf8 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/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index d7fef8c..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); } } 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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 943ed02..3c447db 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -882,7 +882,9 @@ void SurfaceFlinger::rebuildLayerStacks() { void SurfaceFlinger::setUpHWComposer() { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - mDisplays[dpy]->beginFrame(); + bool mustRecompose = + !(mDisplays[dpy]->getDirtyRegion(false).isEmpty()); + mDisplays[dpy]->beginFrame(mustRecompose); } HWComposer& hwc(getHwComposer()); @@ -1380,7 +1382,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()) { @@ -1500,6 +1502,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 @@ -1625,7 +1636,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 @@ -1869,7 +1880,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; } @@ -1943,19 +1956,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) { @@ -2189,6 +2193,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) { @@ -2279,9 +2290,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 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); |