Merge "Send cancelation events to monitors when injection fails." into mnc-dev
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 95c49cf..1d9e6b8 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -109,6 +110,7 @@
 }
 
 static const char mmcblk0[] = "/sys/block/mmcblk0/";
+unsigned long worst_write_perf = 20000; /* in KB/s */
 
 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
     unsigned long fields[11], read_perf, write_perf;
@@ -157,11 +159,111 @@
         write_perf = 512 * fields[6] / fields[7];
     }
     printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
+    if ((write_perf > 1) && (write_perf < worst_write_perf)) {
+        worst_write_perf = write_perf;
+    }
     return 0;
 }
 
+/* Copied policy from system/core/logd/LogBuffer.cpp */
+
+#define LOG_BUFFER_SIZE (256 * 1024)
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+
+static bool valid_size(unsigned long value) {
+    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+        return false;
+    }
+
+    long pages = sysconf(_SC_PHYS_PAGES);
+    if (pages < 1) {
+        return true;
+    }
+
+    long pagesize = sysconf(_SC_PAGESIZE);
+    if (pagesize <= 1) {
+        pagesize = PAGE_SIZE;
+    }
+
+    // maximum memory impact a somewhat arbitrary ~3%
+    pages = (pages + 31) / 32;
+    unsigned long maximum = pages * pagesize;
+
+    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+        return true;
+    }
+
+    return value <= maximum;
+}
+
+static unsigned long property_get_size(const char *key) {
+    unsigned long value;
+    char *cp, property[PROPERTY_VALUE_MAX];
+
+    property_get(key, property, "");
+    value = strtoul(property, &cp, 10);
+
+    switch(*cp) {
+    case 'm':
+    case 'M':
+        value *= 1024;
+    /* FALLTHRU */
+    case 'k':
+    case 'K':
+        value *= 1024;
+    /* FALLTHRU */
+    case '\0':
+        break;
+
+    default:
+        value = 0;
+    }
+
+    if (!valid_size(value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+/* timeout in ms */
+static unsigned long logcat_timeout(char *name) {
+    static const char global_tuneable[] = "persist.logd.size"; // Settings App
+    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
+    char key[PROP_NAME_MAX];
+    unsigned long property_size, default_size;
+
+    default_size = property_get_size(global_tuneable);
+    if (!default_size) {
+        default_size = property_get_size(global_default);
+    }
+
+    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
+    property_size = property_get_size(key);
+
+    if (!property_size) {
+        snprintf(key, sizeof(key), "%s.%s", global_default, name);
+        property_size = property_get_size(key);
+    }
+
+    if (!property_size) {
+        property_size = default_size;
+    }
+
+    if (!property_size) {
+        property_size = LOG_BUFFER_SIZE;
+    }
+
+    /* Engineering margin is ten-fold our guess */
+    return 10 * (property_size + worst_write_perf) / worst_write_perf;
+}
+
+/* End copy from system/core/logd/LogBuffer.cpp */
+
 /* dumps the current system state to stdout */
 static void dumpstate() {
+    unsigned long timeout;
     time_t now = time(NULL);
     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
@@ -210,7 +312,6 @@
     dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
     dump_file("KERNEL SYNC", "/d/sync");
-    dump_file("KERNEL BLUEDROID", "/d/bluedroid");
 
     run_command("PROCESSES", 10, "ps", "-P", NULL);
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
@@ -230,9 +331,22 @@
     }
 
     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
-    run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
+    // calculate timeout
+    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
+    timeout = logcat_timeout("events");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+    timeout = logcat_timeout("radio");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
 
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
@@ -318,6 +432,8 @@
     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
 
+    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
+
     run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
     run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
     run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 99da968..faf48ef 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -745,6 +745,15 @@
     ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
 }
 
+static bool check_boolean_property(const char* property_name, bool default_value = false) {
+    char tmp_property_value[PROPERTY_VALUE_MAX];
+    bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
+    if (!have_property) {
+        return default_value;
+    }
+    return strcmp(tmp_property_value, "true") == 0;
+}
+
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
     bool vm_safe_mode, bool debuggable)
@@ -805,9 +814,8 @@
                              (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
                              (strcmp(vold_decrypt, "1") == 0)));
 
-    char use_jit_property[PROPERTY_VALUE_MAX];
-    bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0;
-    bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0;
+    bool use_jit = check_boolean_property("debug.usejit");
+    bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
 
@@ -900,6 +908,7 @@
                      + (have_dex2oat_threads_flag ? 1 : 0)
                      + (have_dex2oat_swap_fd ? 1 : 0)
                      + (have_dex2oat_relocation_skip_flag ? 2 : 0)
+                     + (generate_debug_info ? 1 : 0)
                      + (debuggable ? 1 : 0)
                      + dex2oat_flags_count];
     int i = 0;
@@ -938,6 +947,9 @@
     if (have_dex2oat_swap_fd) {
         argv[i++] = dex2oat_swap_fd;
     }
+    if (generate_debug_info) {
+        argv[i++] = "--generate-debug-info";
+    }
     if (debuggable) {
         argv[i++] = "--debuggable";
     }
@@ -1778,6 +1790,31 @@
     return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
 }
 
+int link_file(const char* relative_path, const char* from_base, const char* to_base) {
+    char from_path[PKG_PATH_MAX];
+    char to_path[PKG_PATH_MAX];
+    snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
+    snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path);
+
+    if (validate_apk_path_subdirs(from_path)) {
+        ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path);
+        return -1;
+    }
+
+    if (validate_apk_path_subdirs(to_path)) {
+        ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path);
+        return -1;
+    }
+
+    const int ret = link(from_path, to_path);
+    if (ret < 0) {
+        ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
 int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
         const char *instruction_set) {
     char *file_name_start;
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 01e7cdd..297b3a1 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -179,6 +179,12 @@
     return rm_package_dir(arg[0]);
 }
 
+static int do_link_file(char **arg, char reply[REPLY_MAX] __unused)
+{
+    /* relative_path, from_base, to_base */
+    return link_file(arg[0], arg[1], arg[2]);
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -209,7 +215,8 @@
     { "idmap",                3, do_idmap },
     { "restorecondata",       4, do_restorecon_data },
     { "createoatdir",         2, do_create_oat_dir },
-    { "rmpackagedir",         1, do_rm_package_dir},
+    { "rmpackagedir",         1, do_rm_package_dir },
+    { "linkfile",             3, do_link_file }
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index ce6c857..744ed3a 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -203,6 +203,7 @@
 int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
 
 int validate_apk_path(const char *path);
+int validate_apk_path_subdirs(const char *path);
 
 int append_and_increment(char** dst, const char* src, size_t* dst_size);
 
@@ -254,3 +255,4 @@
                             const char *instruction_set);
 int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
                             const char *instruction_set);
+int link_file(const char *relative_path, const char *from_base, const char *to_base);
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 3f679a2..7db3fb9 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -1043,15 +1043,13 @@
 }
 
 /**
- * Check whether path points to a valid path for an APK file. Only one level of
- * subdirectory names is allowed. Returns -1 when an invalid path is encountered
- * and 0 when a valid path is encountered.
+ * Check whether path points to a valid path for an APK file. The path must
+ * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within
+ * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
+ * is encountered.
  */
-int validate_apk_path(const char *path)
-{
+static int validate_apk_path_internal(const char *path, int maxSubdirs) {
     const dir_rec_t* dir = NULL;
-    int maxSubdirs = 1;
-
     if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
         dir = &android_app_dir;
     } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
@@ -1060,7 +1058,9 @@
         dir = &android_asec_dir;
     } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) {
         dir = &android_mnt_expand_dir;
-        maxSubdirs = 2;
+        if (maxSubdirs < 2) {
+            maxSubdirs = 2;
+        }
     } else {
         return -1;
     }
@@ -1068,6 +1068,14 @@
     return validate_path(dir, path, maxSubdirs);
 }
 
