Merge "Atrace: store app list in multiple sysprops" into nyc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ea14c66..b731c53 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -95,6 +95,10 @@
 // TODO: change to "v1" before final N build
 static std::string VERSION_DEFAULT = "v1-dev4";
 
+static bool is_user_build() {
+    return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
+}
+
 /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
  * otherwise gets just those modified in the last half an hour. */
 static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
@@ -872,7 +876,7 @@
     char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
     property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
     if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
-        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
+        if (is_user_build()) {
             // su does not exist on user builds, so try running without it.
             // This way any implementations of vril-dump that do not require
             // root can run on user builds.
@@ -976,6 +980,15 @@
         return false;
     }
 
+    if (is_user_build()) {
+        MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
+        if (remove(bugreport_path.c_str())) {
+            ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
+        }
+    } else {
+        MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
+    }
+
     return true;
 }
 
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index f4d894b..60118a8 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -725,7 +725,7 @@
 static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
         const char* output_file_name, int swap_fd, const char *instruction_set,
         const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete,
-        int profile_fd) {
+        int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -887,7 +887,8 @@
                      + (debuggable ? 1 : 0)
                      + (have_app_image_format ? 1 : 0)
                      + dex2oat_flags_count
-                     + (profile_fd == -1 ? 0 : 1)];
+                     + (profile_fd == -1 ? 0 : 1)
+                     + (shared_libraries != nullptr ? 4 : 0)];
     int i = 0;
     argv[i++] = DEX2OAT_BIN;
     argv[i++] = zip_fd_arg;
@@ -940,6 +941,12 @@
     if (profile_fd != -1) {
         argv[i++] = profile_arg;
     }
+    if (shared_libraries != nullptr) {
+        argv[i++] = RUNTIME_ARG;
+        argv[i++] = "-classpath";
+        argv[i++] = RUNTIME_ARG;
+        argv[i++] = shared_libraries;
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -1311,7 +1318,7 @@
 
 int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
            int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-           const char* volume_uuid ATTRIBUTE_UNUSED)
+           const char* volume_uuid ATTRIBUTE_UNUSED, const char* shared_libraries)
 {
     struct utimbuf ut;
     struct stat input_stat;
@@ -1463,7 +1470,7 @@
             }
             run_dex2oat(input_fd, out_fd, image_fd, input_file_name, out_path, swap_fd,
                         instruction_set, compiler_filter, vm_safe_mode, debuggable, boot_complete,
-                        reference_profile_fd);
+                        reference_profile_fd, shared_libraries);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
             exit(73);
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 81c13b4..41cc209 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -56,7 +56,7 @@
 
 int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
            int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-           const char* volume_uuid);
+           const char* volume_uuid, const char* shared_libraries);
 int mark_boot_complete(const char *instruction_set);
 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index eb51e70..e8fce91 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -266,7 +266,8 @@
                   arg[5],                      // oat_dir
                   dexopt_flags,
                   arg[7],                      // compiler_filter
-                  parse_null(arg[8]));         // volume_uuid
+                  parse_null(arg[8]),          // volume_uuid
+                  parse_null(arg[9]));         // shared_libraries
 }
 
 static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
@@ -414,7 +415,7 @@
     { "create_user_data",     4, do_create_user_data },
     { "destroy_user_data",    3, do_destroy_user_data },
 
-    { "dexopt",               9, do_dexopt },
+    { "dexopt",              10, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "rmdex",                2, do_rm_dex },
     { "freecache",            2, do_free_cache },
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 245694a..ac511ec 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -365,7 +365,8 @@
                 package_parameters_[5],                   // oat_dir
                 atoi(package_parameters_[6]),             // dexopt_flags
                 package_parameters_[7],                   // compiler_filter
-                ParseNull(package_parameters_[8]));       // volume_uuid
+                ParseNull(package_parameters_[8]),        // volume_uuid
+                ParseNull(package_parameters_[9]));       // shared_libraries
         return ret;
     }
 
@@ -483,7 +484,7 @@
     // to compile, instead of the A properties we could get from init/get_property.
     SystemProperties system_properties_;
 
-    const char* package_parameters_[9];
+    const char* package_parameters_[10];
 
     // Store environment values we need to set.
     std::vector<std::string> environ_;
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 1ba339d..aee7bd8 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -11,4 +11,5 @@
     onrestart restart inputflinger
     onrestart restart drm
     onrestart restart cameraserver
+    writepid /dev/cpuset/system-background/tasks
 
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 7256f73..a75ed98 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -184,7 +184,7 @@
 
     // See IGraphicBufferProducer::getLastQueuedBuffer
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
 
 private:
     // This is required by the IBinder::DeathRecipient interface
@@ -227,6 +227,9 @@
     // since the previous buffer might have already been acquired.
     sp<Fence> mLastQueueBufferFence;
 
+    Rect mLastQueuedCrop;
+    uint32_t mLastQueuedTransform;
+
     // Take-a-ticket system for ensuring that onFrame* callbacks are called in
     // the order that frames are queued. While the BufferQueue lock
     // (mCore->mMutex) is held, a ticket is retained by the producer. After
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 8de3302..6267625 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -132,6 +132,12 @@
     // functions.
     void getTransformMatrix(float mtx[16]);
 
+    // Computes the transform matrix documented by getTransformMatrix
+    // from the BufferItem sub parts.
+    static void computeTransformMatrix(float outTransform[16],
+            const sp<GraphicBuffer>& buf, const Rect& cropRect,
+            uint32_t transform, bool filtering);
+
     // getTimestamp retrieves the timestamp associated with the texture image
     // set by the most recent call to updateTexImage.
     //
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 049406c..37ae6df 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -563,9 +563,11 @@
     // the queue, outBuffer will be populated with nullptr and outFence will be
     // populated with Fence::NO_FENCE
     //
+    // outTransformMatrix is not modified if outBuffer is null.
+    //
     // Returns NO_ERROR or the status of the Binder transaction
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) = 0;
+            sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 353003c..3f60741 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -52,12 +52,18 @@
         TYPE_PROXIMITY      = ASENSOR_TYPE_PROXIMITY
     };
 
-    typedef struct {
-        uint8_t b[16];
-    } uuid_t;
+    struct uuid_t{
+        union {
+            uint8_t b[16];
+            int64_t i64[2];
+        };
+        uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+        uuid_t() : b{0} {}
+    };
 
     Sensor(const char * name = "");
     Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+    Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
     ~Sensor();
 
     const String8& getName() const;
@@ -81,6 +87,7 @@
     uint32_t getFlags() const;
     bool isWakeUpSensor() const;
     bool isDynamicSensor() const;
+    bool hasAdditionalInfo() const;
     int32_t getReportingMode() const;
     const uuid_t& getUuid() const;
 
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index bbf427d..646203b 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -130,8 +130,9 @@
     bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
 
     // See IGraphicBufferProducer::getLastQueuedBuffer
+    // See GLConsumer::getTransformMatrix for outTransformMatrix format
     status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence);
+            sp<Fence>* outFence, float outTransformMatrix[16]);
 
 protected:
     virtual ~Surface();
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 4bb5f9a..bf15ee4 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -77,35 +77,35 @@
 
 /** VP9 profiles */
 typedef enum OMX_VIDEO_VP9PROFILETYPE {
-    OMX_VIDEO_VP9Profile0 = 0x1,
-    OMX_VIDEO_VP9Profile1 = 0x2,
-    OMX_VIDEO_VP9Profile2 = 0x4,
-    OMX_VIDEO_VP9Profile3 = 0x8,
+    OMX_VIDEO_VP9Profile0       = 0x1,
+    OMX_VIDEO_VP9Profile1       = 0x2,
+    OMX_VIDEO_VP9Profile2       = 0x4,
+    OMX_VIDEO_VP9Profile3       = 0x8,
     // HDR profiles also support passing HDR metadata
-    OMX_VIDEO_VP9Profile2HDR = 0x1000,
-    OMX_VIDEO_VP9Profile3HDR = 0x2000,
+    OMX_VIDEO_VP9Profile2HDR    = 0x1000,
+    OMX_VIDEO_VP9Profile3HDR    = 0x2000,
     OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
-    OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
+    OMX_VIDEO_VP9ProfileMax     = 0x7FFFFFFF
 } OMX_VIDEO_VP9PROFILETYPE;
 
 /** VP9 levels */
 typedef enum OMX_VIDEO_VP9LEVELTYPE {
-    OMX_VIDEO_VP9Level1  = 0x0,
-    OMX_VIDEO_VP9Level11 = 0x1,
-    OMX_VIDEO_VP9Level2  = 0x2,
-    OMX_VIDEO_VP9Level21 = 0x4,
-    OMX_VIDEO_VP9Level3  = 0x8,
-    OMX_VIDEO_VP9Level31 = 0x10,
-    OMX_VIDEO_VP9Level4  = 0x20,
-    OMX_VIDEO_VP9Level41 = 0x40,
-    OMX_VIDEO_VP9Level5  = 0x80,
-    OMX_VIDEO_VP9Level51 = 0x100,
-    OMX_VIDEO_VP9Level52 = 0x200,
-    OMX_VIDEO_VP9Level6  = 0x400,
-    OMX_VIDEO_VP9Level61 = 0x800,
-    OMX_VIDEO_VP9Level62 = 0x1000,
+    OMX_VIDEO_VP9Level1       = 0x1,
+    OMX_VIDEO_VP9Level11      = 0x2,
+    OMX_VIDEO_VP9Level2       = 0x4,
+    OMX_VIDEO_VP9Level21      = 0x8,
+    OMX_VIDEO_VP9Level3       = 0x10,
+    OMX_VIDEO_VP9Level31      = 0x20,
+    OMX_VIDEO_VP9Level4       = 0x40,
+    OMX_VIDEO_VP9Level41      = 0x80,
+    OMX_VIDEO_VP9Level5       = 0x100,
+    OMX_VIDEO_VP9Level51      = 0x200,
+    OMX_VIDEO_VP9Level52      = 0x400,
+    OMX_VIDEO_VP9Level6       = 0x800,
+    OMX_VIDEO_VP9Level61      = 0x1000,
+    OMX_VIDEO_VP9Level62      = 0x2000,
     OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF,
-    OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF
+    OMX_VIDEO_VP9LevelMax     = 0x7FFFFFFF
 } OMX_VIDEO_VP9LEVELTYPE;
 
 /** VP8 Param */
@@ -262,6 +262,7 @@
     OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
     OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
     OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+    OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
     OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
 } OMX_VIDEO_DOLBYVISIONPROFILETYPE;
 
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 620cf89..3e26e05 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -31,6 +31,7 @@
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
 #include <gui/BufferQueueProducer.h>
+#include <gui/GLConsumer.h>
 #include <gui/IConsumerListener.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
@@ -844,30 +845,31 @@
             mCore->mQueue.push_back(item);
             frameAvailableListener = mCore->mConsumerListener;
         } else {
-            // When the queue is not empty, we need to look at the front buffer
-            // state to see if we need to replace it
-            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
-            if (front->mIsDroppable) {
+            // When the queue is not empty, we need to look at the last buffer
+            // in the queue to see if we need to replace it
+            const BufferItem& last = mCore->mQueue.itemAt(
+                    mCore->mQueue.size() - 1);
+            if (last.mIsDroppable) {
 
-                if (!front->mIsStale) {
-                    mSlots[front->mSlot].mBufferState.freeQueued();
+                if (!last.mIsStale) {
+                    mSlots[last.mSlot].mBufferState.freeQueued();
 
                     // After leaving shared buffer mode, the shared buffer will
                     // still be around. Mark it as no longer shared if this
                     // operation causes it to be free.
                     if (!mCore->mSharedBufferMode &&
-                            mSlots[front->mSlot].mBufferState.isFree()) {
-                        mSlots[front->mSlot].mBufferState.mShared = false;
+                            mSlots[last.mSlot].mBufferState.isFree()) {
+                        mSlots[last.mSlot].mBufferState.mShared = false;
                     }
                     // Don't put the shared buffer on the free list.
-                    if (!mSlots[front->mSlot].mBufferState.isShared()) {
-                        mCore->mActiveBuffers.erase(front->mSlot);
-                        mCore->mFreeBuffers.push_back(front->mSlot);
+                    if (!mSlots[last.mSlot].mBufferState.isShared()) {
+                        mCore->mActiveBuffers.erase(last.mSlot);
+                        mCore->mFreeBuffers.push_back(last.mSlot);
                     }
                 }
 
                 // Overwrite the droppable buffer with the incoming one
-                *front = item;
+                mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                 frameReplacedListener = mCore->mConsumerListener;
             } else {
                 mCore->mQueue.push_back(item);
@@ -922,6 +924,8 @@
         mLastQueueBufferFence->waitForever("Throttling EGL Production");
     }
     mLastQueueBufferFence = fence;
+    mLastQueuedCrop = item.mCrop;
+    mLastQueuedTransform = item.mTransform;
 
     return NO_ERROR;
 }
@@ -1279,11 +1283,14 @@
 
                 // freeBufferLocked puts this slot on the free slots list. Since
                 // we then attached a buffer, move the slot to free buffer list.
-                mCore->mFreeSlots.erase(slot);
                 mCore->mFreeBuffers.push_front(*slot);
 
                 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
                         *slot);
+
+                // Make sure the erase is done after all uses of the slot
+                // iterator since it will be invalid after this point.
+                mCore->mFreeSlots.erase(slot);
             }
 
             mCore->mIsAllocating = false;
@@ -1368,7 +1375,7 @@
 }
 
 status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
     ATRACE_CALL();
     BQ_LOGV("getLastQueuedBuffer");
 
@@ -1382,6 +1389,14 @@
     *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
     *outFence = mLastQueueBufferFence;
 
