am 0e1313cd: Merge "libgui: 64-bit compile issues"

* commit '0e1313cdb1d5d21e4d6123f77b4238f1c8c2d564':
  libgui: 64-bit compile issues
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);