+int validate_apk_path(const char* path) {
+    return validate_apk_path_internal(path, 1 /* maxSubdirs */);
+}
+
+int validate_apk_path_subdirs(const char* path) {
+    return validate_apk_path_internal(path, 3 /* maxSubdirs */);
+}
+
 int append_and_increment(char** dst, const char* src, size_t* dst_size) {
     ssize_t ret = strlcpy(*dst, src, *dst_size);
     if (ret < 0 || (size_t) ret >= *dst_size) {
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index cacfe14..7fa9a39 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -361,6 +361,7 @@
 
     selinux_enabled = is_selinux_enabled();
     sehandle = selinux_android_service_context_handle();
+    selinux_status_open(true);
 
     if (selinux_enabled > 0) {
         if (sehandle == NULL) {
diff --git a/include/android/input.h b/include/android/input.h
index c7635b8..efbbb85 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -453,6 +453,7 @@
     AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
     AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
     AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
+    AINPUT_SOURCE_BLUETOOTH_STYLUS = 0x00008000 | AINPUT_SOURCE_STYLUS,
     AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
     AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
     AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
diff --git a/include/android/trace.h b/include/android/trace.h
new file mode 100644
index 0000000..e42e334
--- /dev/null
+++ b/include/android/trace.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_NATIVE_TRACE_H
+#define ANDROID_NATIVE_TRACE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns true if tracing is enabled. Use this signal to avoid expensive computation only necessary
+ * when tracing is enabled.
+ */
+bool ATrace_isEnabled();
+
+/**
+ * Writes a tracing message to indicate that the given section of code has begun. This call must be
+ * followed by a corresponding call to endSection() on the same thread.
+ *
+ * Note: At this time the vertical bar character '|' and newline character '\n' are used internally
+ * by the tracing mechanism. If sectionName contains these characters they will be replaced with a
+ * space character in the trace.
+ */
+void ATrace_beginSection(const char* sectionName);
+
+/**
+ * Writes a tracing message to indicate that a given section of code has ended. This call must be
+ * preceeded by a corresponding call to beginSection(char*) on the same thread. Calling this method
+ * will mark the end of the most recently begun section of code, so care must be taken to ensure
+ * that beginSection / endSection pairs are properly nested and called from the same thread.
+ */
+void ATrace_endSection();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_TRACE_H
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index da960aa..3ada1e9 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -60,6 +60,7 @@
     status_t            appendFrom(const Parcel *parcel,
                                    size_t start, size_t len);
 
+    bool                allowFds() const;
     bool                pushAllowFds(bool allowFds);
     void                restoreAllowFds(bool lastValue);
 
@@ -130,16 +131,18 @@
     // will be closed once the parcel is destroyed.
     status_t            writeDupFileDescriptor(int fd);
 
-    // Writes a raw fd and optional comm channel fd to the parcel as a ParcelFileDescriptor.
-    // A dup's of the fds are made, which will be closed once the parcel is destroyed.
-    // Null values are passed as -1.
-    status_t            writeParcelFileDescriptor(int fd, int commChannel = -1);
-
     // Writes a blob to the parcel.
     // If the blob is small, then it is stored in-place, otherwise it is
-    // transferred by way of an anonymous shared memory region.
+    // transferred by way of an anonymous shared memory region.  Prefer sending
+    // immutable blobs if possible since they may be subsequently transferred between
+    // processes without further copying whereas mutable blobs always need to be copied.
     // The caller should call release() on the blob after writing its contents.
-    status_t            writeBlob(size_t len, WritableBlob* outBlob);
+    status_t            writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
+
+    // Write an existing immutable blob file descriptor to the parcel.
+    // This allows the client to send the same blob to multiple processes
+    // as long as it keeps a dup of the blob file descriptor handy for later.
+    status_t            writeDupImmutableBlobFileDescriptor(int fd);
 
     status_t            writeObject(const flat_binder_object& val, bool nullMetaData);
 
@@ -198,11 +201,6 @@
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
 
-    // Reads a ParcelFileDescriptor from the parcel.  Returns the raw fd as
-    // the result, and the optional comm channel fd in outCommChannel.
-    // Null values are returned as -1.
-    int                 readParcelFileDescriptor(int& outCommChannel) const;
-
     // Reads a blob from the parcel.
     // The caller should call release() on the blob after reading its contents.
     status_t            readBlob(size_t len, ReadableBlob* outBlob) const;
@@ -280,16 +278,19 @@
         Blob();
         ~Blob();
 
+        void clear();
         void release();
         inline size_t size() const { return mSize; }
+        inline int fd() const { return mFd; };
+        inline bool isMutable() const { return mMutable; }
 
     protected:
-        void init(bool mapped, void* data, size_t size);
-        void clear();
+        void init(int fd, void* data, size_t size, bool isMutable);
 
-        bool mMapped;
+        int mFd; // owned by parcel so not closed when released
         void* mData;
         size_t mSize;
+        bool mMutable;
     };
 
     class FlattenableHelperInterface {
@@ -330,6 +331,7 @@
         friend class Parcel;
     public:
         inline const void* data() const { return mData; }
+        inline void* mutableData() { return isMutable() ? mData : NULL; }
     };
 
     class WritableBlob : public Blob {
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index d7686ec..99134ea 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -275,6 +275,11 @@
     // buffer as the number of frames that have elapsed since it was last queued
     uint64_t mBufferAge;
 
+    // mGenerationNumber stores the current generation number of the attached
+    // producer. Any attempt to attach a buffer with a different generation
+    // number will fail.
+    uint32_t mGenerationNumber;
+
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index ed660fb..9754a89 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -175,6 +175,12 @@
     // See IGraphicBufferProducer::allowAllocation
     virtual status_t allowAllocation(bool allow);
 
+    // See IGraphicBufferProducer::setGenerationNumber
+    virtual status_t setGenerationNumber(uint32_t generationNumber);
+
+    // See IGraphicBufferProducer::getConsumerName
+    virtual String8 getConsumerName() const override;
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 6363a3a..60ec9cc 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -110,7 +110,8 @@
     // will be deallocated as stale.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * BAD_VALUE - outSlot or buffer were NULL
+    // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of
+    //               the buffer did not match the buffer queue.
     // * INVALID_OPERATION - cannot attach the buffer because it would cause too
     //                       many buffers to be acquired.
     // * NO_MEMORY - no free slots available
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 5c50b2b..9530de1 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -218,8 +218,9 @@
     //
     // Return of a negative value means an error has occurred:
     // * NO_INIT - the buffer queue has been abandoned.
-    // * BAD_VALUE - outSlot or buffer were NULL or invalid combination of
-    //               async mode and buffer count override.
+    // * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
+    //               async mode and buffer count override, or the generation
+    //               number of the buffer did not match the buffer queue.
     // * INVALID_OPERATION - cannot attach the buffer because it would cause
     //                       too many buffers to be dequeued, either because
     //                       the producer already has a single buffer dequeued
@@ -470,6 +471,18 @@
     // eligible slot is available, dequeueBuffer will block or return an error
     // as usual.
     virtual status_t allowAllocation(bool allow) = 0;
+
+    // Sets the current generation number of the BufferQueue.
+    //
+    // This generation number will be inserted into any buffers allocated by the
+    // BufferQueue, and any attempts to attach a buffer with a different
+    // generation number will fail. Buffers already in the queue are not
+    // affected and will retain their current generation number. The generation
+    // number defaults to 0.
+    virtual status_t setGenerationNumber(uint32_t generationNumber) = 0;
+
+    // Returns the name of the connected consumer.
+    virtual String8 getConsumerName() const = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index fd6d48c..72f1067 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -101,6 +101,14 @@
      */
     void allocateBuffers();
 
+    /* Sets the generation number on the IGraphicBufferProducer and updates the
+     * generation number on any buffers attached to the Surface after this call.
+     * See IGBP::setGenerationNumber for more information. */
+    status_t setGenerationNumber(uint32_t generationNumber);
+
+    // See IGraphicBufferProducer::getConsumerName
+    String8 getConsumerName() const;
+
 protected:
     virtual ~Surface();
 
@@ -305,6 +313,10 @@
     // When a non-CPU producer is attached, this reflects the surface damage
     // (the change since the previous frame) passed in by the producer.
     Region mDirtyRegion;
+
+    // Stores the current generation number. See setGenerationNumber and
+    // IGraphicBufferProducer::setGenerationNumber for more information.
+    uint32_t mGenerationNumber;
 };
 
 }; // namespace android
diff --git a/include/input/Input.h b/include/input/Input.h
index 1da8356..4a67f47 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -383,6 +383,8 @@
 
     inline int32_t getActionButton() const { return mActionButton; }
 
+    inline void setActionButton(int32_t button) { mActionButton = button; }
+
     inline float getXOffset() const { return mXOffset; }
 
     inline float getYOffset() const { return mYOffset; }
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index a682ab7..5d2201b 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -100,14 +100,11 @@
 // dynamic buffer handling.
 struct VideoGrallocMetadata {
     MetadataBufferType eType;               // must be kMetadataBufferTypeGrallocSource
-    buffer_handle_t hHandle;
+    buffer_handle_t pHandle;
 };
 
 // Legacy name for VideoGrallocMetadata struct.
-struct VideoDecoderOutputMetaData {
-    MetadataBufferType eType;               // must be kMetadataBufferTypeGrallocSource
-    buffer_handle_t pHandle;
-};
+struct VideoDecoderOutputMetaData : public VideoGrallocMetadata {};
 
 struct VideoNativeMetadata {
     MetadataBufferType eType;               // must be kMetadataBufferTypeANWBuffer
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 65eb562..ae8430d 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -524,6 +524,7 @@
         case OMX_IndexConfigAutoFramerateConversion:    return "ConfigAutoFramerateConversion";
         case OMX_IndexConfigPriority:                   return "ConfigPriority";
         case OMX_IndexConfigOperatingRate:              return "ConfigOperatingRate";
+        case OMX_IndexParamConsumerUsageBits:           return "ParamConsumerUsageBits";
         default:                                        return asString((OMX_INDEXTYPE)i, def);
     }
 }
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index 4fc1546..521c223 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -510,8 +510,14 @@
     OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
 
     /** Event when tunneled decoder has rendered an output
-     *  nData1 must contain the lower 32-bits of the buffer timestamp
-     *  nData2 must contain the upper 32-bits of the buffer timestamp
+     *  nData1 must contain the number of timestamps returned
+     *  pEventData must point to an array of the OMX_VIDEO_RENDEREVENTTYPE structs containing the
+     *  render-timestamps of each frame. Component may batch rendered timestamps using this event,
+     *  but must signal the event no more than 40ms after the first frame in the batch. The frames
+     *  must be ordered by system timestamp inside and across batches.
+     *
+     *  If component is doing frame-rate conversion, it must signal the render time of each
+     *  converted frame, and must interpolate media timestamps for in-between frames.
      */
     OMX_EventOutputRendered = 0x7F000001,
     OMX_EventMax = 0x7FFFFFFF
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index 51bba31..25bea1f 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -85,6 +85,7 @@
     OMX_IndexConfigAutoFramerateConversion,         /**< reference: OMX_CONFIG_BOOLEANTYPE */
     OMX_IndexConfigPriority,                        /**< reference: OMX_PARAM_U32TYPE */
     OMX_IndexConfigOperatingRate,                   /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
+    OMX_IndexParamConsumerUsageBits,                /**< reference: OMX_PARAM_U32TYPE */
 
     /* Time configurations */
     OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 3c97e14..34c0405 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -203,6 +203,12 @@
     OMX_BOOL bEnableLoopFilterAcrossSlices;
 } OMX_VIDEO_SLICESEGMENTSTYPE;
 