+    // Currently only SurfaceFlinger internally ever changes
+    // GLConsumer's filtering mode, so we just use 'true' here as
+    // this is slightly specialized for the current client of this API,
+    // which does want filtering.
+    GLConsumer::computeTransformMatrix(outTransformMatrix,
+            mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop,
+            mLastQueuedTransform, true /* filter */);
+
     return NO_ERROR;
 }
 
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 3acd3ab..ac8bc6e 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -44,6 +44,8 @@
 
 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
 
 namespace android {
 
@@ -123,6 +125,26 @@
     return hasIt;
 }
 
+static bool hasEglProtectedContentImpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
+    bool atEnd = (cropExtLen+1) < extsLen &&
+            !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
+    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
+static bool hasEglProtectedContent() {
+    // Only compute whether the extension is present once the first time this
+    // function is called.
+    static bool hasIt = hasEglProtectedContentImpl();
+    return hasIt;
+}
+
 static bool isEglImageCroppable(const Rect& crop) {
     return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
 }
@@ -787,26 +809,40 @@
 
 void GLConsumer::computeCurrentTransformMatrixLocked() {
     GLC_LOGV("computeCurrentTransformMatrixLocked");
+    sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
+            nullptr : mCurrentTextureImage->graphicBuffer();
+    if (buf == nullptr) {
+        GLC_LOGD("computeCurrentTransformMatrixLocked: "
+                "mCurrentTextureImage is NULL");
+    }
+    computeTransformMatrix(mCurrentTransformMatrix, buf,
+        isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
+        mCurrentTransform, mFilteringEnabled);
+}
+
+void GLConsumer::computeTransformMatrix(float outTransform[16],
+        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
+        bool filtering) {
 
     float xform[16];
     for (int i = 0; i < 16; i++) {
         xform[i] = mtxIdentity[i];
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
         float result[16];
         mtxMul(result, xform, mtxFlipH);
         for (int i = 0; i < 16; i++) {
             xform[i] = result[i];
         }
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
         float result[16];
         mtxMul(result, xform, mtxFlipV);
         for (int i = 0; i < 16; i++) {
             xform[i] = result[i];
         }
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
         float result[16];
         mtxMul(result, xform, mtxRot90);
         for (int i = 0; i < 16; i++) {
@@ -814,59 +850,49 @@
         }
     }
 
-    sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ?
-            NULL : mCurrentTextureImage->graphicBuffer();
-
-    if (buf == NULL) {
-        GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
-    }
-
     float mtxBeforeFlipV[16];
-    if (!isEglImageCroppable(mCurrentCrop)) {
-        Rect cropRect = mCurrentCrop;
+    if (!cropRect.isEmpty()) {
         float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
         float bufferWidth = buf->getWidth();
         float bufferHeight = buf->getHeight();
-        if (!cropRect.isEmpty()) {
-            float shrinkAmount = 0.0f;
-            if (mFilteringEnabled) {
-                // In order to prevent bilinear sampling beyond the edge of the
-                // crop rectangle we may need to shrink it by 2 texels in each
-                // dimension.  Normally this would just need to take 1/2 a texel
-                // off each end, but because the chroma channels of YUV420 images
-                // are subsampled we may need to shrink the crop region by a whole
-                // texel on each side.
-                switch (buf->getPixelFormat()) {
-                    case PIXEL_FORMAT_RGBA_8888:
-                    case PIXEL_FORMAT_RGBX_8888:
-                    case PIXEL_FORMAT_RGB_888:
-                    case PIXEL_FORMAT_RGB_565:
-                    case PIXEL_FORMAT_BGRA_8888:
-                        // We know there's no subsampling of any channels, so we
-                        // only need to shrink by a half a pixel.
-                        shrinkAmount = 0.5;
-                        break;
+        float shrinkAmount = 0.0f;
+        if (filtering) {
+            // In order to prevent bilinear sampling beyond the edge of the
+            // crop rectangle we may need to shrink it by 2 texels in each
+            // dimension.  Normally this would just need to take 1/2 a texel
+            // off each end, but because the chroma channels of YUV420 images
+            // are subsampled we may need to shrink the crop region by a whole
+            // texel on each side.
+            switch (buf->getPixelFormat()) {
+                case PIXEL_FORMAT_RGBA_8888:
+                case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGB_888:
+                case PIXEL_FORMAT_RGB_565:
+                case PIXEL_FORMAT_BGRA_8888:
+                    // We know there's no subsampling of any channels, so we
+                    // only need to shrink by a half a pixel.
+                    shrinkAmount = 0.5;
+                    break;
 
-                    default:
-                        // If we don't recognize the format, we must assume the
-                        // worst case (that we care about), which is YUV420.
-                        shrinkAmount = 1.0;
-                        break;
-                }
+                default:
+                    // If we don't recognize the format, we must assume the
+                    // worst case (that we care about), which is YUV420.
+                    shrinkAmount = 1.0;
+                    break;
             }
+        }
 
-            // Only shrink the dimensions that are not the size of the buffer.
-            if (cropRect.width() < bufferWidth) {
-                tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
-                sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
-                        bufferWidth;
-            }
-            if (cropRect.height() < bufferHeight) {
-                ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
-                        bufferHeight;
-                sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
-                        bufferHeight;
-            }
+        // Only shrink the dimensions that are not the size of the buffer.
+        if (cropRect.width() < bufferWidth) {
+            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
+                    bufferWidth;
+        }
+        if (cropRect.height() < bufferHeight) {
+            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
+                    bufferHeight;
+            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
+                    bufferHeight;
         }
         float crop[16] = {
             sx, 0, 0, 0,
@@ -886,7 +912,7 @@
     // coordinate of 0, so GLConsumer must behave the same way.  We don't
     // want to expose this to applications, however, so we must add an
     // additional vertical flip to the transform after all the other transforms.
-    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
+    mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
 }
 
 nsecs_t GLConsumer::getTimestamp() {
@@ -1174,12 +1200,17 @@
         const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
     EGLClientBuffer cbuf =
             static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+    const bool createProtectedImage =
+            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
+            hasEglProtectedContent();
     EGLint attrs[] = {
         EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
         EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
         EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
         EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
         EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
+        createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+        createProtectedImage ? EGL_TRUE : EGL_NONE,
         EGL_NONE,
     };
     if (!crop.isValid()) {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index c36fcad..2c48d83 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -382,7 +382,7 @@
     }
 
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override {
+            sp<Fence>* outFence, float outTransformMatrix[16]) override {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
@@ -395,8 +395,15 @@
         if (result != NO_ERROR) {
             return result;
         }
-        sp<GraphicBuffer> buffer(new GraphicBuffer);
-        result = reply.read(*buffer);
+        bool hasBuffer = reply.readBool();
+        sp<GraphicBuffer> buffer;
+        if (hasBuffer) {
+            buffer = new GraphicBuffer();
+            result = reply.read(*buffer);
+            if (result == NO_ERROR) {
+                result = reply.read(outTransformMatrix, sizeof(float) * 16);
+            }
+        }
         if (result != NO_ERROR) {
             ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
             return result;
@@ -626,12 +633,21 @@
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             sp<GraphicBuffer> buffer(nullptr);
             sp<Fence> fence(Fence::NO_FENCE);
-            status_t result = getLastQueuedBuffer(&buffer, &fence);
+            float transform[16] = {};
+            status_t result = getLastQueuedBuffer(&buffer, &fence, transform);
             reply->writeInt32(result);
             if (result != NO_ERROR) {
                 return result;
             }
-            result = reply->write(*buffer);
+            if (!buffer.get()) {
+                reply->writeBool(false);
+            } else {
+                reply->writeBool(true);
+                result = reply->write(*buffer);
+                if (result == NO_ERROR) {
+                    reply->write(transform, sizeof(float) * 16);
+                }
+            }
             if (result != NO_ERROR) {
                 ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
                 return result;
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 0340d6b..cc865d1 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -14,69 +14,70 @@
  * limitations under the License.
  */
 
+
+#include <binder/AppOpsManager.h>
+#include <binder/IServiceManager.h>
+#include <gui/Sensor.h>
+#include <hardware/sensors.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Flattenable.h>
+
 #include <inttypes.h>
 #include <stdint.h>
 #include <sys/types.h>
 #include <sys/limits.h>
 
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/Flattenable.h>
-
-#include <hardware/sensors.h>
-
-#include <binder/AppOpsManager.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Sensor.h>
-#include <log/log.h>
-
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-Sensor::Sensor(const char * name)
-    : mName(name), mHandle(0), mType(0),
-      mMinValue(0), mMaxValue(0), mResolution(0),
-      mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
-      mFifoMaxEventCount(0), mRequiredAppOp(0),
-      mMaxDelay(0), mFlags(0)
-{
+Sensor::Sensor(const char * name) :
+        mName(name), mHandle(0), mType(0),
+        mMinValue(0), mMaxValue(0), mResolution(0),
+        mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
+        mFifoMaxEventCount(0), mRequiredAppOp(0),
+        mMaxDelay(0), mFlags(0) {
 }
 
-Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
-{
-    mName = hwSensor->name;
-    mVendor = hwSensor->vendor;
-    mVersion = hwSensor->version;
-    mHandle = hwSensor->handle;
-    mType = hwSensor->type;
+Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) :
+        Sensor(*hwSensor, uuid_t(), halVersion) {
+}
+
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+    mName = hwSensor.name;
+    mVendor = hwSensor.vendor;
+    mVersion = hwSensor.version;
+    mHandle = hwSensor.handle;
+    mType = hwSensor.type;
     mMinValue = 0;                      // FIXME: minValue
-    mMaxValue = hwSensor->maxRange;     // FIXME: maxValue
-    mResolution = hwSensor->resolution;
-    mPower = hwSensor->power;
-    mMinDelay = hwSensor->minDelay;
+    mMaxValue = hwSensor.maxRange;     // FIXME: maxValue
+    mResolution = hwSensor.resolution;
+    mPower = hwSensor.power;
+    mMinDelay = hwSensor.minDelay;
     mFlags = 0;
+    mUuid = uuid;
 
     // 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_0) {
-        mFifoReservedEventCount = hwSensor->fifoReservedEventCount;
-        mFifoMaxEventCount = hwSensor->fifoMaxEventCount;
+        mFifoReservedEventCount = hwSensor.fifoReservedEventCount;
+        mFifoMaxEventCount = hwSensor.fifoMaxEventCount;
     } else {
         mFifoReservedEventCount = 0;
         mFifoMaxEventCount = 0;
     }
 
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-        if (hwSensor->maxDelay > INT_MAX) {
+        if (hwSensor.maxDelay > INT_MAX) {
             // Max delay is declared as a 64 bit integer for 64 bit architectures. But it should
             // always fit in a 32 bit integer, log error and cap it to INT_MAX.
             ALOGE("Sensor maxDelay overflow error %s %" PRId64, mName.string(),
-                  static_cast<int64_t>(hwSensor->maxDelay));
+                  static_cast<int64_t>(hwSensor.maxDelay));
             mMaxDelay = INT_MAX;
         } else {
-            mMaxDelay = static_cast<int32_t>(hwSensor->maxDelay);
+            mMaxDelay = static_cast<int32_t>(hwSensor.maxDelay);
         }
     } else {
         // For older hals set maxDelay to 0.
@@ -245,11 +246,11 @@
         break;
     default:
         // Only pipe the stringType, requiredPermission and flags for custom sensors.
-        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) {
-            mStringType = hwSensor->stringType;
+        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
+            mStringType = hwSensor.stringType;
         }
-        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) {
-            mRequiredPermission = hwSensor->requiredPermission;
+        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) {
+            mRequiredPermission = hwSensor.requiredPermission;
             if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
                 AppOpsManager appOps;
                 mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
@@ -257,7 +258,7 @@
         }
 
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-            mFlags = static_cast<uint32_t>(hwSensor->flags);
+            mFlags = static_cast<uint32_t>(hwSensor.flags);
         } else {
             // This is an OEM defined sensor on an older HAL. Use minDelay to determine the
             // reporting mode of the sensor.
@@ -272,31 +273,28 @@
         break;
     }
 
+    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+        // Wake-up flag of HAL 1.3 and above is set here
+        mFlags |= (hwSensor.flags & SENSOR_FLAG_WAKE_UP);
+
+        // Log error if the reporting mode is not as expected, but respect HAL setting.
+        int actualReportingMode = (hwSensor.flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+        int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+        if (actualReportingMode != expectedReportingMode) {
+            ALOGE("Reporting Mode incorrect: sensor %s handle=%#010" PRIx32 " type=%" PRId32 " "
+                   "actual=%d expected=%d",
+                   mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
+        }
+    }
+
+    // Feature flags
     // Set DYNAMIC_SENSOR_MASK and ADDITIONAL_INFO_MASK flag here. Compatible with HAL 1_3.
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-        mFlags |= (hwSensor->flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
+        mFlags |= (hwSensor.flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
     }
-
     // Set DATA_INJECTION flag here. Defined in HAL 1_4.
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
-        mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
-    }
-
-    // For the newer HALs log errors if reporting mask flags are set incorrectly.
-    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-        // Wake-up flag is set here.
-        mFlags |= (hwSensor->flags & SENSOR_FLAG_WAKE_UP);
-        if (mFlags != hwSensor->flags) {
-            int actualReportingMode =
-                 (hwSensor->flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
-            int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
-            if (actualReportingMode != expectedReportingMode) {
-                ALOGE("Reporting Mode incorrect: sensor %s handle=%d type=%d "
-                       "actual=%d expected=%d",
-                       mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
-            }
-
-        }
+        mFlags |= (hwSensor.flags & DATA_INJECTION_MASK);
     }
 
     if (mRequiredPermission.length() > 0) {
@@ -311,8 +309,7 @@
     }
 }
 
-Sensor::~Sensor()
-{
+Sensor::~Sensor() {
 }
 
 const String8& Sensor::getName() const {
@@ -392,11 +389,15 @@
 }
 
 bool Sensor::isWakeUpSensor() const {
-    return mFlags & SENSOR_FLAG_WAKE_UP;
+    return (mFlags & SENSOR_FLAG_WAKE_UP) != 0;
 }
 
 bool Sensor::isDynamicSensor() const {
-    return mFlags & SENSOR_FLAG_DYNAMIC_SENSOR;
+    return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
+}
+
+bool Sensor::hasAdditionalInfo() const {
+    return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
 }
 
 int32_t Sensor::getReportingMode() const {
@@ -407,8 +408,7 @@
     return mUuid;
 }
 
-size_t Sensor::getFlattenedSize() const
-{
+size_t Sensor::getFlattenedSize() const {
     size_t fixedSize =
             sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) +
             sizeof(mMinValue) + sizeof(mMaxValue) + sizeof(mResolution) +
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b304633..6811269 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -128,8 +128,9 @@
 }
 
 status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
-    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence);
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
 }
 
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 9876d94..85d63b4 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -842,8 +842,10 @@
     // Make sure we got the second buffer back
     sp<GraphicBuffer> returnedBuffer;
     sp<Fence> returnedFence;
+    float transform[16];
     ASSERT_EQ(OK,
-            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence));
+            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
+            transform));
     ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
             returnedBuffer->getNativeBuffer()->handle);
 }
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index df639cd..00bfc24 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -117,6 +117,7 @@
         "EGL_KHR_create_context_no_error "
         "EGL_KHR_mutable_render_buffer "
         "EGL_EXT_yuv_surface "
+        "EGL_EXT_protected_content "
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
@@ -605,7 +606,6 @@
     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
     if (result == EGL_TRUE) {
         _s.terminate();
-        dp->removeSurface(surface);
     }
     return result;
 }
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index c368bad..e335a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -90,31 +90,6 @@
     return false;
 }
 
