am c4193f1f: Merge "Migrate keychain directories to /data/misc/user/0"
* commit 'c4193f1fef52314b451f55cce48ce44f94b875b6':
Migrate keychain directories to /data/misc/user/0
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 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 @@
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 @@
" -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 @@
/* 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 @@
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 @@
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 @@
* 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 @@
};
} 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 @@
AUncalibratedEvent uncalibrated_gyro;
AUncalibratedEvent uncalibrated_magnetic;
AMetaDataEvent meta_data;
+ AHeartRateEvent heart_rate;
};
union {
uint64_t data[8];
@@ -281,6 +288,21 @@
*/
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
// 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 @@
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 @@
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:
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 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 @@
{ "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 @@
{ 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 @@
// 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 @@
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 @@
/* 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 @@
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 @@
eVisibilityChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
+ eOpacityChanged = 0x00000200,
};
layer_state_t()
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e83edd5..729cf21 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1361,7 +1361,7 @@
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);
@@ -1375,10 +1375,10 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// --- PointerCoords ---
float PointerCoords::getAxisValue(int32_t axis) const {
- if (axis < 0 || axis > 63) {
+ if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
return 0;
}
-
- uint64_t axisBit = 1LL << axis;
- if (!(bits & axisBit)) {
- 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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 6df6315..148f404 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -206,7 +206,7 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
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/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::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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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() {
}
-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 @@
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 @@
//
// 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 @@
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 @@
mName("unnamed"),
mDebug(false),
mFormat(PIXEL_FORMAT_NONE),
- mOpaqueLayer(true),
mTransactionFlags(0),
mQueuedFrames(0),
mCurrentTransform(0),
@@ -86,7 +85,9 @@
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 @@
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 @@
// 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 @@
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 @@
}
}
-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 @@
// 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 @@
}
// 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 @@
}
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 @@
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 @@
/*
* 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 @@
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..94bef9a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -882,7 +882,9 @@
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 @@
// 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::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 @@
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 @@
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;
}
@@ -2189,6 +2202,13 @@
clearStatsLocked(args, index, result);
dumpAll = false;
}
+
+ if ((index < numArgs) &&
+ (args[index] == String16("--dispsync"))) {
+ index++;
+ mPrimaryDispSync.dump(result);
+ dumpAll = false;
+ }
}
if (dumpAll) {
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);