+/** Structure to return timestamps of rendered output frames for tunneled components */
+typedef struct OMX_VIDEO_RENDEREVENTTYPE {
+    OMX_S64 nMediaTimeUs;  // timestamp of rendered video frame
+    OMX_S64 nSystemTimeNs; // system monotonic time at the time frame was rendered
+} OMX_VIDEO_RENDEREVENTTYPE;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 2fa6ff9..cbe8733 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -39,6 +39,7 @@
     enum {
         eLayerHidden        = 0x01,     // SURFACE_HIDDEN in SurfaceControl.java
         eLayerOpaque        = 0x02,     // SURFACE_OPAQUE
+        eLayerSecure        = 0x80,     // SECURE
     };
 
     enum {
@@ -48,10 +49,9 @@
         eAlphaChanged               = 0x00000008,
         eMatrixChanged              = 0x00000010,
         eTransparentRegionChanged   = 0x00000020,
-        eVisibilityChanged          = 0x00000040,
+        eFlagsChanged               = 0x00000040,
         eLayerStackChanged          = 0x00000080,
         eCropChanged                = 0x00000100,
-        eOpacityChanged             = 0x00000200,
     };
 
     layer_state_t()
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index f91d192..3da720f 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -94,6 +94,11 @@
     Rect getBounds() const              { return Rect(width, height); }
     uint64_t getId() const              { return mId; }
 
+    uint32_t getGenerationNumber() const { return mGenerationNumber; }
+    void setGenerationNumber(uint32_t generation) {
+        mGenerationNumber = generation;
+    }
+
     status_t reallocate(uint32_t inWidth, uint32_t inHeight,
             PixelFormat inFormat, uint32_t inUsage);
 
@@ -166,6 +171,11 @@
     sp<ANativeWindowBuffer> mWrappedBuffer;
 
     uint64_t mId;