-void egl_display_t::addContext(egl_context_t* context) {
-    Mutex::Autolock _l(lock);
-    contexts.add(context);
-}
-
-void egl_display_t::removeContext(egl_context_t* context) {
-    Mutex::Autolock _l(lock);
-    contexts.remove(context);
-}
-
-void egl_display_t::removeSurface(EGLSurface surface) const {
-    Mutex::Autolock _l(lock);
-    for (size_t i = 0; i < contexts.size(); i++) {
-        egl_context_t* context = contexts[i];
-        if (context->read == surface) {
-            SurfaceRef _r(get_surface(context->read));
-            _r.release();
-        }
-        if (context->draw == surface) {
-            SurfaceRef _d(get_surface(context->draw));
-            _d.release();
-        }
-    }
-}
-
 EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
     if (uintptr_t(disp) >= NUM_DISPLAYS)
         return NULL;
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 0ede705..2d86295 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -68,13 +68,6 @@
     // add reference to this object. returns true if this is a valid object.
     bool getObject(egl_object_t* object) const;
 
-    // add context to this display's list
-    void addContext(egl_context_t* context);
-    // remove context from this display's list
-    void removeContext(egl_context_t* context);
-    // search for surface on all contexts and remove the references
-    void removeSurface(EGLSurface surface) const;
-
     // These notifications allow the display to keep track of how many window
     // surfaces exist, which it uses to decide whether to hibernate the
     // underlying EGL implementation. They can be called by any thread without
@@ -142,7 +135,6 @@
     mutable Mutex                       lock, refLock;
     mutable Condition                   refCond;
             SortedVector<egl_object_t*> objects;