+
+    // Stores the generation number of this buffer. If this number does not
+    // match the BufferQueue's internal generation number (set through
+    // IGBP::setGenerationNumber), attempts to attach the buffer will fail.
+    uint32_t mGenerationNumber;
 };
 
 }; // namespace android
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 2d493c1..1339a67 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -49,9 +49,12 @@
     
     status_t append(const char* txt, size_t len) {
         if ((len+bufferPos) > bufferSize) {
-            void* b = realloc(buffer, ((len+bufferPos)*3)/2);
+            size_t newSize = ((len+bufferPos)*3)/2;
+            if (newSize < (len+bufferPos)) return NO_MEMORY;    // overflow
+            void* b = realloc(buffer, newSize);
             if (!b) return NO_MEMORY;
             buffer = (char*)b;
+            bufferSize = newSize;
         }
         memcpy(buffer+bufferPos, txt, len);
         bufferPos += len;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index c1cfb1e..31667d9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -72,9 +72,6 @@
 // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
 #define EX_HAS_REPLY_HEADER -128
 
-// Maximum size of a blob to transfer in-place.
-static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
-
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -89,6 +86,15 @@
 static size_t gParcelGlobalAllocSize = 0;
 static size_t gParcelGlobalAllocCount = 0;
 
+// Maximum size of a blob to transfer in-place.
+static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
+
+enum {
+    BLOB_INPLACE = 0,
+    BLOB_ASHMEM_IMMUTABLE = 1,
+    BLOB_ASHMEM_MUTABLE = 2,
+};
+
 void acquire_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who)
 {
@@ -478,7 +484,8 @@
     if (numObjects > 0) {
         // grow objects
         if (mObjectsCapacity < mObjectsSize + numObjects) {
-            int newSize = ((mObjectsSize + numObjects)*3)/2;
+            size_t newSize = ((mObjectsSize + numObjects)*3)/2;
+            if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
             binder_size_t *objects =
                 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
             if (objects == (binder_size_t*)0) {
@@ -516,6 +523,11 @@
     return err;
 }
 
+bool Parcel::allowFds() const
+{
+    return mAllowFds;
+}
+
 bool Parcel::pushAllowFds(bool allowFds)
 {
     const bool origValue = mAllowFds;
@@ -886,51 +898,24 @@
     return err;
 }
 
-// WARNING: This method must stay in sync with
-// Parcelable.Creator<ParcelFileDescriptor> CREATOR
-// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java
-status_t Parcel::writeParcelFileDescriptor(int fd, int commChannel) {
-    status_t status;
-
-    if (fd < 0) {
-        status = writeInt32(0); // ParcelFileDescriptor is null
-        if (status) return status;
-    } else {
-        status = writeInt32(1); // ParcelFileDescriptor is not null
-        if (status) return status;
-        status = writeDupFileDescriptor(fd);
-        if (status) return status;
-        if (commChannel < 0) {
-            status = writeInt32(0); // commChannel is null
-            if (status) return status;
-        } else {
-            status = writeInt32(1); // commChannel is not null
-            if (status) return status;
-            status = writeDupFileDescriptor(commChannel);
-        }
-    }
-    return status;
-}
-
-status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
+status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
-    status_t status;
-
     if (len > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
         return BAD_VALUE;
     }
 
-    if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+    status_t status;
+    if (!mAllowFds || len <= BLOB_INPLACE_LIMIT) {
         ALOGV("writeBlob: write in place");
-        status = writeInt32(0);
+        status = writeInt32(BLOB_INPLACE);
         if (status) return status;
 
         void* ptr = writeInplace(len);
         if (!ptr) return NO_MEMORY;
 
-        outBlob->init(false /*mapped*/, ptr, len);
+        outBlob->init(-1, ptr, len, false);
         return NO_ERROR;
     }
 
@@ -948,15 +933,17 @@
         if (ptr == MAP_FAILED) {
             status = -errno;
         } else {
-            result = ashmem_set_prot_region(fd, PROT_READ);
+            if (!mutableCopy) {
+                result = ashmem_set_prot_region(fd, PROT_READ);
+            }
             if (result < 0) {
                 status = result;
             } else {
-                status = writeInt32(1);
+                status = writeInt32(mutableCopy ? BLOB_ASHMEM_MUTABLE : BLOB_ASHMEM_IMMUTABLE);
                 if (!status) {
                     status = writeFileDescriptor(fd, true /*takeOwnership*/);
                     if (!status) {
-                        outBlob->init(true /*mapped*/, ptr, len);
+                        outBlob->init(fd, ptr, len, mutableCopy);
                         return NO_ERROR;
                     }
                 }
@@ -968,6 +955,15 @@
     return status;
 }
 
+status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd)
+{
+    // Must match up with what's done in writeBlob.
+    if (!mAllowFds) return FDS_NOT_ALLOWED;
+    status_t status = writeInt32(BLOB_ASHMEM_IMMUTABLE);
+    if (status) return status;
+    return writeDupFileDescriptor(fd);
+}
+
 status_t Parcel::write(const FlattenableHelperInterface& val)
 {
     status_t err;
@@ -1018,6 +1014,15 @@
 restart_write:
         *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
 
+        // remember if it's a file descriptor
+        if (val.type == BINDER_TYPE_FD) {
+            if (!mAllowFds) {
+                // fail before modifying our object index
+                return FDS_NOT_ALLOWED;
+            }
+            mHasFds = mFdsKnown = true;
+        }
+
         // Need to write meta-data?
         if (nullMetaData || val.binder != 0) {
             mObjects[mObjectsSize] = mDataPos;
@@ -1025,14 +1030,6 @@
             mObjectsSize++;
         }
 
-        // remember if it's a file descriptor
-        if (val.type == BINDER_TYPE_FD) {
-            if (!mAllowFds) {
-                return FDS_NOT_ALLOWED;
-            }
-            mHasFds = mFdsKnown = true;
-        }
-
         return finishWrite(sizeof(flat_binder_object));
     }
 
@@ -1042,6 +1039,7 @@
     }
     if (!enoughObjects) {
         size_t newSize = ((mObjectsSize+2)*3)/2;
+        if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
         binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
         if (objects == NULL) return NO_MEMORY;
         mObjects = objects;
@@ -1378,46 +1376,31 @@
     return BAD_TYPE;
 }
 
-// WARNING: This method must stay in sync with writeToParcel()
-// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java
-int Parcel::readParcelFileDescriptor(int& outCommChannel) const {
-    int fd;
-    outCommChannel = -1;
-
-    if (readInt32() == 0) {
-        fd = -1;
-    } else {
-        fd = readFileDescriptor();
-        if (fd >= 0 && readInt32() != 0) {
-            outCommChannel = readFileDescriptor();
-        }
-    }
-    return fd;
-}
-
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
-    int32_t useAshmem;
-    status_t status = readInt32(&useAshmem);
+    int32_t blobType;
+    status_t status = readInt32(&blobType);
     if (status) return status;
 
-    if (!useAshmem) {
+    if (blobType == BLOB_INPLACE) {
         ALOGV("readBlob: read in place");
         const void* ptr = readInplace(len);
         if (!ptr) return BAD_VALUE;
 
-        outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+        outBlob->init(-1, const_cast<void*>(ptr), len, false);
         return NO_ERROR;
     }
 
     ALOGV("readBlob: read from ashmem");
+    bool isMutable = (blobType == BLOB_ASHMEM_MUTABLE);
     int fd = readFileDescriptor();
     if (fd == int(BAD_TYPE)) return BAD_VALUE;
 
-    void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
+            MAP_SHARED, fd, 0);
     if (ptr == MAP_FAILED) return NO_MEMORY;
 
-    outBlob->init(true /*mapped*/, ptr, len);
+    outBlob->init(fd, ptr, len, isMutable);
     return NO_ERROR;
 }
 
@@ -1933,7 +1916,7 @@
 // --- Parcel::Blob ---
 
 Parcel::Blob::Blob() :
-        mMapped(false), mData(NULL), mSize(0) {
+        mFd(-1), mData(NULL), mSize(0), mMutable(false) {
 }
 
 Parcel::Blob::~Blob() {
@@ -1941,22 +1924,24 @@
 }
 
 void Parcel::Blob::release() {
-    if (mMapped && mData) {
+    if (mFd != -1 && mData) {
         ::munmap(mData, mSize);
     }
     clear();
 }
 
-void Parcel::Blob::init(bool mapped, void* data, size_t size) {
-    mMapped = mapped;
+void Parcel::Blob::init(int fd, void* data, size_t size, bool isMutable) {
+    mFd = fd;
     mData = data;
     mSize = size;
+    mMutable = isMutable;
 }
 
 void Parcel::Blob::clear() {
-    mMapped = false;
+    mFd = -1;
     mData = NULL;
     mSize = 0;
+    mMutable = false;
 }
 
 }; // namespace android
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 4174676..ae796b1 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -248,6 +248,13 @@
         return INVALID_OPERATION;
     }
 
+    if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
+        BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
+                "[queue %u]", buffer->getGenerationNumber(),
+                mCore->mGenerationNumber);
+        return BAD_VALUE;
+    }
+
     // Find a free slot to put the buffer into
     int found = BufferQueueCore::INVALID_BUFFER_SLOT;
     if (!mCore->mFreeSlots.empty()) {
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index e784644..851a396 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -71,7 +71,8 @@
     mIsAllocating(false),
     mIsAllocatingCondition(),
     mAllowAllocation(true),
-    mBufferAge(0)
+    mBufferAge(0),
+    mGenerationNumber(0)
 {
     if (allocator == NULL) {
         sp<ISurfaceComposer> composer(ComposerService::getComposerService());
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e318484..38fb757 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -383,6 +383,7 @@
                 return NO_INIT;
             }
 
+            graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
             mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
         } // Autolock scope
     }
@@ -498,6 +499,13 @@
     Mutex::Autolock lock(mCore->mMutex);
     mCore->waitWhileAllocatingLocked();
 
+    if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
+        BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
+                "[queue %u]", buffer->getGenerationNumber(),
+                mCore->mGenerationNumber);
+        return BAD_VALUE;
+    }
+
     status_t returnFlags = NO_ERROR;
     int found;
     // TODO: Should we provide an async flag to attachBuffer? It seems
@@ -1072,6 +1080,21 @@
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
+    ATRACE_CALL();
+    BQ_LOGV("setGenerationNumber: %u", generationNumber);
+
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mGenerationNumber = generationNumber;
+    return NO_ERROR;
+}
+
+String8 BufferQueueProducer::getConsumerName() const {
+    ATRACE_CALL();
+    BQ_LOGV("getConsumerName: %s", mConsumerName.string());
+    return mConsumerName;
+}
+
 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
     // If we're here, it means that a producer we were connected to died.
     // We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 9fcac2d..757e08a 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -901,14 +901,18 @@
 
         // The crop is too wide
         if (newWidth < currentWidth) {
-            uint32_t dw = (currentWidth - newWidth) / 2;
-            outCrop.left += dw;
-            outCrop.right -= dw;
+            uint32_t dw = currentWidth - newWidth;
+            auto halfdw = dw / 2;
+            outCrop.left += halfdw;
+            // Not halfdw because it would subtract 1 too few when dw is odd
+            outCrop.right -= (dw - halfdw);
         // The crop is too tall
         } else if (newHeight < currentHeight) {
-            uint32_t dh = (currentHeight - newHeight) / 2;
-            outCrop.top += dh;
-            outCrop.bottom -= dh;
+            uint32_t dh = currentHeight - newHeight;
+            auto halfdh = dh / 2;
+            outCrop.top += halfdh;
+            // Not halfdh because it would subtract 1 too few when dh is odd
+            outCrop.bottom -= (dh - halfdh);
         }
 
         GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 7093ffa..d7a7885 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -47,6 +47,8 @@
     SET_SIDEBAND_STREAM,
     ALLOCATE_BUFFERS,
     ALLOW_ALLOCATION,
+    SET_GENERATION_NUMBER,
+    GET_CONSUMER_NAME,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -284,6 +286,28 @@
         result = reply.readInt32();
         return result;
     }
+
+    virtual status_t setGenerationNumber(uint32_t generationNumber) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeUint32(generationNumber);
+        status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
+
+    virtual String8 getConsumerName() const {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getConsumerName failed to transact: %d", result);
+            return String8("TransactFailed");
+        }
+        return reply.readString8();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -448,6 +472,18 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case SET_GENERATION_NUMBER: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            uint32_t generationNumber = data.readUint32();
+            status_t result = setGenerationNumber(generationNumber);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case GET_CONSUMER_NAME: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            reply->writeString8(getConsumerName());
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 04ac0f4..4b76f98 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -42,7 +42,8 @@
 Surface::Surface(
         const sp<IGraphicBufferProducer>& bufferProducer,
         bool controlledByApp)
-    : mGraphicBufferProducer(bufferProducer)
+    : mGraphicBufferProducer(bufferProducer),
+      mGenerationNumber(0)
 {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
@@ -102,6 +103,18 @@
             reqHeight, mReqFormat, mReqUsage);
 }
 
+status_t Surface::setGenerationNumber(uint32_t generation) {
+    status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
+    if (result == NO_ERROR) {
+        mGenerationNumber = generation;
+    }
+    return result;
+}
+
+String8 Surface::getConsumerName() const {
+    return mGraphicBufferProducer->getConsumerName();
+}
+
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
     Surface* c = getSelf(window);
     return c->setSwapInterval(interval);