-            SortedVector<egl_context_t*> contexts;
             String8 mVendorString;
             String8 mVersionString;
             String8 mClientApiString;
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 8859387..918faa8 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -91,12 +91,6 @@
         egl_connection_t const* cnx, int version) :
     egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context),
             config(config), read(0), draw(0), cnx(cnx), version(version) {
-    get_display_nowake(dpy)->addContext(this);
-}
-
-void egl_context_t::terminate() {
-    display->removeContext(this);
-    egl_object_t::terminate();
 }
 
 void egl_context_t::onLooseCurrent() {
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8268900..17a8304 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -40,12 +40,11 @@
 class egl_display_t;
 
 class egl_object_t {
+    egl_display_t *display;
     mutable volatile int32_t count;
 
 protected:
     virtual ~egl_object_t();
-    virtual void terminate();
-    egl_display_t *display;
 
 public:
     egl_object_t(egl_display_t* display);
@@ -56,6 +55,7 @@
     inline egl_display_t* getDisplay() const { return display; }
 
 private:
+    void terminate();
     static bool get(egl_display_t const* display, egl_object_t* object);
 
 public:
@@ -143,7 +143,6 @@
 class egl_context_t: public egl_object_t {
 protected:
     ~egl_context_t() {}
-    void terminate() override;
 public:
     typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
 
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 85e96d6..5a36961 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -2,21 +2,22 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	BatteryService.cpp \
-	CorrectedGyroSensor.cpp \
+    BatteryService.cpp \
+    CorrectedGyroSensor.cpp \
     Fusion.cpp \
     GravitySensor.cpp \
     LinearAccelerationSensor.cpp \
     OrientationSensor.cpp \
+    RecentEventLogger.cpp \
     RotationVectorSensor.cpp \
     SensorDevice.cpp \
+    SensorEventConnection.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
-    SensorService.cpp \
-    SensorEventConnection.cpp \
-    MostRecentEventLogger.cpp \
-    SensorRecord.cpp \
     SensorList.cpp \
+    SensorRecord.cpp \
+    SensorService.cpp \
+    SensorServiceUtils.cpp \
 
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
@@ -26,14 +27,14 @@
 LOCAL_CFLAGS += -fvisibility=hidden
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libhardware \
-	libhardware_legacy \
-	libutils \
-	liblog \
-	libbinder \
-	libui \
-	libgui
+    libcutils \
+    libhardware \
+    libhardware_legacy \
+    libutils \
+    liblog \
+    libbinder \
+    libui \
+    libgui
 
 LOCAL_MODULE:= libsensorservice
 
@@ -44,12 +45,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	main_sensorservice.cpp
+    main_sensorservice.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libsensorservice \
-	libbinder \
-	libutils
+    libsensorservice \
+    libbinder \
+    libutils
 
 LOCAL_CFLAGS := -Wall -Werror -Wextra
 
diff --git a/services/sensorservice/MostRecentEventLogger.cpp b/services/sensorservice/MostRecentEventLogger.cpp
deleted file mode 100644
index a5d8456..0000000
--- a/services/sensorservice/MostRecentEventLogger.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2010 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 "MostRecentEventLogger.h"
-
-#include <inttypes.h>
-
-namespace android {
-
-SensorService::MostRecentEventLogger::MostRecentEventLogger(int sensorType) :
-        mNextInd(0), mSensorType(sensorType) {
-
-    mBufSize = (sensorType == SENSOR_TYPE_STEP_COUNTER ||
-                sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
-                sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE : LOG_SIZE_LARGE;
-
-    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
-    mSensorType = sensorType;
-    for (int i = 0; i < mBufSize; ++i) {
-        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
-    }
-}
-
-void SensorService::MostRecentEventLogger::addEvent(const sensors_event_t& event) {
-    TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
-    curr_event->mTimestamp = event.timestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-        curr_event->mStepCounter = event.u64.step_counter;
-    } else {
-        memcpy(curr_event->mData, event.data,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    time_t rawtime = time(NULL);
-    struct tm * timeinfo = localtime(&rawtime);
-    curr_event->mHour = timeinfo->tm_hour;
-    curr_event->mMin = timeinfo->tm_min;
-    curr_event->mSec = timeinfo->tm_sec;
-    mNextInd = (mNextInd + 1) % mBufSize;
-}
-
-void SensorService::MostRecentEventLogger::printBuffer(String8& result) const {
-    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
-    int i = mNextInd, eventNum = 1;
-    result.appendFormat("last %d events = < ", mBufSize);
-    do {
-        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
-            // Sentinel, ignore.
-            i = (i + 1) % mBufSize;
-            continue;
-        }
-        result.appendFormat("%d) ", eventNum++);
-        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-            result.appendFormat("%" PRIu64 ",", mTrimmedSensorEventArr[i]->mStepCounter);
-        } else {
-            for (int j = 0; j < numData; ++j) {
-                result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
-            }
-        }
-        result.appendFormat("%" PRId64 " %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
-                mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
-                mTrimmedSensorEventArr[i]->mSec);
-        i = (i + 1) % mBufSize;
-    } while (i != mNextInd);
-    result.appendFormat(">\n");
-}
-
-bool SensorService::MostRecentEventLogger::populateLastEvent(sensors_event_t *event) {
-    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
-    // Check if the buffer is empty.
-    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
-        return false;
-    }
-    event->version = sizeof(sensors_event_t);
-    event->type = mSensorType;
-    event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-          event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
-    } else {
-        memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    return true;
-}
-
-SensorService::MostRecentEventLogger::~MostRecentEventLogger() {
-    for (int i = 0; i < mBufSize; ++i) {
-        delete mTrimmedSensorEventArr[i];
-    }
-    delete [] mTrimmedSensorEventArr;
-}
-
-// -----------------------------------------------------------------------------
-SensorService::MostRecentEventLogger::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::MostRecentEventLogger::TrimmedSensorEvent::
-    isSentinel(const TrimmedSensorEvent& event) {
-    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
-}
-
-} // namespace android
diff --git a/services/sensorservice/MostRecentEventLogger.h b/services/sensorservice/MostRecentEventLogger.h
deleted file mode 100644
index 68c1661..0000000
--- a/services/sensorservice/MostRecentEventLogger.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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_MOST_RECENT_EVENT_LOGGER_H
-#define ANDROID_MOST_RECENT_EVENT_LOGGER_H
-
-#include "SensorService.h"
-
-namespace android {
-
-class SensorService;
-
-// A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The last N
-// events generated from the sensor are stored in this buffer. The buffer is NOT cleared when the
-// sensor unregisters and as a result very old data in the dumpsys output can be seen, which is an
-// intended behavior.
-class SensorService::MostRecentEventLogger {
-public:
-    MostRecentEventLogger(int sensorType);
-    void addEvent(const sensors_event_t& event);
-    void printBuffer(String8& buffer) const;
-    bool populateLastEvent(sensors_event_t *event);
-    ~MostRecentEventLogger();
-
-private:
-    // sensor_event_t with only the data and the timestamp.
-    static const size_t LOG_SIZE = 10;
-    static const size_t LOG_SIZE_LARGE = 50;
-
-    struct TrimmedSensorEvent {
-        union {
-            float *mData;
-            uint64_t mStepCounter;
-        };
-        // Timestamp from the sensors_event_t.
-        int64_t mTimestamp;
-        // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
-        // for debugging.
-        int32_t mHour, mMin, mSec;
-
-        TrimmedSensorEvent(int sensorType);
-        static bool isSentinel(const TrimmedSensorEvent& event);
-
-        ~TrimmedSensorEvent() {
-            delete [] mData;
-        }
-    };
-
-    int mNextInd;
-    int mSensorType;
-    int mBufSize;
-    TrimmedSensorEvent ** mTrimmedSensorEventArr;
-};
-
-} // namespace android;
-
-#endif // ANDROID_MOST_RECENT_EVENT_LOGGER_H
-
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
new file mode 100644
index 0000000..dba7211
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 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 "RecentEventLogger.h"
+#include "SensorServiceUtils.h"
+
+#include <utils/Timers.h>
+
+#include <inttypes.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+namespace {
+    constexpr size_t LOG_SIZE = 10;
+    constexpr size_t LOG_SIZE_LARGE = 50;  // larger samples for debugging
+}// unnamed namespace
+
+RecentEventLogger::RecentEventLogger(int sensorType) :
+        mSensorType(sensorType), mEventSize(eventSizeBySensorType(mSensorType)),
+        mRecentEvents(logSizeBySensorType(sensorType)) {
+    // blank
+}
+
+void RecentEventLogger::addEvent(const sensors_event_t& event) {
+    std::lock_guard<std::mutex> lk(mLock);
+    mRecentEvents.emplace(event);
+}
+
+bool RecentEventLogger::isEmpty() const {
+    return mRecentEvents.size() == 0;
+}
+
+std::string RecentEventLogger::dump() const {
+    std::lock_guard<std::mutex> lk(mLock);
+
+    //TODO: replace String8 with std::string completely in this function
+    String8 buffer;
+
+    buffer.appendFormat("last %zu events\n", mRecentEvents.size());
+    int j = 0;
+    for (int i = mRecentEvents.size() - 1; i >= 0; --i) {
+        const auto& ev = mRecentEvents[i];
+        struct tm * timeinfo = localtime(&(ev.mWallTime.tv_sec));
+        buffer.appendFormat("\t%2d (ts=%.9f, wall=%02d:%02d:%02d.%03d) ",
+                ++j, ev.mEvent.timestamp/1e9, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
+                (int) ns2ms(ev.mWallTime.tv_nsec));
+
+        // data
+        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+            buffer.appendFormat("%" PRIu64 ", ", ev.mEvent.u64.step_counter);
+        } else {
+            for (size_t k = 0; k < mEventSize; ++k) {
+                buffer.appendFormat("%.2f, ", ev.mEvent.data[k]);
+            }
+        }
+        buffer.append("\n");
+    }
+    return std::string(buffer.string());
+}
+
+bool RecentEventLogger::populateLastEvent(sensors_event_t *event) const {
+    std::lock_guard<std::mutex> lk(mLock);
+
+    if (mRecentEvents.size()) {
+        *event = mRecentEvents[mRecentEvents.size()-1].mEvent;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+size_t RecentEventLogger::logSizeBySensorType(int sensorType) {
+    return (sensorType == SENSOR_TYPE_STEP_COUNTER ||
+            sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+            sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE_LARGE : LOG_SIZE;
+}
+
+RecentEventLogger::SensorEventLog::SensorEventLog(const sensors_event_t& e) : mEvent(e) {
+    clock_gettime(CLOCK_REALTIME, &mWallTime);
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h
new file mode 100644
index 0000000..4f9bc4a
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 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_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
+#include "RingBuffer.h"
+#include "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+#include <mutex>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// A circular buffer that record the last N events of a sensor type for debugging. The size of this
+// buffer depends on sensor type and is controlled by logSizeBySensorType(). The last N events
+// generated from the sensor are stored in this buffer.  The buffer is NOT cleared when the sensor
+// unregisters and as a result very old data in the dumpsys output can be seen, which is an intended
+// behavior.
+class RecentEventLogger : public Dumpable {
+public:
+    RecentEventLogger(int sensorType);
+    void addEvent(const sensors_event_t& event);
+    bool populateLastEvent(sensors_event_t *event) const;
+    bool isEmpty() const;
+    virtual ~RecentEventLogger() {}
+
+    // Dumpable interface
+    virtual std::string dump() const override;
+
+protected:
+    struct SensorEventLog {
+        SensorEventLog(const sensors_event_t& e);
+        timespec mWallTime;
+        sensors_event_t mEvent;
+    };
+
+    const int mSensorType;
+    const size_t mEventSize;
+
+    mutable std::mutex mLock;
+    RingBuffer<SensorEventLog> mRecentEvents;
+
+private:
+    static size_t logSizeBySensorType(int sensorType);
+};
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
diff --git a/services/sensorservice/RingBuffer.h b/services/sensorservice/RingBuffer.h
new file mode 100644
index 0000000..ec98a01
--- /dev/null
+++ b/services/sensorservice/RingBuffer.h
@@ -0,0 +1,361 @@
+/*
+ * 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_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
+#include <utils/Log.h>
+#include <cutils/compiler.h>
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace SensorServiceUtil {
+
+/**
+ * A RingBuffer class that maintains an array of objects that can grow up to a certain size.
+ * Elements added to the RingBuffer are inserted in the logical front of the buffer, and
+ * invalidate all current iterators for that RingBuffer object.
+ */
+template <class T>
+class RingBuffer final {
+public:
+
+    /**
+     * Construct a RingBuffer that can grow up to the given length.
+     */
+    RingBuffer(size_t length);
+
+    /**
+     * Forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        iterator(T* ptr, size_t size, size_t pos, size_t ctr);
+
+        iterator& operator++();
+
+        iterator operator++(int);
+
+        bool operator==(const iterator& rhs);
+
+        bool operator!=(const iterator& rhs);
+
+        T& operator*();
+
+        T* operator->();
+
+    private:
+        T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Constant forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class const_iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr);
+
+        const_iterator& operator++();
+
+        const_iterator operator++(int);
+
+        bool operator==(const const_iterator& rhs);
+
+        bool operator!=(const const_iterator& rhs);
+
+        const T& operator*();
+
+        const T* operator->();
+
+    private:
+        const T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Adds item to the front of this RingBuffer.  If the RingBuffer is at its maximum length,
+     * this will result in the last element being replaced (this is done using the element's
+     * assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(const T& item);
+
+    /**
+     * Moves item to the front of this RingBuffer.  Following a call to this, item should no
+     * longer be used.  If the RingBuffer is at its maximum length, this will result in the
+     * last element being replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(T&& item);
+
+    /**
+     * Construct item in-place in the front of this RingBuffer using the given arguments.  If
+     * the RingBuffer is at its maximum length, this will result in the last element being
+     * replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    template <class... Args>
+    void emplace(Args&&... args);
+
+    /**
+     * Get an iterator to the front of this RingBuffer.
+     */
+    iterator begin();
+
+    /**
+     * Get an iterator to the end of this RingBuffer.
+     */
+    iterator end();
+
+    /**
+     * Get a const_iterator to the front of this RingBuffer.
+     */
+    const_iterator begin() const;
+
+    /**
+     * Get a const_iterator to the end of this RingBuffer.
+     */
+    const_iterator end() const;
+
+    /**
+     * Return a reference to the element at a given index.  If the index is out of range for
+     * this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    T& operator[](size_t index);
+
+    /**
+     * Return a const reference to the element at a given index.  If the index is out of range
+     * for this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    const T& operator[](size_t index) const;
+
+    /**
+     * Return the current size of this RingBuffer.
+     */
+    size_t size() const;
+
+    /**
+     * Remove all elements from this RingBuffer and set the size to 0.
+     */
+    void clear();
+
+private:
+    size_t mFrontIdx;
+    size_t mMaxBufferSize;
+    std::vector<T> mBuffer;
+}; // class RingBuffer
+
+
+template <class T>
+RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {}
+
+template <class T>
+RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) {
+    iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator==(const iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+T& RingBuffer<T>::iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+T* RingBuffer<T>::iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) {
+    const_iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+const T& RingBuffer<T>::const_iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+const T* RingBuffer<T>::const_iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+void RingBuffer<T>::add(const T& item) {
+    if (mBuffer.size() < mMaxBufferSize) {
+        mBuffer.push_back(item);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    mBuffer[mFrontIdx] = item;
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+void RingBuffer<T>::add(T&& item) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.push_back(std::forward<T>(item));
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = std::forward<T>(item);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+template <class... Args>
+void RingBuffer<T>::emplace(Args&&... args) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.emplace_back(std::forward<Args>(args)...);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = T(std::forward<Args>(args)...);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::begin() {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::end() {
+    size_t s = mBuffer.size();
+    return iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return const_iterator(mBuffer.data(), mBuffer.size(),
+            (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const {
+    size_t s = mBuffer.size();
+    return const_iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+T& RingBuffer<T>::operator[](size_t index) {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+const T& RingBuffer<T>::operator[](size_t index) const {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+size_t RingBuffer<T>::size() const {
+    return mBuffer.size();
+}
+
+template <class T>
+void RingBuffer<T>::clear() {
+    mBuffer.clear();
+    mFrontIdx = 0;
+}
+
+}  // namespace SensorServiceUtil
+}; // namespace android
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 179b1c5..4fbaa50 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -39,8 +39,7 @@
 
 SensorDevice::SensorDevice()
     :  mSensorDevice(0),
-       mSensorModule(0)
-{
+       mSensorModule(0) {
     status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
             (hw_module_t const**)&mSensorModule);
 
@@ -84,37 +83,43 @@
     }
 }
 
-void SensorDevice::dump(String8& result)
-{
-    if (!mSensorModule) return;
-    sensor_t const* list;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+std::string SensorDevice::dump() const {
+    if (!mSensorModule) return "HAL not initialized\n";
 
-    result.appendFormat("halVersion 0x%08x\n", getHalDeviceVersion());
-    result.appendFormat("%d h/w sensors:\n", int(count));
+    String8 result;
+    sensor_t const* list;
+    int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+
+    result.appendFormat("HAL: %s (%s), version %#010x\n",
+                        mSensorModule->common.name,
+                        mSensorModule->common.author,
+                        getHalDeviceVersion());
+    result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size());
 
     Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i<size_t(count) ; i++) {
+    for (int i = 0 ; i < count ; i++) {
         const Info& info = mActivationCount.valueFor(list[i].handle);
         if (info.batchParams.isEmpty()) continue;
-        result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
+        result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle,
                             info.batchParams.size());
+
+        result.append("sampling_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
             const BatchParams& params = info.batchParams.valueAt(j);
-            result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
+            result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchDelay / 1e6f);
+        result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
 
-        result.appendFormat("handle=0x%08x, active-count=%zu, batch_timeout(ms)={ ", list[i].handle,
-                            info.batchParams.size());
+        result.append("batching_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
             BatchParams params = info.batchParams.valueAt(j);
-            result.appendFormat("%4.1f%s", params.batchTimeout / 1e6f,
+            result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
+        result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
     }
+    return result.string();
 }
 
 ssize_t SensorDevice::getSensorList(sensor_t const** list) {
@@ -143,8 +148,7 @@
     info.removeBatchParamsForIdent(ident);
 }
 
-status_t SensorDevice::activate(void* ident, int handle, int enabled)
-{
+status_t SensorDevice::activate(void* ident, int handle, int enabled) {
     if (!mSensorDevice) return NO_INIT;
     status_t err(NO_ERROR);
     bool actuateHardware = false;
@@ -293,8 +297,7 @@
     return err;
 }
 
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
-{
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
     if (!mSensorDevice) return NO_INIT;
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index c12630a..68bb853 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,21 +17,44 @@
 #ifndef ANDROID_SENSOR_DEVICE_H
 #define ANDROID_SENSOR_DEVICE_H
 
-#include <stdint.h>
-#include <sys/types.h>
+#include "SensorServiceUtils.h"
 
+#include <gui/Sensor.h>
 #include <utils/KeyedVector.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 
-#include <gui/Sensor.h>
+#include <stdint.h>
+#include <sys/types.h>
 
 // ---------------------------------------------------------------------------
 
 namespace android {
 // ---------------------------------------------------------------------------
+using SensorServiceUtil::Dumpable;
 
-class SensorDevice : public Singleton<SensorDevice> {
+class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
+public:
+    ssize_t getSensorList(sensor_t const** list);
+    void handleDynamicSensorConnection(int handle, bool connected);
+    status_t initCheck() const;
+    int getHalDeviceVersion() const;
+    ssize_t poll(sensors_event_t* buffer, size_t count);
+    status_t activate(void* ident, int handle, int enabled);
+    status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+                   int64_t maxBatchReportLatencyNs);
+    // Call batch with timeout zero instead of calling setDelay() for newer devices.
+    status_t setDelay(void* ident, int handle, int64_t ns);
+    status_t flush(void* ident, int handle);
+    status_t setMode(uint32_t mode);
+    void disableAllSensors();
+    void enableAllSensors();
+    void autoDisable(void *ident, int handle);
+    status_t injectSensorData(const sensors_event_t *event);
+
+    // Dumpable
+    virtual std::string dump() const;
+private:
     friend class Singleton<SensorDevice>;
     sensors_poll_device_1_t* mSensorDevice;
     struct sensors_module_t* mSensorModule;
@@ -87,24 +110,6 @@
 
     bool isClientDisabled(void* ident);
     bool isClientDisabledLocked(void* ident);
-public:
-    ssize_t getSensorList(sensor_t const** list);
-    void handleDynamicSensorConnection(int handle, bool connected);
-    status_t initCheck() const;
-    int getHalDeviceVersion() const;
-    ssize_t poll(sensors_event_t* buffer, size_t count);
-    status_t activate(void* ident, int handle, int enabled);
-    status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
-                   int64_t maxBatchReportLatencyNs);
-    // Call batch with timeout zero instead of calling setDelay() for newer devices.
-    status_t setDelay(void* ident, int handle, int64_t ns);
-    status_t flush(void* ident, int handle);
-    status_t setMode(uint32_t mode);
-    void disableAllSensors();
-    void enableAllSensors();
-    void autoDisable(void *ident, int handle);
-    status_t injectSensorData(const sensors_event_t *event);
-    void dump(String8& result);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index cb24229..73a6db5 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -34,12 +34,21 @@
         mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) {
 }
 
+BaseSensor::BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]) :
+        mSensorDevice(SensorDevice::getInstance()),
+        mSensor(sensor, Sensor::uuid_t(uuid), mSensorDevice.getHalDeviceVersion()) {
+}
+
 // ---------------------------------------------------------------------------
 
 HardwareSensor::HardwareSensor(const sensor_t& sensor):
         BaseSensor(sensor) {
 }
 
+HardwareSensor::HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]):
+        BaseSensor(sensor, uuid) {
+}
+
 HardwareSensor::~HardwareSensor() {
 }
 
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index d1cee41..dafcf2d 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -48,6 +48,7 @@
 class BaseSensor : public SensorInterface {
 public:
     BaseSensor(const sensor_t& sensor);
+    BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
 
     // Not all sensors need to support batching.
     virtual status_t batch(void* ident, int handle, int, int64_t samplingPeriodNs,
@@ -74,6 +75,7 @@
 class HardwareSensor : public BaseSensor {
 public:
     HardwareSensor(const sensor_t& sensor);
+    HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
 
     virtual ~HardwareSensor();
 
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index c23e21f..f6d3d94 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -19,6 +19,8 @@
 #include <hardware/sensors.h>
 #include <utils/String8.h>
 
+#include <cinttypes>
+
 namespace android {
 namespace SensorServiceUtil {
 
@@ -119,17 +121,17 @@
 std::string SensorList::dump() const {
     String8 result;
 
-    result.append("Sensor List:\n");
     forEachSensor([&result] (const Sensor& s) -> bool {
             result.appendFormat(
-                    "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+                    "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
+                        ") | perm: %s\n\t",
+                    s.getHandle(),
                     s.getName().string(),
                     s.getVendor().string(),
                     s.getVersion(),
                     s.getStringType().string(),
-                    s.getHandle(),
-                    s.getRequiredPermission().string(),
-                    s.getType());
+                    s.getType(),
+                    s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
 
             const int reportingMode = s.getReportingMode();
             if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
@@ -147,18 +149,19 @@
             if (s.getMaxDelay() > 0) {
                 result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
             } else {
-                result.appendFormat("maxDelay=%dus | ", s.getMaxDelay());
+                result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
             }
 
             if (s.getMinDelay() > 0) {
                 result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
             } else {
-                result.appendFormat("minDelay=%dus | ", s.getMinDelay());
+                result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
             }
 
             if (s.getFifoMaxEventCount() > 0) {
-                result.appendFormat("FifoMax=%d events | ",
-                        s.getFifoMaxEventCount());
+                result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
+                        s.getFifoMaxEventCount(),
+                        s.getFifoReservedEventCount());
             } else {
                 result.append("no batching | ");
             }
@@ -169,6 +172,20 @@
                 result.appendFormat("non-wakeUp | ");
             }
 
+            if (s.isDynamicSensor()) {
+                result.appendFormat("dynamic, ");
+            }
+            if (s.hasAdditionalInfo()) {
+                result.appendFormat("has-additional-info, ");
+            }
+            result.append("| ");
+
+            if (s.isDynamicSensor()) {
+                result.append("uuid: ");
+                for (uint8_t i : s.getUuid().b) {
+                    result.appendFormat("%02x", i);
+                }
+            }
             result.append("\n");
             return true;
         });
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
index ffde619..8209d96 100644
--- a/services/sensorservice/SensorList.h
+++ b/services/sensorservice/SensorList.h
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SENSOR_LIST_H
-#define ANDROID_SENSOR_LIST_H
+#ifndef ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
+#define ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
 
 #include "SensorInterface.h"
+#include "SensorServiceUtils.h"
 
 #include <gui/Sensor.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
-#include <mutex>
 #include <map>
-#include <string>
+#include <mutex>
 #include <unordered_set>
 #include <vector>
 
@@ -34,13 +34,6 @@
 
 namespace SensorServiceUtil {
 
-class Dumpable {
-public:
-    virtual std::string dump() const;
-    virtual void setFormat(std::string ) {}
-    virtual ~Dumpable() {}
-};
-
 class SensorList : public Dumpable {
 public:
     // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
@@ -142,4 +135,4 @@
 } // namespace SensorServiceUtil
 } // namespace android
 
-#endif // ANDROID_SENSOR_LIST_H
+#endif // ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index b7a8740..6caa85b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -36,11 +36,10 @@
 #include "SensorInterface.h"
 
 #include "SensorService.h"
-#include "SensorEventConnection.h"
 #include "SensorEventAckReceiver.h"
+#include "SensorEventConnection.h"
 #include "SensorRecord.h"
 #include "SensorRegistrationInfo.h"
-#include "MostRecentEventLogger.h"
 
 #include <inttypes.h>
 #include <math.h>
@@ -86,7 +85,6 @@
                     (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |
                     (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
 
-            mLastEventSeen.setCapacity(count);
             for (ssize_t i=0 ; i<count ; i++) {
                 bool useThisSensor=true;
 
@@ -218,25 +216,27 @@
 
 const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
     int handle = s->getSensor().getHandle();
+    int type = s->getSensor().getType();
     if (mSensors.add(handle, s, isDebug, isVirtual)){
-        mLastEventSeen.add(handle, nullptr);
+        mRecentEvent.emplace(handle, new RecentEventLogger(type));
         return s->getSensor();
     } else {
         return mSensors.getNonSensor();
     }
 }
 
-const Sensor& SensorService::registerDynamicSensor(SensorInterface* s, bool isDebug) {
+const Sensor& SensorService::registerDynamicSensorLocked(SensorInterface* s, bool isDebug) {
     return registerSensor(s, isDebug);
 }
 
-bool SensorService::unregisterDynamicSensor(int handle) {
+bool SensorService::unregisterDynamicSensorLocked(int handle) {
     bool ret = mSensors.remove(handle);
-    MostRecentEventLogger *buf = mLastEventSeen.valueFor(handle);
-    if (buf) {
-        delete buf;
+
+    const auto i = mRecentEvent.find(handle);
+    if (i != mRecentEvent.end()) {
+        delete i->second;
+        mRecentEvent.erase(i);
     }
-    mLastEventSeen.removeItem(handle);
     return ret;
 }
 
@@ -245,6 +245,9 @@
 }
 
 SensorService::~SensorService() {
+    for (auto && entry : mRecentEvent) {
+        delete entry.second;
+    }
 }
 
 status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -313,25 +316,25 @@
         } else {
             // Default dump the sensor list and debugging information.
             //
+            result.append("Sensor Device:\n");
+            result.append(SensorDevice::getInstance().dump().c_str());
+
+            result.append("Sensor List:\n");
             result.append(mSensors.dump().c_str());
 
+            result.append("Fusion States:\n");
             SensorFusion::getInstance().dump(result);
-            SensorDevice::getInstance().dump(result);
 
             result.append("Recent Sensor events:\n");
-            auto& lastEvents = mLastEventSeen;
-            mSensors.forEachSensor([&result, &lastEvents] (const Sensor& s) -> bool {
-                    int bufIndex = lastEvents.indexOfKey(s.getHandle());
-                    if (bufIndex >= 0) {
-                        const MostRecentEventLogger* buf = lastEvents.valueAt(bufIndex);
-                        if (buf != nullptr && s.getRequiredPermission().isEmpty()) {
-                            result.appendFormat("%s (handle:0x%08x): ",
-                                          s.getName().string(), s.getHandle());
-                            buf->printBuffer(result);
-                        }
-                    }
-                    return true;
-                });
+            for (auto&& i : mRecentEvent) {
+                sp<SensorInterface> s = mSensors.getInterface(i.first);
+                if (!i.second->isEmpty() &&
+                    s->getSensor().getRequiredPermission().isEmpty()) {
+                    // if there is events and sensor does not need special permission.
+                    result.appendFormat("%s: ", s->getSensor().getName().string());
+                    result.append(i.second->dump().c_str());
+                }
+            }
 
             result.append("Active sensors:\n");
             for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
@@ -554,17 +557,19 @@
                           handle, dynamicSensor.type, dynamicSensor.name);
 
                     if (mSensors.isNewHandle(handle)) {
+                        const auto& uuid = mSensorEventBuffer[i].dynamic_sensor_meta.uuid;
                         sensor_t s = dynamicSensor;
                         // make sure the dynamic sensor flag is set
                         s.flags |= DYNAMIC_SENSOR_MASK;
                         // force the handle to be consistent
                         s.handle = handle;
-                        SensorInterface *si = new HardwareSensor(s);
+
+                        SensorInterface *si = new HardwareSensor(s, uuid);
 
                         // This will release hold on dynamic sensor meta, so it should be called
                         // after Sensor object is created.
                         device.handleDynamicSensorConnection(handle, true /*connected*/);
-                        registerDynamicSensor(si);
+                        registerDynamicSensorLocked(si);
                     } else {
                         ALOGE("Handle %d has been used, cannot use again before reboot.", handle);
                     }
@@ -573,7 +578,7 @@
                     ALOGI("Dynamic sensor handle 0x%x disconnected", handle);
 
                     device.handleDynamicSensorConnection(handle, false /*connected*/);
-                    if (!unregisterDynamicSensor(handle)) {
+                    if (!unregisterDynamicSensorLocked(handle)) {
                         ALOGE("Dynamic sensor release error.");
                     }
 
@@ -674,16 +679,14 @@
     for (size_t i = 0; i < count; i++) {
         if (buffer[i].type == SENSOR_TYPE_META_DATA ||
             buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META ||
-            buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO ||
-            mLastEventSeen.indexOfKey(buffer[i].sensor) <0 ) {
+            buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
             continue;
         }
 
-        MostRecentEventLogger* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
-        if (circular_buf == NULL) {
-            circular_buf = new MostRecentEventLogger(buffer[i].type);
+        auto logger = mRecentEvent.find(buffer[i].sensor);
+        if (logger != mRecentEvent.end()) {
+            logger->second->addEvent(buffer[i]);
         }
-        circular_buf->addEvent(buffer[i]);
     }
 }
 
@@ -881,14 +884,14 @@
             if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
                 // NOTE: The wake_up flag of this event may get set to
                 // WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
-                MostRecentEventLogger *circular_buf = mLastEventSeen.valueFor(handle);
-                if (circular_buf) {
+
+                auto logger = mRecentEvent.find(handle);
+                if (logger != mRecentEvent.end()) {
                     sensors_event_t event;
-                    memset(&event, 0, sizeof(event));
                     // It is unlikely that this buffer is empty as the sensor is already active.
                     // One possible corner case may be two applications activating an on-change
                     // sensor at the same time.
-                    if(circular_buf->populateLastEvent(&event)) {
+                    if(logger->second->populateLastEvent(&event)) {
                         event.sensor = handle;
                         if (event.version == sizeof(sensors_event_t)) {
                             if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
@@ -1179,31 +1182,5 @@
     return (packageName.contains(mWhiteListedPackage.string()));
 }
 
-int SensorService::getNumEventsForSensorType(int sensor_event_type) {
-    if (sensor_event_type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
-        return 16;
-    }
-    switch (sensor_event_type) {
-        case SENSOR_TYPE_ROTATION_VECTOR:
-        case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
-            return 5;
-
-        case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
-        case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-            return 6;
-
-        case SENSOR_TYPE_GAME_ROTATION_VECTOR:
-            return 4;
-
-        case SENSOR_TYPE_SIGNIFICANT_MOTION:
-        case SENSOR_TYPE_STEP_DETECTOR:
-        case SENSOR_TYPE_STEP_COUNTER:
-            return 1;
-
-         default:
-            return 3;
-    }
-}
-
 }; // namespace android
 
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 6473edb..0d04478 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -18,6 +18,7 @@
 #define ANDROID_SENSOR_SERVICE_H
 
 #include "SensorList.h"
+#include "RecentEventLogger.h"
 
 #include <binder/BinderService.h>
 #include <cutils/compiler.h>
@@ -35,6 +36,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <unordered_map>
 #include <unordered_set>
 
 #if __clang__
@@ -56,6 +58,7 @@
 namespace android {
 // ---------------------------------------------------------------------------
 class SensorInterface;
+using namespace SensorServiceUtil;
 
 class SensorService :
         public BinderService<SensorService>,
@@ -86,8 +89,6 @@
     // nested class/struct for internal use
     class SensorRecord;
     class SensorEventAckReceiver;
-    struct TrimmedSensorEvent;
-    class MostRecentEventLogger;
     struct SensorRegistrationInfo;
 
     enum Mode {
@@ -155,7 +156,6 @@
     virtual int isDataInjectionEnabled();
     virtual status_t dump(int fd, const Vector<String16>& args);
 
-    static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
     sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
@@ -165,8 +165,8 @@
     const Sensor& registerSensor(SensorInterface* sensor,
                                  bool isDebug = false, bool isVirtual = false);
     const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
-    const Sensor& registerDynamicSensor(SensorInterface* sensor, bool isDebug = false);
-    bool unregisterDynamicSensor(int handle);
+    const Sensor& registerDynamicSensorLocked(SensorInterface* sensor, bool isDebug = false);
+    bool unregisterDynamicSensorLocked(int handle);
     status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
     status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
     void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
@@ -208,7 +208,7 @@
     status_t resetToNormalMode();
     status_t resetToNormalModeLocked();
 
-    SensorServiceUtil::SensorList mSensors;
+    SensorList mSensors;
     status_t mInitCheck;
 
     // Socket buffersize used to initialize BitTube. This size depends on whether batching is
@@ -225,7 +225,7 @@
     bool mWakeLockAcquired;
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
     SensorEventConnection const **mMapFlushEventsToConnections;
-    KeyedVector<int32_t, MostRecentEventLogger*> mLastEventSeen;
+    std::unordered_map<int, RecentEventLogger*> mRecentEvent;
     Mode mCurrentOperatingMode;
 
     // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
new file mode 100644
index 0000000..1996a00
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 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 "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// Keep in sync with sSensorReportingMode in Sensor.java
+size_t eventSizeBySensorType(int type) {
+    if (type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
+        return 16;
+    }
+    switch (type) {
+        case SENSOR_TYPE_POSE_6DOF:
+            return 16;
+
+        case SENSOR_TYPE_ROTATION_VECTOR:
+        case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+            return 5;
+
+        case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+        case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+            return 6;
+
+        case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+            return 4;
+
+        case SENSOR_TYPE_SIGNIFICANT_MOTION:
+        case SENSOR_TYPE_STEP_DETECTOR:
+        case SENSOR_TYPE_STEP_COUNTER:
+        case SENSOR_TYPE_HEART_RATE:
+        case SENSOR_TYPE_TILT_DETECTOR:
+        case SENSOR_TYPE_WAKE_GESTURE:
+        case SENSOR_TYPE_GLANCE_GESTURE:
+        case SENSOR_TYPE_PICK_UP_GESTURE:
+        case SENSOR_TYPE_WRIST_TILT_GESTURE:
+        case SENSOR_TYPE_DEVICE_ORIENTATION:
+        case SENSOR_TYPE_STATIONARY_DETECT:
+        case SENSOR_TYPE_MOTION_DETECT:
+        case SENSOR_TYPE_HEART_BEAT:
+            return 1;
+
+        default:
+            return 3;
+    }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android;
diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h
new file mode 100644
index 0000000..1558feb
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 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_SENSOR_SERVICE_UTIL
+#define ANDROID_SENSOR_SERVICE_UTIL
+
+#include <cstddef>
+#include <string>
+
+namespace android {
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+    virtual std::string dump() const = 0;
+    virtual void setFormat(std::string ) {}
+    virtual ~Dumpable() {}
+};
+
+size_t eventSizeBySensorType(int type);
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
index cfdf6a3..186b60c 100644
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ b/services/sensorservice/tests/sensorservicetest.cpp
@@ -62,7 +62,7 @@
 
 int main()
 {
-    SensorManager mgr(String16("Sensor Service Test"));
+    SensorManager& mgr = SensorManager::getInstanceForPackage(String16("Sensor Service Test"));
 
     Sensor const* const* list;
     ssize_t count = mgr.getSensorList(&list);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 7e4e797..bc8dfbb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -606,7 +606,8 @@
 }
 
 status_t VirtualDisplaySurface::getLastQueuedBuffer(
-        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/) {
+        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/,
+        float[16] /* outTransformMatrix*/) {
     ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
     return INVALID_OPERATION;
 }
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index bd1cfb1..29563b6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -127,7 +127,7 @@
     virtual status_t setAutoRefresh(bool autoRefresh) override;
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
 
     //
     // Utility methods
@@ -254,4 +254,3 @@
 // ---------------------------------------------------------------------------
 
 #endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6ccd4ff..c640f58 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -251,7 +251,7 @@
             ALOGE("Can't replace a frame on an empty queue");
             return;
         }
-        mQueueItems.editItemAt(0) = item;
+        mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
 
         // Wake up any pending callbacks
         mLastFrameNumberReceived = item.mFrameNumber;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index e689127..faab62c 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -144,8 +144,9 @@
 }
 
 status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
-    return mProducer->getLastQueuedBuffer(outBuffer, outFence);
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
 }
 
 IBinder* MonitoredProducer::onAsBinder() {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index d2b4b43..ce756dc 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -60,7 +60,7 @@
     virtual uint64_t getNextFrameNumber() const override;
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual IBinder* onAsBinder();
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index e7f10b3..28b172d 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -116,7 +116,7 @@
     };
 
     void AddImplicitLayers() {
-        if (!driver::Debuggable())
+        if (!is_instance_ || !driver::Debuggable())
             return;
 
         ParseDebugVulkanLayers();
@@ -367,6 +367,14 @@
 // chaining.
 class LayerChain {
    public:
+    struct ActiveLayer {
+        LayerRef ref;
+        union {
+            VkLayerInstanceLink instance_link;
+            VkLayerDeviceLink device_link;
+        };
+    };
+
     static VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
                                    const VkAllocationCallbacks* allocator,
                                    VkInstance* instance_out);
@@ -382,15 +390,10 @@
     static void DestroyDevice(VkDevice dev,
                               const VkAllocationCallbacks* allocator);
 
-   private:
-    struct ActiveLayer {
-        LayerRef ref;
-        union {
-            VkLayerInstanceLink instance_link;
-            VkLayerDeviceLink device_link;
-        };
-    };
+    static const ActiveLayer* GetActiveLayers(VkPhysicalDevice physical_dev,
+                                              uint32_t& count);
 
+   private:
     LayerChain(bool is_instance, const VkAllocationCallbacks& allocator);
     ~LayerChain();
 
@@ -398,6 +401,11 @@
                             uint32_t layer_count,
                             const char* const* extension_names,
                             uint32_t extension_count);
+    VkResult ActivateLayers(VkPhysicalDevice physical_dev,
+                            const char* const* layer_names,
+                            uint32_t layer_count,
+                            const char* const* extension_names,
+                            uint32_t extension_count);
     ActiveLayer* AllocateLayerArray(uint32_t count) const;
     VkResult LoadLayer(ActiveLayer& layer, const char* name);
     void SetupLayerLinks();
@@ -507,8 +515,6 @@
     if (!layer_count) {
         // point head of chain to the driver
         get_instance_proc_addr_ = driver::GetInstanceProcAddr;
-        if (!is_instance_)
-            get_device_proc_addr_ = driver::GetDeviceProcAddr;
 
         return VK_SUCCESS;
     }
@@ -532,10 +538,76 @@
     return VK_SUCCESS;
 }
 
+VkResult LayerChain::ActivateLayers(VkPhysicalDevice physical_dev,
+                                    const char* const* layer_names,
+                                    uint32_t layer_count,
+                                    const char* const* extension_names,
+                                    uint32_t extension_count) {
+    uint32_t instance_layer_count;
+    const ActiveLayer* instance_layers =
+        GetActiveLayers(physical_dev, instance_layer_count);
+
+    // log a message if the application device layer array is not empty nor an
+    // exact match of the instance layer array.
+    if (layer_count) {
+        bool exact_match = (instance_layer_count == layer_count);
+        if (exact_match) {
+            for (uint32_t i = 0; i < instance_layer_count; i++) {
+                const Layer& l = *instance_layers[i].ref;
+                if (strcmp(GetLayerProperties(l).layerName, layer_names[i])) {
+                    exact_match = false;
+                    break;
+                }
+            }
+        }
+
+        if (!exact_match) {
+            ALOGW("Device layers");
+            for (uint32_t i = 0; i < layer_count; i++)
+                ALOGW("  %s", layer_names[i]);
+            ALOGW(
+                "disagree with instance layers and are overridden by "
+                "instance layers");
+        }
+    }
+
+    VkResult result =
+        override_extensions_.Parse(extension_names, extension_count);
+    if (result != VK_SUCCESS)
+        return result;
+
+    if (!instance_layer_count) {
+        // point head of chain to the driver
+        get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+        get_device_proc_addr_ = driver::GetDeviceProcAddr;
+
+        return VK_SUCCESS;
+    }
+
+    layers_ = AllocateLayerArray(instance_layer_count);
+    if (!layers_)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    for (uint32_t i = 0; i < instance_layer_count; i++) {
+        const Layer& l = *instance_layers[i].ref;
+
+        // no need to and cannot chain non-global layers
+        if (!IsLayerGlobal(l))
+            continue;
+
+        // this never fails
+        new (&layers_[layer_count_++]) ActiveLayer{GetLayerRef(l), {}};
+    }
+
+    SetupLayerLinks();
+
+    return VK_SUCCESS;
+}
+
 LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const {
     VkSystemAllocationScope scope = (is_instance_)
                                         ? VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
-                                        : VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
+                                        : VK_SYSTEM_ALLOCATION_SCOPE_COMMAND;
 
     return reinterpret_cast<ActiveLayer*>(allocator_.pfnAllocation(
         allocator_.pUserData, sizeof(ActiveLayer) * count, alignof(ActiveLayer),
@@ -543,18 +615,20 @@
 }
 
 VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
-    if (is_instance_)
-        new (&layer) ActiveLayer{GetInstanceLayerRef(name), {}};
-    else
-        new (&layer) ActiveLayer{GetDeviceLayerRef(name), {}};
+    const Layer* l = FindLayer(name);
+    if (!l) {
+        ALOGW("Failed to find layer %s", name);
+        return VK_ERROR_LAYER_NOT_PRESENT;
+    }
 
+    new (&layer) ActiveLayer{GetLayerRef(*l), {}};
     if (!layer.ref) {
-        ALOGE("Failed to load layer %s", name);
+        ALOGW("Failed to open layer %s", name);
         layer.ref.~LayerRef();
         return VK_ERROR_LAYER_NOT_PRESENT;
     }
 
-    ALOGI("Loaded %s layer %s", (is_instance_) ? "instance" : "device", name);
+    ALOGI("Loaded layer %s", name);
 
     return VK_SUCCESS;
 }
@@ -698,8 +772,6 @@
     // initialize InstanceData
     InstanceData& data = GetData(instance);
 
-    data.instance = instance;
-
     if (!InitDispatchTable(instance, get_instance_proc_addr_,
                            enabled_extensions_)) {
         if (data.dispatch.DestroyInstance)
@@ -763,13 +835,8 @@
         return result;
 
     // call down the chain
-    //
-    // TODO Instance call chain available at
-    // GetData(physical_dev).dispatch.CreateDevice is ignored.  Is that
-    // right?
-    VkInstance instance = GetData(physical_dev).instance;
-    PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
-        get_instance_proc_addr_(instance, "vkCreateDevice"));
+    PFN_vkCreateDevice create_device =
+        GetData(physical_dev).dispatch.CreateDevice;
     VkDevice dev;
     result = create_device(physical_dev, create_info, allocator, &dev);
     if (result != VK_SUCCESS)
@@ -785,8 +852,8 @@
         return VK_ERROR_INITIALIZATION_FAILED;
     }
 
-    StealLayers(data);
-
+    // no StealLayers so that active layers are destroyed with this
+    // LayerChain
     *dev_out = dev;
 
     return VK_SUCCESS;
@@ -872,10 +939,18 @@
 }
 
 bool LayerChain::IsLayerExtension(const char* name) const {
-    for (uint32_t i = 0; i < layer_count_; i++) {
-        const ActiveLayer& layer = layers_[i];
-        if (layer.ref.SupportsExtension(name))
-            return true;
+    if (is_instance_) {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            const ActiveLayer& layer = layers_[i];
+            if (FindLayerInstanceExtension(*layer.ref, name))
+                return true;
+        }
+    } else {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            const ActiveLayer& layer = layers_[i];
+            if (FindLayerDeviceExtension(*layer.ref, name))
+                return true;
+        }
     }
 
     return false;
@@ -990,10 +1065,10 @@
                                 ? *allocator
                                 : driver::GetData(physical_dev).allocator);
 
-    VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
-                                           create_info->enabledLayerCount,
-                                           create_info->ppEnabledExtensionNames,
-                                           create_info->enabledExtensionCount);
+    VkResult result = chain.ActivateLayers(
+        physical_dev, create_info->ppEnabledLayerNames,
+        create_info->enabledLayerCount, create_info->ppEnabledExtensionNames,
+        create_info->enabledExtensionCount);
     if (result != VK_SUCCESS)
         return result;
 
@@ -1032,19 +1107,15 @@
 void LayerChain::DestroyDevice(VkDevice device,
                                const VkAllocationCallbacks* allocator) {
     DeviceData& data = GetData(device);
-
-    ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
-    uint32_t layer_count = data.layer_count;
-
-    VkAllocationCallbacks local_allocator;
-    if (!allocator)
-        local_allocator = driver::GetData(device).allocator;
-
     // this also destroys DeviceData
     data.dispatch.DestroyDevice(device, allocator);
+}
 
-    DestroyLayers(layers, layer_count,
-                  (allocator) ? *allocator : local_allocator);
+const LayerChain::ActiveLayer* LayerChain::GetActiveLayers(
+    VkPhysicalDevice physical_dev,
+    uint32_t& count) {
+    count = GetData(physical_dev).layer_count;
+    return reinterpret_cast<const ActiveLayer*>(GetData(physical_dev).layers);
 }
 
 // ----------------------------------------------------------------------------
@@ -1098,13 +1169,19 @@
     if (!EnsureInitialized())
         return VK_ERROR_INITIALIZATION_FAILED;
 
-    uint32_t count =
-        EnumerateInstanceLayers(pProperties ? *pPropertyCount : 0, pProperties);
+    uint32_t count = GetLayerCount();
 
-    if (!pProperties || *pPropertyCount > count)
+    if (!pProperties) {
         *pPropertyCount = count;
+        return VK_SUCCESS;
+    }
 
-    return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+    uint32_t copied = std::min(*pPropertyCount, count);
+    for (uint32_t i = 0; i < copied; i++)
+        pProperties[i] = GetLayerProperties(GetLayer(i));
+    *pPropertyCount = copied;
+
+    return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
 }
 
 VkResult EnumerateInstanceExtensionProperties(
@@ -1115,9 +1192,13 @@
         return VK_ERROR_INITIALIZATION_FAILED;
 
     if (pLayerName) {
-        const VkExtensionProperties* props;
+        const Layer* layer = FindLayer(pLayerName);
+        if (!layer)
+            return VK_ERROR_LAYER_NOT_PRESENT;
+
         uint32_t count;
-        GetInstanceLayerExtensions(pLayerName, &props, &count);
+        const VkExtensionProperties* props =
+            GetLayerInstanceExtensions(*layer, count);
 
         if (!pProperties || *pPropertyCount > count)
             *pPropertyCount = count;
@@ -1135,15 +1216,21 @@
 VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
                                         uint32_t* pPropertyCount,
                                         VkLayerProperties* pProperties) {
-    (void)physicalDevice;
+    uint32_t count;
+    const LayerChain::ActiveLayer* layers =
+        LayerChain::GetActiveLayers(physicalDevice, count);
 
-    uint32_t count =
-        EnumerateDeviceLayers(pProperties ? *pPropertyCount : 0, pProperties);
-
-    if (!pProperties || *pPropertyCount > count)
+    if (!pProperties) {
         *pPropertyCount = count;
+        return VK_SUCCESS;
+    }
 
-    return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+    uint32_t copied = std::min(*pPropertyCount, count);
+    for (uint32_t i = 0; i < copied; i++)
+        pProperties[i] = GetLayerProperties(*layers[i].ref);
+    *pPropertyCount = copied;
+
+    return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
 }
 
 VkResult EnumerateDeviceExtensionProperties(
@@ -1152,9 +1239,16 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
     if (pLayerName) {
-        const VkExtensionProperties* props;
+        // EnumerateDeviceLayerProperties enumerates active layers for
+        // backward compatibility.  The extension query here should work for
+        // all layers.
+        const Layer* layer = FindLayer(pLayerName);
+        if (!layer)
+            return VK_ERROR_LAYER_NOT_PRESENT;
+
         uint32_t count;
-        GetDeviceLayerExtensions(pLayerName, &props, &count);
+        const VkExtensionProperties* props =
+            GetLayerDeviceExtensions(*layer, count);
 
         if (!pProperties || *pPropertyCount > count)
             *pPropertyCount = count;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 17ccc72..b02f5b4 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -480,17 +480,20 @@
         if (hook->type == ProcHook::GLOBAL)
             return hook->proc;
 
+        // v0 layers expect
+        //
+        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+        //
+        // to work.
+        if (strcmp(pName, "vkCreateDevice") == 0)
+            return hook->proc;
+
         ALOGE(
             "Invalid use of vkGetInstanceProcAddr to query %s without an "
             "instance",
             pName);
 
-        // Some naughty layers expect
-        //
-        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
-        //
-        // to work.
-        return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
+        return nullptr;
     }
 
     PFN_vkVoidFunction proc;
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 85b36b6..2b1f545 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -40,9 +40,6 @@
 struct InstanceData {
     InstanceDispatchTable dispatch;
 
-    // for VkPhysicalDevice->VkInstance mapping
-    VkInstance instance;
-
     // LayerChain::ActiveLayer array
     void* layers;
     uint32_t layer_count;
@@ -54,10 +51,6 @@
 
 struct DeviceData {
     DeviceDispatchTable dispatch;
-
-    // LayerChain::ActiveLayer array
-    void* layers;
-    uint32_t layer_count;
 };
 
 }  // namespace api
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 6b53a9a..f9b1002 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -43,75 +43,119 @@
 // probably want to intern strings, etc., and will need some custom/manual data
 // structures.
 
-// TODO(jessehall): Currently we have separate lists for instance and device
-// layers. Most layers are both; we should use one entry for each layer name,
-// with a mask saying what kind(s) it is.
-
 namespace vulkan {
 namespace api {
 
 struct Layer {
     VkLayerProperties properties;
     size_t library_idx;
-    std::vector<VkExtensionProperties> extensions;
+
+    // true if the layer intercepts vkCreateDevice and device commands
+    bool is_global;
+
+    std::vector<VkExtensionProperties> instance_extensions;
+    std::vector<VkExtensionProperties> device_extensions;
 };
 
 namespace {
 
-std::mutex g_library_mutex;
-struct LayerLibrary {
-    std::string path;
-    void* dlhandle;
-    size_t refcount;
-};
-std::vector<LayerLibrary> g_layer_libraries;
-std::vector<Layer> g_instance_layers;
-std::vector<Layer> g_device_layers;
+class LayerLibrary {
+   public:
+    LayerLibrary(const std::string& path)
+        : path_(path), dlhandle_(nullptr), refcount_(0) {}
 
-void AddLayerLibrary(const std::string& path) {
-    ALOGV("examining layer library '%s'", path.c_str());
-
-    void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
-    if (!dlhandle) {
-        ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
-        return;
+    LayerLibrary(LayerLibrary&& other)
+        : path_(std::move(other.path_)),
+          dlhandle_(other.dlhandle_),
+          refcount_(other.refcount_) {
+        other.dlhandle_ = nullptr;
+        other.refcount_ = 0;
     }
 
+    LayerLibrary(const LayerLibrary&) = delete;
+    LayerLibrary& operator=(const LayerLibrary&) = delete;
+
+    // these are thread-safe
+    bool Open();
+    void Close();
+
+    bool EnumerateLayers(size_t library_idx,
+                         std::vector<Layer>& instance_layers) const;
+
+    void* GetGPA(const Layer& layer,
+                 const char* gpa_name,
+                 size_t gpa_name_len) const;
+
+   private:
+    const std::string path_;
+
+    std::mutex mutex_;
+    void* dlhandle_;
+    size_t refcount_;
+};
+
+bool LayerLibrary::Open() {
+    std::lock_guard<std::mutex> lock(mutex_);
+
+    if (refcount_++ == 0) {
+        dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+        ALOGV("Opening library %s", path_.c_str());
+        if (!dlhandle_) {
+            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+                  dlerror());
+            refcount_ = 0;
+            return false;
+        }
+    }
+    ALOGV("Refcount on activate is %zu", refcount_);
+    return true;
+}
+
+void LayerLibrary::Close() {
+    std::lock_guard<std::mutex> lock(mutex_);
+
+    if (--refcount_ == 0) {
+        ALOGV("Closing library %s", path_.c_str());
+        dlclose(dlhandle_);
+        dlhandle_ = nullptr;
+    }
+    ALOGV("Refcount on destruction is %zu", refcount_);
+}
+
+bool LayerLibrary::EnumerateLayers(size_t library_idx,
+                                   std::vector<Layer>& instance_layers) const {
     PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
         reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
-            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
+            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
     PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
         reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
-            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
-    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
-        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
-            dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
-    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
-        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
-            dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
-    if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
-          (enumerate_device_layers && enumerate_device_extensions))) {
-        ALOGV(
-            "layer library '%s' has neither instance nor device enumeraion "
-            "functions",
-            path.c_str());
-        dlclose(dlhandle);
-        return;
+            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
+        ALOGV("layer library '%s' misses some instance enumeraion functions",
+              path_.c_str());
+        return false;
     }
 
-    VkResult result;
+    // device functions are optional
+    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
+        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
+            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
+        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+
+    // get layer counts
     uint32_t num_instance_layers = 0;
     uint32_t num_device_layers = 0;
-    if (enumerate_instance_layers) {
-        result = enumerate_instance_layers(&num_instance_layers, nullptr);
+    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
+    if (result != VK_SUCCESS || !num_instance_layers) {
         if (result != VK_SUCCESS) {
             ALOGW(
                 "vkEnumerateInstanceLayerProperties failed for library '%s': "
                 "%d",
-                path.c_str(), result);
-            dlclose(dlhandle);
-            return;
+                path_.c_str(), result);
         }
+        return false;
     }
     if (enumerate_device_layers) {
         result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -119,23 +163,19 @@
         if (result != VK_SUCCESS) {
             ALOGW(
                 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
-                path.c_str(), result);
-            dlclose(dlhandle);
-            return;
+                path_.c_str(), result);
+            return false;
         }
     }
+
+    // get layer properties
     VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
         (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
-    if (num_instance_layers > 0) {
-        result = enumerate_instance_layers(&num_instance_layers, properties);
-        if (result != VK_SUCCESS) {
-            ALOGW(
-                "vkEnumerateInstanceLayerProperties failed for library '%s': "
-                "%d",
-                path.c_str(), result);
-            dlclose(dlhandle);
-            return;
-        }
+    result = enumerate_instance_layers(&num_instance_layers, properties);
+    if (result != VK_SUCCESS) {
+        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+              path_.c_str(), result);
+        return false;
     }
     if (num_device_layers > 0) {
         result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -143,102 +183,121 @@
         if (result != VK_SUCCESS) {
             ALOGW(
                 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
-                path.c_str(), result);
-            dlclose(dlhandle);
-            return;
+                path_.c_str(), result);
+            return false;
         }
     }
 
-    size_t library_idx = g_layer_libraries.size();
-    size_t prev_num_instance_layers = g_instance_layers.size();
-    size_t prev_num_device_layers = g_device_layers.size();
-    g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
-    g_device_layers.reserve(prev_num_device_layers + num_device_layers);
+    // append layers to instance_layers
+    size_t prev_num_instance_layers = instance_layers.size();
+    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
     for (size_t i = 0; i < num_instance_layers; i++) {
         const VkLayerProperties& props = properties[i];
 
         Layer layer;
         layer.properties = props;
         layer.library_idx = library_idx;
+        layer.is_global = false;
 
-        if (enumerate_instance_extensions) {
-            uint32_t count = 0;
-            result =
-                enumerate_instance_extensions(props.layerName, &count, nullptr);
-            if (result != VK_SUCCESS) {
-                ALOGW(
-                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
-                    "library "
-                    "'%s': %d",
-                    props.layerName, path.c_str(), result);
-                g_instance_layers.resize(prev_num_instance_layers);
-                dlclose(dlhandle);
-                return;
-            }
-            layer.extensions.resize(count);
-            result = enumerate_instance_extensions(props.layerName, &count,
-                                                   layer.extensions.data());
-            if (result != VK_SUCCESS) {
-                ALOGW(
-                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
-                    "library "
-                    "'%s': %d",
-                    props.layerName, path.c_str(), result);
-                g_instance_layers.resize(prev_num_instance_layers);
-                dlclose(dlhandle);
-                return;
+        uint32_t count = 0;
+        result =
+            enumerate_instance_extensions(props.layerName, &count, nullptr);
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+                "'%s': %d",
+                props.layerName, path_.c_str(), result);
+            instance_layers.resize(prev_num_instance_layers);
+            return false;
+        }
+        layer.instance_extensions.resize(count);
+        result = enumerate_instance_extensions(
+            props.layerName, &count, layer.instance_extensions.data());
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+                "'%s': %d",
+                props.layerName, path_.c_str(), result);
+            instance_layers.resize(prev_num_instance_layers);
+            return false;
+        }
+
+        for (size_t j = 0; j < num_device_layers; j++) {
+            const auto& dev_props = properties[num_instance_layers + j];
+            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
+                layer.is_global = true;
+                break;
             }
         }
 
-        g_instance_layers.push_back(layer);
-        ALOGV("  added instance layer '%s'", props.layerName);
-    }
-    for (size_t i = 0; i < num_device_layers; i++) {
-        const VkLayerProperties& props = properties[num_instance_layers + i];
-
-        Layer layer;
-        layer.properties = props;
-        layer.library_idx = library_idx;
-
-        if (enumerate_device_extensions) {
-            uint32_t count;
+        if (layer.is_global && enumerate_device_extensions) {
             result = enumerate_device_extensions(
                 VK_NULL_HANDLE, props.layerName, &count, nullptr);
             if (result != VK_SUCCESS) {
                 ALOGW(
                     "vkEnumerateDeviceExtensionProperties(%s) failed for "
-                    "library "
-                    "'%s': %d",
-                    props.layerName, path.c_str(), result);
-                g_instance_layers.resize(prev_num_instance_layers);
-                g_device_layers.resize(prev_num_device_layers);
-                dlclose(dlhandle);
-                return;
+                    "library '%s': %d",
+                    props.layerName, path_.c_str(), result);
+                instance_layers.resize(prev_num_instance_layers);
+                return false;
             }
-            layer.extensions.resize(count);
-            result =
-                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
-                                            &count, layer.extensions.data());
+            layer.device_extensions.resize(count);
+            result = enumerate_device_extensions(
+                VK_NULL_HANDLE, props.layerName, &count,
+                layer.device_extensions.data());
             if (result != VK_SUCCESS) {
                 ALOGW(
                     "vkEnumerateDeviceExtensionProperties(%s) failed for "
-                    "library "
-                    "'%s': %d",
-                    props.layerName, path.c_str(), result);
-                g_instance_layers.resize(prev_num_instance_layers);
-                g_device_layers.resize(prev_num_device_layers);
-                dlclose(dlhandle);
-                return;
+                    "library '%s': %d",
+                    props.layerName, path_.c_str(), result);
+                instance_layers.resize(prev_num_instance_layers);
+                return false;
             }
         }
 
-        g_device_layers.push_back(layer);
-        ALOGV("  added device layer '%s'", props.layerName);
+        instance_layers.push_back(layer);
+        ALOGV("  added %s layer '%s'",
+              (layer.is_global) ? "global" : "instance", props.layerName);
     }
 
-    dlclose(dlhandle);
+    return true;
+}
 
-    g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
+void* LayerLibrary::GetGPA(const Layer& layer,
+                           const char* gpa_name,
+                           size_t gpa_name_len) const {
+    void* gpa;
+    size_t layer_name_len =
+        std::max(size_t{2}, strlen(layer.properties.layerName));
+    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+    strcpy(name, layer.properties.layerName);
+    strcpy(name + layer_name_len, gpa_name);
+    if (!(gpa = dlsym(dlhandle_, name))) {
+        strcpy(name, "vk");
+        strcpy(name + 2, gpa_name);
+        gpa = dlsym(dlhandle_, name);
+    }
+    return gpa;
+}
+
+std::vector<LayerLibrary> g_layer_libraries;
+std::vector<Layer> g_instance_layers;
+
+void AddLayerLibrary(const std::string& path) {
+    ALOGV("examining layer library '%s'", path.c_str());
+
+    LayerLibrary library(path);
+    if (!library.Open())
+        return;
+
+    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
+        library.Close();
+        return;
+    }
+
+    library.Close();
+
+    g_layer_libraries.emplace_back(std::move(library));
 }
 
 void DiscoverLayersInDirectory(const std::string& dir_path) {
@@ -271,71 +330,21 @@
     closedir(directory);
 }
 
+const VkExtensionProperties* FindExtension(
+    const std::vector<VkExtensionProperties>& extensions,
+    const char* name) {
+    auto it = std::find_if(extensions.cbegin(), extensions.cend(),
+                           [=](const VkExtensionProperties& ext) {
+                               return (strcmp(ext.extensionName, name) == 0);
+                           });
+    return (it != extensions.cend()) ? &*it : nullptr;
+}
+
 void* GetLayerGetProcAddr(const Layer& layer,
                           const char* gpa_name,
                           size_t gpa_name_len) {
     const LayerLibrary& library = g_layer_libraries[layer.library_idx];
-    void* gpa;
-    size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
-    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
-    strcpy(name, layer.properties.layerName);
-    strcpy(name + layer_name_len, gpa_name);
-    if (!(gpa = dlsym(library.dlhandle, name))) {
-        strcpy(name, "vk");
-        strcpy(name + 2, gpa_name);
-        gpa = dlsym(library.dlhandle, name);
-    }
-    return gpa;
-}
-
-uint32_t EnumerateLayers(const std::vector<Layer>& layers,
-                         uint32_t count,
-                         VkLayerProperties* properties) {
-    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
-    for (uint32_t i = 0; i < n; i++) {
-        properties[i] = layers[i].properties;
-    }
-    return static_cast<uint32_t>(layers.size());
-}
-
-void GetLayerExtensions(const std::vector<Layer>& layers,
-                        const char* name,
-                        const VkExtensionProperties** properties,
-                        uint32_t* count) {
-    auto layer =
-        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
-            return strcmp(entry.properties.layerName, name) == 0;
-        });
-    if (layer == layers.cend()) {
-        *properties = nullptr;
-        *count = 0;
-    } else {
-        *properties = layer->extensions.data();
-        *count = static_cast<uint32_t>(layer->extensions.size());
-    }
-}
-
-LayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
-    for (uint32_t id = 0; id < layers.size(); id++) {
-        if (strcmp(name, layers[id].properties.layerName) == 0) {
-            LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
-            std::lock_guard<std::mutex> lock(g_library_mutex);
-            if (library.refcount++ == 0) {
-                library.dlhandle =
-                    dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
-                ALOGV("Opening library %s", library.path.c_str());
-                if (!library.dlhandle) {
-                    ALOGE("failed to load layer library '%s': %s",
-                          library.path.c_str(), dlerror());
-                    library.refcount = 0;
-                    return LayerRef(nullptr);
-                }
-            }
-            ALOGV("Refcount on activate is %zu", library.refcount);
-            return LayerRef(&layers[id]);
-        }
-    }
-    return LayerRef(nullptr);
+    return library.GetGPA(layer, gpa_name, gpa_name_len);
 }
 
 }  // anonymous namespace
@@ -347,59 +356,68 @@
         DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
 }
 
-uint32_t EnumerateInstanceLayers(uint32_t count,
-                                 VkLayerProperties* properties) {
-    return EnumerateLayers(g_instance_layers, count, properties);
+uint32_t GetLayerCount() {
+    return static_cast<uint32_t>(g_instance_layers.size());
 }
 
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
-    return EnumerateLayers(g_device_layers, count, properties);
+const Layer& GetLayer(uint32_t index) {
+    return g_instance_layers[index];
 }
 
-void GetInstanceLayerExtensions(const char* name,
-                                const VkExtensionProperties** properties,
-                                uint32_t* count) {
-    GetLayerExtensions(g_instance_layers, name, properties, count);
+const Layer* FindLayer(const char* name) {
+    auto layer =
+        std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
+                     [=](const Layer& entry) {
+                         return strcmp(entry.properties.layerName, name) == 0;
+                     });
+    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
 }
 
-void GetDeviceLayerExtensions(const char* name,
-                              const VkExtensionProperties** properties,
-                              uint32_t* count) {
-    GetLayerExtensions(g_device_layers, name, properties, count);
+const VkLayerProperties& GetLayerProperties(const Layer& layer) {
+    return layer.properties;
 }
 
-LayerRef GetInstanceLayerRef(const char* name) {
-    return GetLayerRef(g_instance_layers, name);
+bool IsLayerGlobal(const Layer& layer) {
+    return layer.is_global;
 }
 
-LayerRef GetDeviceLayerRef(const char* name) {
-    return GetLayerRef(g_device_layers, name);
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+                                                        uint32_t& count) {
+    count = static_cast<uint32_t>(layer.instance_extensions.size());
+    return layer.instance_extensions.data();
 }
 
-LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+                                                      uint32_t& count) {
+    count = static_cast<uint32_t>(layer.device_extensions.size());
+    return layer.device_extensions.data();
+}
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+                                                        const char* name) {
+    return FindExtension(layer.instance_extensions, name);
+}
+
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+                                                      const char* name) {
+    return FindExtension(layer.device_extensions, name);
+}
+
+LayerRef GetLayerRef(const Layer& layer) {
+    LayerLibrary& library = g_layer_libraries[layer.library_idx];
+    return LayerRef((library.Open()) ? &layer : nullptr);
+}
+
+LayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
 
 LayerRef::~LayerRef() {
     if (layer_) {
         LayerLibrary& library = g_layer_libraries[layer_->library_idx];
-        std::lock_guard<std::mutex> lock(g_library_mutex);
-        if (--library.refcount == 0) {
-            ALOGV("Closing library %s", library.path.c_str());
-            dlclose(library.dlhandle);
-            library.dlhandle = nullptr;
-        }
-        ALOGV("Refcount on destruction is %zu", library.refcount);
+        library.Close();
     }
 }
 
-const char* LayerRef::GetName() const {
-    return layer_->properties.layerName;
-}
-
-uint32_t LayerRef::GetSpecVersion() {
-    return layer_->properties.specVersion;
-}
-
-LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
+LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
     other.layer_ = nullptr;
 }
 
@@ -415,12 +433,5 @@
                   : nullptr;
 }
 
-bool LayerRef::SupportsExtension(const char* name) const {
-    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
-                        [=](const VkExtensionProperties& ext) {
-                            return strcmp(ext.extensionName, name) == 0;
-                        }) != layer_->extensions.cend();
-}
-
 }  // namespace api
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 7e7bfd3..79fe59d 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -23,40 +23,44 @@
 namespace api {
 
 struct Layer;
+
 class LayerRef {
    public:
-    LayerRef(Layer* layer);
+    LayerRef(const Layer* layer);
     LayerRef(LayerRef&& other);
     ~LayerRef();
     LayerRef(const LayerRef&) = delete;
     LayerRef& operator=(const LayerRef&) = delete;
 
-    const char* GetName() const;
-    uint32_t GetSpecVersion();
-
     // provides bool-like behavior
     operator const Layer*() const { return layer_; }
 
     PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
     PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
 
-    bool SupportsExtension(const char* name) const;
-
    private:
-    Layer* layer_;
+    const Layer* layer_;
 };
 
 void DiscoverLayers();
-uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
-void GetInstanceLayerExtensions(const char* name,
-                                const VkExtensionProperties** properties,
-                                uint32_t* count);
-void GetDeviceLayerExtensions(const char* name,
-                              const VkExtensionProperties** properties,
-                              uint32_t* count);
-LayerRef GetInstanceLayerRef(const char* name);
-LayerRef GetDeviceLayerRef(const char* name);
+
+uint32_t GetLayerCount();
+const Layer& GetLayer(uint32_t index);
+const Layer* FindLayer(const char* name);
+
+const VkLayerProperties& GetLayerProperties(const Layer& layer);
+bool IsLayerGlobal(const Layer& layer);
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+                                                        uint32_t& count);
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+                                                      uint32_t& count);
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+                                                        const char* name);
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+                                                      const char* name);
+
+LayerRef GetLayerRef(const Layer& layer);
 
 }  // namespace api
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 89fcebb..a74d370 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -83,7 +83,7 @@
     std::lock_guard<std::mutex> lock(g_instance_mutex);
     ssize_t idx =
         reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