@@ -331,20 +344,61 @@
     if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
         input.setSurfaceDamage(Region::INVALID_REGION);
     } else {
-        // The surface damage was specified using the OpenGL ES convention of
-        // the origin being in the bottom-left corner. Here we flip to the
-        // convention that the rest of the system uses (top-left corner) by
-        // subtracting all top/bottom coordinates from the buffer height.
+        // Here we do two things:
+        // 1) The surface damage was specified using the OpenGL ES convention of
+        //    the origin being in the bottom-left corner. Here we flip to the
+        //    convention that the rest of the system uses (top-left corner) by
+        //    subtracting all top/bottom coordinates from the buffer height.
+        // 2) If the buffer is coming in rotated (for example, because the EGL
+        //    implementation is reacting to the transform hint coming back from
+        //    SurfaceFlinger), the surface damage needs to be rotated the
+        //    opposite direction, since it was generated assuming an unrotated
+        //    buffer (the app doesn't know that the EGL implementation is
+        //    reacting to the transform hint behind its back). The
+        //    transformations in the switch statement below apply those
+        //    complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
+
+        int width = buffer->width;
         int height = buffer->height;
-        if ((mTransform ^ mStickyTransform) & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            height = buffer->width;
+        bool rotated90 = (mTransform ^ mStickyTransform) &
+                NATIVE_WINDOW_TRANSFORM_ROT_90;
+        if (rotated90) {
+            std::swap(width, height);
         }
+
         Region flippedRegion;
         for (auto rect : mDirtyRegion) {
-            auto top = height - rect.bottom;
-            auto bottom = height - rect.top;
-            Rect flippedRect{rect.left, top, rect.right, bottom};
-            flippedRegion.orSelf(flippedRect);
+            int left = rect.left;
+            int right = rect.right;
+            int top = height - rect.bottom; // Flip from OpenGL convention
+            int bottom = height - rect.top; // Flip from OpenGL convention
+            switch (mTransform ^ mStickyTransform) {
+                case NATIVE_WINDOW_TRANSFORM_ROT_90: {
+                    // Rotate 270 degrees
+                    Rect flippedRect{top, width - right, bottom, width - left};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                case NATIVE_WINDOW_TRANSFORM_ROT_180: {
+                    // Rotate 180 degrees
+                    Rect flippedRect{width - right, height - bottom,
+                            width - left, height - top};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                case NATIVE_WINDOW_TRANSFORM_ROT_270: {
+                    // Rotate 90 degrees
+                    Rect flippedRect{height - bottom, left,
+                            height - top, right};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                default: {
+                    Rect flippedRect{left, top, right, bottom};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+            }
         }
 
         input.setSurfaceDamage(flippedRegion);
@@ -698,11 +752,14 @@
     Mutex::Autolock lock(mMutex);
 
     sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
+    uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
+    graphicBuffer->mGenerationNumber = mGenerationNumber;
     int32_t attachedSlot = -1;
     status_t result = mGraphicBufferProducer->attachBuffer(
             &attachedSlot, graphicBuffer);
     if (result != NO_ERROR) {
         ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
+        graphicBuffer->mGenerationNumber = priorGeneration;
         return result;
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 707a321..6ad47d8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -310,11 +310,10 @@
     layer_state_t* s = getLayerStateLocked(client, id);
     if (!s)
         return BAD_INDEX;
-    if (mask & layer_state_t::eLayerOpaque) {
-        s->what |= layer_state_t::eOpacityChanged;
-    }
-    if (mask & layer_state_t::eLayerHidden) {
-        s->what |= layer_state_t::eVisibilityChanged;
+    if (mask & layer_state_t::eLayerOpaque ||
+            mask & layer_state_t::eLayerHidden ||
+            mask & layer_state_t::eLayerSecure) {
+        s->what |= layer_state_t::eFlagsChanged;
     }
     s->flags &= ~mask;
     s->flags |= (flags & mask);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 1584fef..1a54875 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "BufferQueue_test"
 //#define LOG_NDEBUG 0
 
+#include "DummyConsumer.h"
+
 #include <gui/BufferItem.h>
 #include <gui/BufferQueue.h>
 #include <gui/IProducerListener.h>
@@ -67,12 +69,6 @@
     sp<IGraphicBufferConsumer> mConsumer;
 };
 
-struct DummyConsumer : public BnConsumerListener {
-    virtual void onFrameAvailable(const BufferItem& /* item */) {}
-    virtual void onBuffersReleased() {}
-    virtual void onSidebandStreamChanged() {}
-};
-
 static const uint32_t TEST_DATA = 0x12345678u;
 
 // XXX: Tests that fork a process to hold the BufferQueue must run before tests
@@ -402,4 +398,46 @@
             WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
 }
 
+TEST_F(BufferQueueTest, TestGenerationNumbers) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
+
+    // Get one buffer to play with
+    int slot;
+    sp<Fence> fence;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
+
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+    // Ensure that the generation number we set propagates to allocated buffers
+    ASSERT_EQ(1U, buffer->getGenerationNumber());
+
+    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
+
+    ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
+
+    // These should fail, since we've changed the generation number on the queue
+    int outSlot;
+    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
+    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
+
+    buffer->setGenerationNumber(2);
+
+    // This should succeed now that we've changed the buffer's generation number
+    ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
+
+    ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
+
+    // This should also succeed with the new generation number
+    ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
+}
+
 } // namespace android
diff --git a/libs/gui/tests/DummyConsumer.h b/libs/gui/tests/DummyConsumer.h
new file mode 100644
index 0000000..0511e16
--- /dev/null
+++ b/libs/gui/tests/DummyConsumer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#include <gui/IConsumerListener.h>
+
+namespace android {
+
+struct DummyConsumer : public BnConsumerListener {
+    virtual void onFrameAvailable(const BufferItem& /* item */) {}
+    virtual void onBuffersReleased() {}
+    virtual void onSidebandStreamChanged() {}
+};
+
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 4f87824..3f495f8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "DummyConsumer.h"
+
 #include <gtest/gtest.h>
 
 #include <binder/IMemory.h>
@@ -177,4 +179,53 @@
     ASSERT_EQ(TEST_DATASPACE, dataSpace);
 }
 
+TEST_F(SurfaceTest, SettingGenerationNumber) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+
+    // Allocate a buffer with a generation number of 0
+    ANativeWindowBuffer* buffer;
+    int fenceFd;
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
+
+    // Detach the buffer and check its generation number
+    sp<GraphicBuffer> graphicBuffer;
+    sp<Fence> fence;
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&graphicBuffer, &fence));
+    ASSERT_EQ(0U, graphicBuffer->getGenerationNumber());
+
+    ASSERT_EQ(NO_ERROR, surface->setGenerationNumber(1));
+    buffer = static_cast<ANativeWindowBuffer*>(graphicBuffer.get());
+
+    // This should change the generation number of the GraphicBuffer
+    ASSERT_EQ(NO_ERROR, surface->attachBuffer(buffer));
+
+    // Check that the new generation number sticks with the buffer
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, -1));
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+    graphicBuffer = static_cast<GraphicBuffer*>(buffer);
+    ASSERT_EQ(1U, graphicBuffer->getGenerationNumber());
+}
+
+TEST_F(SurfaceTest, GetConsumerName) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+    EXPECT_STREQ("TestConsumer", surface->getConsumerName().string());
+}
+
 }
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 6a42a22..e55db30 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -278,7 +278,7 @@
 }
 
 size_t GraphicBuffer::getFlattenedSize() const {
-    return static_cast<size_t>(10 + (handle ? handle->numInts : 0)) * sizeof(int);
+    return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
@@ -301,15 +301,16 @@
     buf[5] = usage;
     buf[6] = static_cast<int32_t>(mId >> 32);
     buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
-    buf[8] = 0;
+    buf[8] = static_cast<int32_t>(mGenerationNumber);
     buf[9] = 0;
+    buf[10] = 0;
 
     if (handle) {
-        buf[8] = handle->numFds;
-        buf[9] = handle->numInts;
+        buf[9] = handle->numFds;
+        buf[10] = handle->numInts;
         memcpy(fds, handle->data,
                 static_cast<size_t>(handle->numFds) * sizeof(int));
-        memcpy(&buf[10], handle->data + handle->numFds,
+        memcpy(&buf[11], handle->data + handle->numFds,
                 static_cast<size_t>(handle->numInts) * sizeof(int));
     }
 
@@ -325,20 +326,20 @@
 
 status_t GraphicBuffer::unflatten(
         void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-    if (size < 8*sizeof(int)) return NO_MEMORY;
+    if (size < 11 * sizeof(int)) return NO_MEMORY;
 
     int const* buf = static_cast<int const*>(buffer);
     if (buf[0] != 'GBFR') return BAD_TYPE;
 
-    const size_t numFds  = static_cast<size_t>(buf[8]);
-    const size_t numInts = static_cast<size_t>(buf[9]);
+    const size_t numFds  = static_cast<size_t>(buf[9]);
+    const size_t numInts = static_cast<size_t>(buf[10]);
 
     // Limit the maxNumber to be relatively small. The number of fds or ints
     // should not come close to this number, and the number itself was simply
     // chosen to be high enough to not cause issues and low enough to prevent
     // overflow problems.
     const size_t maxNumber = 4096;
-    if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
+    if (numFds >= maxNumber || numInts >= (maxNumber - 11)) {
         width = height = stride = format = usage = 0;
         handle = NULL;
         ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
@@ -346,7 +347,7 @@
         return BAD_VALUE;
     }
 
-    const size_t sizeNeeded = (10 + numInts) * sizeof(int);
+    const size_t sizeNeeded = (11 + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
     size_t fdCountNeeded = numFds;
@@ -372,7 +373,7 @@
             return NO_MEMORY;
         }
         memcpy(h->data, fds, numFds * sizeof(int));
-        memcpy(h->data + numFds, &buf[10], numInts * sizeof(int));
+        memcpy(h->data + numFds, &buf[11], numInts * sizeof(int));
         handle = h;
     } else {
         width = height = stride = format = usage = 0;
@@ -382,6 +383,8 @@
     mId = static_cast<uint64_t>(buf[6]) << 32;
     mId |= static_cast<uint32_t>(buf[7]);
 
+    mGenerationNumber = static_cast<uint32_t>(buf[8]);
+
     mOwner = ownHandle;
 
     if (handle != 0) {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index b54503e..f3cb0e6 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3104,9 +3104,12 @@
             && mParameters.hasAssociatedDisplay) {
         mSource = AINPUT_SOURCE_TOUCHSCREEN;
         mDeviceMode = DEVICE_MODE_DIRECT;
-        if (hasStylus() || hasExternalStylus()) {
+        if (hasStylus()) {
             mSource |= AINPUT_SOURCE_STYLUS;
         }
+        if (hasExternalStylus()) {
+            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
+        }
     } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
         mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
         mDeviceMode = DEVICE_MODE_NAVIGATION;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 6267a4c..dd1bccf 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -89,7 +89,7 @@
         result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
                             info.batchParams.size());
         for (size_t j = 0; j < info.batchParams.size(); j++) {
-            BatchParams params = info.batchParams.valueAt(j);
+            const BatchParams& params = info.batchParams.valueAt(j);
             result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index ae8b3b3..550107c 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -66,7 +66,7 @@
 
 const char* SensorService::WAKE_LOCK_NAME = "SensorService";
 // Permissions.
-static const String16 sDataInjectionPermission("android.permission.HARDWARE_TEST");
+static const String16 sDataInjectionPermission("android.permission.LOCATION_HARDWARE");
 static const String16 sDump("android.permission.DUMP");
 
 SensorService::SensorService()
@@ -195,9 +195,14 @@
             mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
             mCurrentOperatingMode = NORMAL;
 
+            mNextSensorRegIndex = 0;
+            for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
+                mLastNSensorRegistrations.push();
+            }
+
+            mInitCheck = NO_ERROR;
             mAckReceiver = new SensorEventAckReceiver(this);
             mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
-            mInitCheck = NO_ERROR;
             run("SensorService", PRIORITY_URGENT_DISPLAY);
         }
     }
@@ -271,6 +276,8 @@
                 dev.enableAllSensors();
             }
             return status_t(NO_ERROR);
+        } else if (mSensorList.size() == 0) {
+            result.append("No Sensors on the device\n");
         } else {
             // Default dump the sensor list and debugging information.
             result.append("Sensor List:\n");
@@ -322,11 +329,14 @@
                     result.appendFormat("non-wakeUp | ");
                 }
 
-                const CircularBuffer* buf = mLastEventSeen.valueFor(s.getHandle());
-                if (buf != NULL && s.getRequiredPermission().isEmpty()) {
-                    buf->printBuffer(result);
-                } else {
-                    result.append("last=<> \n");
+                int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
+                if (bufIndex >= 0) {
+                    const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
+                    if (buf != NULL && s.getRequiredPermission().isEmpty()) {
+                        buf->printBuffer(result);
+                    } else {
+                        result.append("last=<> \n");
+                    }
                 }
                 result.append("\n");
             }
@@ -344,7 +354,8 @@
 
             result.appendFormat("Socket Buffer size = %d events\n",
                                 mSocketBufferSize/sizeof(sensors_event_t));
-            result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
+            result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" :
+                    "not held");
             result.appendFormat("Mode :");
             switch(mCurrentOperatingMode) {
                case NORMAL:
@@ -365,6 +376,34 @@
                     connection->dump(result);
                 }
             }
+
+            result.appendFormat("Previous Registrations:\n");
+            // Log in the reverse chronological order.
+            int currentIndex = (mNextSensorRegIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                SENSOR_REGISTRATIONS_BUF_SIZE;
+            const int startIndex = currentIndex;
+            do {
+                const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[currentIndex];
+                if (SensorRegistrationInfo::isSentinel(reg_info)) {
+                    // Ignore sentinel, proceed to next item.
+                    currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                        SENSOR_REGISTRATIONS_BUF_SIZE;
+                    continue;
+                }
+                if (reg_info.mActivated) {
+                   result.appendFormat("%02d:%02d:%02d activated package=%s handle=0x%08x "
+                           "samplingRate=%dus maxReportLatency=%dus\n",
+                           reg_info.mHour, reg_info.mMin, reg_info.mSec,
+                           reg_info.mPackageName.string(), reg_info.mSensorHandle,
+                           reg_info.mSamplingRateUs, reg_info.mMaxReportLatencyUs);
+                } else {
+                   result.appendFormat("%02d:%02d:%02d de-activated package=%s handle=0x%08x\n",
+                           reg_info.mHour, reg_info.mMin, reg_info.mSec,
+                           reg_info.mPackageName.string(), reg_info.mSensorHandle);
+                }
+                currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                        SENSOR_REGISTRATIONS_BUF_SIZE;
+            } while(startIndex != currentIndex);
         }
     }
     write(fd, result.string(), result.size());
@@ -888,6 +927,19 @@
 
     if (err == NO_ERROR) {
         connection->updateLooperRegistration(mLooper);
+        SensorRegistrationInfo &reg_info =
+            mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+        reg_info.mSensorHandle = handle;
+        reg_info.mSamplingRateUs = samplingPeriodNs/1000;
+        reg_info.mMaxReportLatencyUs = maxBatchReportLatencyNs/1000;
+        reg_info.mActivated = true;
+        reg_info.mPackageName = connection->getPackageName();
+        time_t rawtime = time(NULL);
+        struct tm * timeinfo = localtime(&rawtime);
+        reg_info.mHour = timeinfo->tm_hour;
+        reg_info.mMin = timeinfo->tm_min;
+        reg_info.mSec = timeinfo->tm_sec;
+        mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
     }
 
     if (err != NO_ERROR) {
@@ -908,6 +960,20 @@
     if (err == NO_ERROR) {
         SensorInterface* sensor = mSensorMap.valueFor(handle);
         err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+
+    }
+    if (err == NO_ERROR) {
+        SensorRegistrationInfo &reg_info =
+            mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+        reg_info.mActivated = false;
+        reg_info.mPackageName= connection->getPackageName();
+        reg_info.mSensorHandle = handle;
+        time_t rawtime = time(NULL);
+        struct tm * timeinfo = localtime(&rawtime);
+        reg_info.mHour = timeinfo->tm_hour;
+        reg_info.mMin = timeinfo->tm_min;
+        reg_info.mSec = timeinfo->tm_sec;
+        mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
     }
     return err;
 }
@@ -1180,14 +1246,38 @@
     mPendingFlushConnections.clear();
 }
 