-    ALOG_ASSERT(idx >= 0 && idx < g_instance_used.size(),
+    ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
                 "DestroyInstance: invalid instance handle");
     g_instance_used[static_cast<size_t>(idx)] = false;
 }
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e990cf4..69e8e84 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -329,6 +329,17 @@
     int err;
     VkResult result = VK_SUCCESS;
 
+    ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
+          " minImageCount=%u imageFormat=%u imageColorSpace=%u"
+          " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
+          " oldSwapchain=0x%" PRIx64,
+          reinterpret_cast<uint64_t>(create_info->surface),
+          create_info->minImageCount, create_info->imageFormat,
+          create_info->imageColorSpace, create_info->imageExtent.width,
+          create_info->imageExtent.height, create_info->imageUsage,
+          create_info->preTransform, create_info->presentMode,
+          reinterpret_cast<uint64_t>(create_info->oldSwapchain));
+
     if (!allocator)
         allocator = &GetData(device).allocator;
 
@@ -348,9 +359,32 @@
              "swapchain present mode %d not supported",
              create_info->presentMode);
 
+    Surface& surface = *SurfaceFromHandle(create_info->surface);
+
+    // -- Reset the native window --
+    // The native window might have been used previously, and had its properties
+    // changed from defaults. That will affect the answer we get for queries
+    // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
+    // attempt such queries.
+
+    err = native_window_set_buffer_count(surface.window.get(), 0);
+    if (err != 0) {
+        ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    err = surface.window->setSwapInterval(surface.window.get(), 1);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
     // -- Configure the native window --
 
-    Surface& surface = *SurfaceFromHandle(create_info->surface);
     const auto& dispatch = GetData(device).driver;
 
     int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
@@ -451,8 +485,8 @@
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
-        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
-              err);
+        ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
+              strerror(-err), err);
         return VK_ERROR_INITIALIZATION_FAILED;
     }
 