+
+// ---------------------------------------------------------------------------
+SensorService::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
+    mTimestamp = -1;
+    const int numData = SensorService::getNumEventsForSensorType(sensorType);
+    if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
+        mStepCounter = 0;
+    } else {
+        mData = new float[numData];
+        for (int i = 0; i < numData; ++i) {
+            mData[i] = -1.0;
+        }
+    }
+    mHour = mMin = mSec = INT32_MIN;
+}
+
+bool SensorService::TrimmedSensorEvent::isSentinel(const TrimmedSensorEvent& event) {
+    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
+}
 // --------------------------------------------------------------------------
 SensorService::CircularBuffer::CircularBuffer(int sensor_event_type) {
     mNextInd = 0;
-    mTrimmedSensorEventArr = new TrimmedSensorEvent *[CIRCULAR_BUF_SIZE];
+    mBufSize = CIRCULAR_BUF_SIZE;
+    if (sensor_event_type == SENSOR_TYPE_STEP_COUNTER ||
+            sensor_event_type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+            sensor_event_type == SENSOR_TYPE_ACCELEROMETER) {
+        mBufSize = CIRCULAR_BUF_SIZE * 5;
+    }
+    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
     mSensorType = sensor_event_type;
-    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
-    for (int i = 0; i < CIRCULAR_BUF_SIZE; ++i) {
-        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(numData, mSensorType);
+    for (int i = 0; i < mBufSize; ++i) {
+        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
     }
 }
 
@@ -1205,17 +1295,17 @@
     curr_event->mHour = timeinfo->tm_hour;
     curr_event->mMin = timeinfo->tm_min;
     curr_event->mSec = timeinfo->tm_sec;
-    mNextInd = (mNextInd + 1) % CIRCULAR_BUF_SIZE;
+    mNextInd = (mNextInd + 1) % mBufSize;
 }
 
 void SensorService::CircularBuffer::printBuffer(String8& result) const {
     const int numData = SensorService::getNumEventsForSensorType(mSensorType);
     int i = mNextInd, eventNum = 1;
-    result.appendFormat("last %d events = < ", CIRCULAR_BUF_SIZE);
+    result.appendFormat("last %d events = < ", mBufSize);
     do {
-        if (mTrimmedSensorEventArr[i]->mTimestamp == -1) {
+        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
             // Sentinel, ignore.
-            i = (i + 1) % CIRCULAR_BUF_SIZE;
+            i = (i + 1) % mBufSize;
             continue;
         }
         result.appendFormat("%d) ", eventNum++);
@@ -1229,15 +1319,15 @@
         result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
                 mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
                 mTrimmedSensorEventArr[i]->mSec);
-        i = (i + 1) % CIRCULAR_BUF_SIZE;
+        i = (i + 1) % mBufSize;
     } while (i != mNextInd);
     result.appendFormat(">\n");
 }
 
 bool SensorService::CircularBuffer::populateLastEvent(sensors_event_t *event) {
-    int lastEventInd = (mNextInd - 1 + CIRCULAR_BUF_SIZE) % CIRCULAR_BUF_SIZE;
+    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
     // Check if the buffer is empty.
-    if (mTrimmedSensorEventArr[lastEventInd]->mTimestamp == -1) {
+    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
         return false;
     }
     event->version = sizeof(sensors_event_t);
@@ -1253,7 +1343,7 @@
 }
 
 SensorService::CircularBuffer::~CircularBuffer() {
-    for (int i = 0; i < CIRCULAR_BUF_SIZE; ++i) {
+    for (int i = 0; i < mBufSize; ++i) {
         delete mTrimmedSensorEventArr[i];
     }
     delete [] mTrimmedSensorEventArr;
@@ -1299,8 +1389,9 @@
 void SensorService::SensorEventConnection::dump(String8& result) {
     Mutex::Autolock _l(mConnectionLock);
     result.appendFormat("Operating Mode: %s\n", mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
-    result.appendFormat("\t%s | WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
-            mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
+    result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
+            "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
+            mMaxCacheSize);
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
         result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 7c466c1..0a7abe8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -54,6 +54,7 @@
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
 #define CIRCULAR_BUF_SIZE 10
+#define SENSOR_REGISTRATIONS_BUF_SIZE 20
 
 struct sensors_poll_device_t;
 struct sensors_module_t;
@@ -272,18 +273,8 @@
         // for debugging.
         int32_t mHour, mMin, mSec;
 
-        TrimmedSensorEvent(int numData, int sensorType) {
-            mTimestamp = -1;
-            if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
-                mStepCounter = 0;
-            } else {
-                mData = new float[numData];
-                for (int i = 0; i < numData; ++i) {
-                    mData[i] = -1.0;
-                }
-            }
-            mHour = mMin = mSec = 0;
-        }
+        TrimmedSensorEvent(int sensorType);
+        static bool isSentinel(const TrimmedSensorEvent& event);
 
         ~TrimmedSensorEvent() {
             delete [] mData;
@@ -297,6 +288,7 @@
     class CircularBuffer {
         int mNextInd;
         int mSensorType;
+        int mBufSize;
         TrimmedSensorEvent ** mTrimmedSensorEventArr;
     public:
         CircularBuffer(int sensor_event_type);
@@ -306,6 +298,25 @@
         ~CircularBuffer();
     };
 
+    struct SensorRegistrationInfo {
+        int32_t mSensorHandle;
+        String8 mPackageName;
+        bool mActivated;
+        int32_t mSamplingRateUs;
+        int32_t mMaxReportLatencyUs;
+        int32_t mHour, mMin, mSec;
+
+        SensorRegistrationInfo() : mPackageName() {
+            mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
+            mHour = mMin = mSec = INT32_MIN;
+            mActivated = false;
+        }
+
+        static bool isSentinel(const SensorRegistrationInfo& info) {
+           return (info.mHour == INT32_MIN && info.mMin == INT32_MIN && info.mSec == INT32_MIN);
+        }
+    };
+
     static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
@@ -387,6 +398,8 @@
     // The size of this vector is constant, only the items are mutable
     KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
 
+    int mNextSensorRegIndex;
+    Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
 public:
     void cleanupConnection(SensorEventConnection* connection);
     status_t enable(const sp<SensorEventConnection>& connection, int handle,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 02c31ff..2dad005 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -635,6 +635,7 @@
 }
 
 status_t HWComposer::prepare() {
+    Mutex::Autolock _l(mDisplayLock);
     for (size_t i=0 ; i<mNumDisplays ; i++) {
         DisplayData& disp(mDisplayData[i]);
         if (disp.framebufferTarget) {
@@ -1145,6 +1146,7 @@
 }
 
 void HWComposer::dump(String8& result) const {
+    Mutex::Autolock _l(mDisplayLock);
     if (mHwc) {
         result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 28d8c65..cc98b4c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -354,6 +354,8 @@
     // mLists[i>0] can be NULL. that display is to be ignored
     struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
     DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    // protect mDisplayData from races between prepare and dump
+    mutable Mutex mDisplayLock;
     size_t                          mNumDisplays;
 
     cb_context*                     mCBContext;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 11cbdc6..ba4c198 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -530,6 +530,15 @@
     return INVALID_OPERATION;
 }
 
+status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
+    ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
+String8 VirtualDisplaySurface::getConsumerName() const {
+    return String8("VirtualDisplaySurface");
+}
+
 void VirtualDisplaySurface::updateQueueBufferOutput(
         const QueueBufferOutput& qbo) {
     uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 97af980..6298751 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -116,6 +116,8 @@
     virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
+    virtual status_t setGenerationNumber(uint32_t generationNumber);
+    virtual String8 getConsumerName() const override;
 
     //
     // Utility methods
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8d8af52..91f80b6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -76,7 +76,6 @@
         mFiltering(false),
         mNeedsFiltering(false),
         mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
-        mSecure(false),
         mProtectedByApp(false),
         mHasSurface(false),
         mClientRef(client),
@@ -96,6 +95,8 @@
         layerFlags |= layer_state_t::eLayerHidden;
     if (flags & ISurfaceComposerClient::eOpaque)
         layerFlags |= layer_state_t::eLayerOpaque;
+    if (flags & ISurfaceComposerClient::eSecure)
+        layerFlags |= layer_state_t::eLayerSecure;
 
     if (flags & ISurfaceComposerClient::eNonPremultiplied)
         mPremultipliedAlpha = false;
@@ -256,7 +257,6 @@
     mFormat = format;
 
     mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
-    mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
     mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
     mCurrentOpacity = getOpacityForFormat(format);
 
@@ -551,16 +551,7 @@
     const Transform& tr = hw->getTransform();
     Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
     layer.setVisibleRegionScreen(visible);
-
-    // Pass full-surface damage down untouched
-    if (surfaceDamageRegion.isRect() &&
-            surfaceDamageRegion.getBounds() == Rect::INVALID_RECT) {
-        layer.setSurfaceDamage(surfaceDamageRegion);
-    } else {
-        Region surfaceDamage =
-            tr.transform(surfaceDamageRegion.intersect(hw->getViewport()));
-        layer.setSurfaceDamage(surfaceDamage);
-    }
+    layer.setSurfaceDamage(surfaceDamageRegion);
 
     if (mSidebandStream.get()) {
         layer.setSidebandStream(mSidebandStream);
@@ -860,6 +851,12 @@
     return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
 }
 
+bool Layer::isSecure() const
+{
+    const Layer::State& s(mDrawingState);
+    return (s.flags & layer_state_t::eLayerSecure);
+}
+
 bool Layer::isProtected() const
 {
     const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4e222b7..c1e5e9f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -174,7 +174,7 @@
      * isSecure - true if this surface is secure, that is if it prevents
      * screenshots or VNC servers.
      */
-    virtual bool isSecure() const           { return mSecure; }
+    virtual bool isSecure() const;
 
     /*
      * isProtected - true if the layer may contain protected content in the
@@ -402,7 +402,6 @@
     mutable Texture mTexture;
 
     // page-flip thread (currently main thread)
-    bool mSecure; // no screenshots
     bool mProtectedByApp; // application requires protected path to external sink
 
     // protected by mLock
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 9fb555b..fb7af97 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -114,6 +114,14 @@
     return mProducer->allowAllocation(allow);
 }
 
+status_t MonitoredProducer::setGenerationNumber(uint32_t generationNumber) {
+    return mProducer->setGenerationNumber(generationNumber);
+}
+
+String8 MonitoredProducer::getConsumerName() const {
+    return mProducer->getConsumerName();
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return IInterface::asBinder(mProducer).get();
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index b2f8293..da95766 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -54,6 +54,8 @@
     virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
+    virtual status_t setGenerationNumber(uint32_t generationNumber);
+    virtual String8 getConsumerName() const override;
     virtual IBinder* onAsBinder();
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1388ce8..de0f921 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -550,7 +550,7 @@
 
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
-    if (configs == NULL) {
+    if ((configs == NULL) || (display.get() == NULL)) {
         return BAD_VALUE;
     }
 
@@ -2235,9 +2235,7 @@
             if (layer->setTransparentRegionHint(s.transparentRegion))
                 flags |= eTraversalNeeded;
         }
-        if ((what & layer_state_t::eVisibilityChanged) ||
-                (what & layer_state_t::eOpacityChanged)) {
-            // TODO: should we just use an eFlagsChanged for this?
+        if (what & layer_state_t::eFlagsChanged) {
             if (layer->setFlags(s.flags, s.mask))
                 flags |= eTraversalNeeded;
         }
@@ -3320,8 +3318,12 @@
     ATRACE_CALL();
 
     // get screen geometry
-    const uint32_t hw_w = hw->getWidth();
-    const uint32_t hw_h = hw->getHeight();
+    uint32_t hw_w = hw->getWidth();
+    uint32_t hw_h = hw->getHeight();
+
+    if (rotation & Transform::ROT_90) {
+        std::swap(hw_w, hw_h);
+    }
 
     if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
         ALOGE("size mismatch (%d, %d) > (%d, %d)",