@@ -477,14 +511,14 @@
         return VK_ERROR_INITIALIZATION_FAILED;
     }
 
-    err = surface.window->setSwapInterval(
-        surface.window.get(),
-        create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1);
+    int swap_interval =
+        create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
+    err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
-        ALOGE("native_window->setSwapInterval failed: %s (%d)", strerror(-err),
-              err);
+        ALOGE("native_window->setSwapInterval(%d) failed: %s (%d)",
+              swap_interval, strerror(-err), err);
         return VK_ERROR_INITIALIZATION_FAILED;
     }
 
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 6f57238..f29cb68 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <array>
 #include <inttypes.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <log/log.h>
@@ -186,6 +187,58 @@
         AllocHandle(type, &device->next_handle[type]));
 }
 
+VKAPI_ATTR void* DefaultAllocate(void*,
+                                 size_t size,
+                                 size_t alignment,
+                                 VkSystemAllocationScope) {
+    void* ptr = nullptr;
+    // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+    // additionally requires that it be at least sizeof(void*).
+    int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+    return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+                                   void* ptr,
+                                   size_t size,
+                                   size_t alignment,
+                                   VkSystemAllocationScope) {
+    if (size == 0) {
+        free(ptr);
+        return nullptr;
+    }
+
+    // TODO(jessehall): Right now we never shrink allocations; if the new
+    // request is smaller than the existing chunk, we just continue using it.
+    // The null driver never reallocs, so this doesn't matter. If that changes,
+    // or if this code is copied into some other project, this should probably
+    // have a heuristic to allocate-copy-free when doing so will save "enough"
+    // space.
+    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+    if (size <= old_size)
+        return ptr;
+
+    void* new_ptr = nullptr;
+    if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+        return nullptr;
+    if (ptr) {
+        memcpy(new_ptr, ptr, std::min(old_size, size));
+        free(ptr);
+    }
+    return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+    free(ptr);
+}
+
+const VkAllocationCallbacks kDefaultAllocCallbacks = {
+    .pUserData = nullptr,
+    .pfnAllocation = DefaultAllocate,
+    .pfnReallocation = DefaultReallocate,
+    .pfnFree = DefaultFree,
+};
+
 }  // namespace
 
 namespace null_driver {
@@ -239,10 +292,8 @@
 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
                         const VkAllocationCallbacks* allocator,
                         VkInstance* out_instance) {
-    // Assume the loader provided alloc callbacks even if the app didn't.
-    ALOG_ASSERT(
-        allocator,
-        "Missing alloc callbacks, loader or app should have provided them");
+    if (!allocator)
+        allocator = &kDefaultAllocCallbacks;
 
     VkInstance_T* instance =
         static_cast<VkInstance_T*>(allocator->pfnAllocation(
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index e97e5f5..62d8240 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -162,8 +162,11 @@
     uint32_t num_extensions = 0;
     for (const auto& desired_ext : kDesiredExtensions) {
         bool available = HasExtension(info.extensions, desired_ext);
-        for (size_t i = 0; !available && i < info.layer_extensions.size(); i++)
-            available = HasExtension(info.layer_extensions[i], desired_ext);
+        if (options.validate) {
+            for (size_t i = 0; !available && i < info.layer_extensions.size();
+                 i++)
+                available = HasExtension(info.layer_extensions[i], desired_ext);
+        }
         if (available)
             extensions[num_extensions++] = desired_ext;
     }
@@ -179,12 +182,11 @@
     // clang-format off
     const char *kValidationLayers[] = {
         "VK_LAYER_GOOGLE_threading",
+        "VK_LAYER_LUNARG_parameter_validation",
         "VK_LAYER_LUNARG_device_limits",
-        "VK_LAYER_LUNARG_draw_state",
-        "VK_LAYER_LUNARG_image",
-        "VK_LAYER_LUNARG_mem_tracker",
         "VK_LAYER_LUNARG_object_tracker",
-        "VK_LAYER_LUNARG_param_checker",
+        "VK_LAYER_LUNARG_image",
+        "VK_LAYER_LUNARG_core_validation",
         "VK_LAYER_LUNARG_swapchain",
         "VK_LAYER_GOOGLE_unique_objects"
     };
@@ -236,8 +238,12 @@
     uint32_t num_extensions = 0;
     for (const auto& desired_ext : kDesiredExtensions) {
         bool available = HasExtension(info->extensions, desired_ext);
-        for (size_t i = 0; !available && i < info->layer_extensions.size(); i++)
-            available = HasExtension(info->layer_extensions[i], desired_ext);
+        if (options.validate) {
+            for (size_t i = 0; !available && i < info->layer_extensions.size();
+                 i++)
+                available =
+                    HasExtension(info->layer_extensions[i], desired_ext);
+        }
         if (available)
             extensions[num_extensions++] = desired_ext;
     }
@@ -245,12 +251,11 @@
     // clang-format off
     const char *kValidationLayers[] = {
         "VK_LAYER_GOOGLE_threading",
+        "VK_LAYER_LUNARG_parameter_validation",
         "VK_LAYER_LUNARG_device_limits",
-        "VK_LAYER_LUNARG_draw_state",
-        "VK_LAYER_LUNARG_image",
-        "VK_LAYER_LUNARG_mem_tracker",
         "VK_LAYER_LUNARG_object_tracker",
-        "VK_LAYER_LUNARG_param_checker",
+        "VK_LAYER_LUNARG_image",
+        "VK_LAYER_LUNARG_core_validation",
         "VK_LAYER_LUNARG_swapchain",
         "VK_LAYER_GOOGLE_unique_objects"
     };