Merge "Move servicemanager into system-background cpuset." into nyc-dev
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
index b6856bb..19d2d64 100644
--- a/cmds/bugreportz/bugreportz.cpp
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <errno.h>
+#include <getopt.h>
 #include <stdio.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -23,9 +24,47 @@
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
 
-// TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
-// should be reused instead.
-int main() {
+static constexpr char VERSION[] = "1.0";
+
+static void show_usage() {
+  fprintf(stderr,
+          "usage: bugreportz [-h | -v]\n"
+          "  -h: to display this help message\n"
+          "  -v: to display the version\n"
+          "  or no arguments to generate a zipped bugreport\n");
+}
+
+static void show_version() {
+  fprintf(stderr, "%s\n", VERSION);
+}
+
+int main(int argc, char *argv[]) {
+
+    if (argc > 1) {
+        /* parse arguments */
+        int c;
+        while ((c = getopt(argc, argv, "vh")) != -1) {
+            switch (c) {
+                case 'h':
+                    show_usage();
+                    return EXIT_SUCCESS;
+                case 'v':
+                    show_version();
+                    return EXIT_SUCCESS;
+                default:
+                    show_usage();
+                    return EXIT_FAILURE;
+            }
+        }
+        // passed an argument not starting with -
+        if (optind > 1 || argv[optind] != nullptr) {
+            show_usage();
+            return EXIT_FAILURE;
+        }
+    }
+
+    // TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+    // should be reused instead.
 
     // Start the dumpstatez service.
     property_set("ctl.start", "dumpstatez");
@@ -42,7 +81,7 @@
 
     if (s == -1) {
         printf("Failed to connect to dumpstatez service: %s\n", strerror(errno));
-        return 1;
+        return EXIT_FAILURE;
     }
 
     // Set a timeout so that if nothing is read in 10 minutes, we'll stop
@@ -81,13 +120,12 @@
                 printf(
                         "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
                         bytes_read, bytes_to_send, strerror(errno));
-                return 1;
+                return EXIT_FAILURE;
             }
             bytes_to_send -= bytes_written;
         } while (bytes_written != 0 && bytes_to_send > 0);
     }
 
     close(s);
-    return 0;
-
+    return EXIT_SUCCESS;
 }
diff --git a/cmds/bugreportz/readme.md b/cmds/bugreportz/readme.md
new file mode 100644
index 0000000..85aafce
--- /dev/null
+++ b/cmds/bugreportz/readme.md
@@ -0,0 +1,12 @@
+# bugreportz protocol
+
+`bugreportz` is used to generate a zippped bugreport whose path is passed back to `adb`, using
+the simple protocol defined below.
+
+
+## Version 1.0
+On version 1.0, `bugreportz` does not generate any output on `stdout` until the bugreport is
+finished, when it then prints one line with the result:
+
+- `OK:<path_to_bugreport_file>` in case of success.
+- `FAIL:<error message>` in case of failure.
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 20ad5f9..f4d894b 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -419,38 +419,29 @@
     return -1;
 }
 
-int make_user_config(userid_t userid)
-{
-    if (ensure_config_user_dirs(userid) == -1) {
-        return -1;
+int create_user_data(const char *uuid, userid_t userid, int user_serial ATTRIBUTE_UNUSED,
+        int flags) {
+    if (flags & FLAG_STORAGE_DE) {
+        if (uuid == nullptr) {
+            return ensure_config_user_dirs(userid);
+        }
     }
-
     return 0;
 }
 
-int delete_user(const char *uuid, userid_t userid) {
+int destroy_user_data(const char *uuid, userid_t userid, int flags) {
     int res = 0;
-
-    std::string data_path(create_data_user_ce_path(uuid, userid));
-    std::string data_de_path(create_data_user_de_path(uuid, userid));
-    std::string media_path(create_data_media_path(uuid, userid));
-    std::string profiles_path(create_data_user_profiles_path(userid));
-
-    res |= delete_dir_contents_and_dir(data_path);
-    // TODO: include result once 25796509 is fixed
-    delete_dir_contents_and_dir(data_de_path);
-    res |= delete_dir_contents_and_dir(media_path);
-    res |= delete_dir_contents_and_dir(profiles_path);
-
-    // Config paths only exist on internal storage
-    if (uuid == nullptr) {
-        char config_path[PATH_MAX];
-        if ((create_user_config_path(config_path, userid) != 0)
-                || (delete_dir_contents(config_path, 1, NULL) != 0)) {
-            res = -1;
+    if (flags & FLAG_STORAGE_DE) {
+        res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid, userid), true);
+        if (uuid == nullptr) {
+            res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userid), true);
+            res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userid), true);
         }
     }
-
+    if (flags & FLAG_STORAGE_CE) {
+        res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid, userid), true);
+        res |= delete_dir_contents_and_dir(create_data_media_path(uuid, userid), true);
+    }
     return res;
 }
 
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index f13ceea..81c13b4 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -46,8 +46,9 @@
         int64_t *asecsize);
 int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
 
-int make_user_config(userid_t userid);
-int delete_user(const char *uuid, userid_t userid);
+int create_user_data(const char *uuid, userid_t userid, int user_serial, int flags);
+int destroy_user_data(const char *uuid, userid_t userid, int flags);
+
 int rm_dex(const char *path, const char *instruction_set);
 int free_cache(const char *uuid, int64_t free_size);
 
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 5c29eb4..eb51e70 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -336,14 +336,16 @@
                              atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return make_user_config(atoi(arg[0])); /* userid */
+    /* const char *uuid, userid_t userid, int user_serial, int flags */
+    return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
 }
 
-static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
+    /* const char *uuid, userid_t userid, int flags */
+    return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
 }
 
 static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -409,13 +411,14 @@
     { "get_app_size",         6, do_get_app_size },
     { "get_app_data_inode",   4, do_get_app_data_inode },
 
+    { "create_user_data",     4, do_create_user_data },
+    { "destroy_user_data",    3, do_destroy_user_data },
+
     { "dexopt",               9, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "rmdex",                2, do_rm_dex },
     { "freecache",            2, do_free_cache },
     { "linklib",              4, do_linklib },
-    { "mkuserconfig",         1, do_mk_user_config },
-    { "rmuser",               2, do_rm_user },
     { "idmap",                3, do_idmap },
     { "createoatdir",         2, do_create_oat_dir },
     { "rmpackagedir",         1, do_rm_package_dir },
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 5c2ad2d..90d2a9e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -193,6 +193,10 @@
     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
 }
 
+std::string create_data_misc_legacy_path(userid_t userid) {
+    return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
+}
+
 std::string create_data_user_profiles_path(userid_t userid) {
     return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
 }
@@ -239,17 +243,6 @@
     return users;
 }
 
-/**
- * Create the path name for config for a certain userid.
- * Returns 0 on success, and -1 on failure.
- */
-int create_user_config_path(char path[PATH_MAX], userid_t userid) {
-    if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) {
-        return -1;
-    }
-    return 0;
-}
-
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
@@ -1219,19 +1212,13 @@
 }
 
 int ensure_config_user_dirs(userid_t userid) {
-    char config_user_path[PATH_MAX];
-
     // writable by system, readable by any app within the same user
     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
 
     // Ensure /data/misc/user/<userid> exists
-    create_user_config_path(config_user_path, userid);
-    if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
-        return -1;
-    }
-
-   return 0;
+    auto path = create_data_misc_legacy_path(userid);
+    return fs_prepare_dir(path.c_str(), 0750, uid, gid);
 }
 
 int wait_child(pid_t pid)
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 9d9a423..477baea 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -85,6 +85,8 @@
 
 std::string create_data_media_path(const char* volume_uuid, userid_t userid);
 
+std::string create_data_misc_legacy_path(userid_t userid);
+
 std::string create_data_user_profiles_path(userid_t userid);
 std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
 std::string create_data_ref_profile_package_path(const char* package_name);
@@ -140,8 +142,6 @@
 char *build_string2(const char *s1, const char *s2);
 char *build_string3(const char *s1, const char *s2, const char *s3);
 
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(const char* uuid, userid_t userid);
 int ensure_config_user_dirs(userid_t userid);
 
 int wait_child(pid_t pid);
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index ae0b4d4..4b7a706 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -22,7 +22,8 @@
 -->
 <permissions>
     <feature name="android.hardware.location" />
-    <feature name="android.hardware.sensor.compass" />
+    <!-- devices supporting compass/magnitometer sensor must include
+	 android.hardware.sensor.compass.xml -->
     <feature name="android.hardware.sensor.accelerometer" />
     <feature name="android.hardware.bluetooth" />
     <feature name="android.hardware.touchscreen" />
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index f9edc2a..64cf72e 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -91,6 +91,8 @@
             size_t              mExecutingThreadsCount;
             // Maximum number for binder threads allowed for this process.
             size_t              mMaxThreads;
+            // Time when thread pool was emptied
+            int64_t             mStarvationStartTimeMs;
 
     mutable Mutex               mLock;  // protects everything below.
 
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index d232dbb..4337da9 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -319,6 +319,9 @@
         android_dataspace dataspace;
     } mSharedBufferCache;
 
+    // The slot of the last queued buffer
+    int mLastQueuedSlot;
+
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 691487d..7256f73 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -182,6 +182,10 @@
     // See IGraphicBufferProducer::setDequeueTimeout
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
 
+    // See IGraphicBufferProducer::getLastQueuedBuffer
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence) override;
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 32bf988..049406c 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -557,6 +557,15 @@
     //               happen because of trying to allocate/deallocate the async
     //               buffer.
     virtual status_t setDequeueTimeout(nsecs_t timeout) = 0;
+
+    // Returns the last queued buffer along with a fence which must signal
+    // before the contents of the buffer are read. If there are no buffers in
+    // the queue, outBuffer will be populated with nullptr and outFence will be
+    // populated with Fence::NO_FENCE
+    //
+    // Returns NO_ERROR or the status of the Binder transaction
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index f76a9be..bbf427d 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -129,6 +129,10 @@
      */
     bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
 
+    // See IGraphicBufferProducer::getLastQueuedBuffer
+    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence);
+
 protected:
     virtual ~Surface();
 
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 9161dbb..73f923c 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -138,6 +138,8 @@
     status_t    setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
     status_t    deferTransactionUntil(const sp<IBinder>& id,
             const sp<IBinder>& handle, uint64_t frameNumber);
+    status_t    setOverrideScalingMode(const sp<IBinder>& id,
+            int32_t overrideScalingMode);
     status_t    destroySurface(const sp<IBinder>& id);
 
     status_t clearLayerFrameStats(const sp<IBinder>& token) const;
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 35644db..bedebb6 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -77,6 +77,11 @@
     // identified by handle reaches the given frameNumber
     status_t deferTransactionUntil(sp<IBinder> handle, uint64_t frameNumber);
 
+    // Set an override scaling mode as documented in <system/window.h>
+    // the override scaling mode will take precedence over any client
+    // specified scaling mode. -1 will clear the override scaling mode.
+    status_t setOverrideScalingMode(int32_t overrideScalingMode);
+
     static status_t writeSurfaceToParcel(
             const sp<SurfaceControl>& control, Parcel* parcel);
 
diff --git a/include/input/Input.h b/include/input/Input.h
index 3b1c86b..55787e7 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -45,6 +45,19 @@
 };
 
 enum {
+
+    /**
+     * This flag indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it.  This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches.  An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2,
+
     /* Motion event is inconsistent with previously sent motion events. */
     AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
 };
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 078720a..92d31d1 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -53,7 +53,8 @@
         eLayerStackChanged          = 0x00000080,
         eCropChanged                = 0x00000100,
         eDeferTransaction           = 0x00000200,
-        eFinalCropChanged           = 0x00000400
+        eFinalCropChanged           = 0x00000400,
+        eOverrideScalingModeChanged = 0x00000800
     };
 
     layer_state_t()
@@ -61,7 +62,8 @@
             x(0), y(0), z(0), w(0), h(0), layerStack(0),
             alpha(0), flags(0), mask(0),
             reserved(0), crop(Rect::INVALID_RECT),
-            finalCrop(Rect::INVALID_RECT), frameNumber(0)
+            finalCrop(Rect::INVALID_RECT), frameNumber(0),
+            overrideScalingMode(-1)
     {
         matrix.dsdx = matrix.dtdy = 1.0f;
         matrix.dsdy = matrix.dtdx = 0.0f;
@@ -93,6 +95,7 @@
             Rect            finalCrop;
             sp<IBinder>     handle;
             uint64_t        frameNumber;
+            int32_t         overrideScalingMode;
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 1cbcfe4..d90798f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -24,12 +24,14 @@
 
 #include <cutils/sched_policy.h>
 #include <utils/Log.h>
+#include <utils/SystemClock.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
 #include <private/binder/Static.h>
 
 #include <errno.h>
+#include <inttypes.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
@@ -434,12 +436,25 @@
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount++;
+        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
+                mProcess->mStarvationStartTimeMs == 0) {
+            mProcess->mStarvationStartTimeMs = uptimeMillis();
+        }
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
 
         result = executeCommand(cmd);
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount--;
+        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
+                mProcess->mStarvationStartTimeMs != 0) {
+            int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
+            if (starvationTimeMs > 100) {
+                ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
+                      mProcess->mMaxThreads, starvationTimeMs);
+            }
+            mProcess->mStarvationStartTimeMs = 0;
+        }
         pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
 
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index b221e51..f13f49f 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -343,6 +343,7 @@
     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
     , mExecutingThreadsCount(0)
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
+    , mStarvationStartTimeMs(0)
     , mManagesContexts(false)
     , mBinderContextCheckFunc(NULL)
     , mBinderContextUserData(NULL)
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index b591c4e..cbc8893 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -622,6 +622,10 @@
             return NO_INIT;
         }
 
+        if (maxAcquiredBuffers == mCore->mMaxAcquiredBufferCount) {
+            return NO_ERROR;
+        }
+
         // The new maxAcquiredBuffers count should not be violated by the number
         // of currently acquired buffers
         int acquiredCount = 0;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index cdece73..052de3d 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -200,6 +200,10 @@
     }
     mSlots[slot].mFence = Fence::NO_FENCE;
     mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
+
+    if (mLastQueuedSlot == slot) {
+        mLastQueuedSlot = INVALID_BUFFER_SLOT;
+    }
 }
 
 void BufferQueueCore::freeAllBuffersLocked() {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index bb8d39b..0b7ce17 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -101,6 +101,10 @@
             return NO_INIT;
         }
 
+        if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
+            return NO_ERROR;
+        }
+
         // The new maxDequeuedBuffer count should not be violated by the number
         // of currently dequeued buffers
         int dequeuedCount = 0;
@@ -175,6 +179,10 @@
             return NO_INIT;
         }
 
+        if (async == mCore->mAsyncMode) {
+            return NO_ERROR;
+        }
+
         if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
                 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
                 mCore->mMaxBufferCount) {
@@ -199,7 +207,9 @@
         mCore->mAsyncMode = async;
         VALIDATE_CONSISTENCY();
         mCore->mDequeueCondition.broadcast();
-        listener = mCore->mConsumerListener;
+        if (delta < 0) {
+            listener = mCore->mConsumerListener;
+        }
     } // Autolock scope
 
     // Call back without lock held
@@ -834,30 +844,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);
@@ -867,6 +878,7 @@
 
         mCore->mBufferHasBeenQueued = true;
         mCore->mDequeueCondition.broadcast();
+        mCore->mLastQueuedSlot = slot;
 
         output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
                 mCore->mTransformHint,
@@ -909,8 +921,8 @@
         // third. In the event that frames take varying time, this makes a
         // small trade-off in favor of latency rather than throughput.
         mLastQueueBufferFence->waitForever("Throttling EGL Production");
-        mLastQueueBufferFence = fence;
     }
+    mLastQueueBufferFence = fence;
 
     return NO_ERROR;
 }
@@ -1356,6 +1368,24 @@
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence) {
+    ATRACE_CALL();
+    BQ_LOGV("getLastQueuedBuffer");
+
+    Mutex::Autolock lock(mCore->mMutex);
+    if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
+        *outBuffer = nullptr;
+        *outFence = Fence::NO_FENCE;
+        return NO_ERROR;
+    }
+
+    *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
+    *outFence = mLastQueueBufferFence;
+
+    return NO_ERROR;
+}
+
 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
     // If we're here, it means that a producer we were connected to died.
     // We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 7cdb8f4..c36fcad 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -54,6 +54,7 @@
     SET_SHARED_BUFFER_MODE,
     SET_AUTO_REFRESH,
     SET_DEQUEUE_TIMEOUT,
+    GET_LAST_QUEUED_BUFFER,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -379,6 +380,37 @@
         }
         return reply.readInt32();
     }
+
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence) override {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
+                &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result != NO_ERROR) {
+            return result;
+        }
+        sp<GraphicBuffer> buffer(new GraphicBuffer);
+        result = reply.read(*buffer);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
+            return result;
+        }
+        sp<Fence> fence(new Fence);
+        result = reply.read(*fence);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
+            return result;
+        }
+        *outBuffer = buffer;
+        *outFence = fence;
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -590,6 +622,27 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case GET_LAST_QUEUED_BUFFER: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            sp<GraphicBuffer> buffer(nullptr);
+            sp<Fence> fence(Fence::NO_FENCE);
+            status_t result = getLastQueuedBuffer(&buffer, &fence);
+            reply->writeInt32(result);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            result = reply->write(*buffer);
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
+                return result;
+            }
+            result = reply->write(*fence);
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write fence: %d", result);
+                return result;
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e43342e..d1c576e 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -41,6 +41,7 @@
     output.write(finalCrop);
     output.writeStrongBinder(handle);
     output.writeUint64(frameNumber);
+    output.writeInt32(overrideScalingMode);
     output.write(transparentRegion);
     return NO_ERROR;
 }
@@ -68,6 +69,7 @@
     input.read(finalCrop);
     handle = input.readStrongBinder();
     frameNumber = input.readUint64();
+    overrideScalingMode = input.readInt32();
     input.read(transparentRegion);
     return NO_ERROR;
 }
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 4b9a2ab..0340d6b 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -272,6 +272,11 @@
         break;
     }
 
+    // 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));
+    }
+
     // Set DATA_INJECTION flag here. Defined in HAL 1_4.
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
         mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 5efc333..b304633 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -127,6 +127,11 @@
     return mGraphicBufferProducer->setDequeueTimeout(timeout);
 }
 
+status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence) {
+    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence);
+}
+
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
     Surface* c = getSelf(window);
     return c->setSwapInterval(interval);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 418892a..e33cc37 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -163,6 +163,8 @@
     status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
             const sp<IBinder>& id, const sp<IBinder>& handle,
             uint64_t frameNumber);
+    status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
+            const sp<IBinder>& id, int32_t overrideScalingMode);
 
     void setDisplaySurface(const sp<IBinder>& token,
             const sp<IGraphicBufferProducer>& bufferProducer);
@@ -414,6 +416,33 @@
     return NO_ERROR;
 }
 
+status_t Composer::setOverrideScalingMode(
+        const sp<SurfaceComposerClient>& client,
+        const sp<IBinder>& id, int32_t overrideScalingMode) {
+    Mutex::Autolock lock(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+
+    switch (overrideScalingMode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+        case -1:
+            break;
+        default:
+            ALOGE("unknown scaling mode: %d",
+                    overrideScalingMode);
+            return BAD_VALUE;
+    }
+
+    s->what |= layer_state_t::eOverrideScalingModeChanged;
+    s->overrideScalingMode = overrideScalingMode;
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
@@ -650,6 +679,12 @@
     return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
 }
 
+status_t SurfaceComposerClient::setOverrideScalingMode(
+        const sp<IBinder>& id, int32_t overrideScalingMode) {
+    return getComposer().setOverrideScalingMode(
+            this, id, overrideScalingMode);
+}
+
 // ----------------------------------------------------------------------------
 
 void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 184de71..314d83a 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -165,6 +165,12 @@
     return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
 }
 
+status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
+}
+
 status_t SurfaceControl::clearLayerFrameStats() const {
     status_t err = validate();
     if (err < 0) return err;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 82df9a9..9876d94 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -796,4 +796,56 @@
     ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
 }
 
+TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, false, &output));
+
+    // Dequeue and queue the first buffer, storing the handle
+    int slot = BufferQueue::INVALID_BUFFER_SLOT;
+    sp<Fence> fence;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+    sp<GraphicBuffer> firstBuffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
+
+    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
+        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    // Dequeue a second buffer
+    slot = BufferQueue::INVALID_BUFFER_SLOT;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+    sp<GraphicBuffer> secondBuffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
+
+    // Ensure it's a new buffer
+    ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
+            secondBuffer->getNativeBuffer()->handle);
+
+    // Queue the second buffer
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    // Acquire and release both buffers
+    for (size_t i = 0; i < 2; ++i) {
+        BufferItem item;
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+    }
+
+    // Make sure we got the second buffer back
+    sp<GraphicBuffer> returnedBuffer;
+    sp<Fence> returnedFence;
+    ASSERT_EQ(OK,
+            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence));
+    ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
+            returnedBuffer->getNativeBuffer()->handle);
+}
+
 } // namespace android
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 613b63b..df639cd 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -116,6 +116,7 @@
         "EGL_EXT_buffer_age "                   // strongly recommended with partial_update
         "EGL_KHR_create_context_no_error "
         "EGL_KHR_mutable_render_buffer "
+        "EGL_EXT_yuv_surface "
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index d849693..c368bad 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -44,9 +44,10 @@
 
 static bool findExtension(const char* exts, const char* name, size_t nameLen) {
     if (exts) {
-        const char* match = strstr(exts, name);
-        if (match && (match[nameLen] == '\0' || match[nameLen] == ' ')) {
-            return true;
+        for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
+            if (match[nameLen] == '\0' || match[nameLen] == ' ') {
+                return true;
+            }
         }
     }
     return false;
diff --git a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
new file mode 100644
index 0000000..a6fae80
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
@@ -0,0 +1,197 @@
+Name
+
+    ANDROID_create_native_client_buffer
+
+Name Strings
+
+    EGL_ANDROID_create_native_client_buffer
+
+Contributors
+
+    Craig Donner
+
+Contact
+
+    Craig Donner, Google Inc. (cdonner 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, January 19, 2016
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.2.
+
+    EGL_ANDROID_image_native_buffer and EGL_KHR_image_base are required.
+
+    This extension is written against the wording of the EGL 1.2
+    Specification as modified by EGL_KHR_image_base and
+    EGL_ANDROID_image_native_buffer.
+
+Overview
+
+    This extension allows creating an EGLClientBuffer backed by an Android
+    window buffer (struct ANativeWindowBuffer) which can be later used to
+    create an EGLImage.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+EGLClientBuffer eglCreateNativeClientBufferANDROID(
+                        const EGLint *attrib_list)
+
+New Tokens
+
+    EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
+    EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+    EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+    EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+
+Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
+
+    Add the following to section 2.5.1 "EGLImage Specification" (as modified by
+    the EGL_KHR_image_base and EGL_ANDROID_image_native_buffer specifications),
+    below the description of eglCreateImageKHR:
+
+   "The command
+
+        EGLClientBuffer eglCreateNativeClientBufferANDROID(
+                                const EGLint *attrib_list)
+
+    may be used to create an EGLClientBuffer backed by an ANativeWindowBuffer
+    struct. EGL implementations must guarantee that the lifetime of the
+    returned EGLClientBuffer is at least as long as the EGLImage(s) it is bound
+    to, following the lifetime semantics described below in section 2.5.2; the
+    EGLClientBuffer must be destroyed no earlier than when all of its associated
+    EGLImages are destroyed by eglDestroyImageKHR. <attrib_list> is a list of
+    attribute-value pairs which is used to specify the dimensions, format, and
+    usage of the underlying buffer structure. If <attrib_list> is non-NULL, the
+    last attribute specified in the list must be EGL_NONE.
+
+    Attribute names accepted in <attrib_list> are shown in Table aaa,
+    together with the <target> for which each attribute name is valid, and
+    the default value used for each attribute if it is not included in
+    <attrib_list>.
+
+      +---------------------------------+----------------------+---------------+
+      | Attribute                       | Description          | Default Value |
+      |                                 |                      |               |
+      +---------------------------------+----------------------+---------------+
+      | EGL_NONE                        | Marks the end of the | N/A           |
+      |                                 | attribute-value list |               |
+      | EGL_WIDTH                       | The width of the     | 0             |
+      |                                 | buffer data          |               |
+      | EGL_HEIGHT                      | The height of the    | 0             |
+      |                                 | buffer data          |               |
+      | EGL_RED_SIZE                    | The bits of Red in   | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_GREEN_SIZE                  | The bits of Green in | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_BLUE_SIZE                   | The bits of Blue in  | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_ALPHA_SIZE                  | The bits of Alpha in | 0             |
+      |                                 | the color buffer     |               |
+      |                                 | buffer data          |               |
+      | EGL_NATIVE_BUFFER_USAGE_ANDROID | The usage bits of    | 0             |
+      |                                 | the buffer data      |               |
+      +---------------------------------+----------------------+---------------+
+       Table aaa.  Legal attributes for eglCreateNativeClientBufferANDROID
+       <attrib_list> parameter.
+
+    The maximum width and height may depend on the amount of available memory,
+    which may also depend on the format and usage flags. The values of
+    EGL_RED_SIZE, EGL_GREEN_SIZE, and EGL_BLUE_SIZE must be non-zero and
+    correspond to a valid pixel format for the implementation. If EGL_ALPHA_SIZE
+    is non-zero then the combination of all four sizes must correspond to a
+    valid pixel format for the implementation. The
+    EGL_NATIVE_BUFFER_USAGE_ANDROID flag may include any of the following bits:
+
+        EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID: Indicates that the
+        created buffer must have a hardware-protected path to external display
+        sink. If a hardware-protected path is not available, then either don't
+        composite only this buffer (preferred) to the external sink, or (less
+        desirable) do not route the entire composition to the external sink.
+
+        EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID: The buffer will be
+        used to create a renderbuffer. This flag must not be set if
+        EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID is set.
+
+        EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID: The buffer will be used to
+        create a texture. This flag must not be set if
+        EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID is set.
+
+    Errors
+
+        If eglCreateNativeClientBufferANDROID fails, NULL will be returned, no
+        memory will be allocated, and one of the following errors will be
+        generated:
+
+       * If the value of EGL_WIDTH or EGL_HEIGHT is not positive, the error
+         EGL_BAD_PARAMETER is generated.
+
+       * If the combination of the values of EGL_RED_SIZE, EGL_GREEN_SIZE,
+         EGL_BLUE_SIZE, and EGL_ALPHA_SIZE is not a valid pixel format for the
+         EGL implementation, the error EGL_BAD_PARAMETER is generated.
+
+       * If the value of EGL_NATIVE_BUFFER_ANDROID is not a valid combination
+         of gralloc usage flags for the EGL implementation, or is incompatible
+         with the value of EGL_FORMAT, the error EGL_BAD_PARAMETER is
+         Generated.
+
+       * If both the EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID and
+         EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID are set in the value of
+         EGL_NATIVE_BUFFER_USAGE_ANDROID, the error EGL_BAD_PARAMETER is
+         Generated."
+
+Issues
+
+    1. Should this extension define what combinations of formats and usage flags
+    EGL implementations are required to support?
+
+    RESOLVED: Partially.
+
+    The set of valid color combinations is implementation-specific and may
+    depend on additional EGL extensions, but generally RGB565 and RGBA888 should
+    be supported. The particular valid combinations for a given Android version
+    and implementation should be documented by that version.
+
+    2. Should there be an eglDestroyNativeClientBufferANDROID to destroy the
+    client buffers created by this extension?
+
+    RESOLVED: No.
+
+    A destroy function would add several complications:
+
+        a) ANativeWindowBuffer is a reference counted object, may be used
+           outside of EGL.
+        b) The same buffer may back multiple EGLImages, though this usage may
+           result in undefined behavior.
+        c) The interactions between the lifetimes of EGLImages and their
+           EGLClientBuffers would become needlessly complex.
+
+    Because ANativeWindowBuffer is a reference counted object, implementations
+    of this extension should ensure the buffer has a lifetime at least as long
+    as a generated EGLImage (via EGL_ANDROID_image_native_buffer). The simplest
+    method is to increment the reference count of the buffer in
+    eglCreateImagKHR, and then decrement it in eglDestroyImageKHR. This should
+    ensure proper lifetime semantics.
+
+Revision History
+
+#2 (Craig Donner, April 15, 2016)
+    - Set color formats and usage bits explicitly using additional attributes,
+    and add value for new token EGL_NATIVE_BUFFER_USAGE_ANDROID.
+
+#1 (Craig Donner, January 19, 2016)
+    - Initial draft.
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index eed14ab..3f69d49 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1227,6 +1227,8 @@
                     int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
                     if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
                         outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+                    } else if (isWindowObscuredLocked(windowHandle)) {
+                        outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
                     }
 
                     mTempTouchState.addOrUpdateWindow(
@@ -1264,6 +1266,8 @@
         }
         if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
             targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+        } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
+            targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
         }
 
         // Update hover state.
@@ -1439,6 +1443,7 @@
                                 == InputWindowInfo::TYPE_WALLPAPER) {
                     mTempTouchState.addOrUpdateWindow(windowHandle,
                             InputTarget::FLAG_WINDOW_IS_OBSCURED
+                                    | InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED
                                     | InputTarget::FLAG_DISPATCH_AS_IS,
                             BitSet32(0));
                 }
@@ -1633,6 +1638,27 @@
     return false;
 }
 
+
+bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
+    int32_t displayId = windowHandle->getInfo()->displayId;
+    const InputWindowInfo* windowInfo = windowHandle->getInfo();
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+        if (otherHandle == windowHandle) {
+            break;
+        }
+
+        const InputWindowInfo* otherInfo = otherHandle->getInfo();
+        if (otherInfo->displayId == displayId
+                && otherInfo->visible && !otherInfo->isTrustedOverlay()
+                && otherInfo->overlaps(windowInfo)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
         const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
         const char* targetType) {
@@ -1907,6 +1933,9 @@
         if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
             dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
         }
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
+            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+        }
 
         if (!connection->inputState.trackMotion(motionEntry,
                 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 98355c6..1c054f5 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -89,7 +89,7 @@
         /* This flag indicates that the event is being delivered to a foreground application. */
         FLAG_FOREGROUND = 1 << 0,
 
-        /* This flag indicates that the target of a MotionEvent is partly or wholly
+        /* This flag indicates that the MotionEvent falls within the area of the target
          * obscured by another visible window above it.  The motion event should be
          * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
         FLAG_WINDOW_IS_OBSCURED = 1 << 1,
@@ -139,6 +139,12 @@
                 | FLAG_DISPATCH_AS_HOVER_EXIT
                 | FLAG_DISPATCH_AS_SLIPPERY_EXIT
                 | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
+
+        /* This flag indicates that the target of a MotionEvent is partly or wholly
+         * obscured by another visible window above it.  The motion event should be
+         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
+        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
+
     };
 
     // The input channel to be targeted.
@@ -1048,6 +1054,7 @@
             const InjectionState* injectionState);
     bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
             int32_t x, int32_t y) const;
+    bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const;
     String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle);
 
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index fda3ffa..1b913c5 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -36,14 +36,16 @@
 }
 
 bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
-    return x >= frameLeft && x <= frameRight
-            && y >= frameTop && y <= frameBottom;
+    return x >= frameLeft && x < frameRight
+            && y >= frameTop && y < frameBottom;
 }
 
 bool InputWindowInfo::isTrustedOverlay() const {
     return layoutParamsType == TYPE_INPUT_METHOD
             || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
             || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
+            || layoutParamsType == TYPE_STATUS_BAR
+            || layoutParamsType == TYPE_NAVIGATION_BAR
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
@@ -51,6 +53,11 @@
     return layoutParamsFlags & FLAG_SPLIT_TOUCH;
 }
 
+bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
+    return frameLeft < other->frameRight && frameRight > other->frameLeft
+            && frameTop < other->frameBottom && frameBottom > other->frameTop;
+}
+
 
 // --- InputWindowHandle ---
 
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 42457ce..0ac7fce 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -146,6 +146,8 @@
     bool isTrustedOverlay() const;
 
     bool supportsSplitTouch() const;
+
+    bool overlaps(const InputWindowInfo* other) const;
 };
 
 
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 788def9..005af18 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -30,9 +30,7 @@
 // ---------------------------------------------------------------------------
 
 CorrectedGyroSensor::CorrectedGyroSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+    : VirtualSensor() {
     for (size_t i=0 ; i<count ; i++) {
         if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
             mGyro = Sensor(list + i);
@@ -40,17 +38,18 @@
         }
     }
 
-    sensor_t hwSensor;
-    hwSensor.name       = "Corrected Gyroscope Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_cgy';
-    hwSensor.type       = SENSOR_TYPE_GYROSCOPE;
-    hwSensor.maxRange   = mGyro.getMaxValue();
-    hwSensor.resolution = mGyro.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mGyro.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+    const sensor_t sensor = {
+            .name       = "Corrected Gyroscope Sensor",
+            .vendor     = "AOSP",
+            .version    = 1,
+            .handle     = '_cgy',
+            .type       = SENSOR_TYPE_GYROSCOPE,
+            .maxRange   = mGyro.getMaxValue(),
+            .resolution = mGyro.getResolution(),
+            .power      = mSensorFusion.getPowerUsage(),
+            .minDelay   = mGyro.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
@@ -78,10 +77,6 @@
     return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
-const Sensor& CorrectedGyroSensor::getSensor() const {
-    return mSensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
index 3419a8a..68acd43 100644
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ b/services/sensorservice/CorrectedGyroSensor.h
@@ -31,19 +31,14 @@
 class SensorDevice;
 class SensorFusion;
 
-class CorrectedGyroSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
+class CorrectedGyroSensor : public VirtualSensor {
     Sensor mGyro;
-    Sensor mSensor;
 
 public:
     CorrectedGyroSensor(sensor_t const* list, size_t count);
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 0e80f16..9d8add1 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -29,10 +29,7 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-GravitySensor::GravitySensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+GravitySensor::GravitySensor(sensor_t const* list, size_t count) {
     for (size_t i=0 ; i<count ; i++) {
         if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
             mAccelerometer = Sensor(list + i);
@@ -40,17 +37,18 @@
         }
     }
 
-    sensor_t hwSensor;
-    hwSensor.name       = "Gravity Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_grv';
-    hwSensor.type       = SENSOR_TYPE_GRAVITY;
-    hwSensor.maxRange   = GRAVITY_EARTH * 2;
-    hwSensor.resolution = mAccelerometer.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+    const sensor_t sensor = {
+        .name       = "Gravity Sensor",
+        .vendor     = "AOSP",
+        .version    = 3,
+        .handle     = '_grv',
+        .type       = SENSOR_TYPE_GRAVITY,
+        .maxRange   = GRAVITY_EARTH * 2,
+        .resolution = mAccelerometer.getResolution(),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool GravitySensor::process(sensors_event_t* outEvent,
@@ -85,10 +83,6 @@
     return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
 }
 
-const Sensor& GravitySensor::getSensor() const {
-    return mSensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index f9c0a99..8e33a73 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -31,19 +31,14 @@
 class SensorDevice;
 class SensorFusion;
 
-class GravitySensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
+class GravitySensor : public VirtualSensor {
     Sensor mAccelerometer;
-    Sensor mSensor;
 
 public:
     GravitySensor(sensor_t const* list, size_t count);
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index 04beced..d1cd732 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -29,22 +29,21 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mGravitySensor(list, count)
-{
+LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count) :
+        mGravitySensor(list, count) {
     const Sensor &gsensor = mGravitySensor.getSensor();
-    sensor_t hwSensor;
-    hwSensor.name       = "Linear Acceleration Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = gsensor.getVersion();
-    hwSensor.handle     = '_lin';
-    hwSensor.type       = SENSOR_TYPE_LINEAR_ACCELERATION;
-    hwSensor.maxRange   = gsensor.getMaxValue();
-    hwSensor.resolution = gsensor.getResolution();
-    hwSensor.power      = gsensor.getPowerUsage();
-    hwSensor.minDelay   = gsensor.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+    const sensor_t sensor = {
+        .name       = "Linear Acceleration Sensor",
+        .vendor     = "AOSP",
+        .version    = gsensor.getVersion(),
+        .handle     = '_lin',
+        .type       = SENSOR_TYPE_LINEAR_ACCELERATION,
+        .maxRange   = gsensor.getMaxValue(),
+        .resolution = gsensor.getResolution(),
+        .power      = gsensor.getPowerUsage(),
+        .minDelay   = gsensor.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
@@ -70,10 +69,6 @@
     return mGravitySensor.setDelay(ident, handle, ns);
 }
 
-const Sensor& LinearAccelerationSensor::getSensor() const {
-    return mSensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index 6b8027b..428baa6 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -32,10 +32,8 @@
 class SensorDevice;
 class SensorFusion;
 
-class LinearAccelerationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
+class LinearAccelerationSensor : public VirtualSensor {
     GravitySensor mGravitySensor;
-    Sensor mSensor;
 
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
@@ -43,8 +41,6 @@
     LinearAccelerationSensor(sensor_t const* list, size_t count);
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index 20b49be..ea5dbc9 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -29,24 +29,19 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-OrientationSensor::OrientationSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    // FIXME: instead of using the SensorFusion code, we should use
-    // the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
-    // HAL's implementation.
-    sensor_t hwSensor;
-    hwSensor.name       = "Orientation Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_ypr';
-    hwSensor.type       = SENSOR_TYPE_ORIENTATION;
-    hwSensor.maxRange   = 360.0f;
-    hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+OrientationSensor::OrientationSensor() {
+    const sensor_t sensor = {
+        .name       = "Orientation Sensor",
+        .vendor     = "AOSP",
+        .version    = 1,
+        .handle     = '_ypr',
+        .type       = SENSOR_TYPE_ORIENTATION,
+        .maxRange   = 360.0f,
+        .resolution = 1.0f/256.0f, // FIXME: real value here
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -84,10 +79,6 @@
     return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
-const Sensor& OrientationSensor::getSensor() const {
-    return mSensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
index 644a774..30ff226 100644
--- a/services/sensorservice/OrientationSensor.h
+++ b/services/sensorservice/OrientationSensor.h
@@ -31,18 +31,12 @@
 class SensorDevice;
 class SensorFusion;
 
-class OrientationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mSensor;
-
+class OrientationSensor : public VirtualSensor {
 public:
     OrientationSensor();
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 5a40ef9..7b00f4d 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,22 +27,20 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-RotationVectorSensor::RotationVectorSensor(int mode)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance()),
-      mMode(mode)
-{
-    sensor_t hwSensor;
-    hwSensor.name       = getSensorName();
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 3;
-    hwSensor.handle     = getSensorToken();
-    hwSensor.type       = getSensorType();
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+RotationVectorSensor::RotationVectorSensor(int mode) :
+      mMode(mode) {
+    const sensor_t sensor = {
+        .name       = getSensorName(),
+        .vendor     = "AOSP",
+        .version    = 3,
+        .handle     = getSensorToken(),
+        .type       = getSensorType(),
+        .maxRange   = 1,
+        .resolution = 1.0f / (1<<24),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool RotationVectorSensor::process(sensors_event_t* outEvent,
@@ -72,10 +70,6 @@
     return mSensorFusion.setDelay(mMode, ident, ns);
 }
 
-const Sensor& RotationVectorSensor::getSensor() const {
-    return mSensor;
-}
-
 int RotationVectorSensor::getSensorType() const {
     switch(mMode) {
         case FUSION_9AXIS:
@@ -120,21 +114,19 @@
 
 // ---------------------------------------------------------------------------
 
-GyroDriftSensor::GyroDriftSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    sensor_t hwSensor;
-    hwSensor.name       = "Gyroscope Bias (debug)";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_gbs';
-    hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    mSensor = Sensor(&hwSensor);
+GyroDriftSensor::GyroDriftSensor() {
+    const sensor_t sensor = {
+        .name       = "Gyroscope Bias (debug)",
+        .vendor     = "AOSP",
+        .version    = 1,
+        .handle     = '_gbs',
+        .type       = SENSOR_TYPE_ACCELEROMETER,
+        .maxRange   = 1,
+        .resolution = 1.0f / (1<<24),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool GyroDriftSensor::process(sensors_event_t* outEvent,
@@ -163,10 +155,6 @@
     return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
-const Sensor& GyroDriftSensor::getSensor() const {
-    return mSensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index 5dba0d5..3cc2248 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -32,23 +32,18 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class RotationVectorSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    int mMode;
-    Sensor mSensor;
-
-    int getSensorType() const;
-    const char* getSensorName() const ;
-    int getSensorToken() const ;
-
+class RotationVectorSensor : public VirtualSensor {
 public:
     RotationVectorSensor(int mode = FUSION_9AXIS);
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
+
+protected:
+    const int mMode;
+    int getSensorType() const;
+    const char* getSensorName() const ;
+    int getSensorToken() const ;
 };
 
 class GameRotationVectorSensor : public RotationVectorSensor {
@@ -61,18 +56,12 @@
     GeoMagRotationVectorSensor() : RotationVectorSensor(FUSION_NOGYRO) {}
 };
 
-class GyroDriftSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mSensor;
-
+class GyroDriftSensor : public VirtualSensor {
 public:
     GyroDriftSensor();
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
     virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
-    virtual const Sensor& getSensor() const override;
-    virtual bool isVirtual() const override { return true; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index ca26535..c1e1bad 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -21,6 +21,7 @@
 
 #include "vec.h"
 #include "SensorEventConnection.h"
+#include "SensorDevice.h"
 
 namespace android {
 
@@ -88,15 +89,14 @@
 
 bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
     Mutex::Autolock _l(mConnectionLock);
-    if (!canAccessSensor(mService->getSensorFromHandle(handle),
-            "Tried adding", mOpPackageName)) {
+    sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+    if (si == nullptr ||
+        !canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
+        mSensorInfo.indexOfKey(handle) >= 0) {
         return false;
     }
-    if (mSensorInfo.indexOfKey(handle) < 0) {
-        mSensorInfo.add(handle, FlushInfo());
-        return true;
-    }
-    return false;
+    mSensorInfo.add(handle, FlushInfo());
+    return true;
 }
 
 bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
@@ -121,7 +121,8 @@
     Mutex::Autolock _l(mConnectionLock);
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const int handle = mSensorInfo.keyAt(i);
-        if (mService->getSensorFromHandle(handle).getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si != nullptr && si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
             return true;
         }
     }
@@ -164,9 +165,9 @@
     if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const int handle = mSensorInfo.keyAt(i);
-        if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si != nullptr && si->getSensor().isWakeUpSensor()) {
             looper_flags |= ALOOPER_EVENT_INPUT;
-            break;
         }
     }
 
@@ -385,11 +386,16 @@
     // Loop through all the sensors for this connection and check if there are any pending
     // flush complete events to be sent.
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si == nullptr) {
+            continue;
+        }
+
         FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
         while (flushInfo.mPendingFlushEventsToSend > 0) {
-            const int sensor_handle = mSensorInfo.keyAt(i);
-            flushCompleteEvent.meta_data.sensor = sensor_handle;
-            bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
+            flushCompleteEvent.meta_data.sensor = handle;
+            bool wakeUpSensor = si->getSensor().isWakeUpSensor();
             if (wakeUpSensor) {
                ++mWakeLockRefCount;
                flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
@@ -544,37 +550,41 @@
         unsigned char buf[sizeof(sensors_event_t)];
         ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
         {
-           Mutex::Autolock _l(mConnectionLock);
-           if (numBytesRead == sizeof(sensors_event_t)) {
-               if (!mDataInjectionMode) {
-                   ALOGE("Data injected in normal mode, dropping event"
-                         "package=%s uid=%d", mPackageName.string(), mUid);
-                   // Unregister call backs.
-                   return 0;
-               }
-               SensorDevice& dev(SensorDevice::getInstance());
-               sensors_event_t sensor_event;
-               memset(&sensor_event, 0, sizeof(sensor_event));
-               memcpy(&sensor_event, buf, sizeof(sensors_event_t));
-               Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
-               sensor_event.type = sensor.getType();
-               dev.injectSensorData(&sensor_event);
+            Mutex::Autolock _l(mConnectionLock);
+            if (numBytesRead == sizeof(sensors_event_t)) {
+                if (!mDataInjectionMode) {
+                    ALOGE("Data injected in normal mode, dropping event"
+                          "package=%s uid=%d", mPackageName.string(), mUid);
+                    // Unregister call backs.
+                    return 0;
+                }
+                sensors_event_t sensor_event;
+                memcpy(&sensor_event, buf, sizeof(sensors_event_t));
+                sp<SensorInterface> si =
+                        mService->getSensorInterfaceFromHandle(sensor_event.sensor);
+                if (si == nullptr) {
+                    return 1;
+                }
+
+                SensorDevice& dev(SensorDevice::getInstance());
+                sensor_event.type = si->getSensor().getType();
+                dev.injectSensorData(&sensor_event);
 #if DEBUG_CONNECTIONS
-               ++mEventsReceived;
+                ++mEventsReceived;
 #endif
-           } else if (numBytesRead == sizeof(uint32_t)) {
-               uint32_t numAcks = 0;
-               memcpy(&numAcks, buf, numBytesRead);
-               // Sanity check to ensure  there are no read errors in recv, numAcks is always
-               // within the range and not zero. If any of the above don't hold reset
-               // mWakeLockRefCount to zero.
-               if (numAcks > 0 && numAcks < mWakeLockRefCount) {
-                   mWakeLockRefCount -= numAcks;
-               } else {
-                   mWakeLockRefCount = 0;
-               }
+            } else if (numBytesRead == sizeof(uint32_t)) {
+                uint32_t numAcks = 0;
+                memcpy(&numAcks, buf, numBytesRead);
+                // Sanity check to ensure  there are no read errors in recv, numAcks is always
+                // within the range and not zero. If any of the above don't hold reset
+                // mWakeLockRefCount to zero.
+                if (numAcks > 0 && numAcks < mWakeLockRefCount) {
+                    mWakeLockRefCount -= numAcks;
+                } else {
+                    mWakeLockRefCount = 0;
+                }
 #if DEBUG_CONNECTIONS
-               mTotalAcksReceived += numAcks;
+                mTotalAcksReceived += numAcks;
 #endif
            } else {
                // Read error, reset wakelock refcount.
@@ -601,7 +611,11 @@
     size_t fifoWakeUpSensors = 0;
     size_t fifoNonWakeUpSensors = 0;
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const Sensor& sensor = mService->getSensorFromHandle(mSensorInfo.keyAt(i));
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(mSensorInfo.keyAt(i));
+        if (si == nullptr) {
+            continue;
+        }
+        const Sensor& sensor = si->getSensor();
         if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
             // Each sensor has a reserved fifo. Sum up the fifo sizes for all wake up sensors and
             // non wake_up sensors.
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index bb2a8a2..cb24229 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -14,24 +14,30 @@
  * limitations under the License.
  */
 
+#include "SensorInterface.h"
+#include "SensorDevice.h"
+#include "SensorFusion.h"
+
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "SensorInterface.h"
-
 namespace android {
 // ---------------------------------------------------------------------------
 
-SensorInterface::~SensorInterface()
-{
+namespace {
+const sensor_t DUMMY_SENSOR = {
+        .name = "", .vendor = "", .stringType = "", .requiredPermission = ""};
+} //unnamed namespace
+
+BaseSensor::BaseSensor(const sensor_t& sensor) :
+        mSensorDevice(SensorDevice::getInstance()),
+        mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) {
 }
 
 // ---------------------------------------------------------------------------
 
-HardwareSensor::HardwareSensor(const sensor_t& sensor)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensor(&sensor, mSensorDevice.getHalDeviceVersion())
-{
+HardwareSensor::HardwareSensor(const sensor_t& sensor):
+        BaseSensor(sensor) {
 }
 
 HardwareSensor::~HardwareSensor() {
@@ -65,10 +71,9 @@
     mSensorDevice.autoDisable(ident, handle);
 }
 
-const Sensor& HardwareSensor::getSensor() const {
-    return mSensor;
+VirtualSensor::VirtualSensor() :
+        BaseSensor(DUMMY_SENSOR), mSensorFusion(SensorFusion::getInstance()) {
 }
 
-
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 06cca75..d1cee41 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -17,52 +17,61 @@
 #ifndef ANDROID_SENSOR_INTERFACE_H
 #define ANDROID_SENSOR_INTERFACE_H
 
-#include <stdint.h>
-#include <sys/types.h>
-
 #include <gui/Sensor.h>
-
-#include "SensorDevice.h"
+#include <utils/RefBase.h>
 
 // ---------------------------------------------------------------------------
 
 namespace android {
 // ---------------------------------------------------------------------------
+class SensorDevice;
+class SensorFusion;
 
-class SensorInterface {
+class SensorInterface : public VirtualLightRefBase {
 public:
-    virtual ~SensorInterface();
+    virtual ~SensorInterface() {}
 
     virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) = 0;
 
     virtual status_t activate(void* ident, bool enabled) = 0;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
+    virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
+                           int64_t maxBatchReportLatencyNs) = 0;
+
+    virtual status_t flush(void* /*ident*/, int /*handle*/) = 0;
+
+    virtual const Sensor& getSensor() const = 0;
+    virtual bool isVirtual() const = 0;
+    virtual void autoDisable(void* /*ident*/, int /*handle*/) = 0;
+};
+
+class BaseSensor : public SensorInterface {
+public:
+    BaseSensor(const sensor_t& sensor);
 
     // Not all sensors need to support batching.
-    virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
-                           int64_t maxBatchReportLatencyNs) {
+    virtual status_t batch(void* ident, int handle, int, int64_t samplingPeriodNs,
+                           int64_t maxBatchReportLatencyNs) override {
         if (maxBatchReportLatencyNs == 0) {
             return setDelay(ident, handle, samplingPeriodNs);
         }
         return -EINVAL;
     }
 
-    virtual status_t flush(void* /*ident*/, int /*handle*/) {
+    virtual status_t flush(void* /*ident*/, int /*handle*/) override {
         return -EINVAL;
     }
 
-    virtual const Sensor& getSensor() const = 0;
-    virtual bool isVirtual() const = 0;
-    virtual void autoDisable(void* /*ident*/, int /*handle*/) { }
+    virtual const Sensor& getSensor() const override { return mSensor; }
+    virtual void autoDisable(void* /*ident*/, int /*handle*/) override { }
+protected:
+    SensorDevice& mSensorDevice;
+    Sensor mSensor;
 };
 
 // ---------------------------------------------------------------------------
 
-class HardwareSensor : public SensorInterface
-{
-    SensorDevice& mSensorDevice;
-    Sensor mSensor;
-
+class HardwareSensor : public BaseSensor {
 public:
     HardwareSensor(const sensor_t& sensor);
 
@@ -76,11 +85,19 @@
                            int64_t maxBatchReportLatencyNs) override;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
     virtual status_t flush(void* ident, int handle) override;
-    virtual const Sensor& getSensor() const override;
     virtual bool isVirtual() const override { return false; }
     virtual void autoDisable(void *ident, int handle) override;
 };
 
+class VirtualSensor : public BaseSensor
+{
+public:
+    VirtualSensor();
+    virtual bool isVirtual() const override { return true; }
+protected:
+    SensorFusion& mSensorFusion;
+};
+
 
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index f28acd2..c23e21f 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -41,7 +41,6 @@
     std::lock_guard<std::mutex> lk(mLock);
     auto entry = mHandleMap.find(handle);
     if (entry != mHandleMap.end()) {
-        mRecycle.push_back(entry->second.si);
         mHandleMap.erase(entry);
         return true;
     }
@@ -54,14 +53,9 @@
             mNonSensor.getName());
 }
 
-const Sensor& SensorList::get(int handle) const {
-    return getOne<const Sensor&>(
-            handle, [] (const Entry& e) -> const Sensor& {return e.si->getSensor();}, mNonSensor);
-}
-
-SensorInterface* SensorList::getInterface(int handle) const {
-    return getOne<SensorInterface *>(
-            handle, [] (const Entry& e) -> SensorInterface* {return e.si;}, nullptr);
+sp<SensorInterface> SensorList::getInterface(int handle) const {
+    return getOne<sp<SensorInterface>>(
+            handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
 }
 
 
@@ -182,15 +176,6 @@
 }
 
 SensorList::~SensorList() {
-    // from this point on no one should access anything in SensorList
-    mLock.lock();
-    for (auto i : mRecycle) {
-        delete i;
-    }
-    for (auto&& i : mHandleMap) {
-        delete i.second.si;
-    }
-    // the lock will eventually get destructed, there is no guarantee after that.
 }
 
 } // namespace SensorServiceUtil
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
index 3fe73cc..ffde619 100644
--- a/services/sensorservice/SensorList.h
+++ b/services/sensorservice/SensorList.h
@@ -46,6 +46,9 @@
     // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
     // object it pointed to and the object should not be released elsewhere.
     bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
+
+    // After a handle is removed, the object that SensorInterface * pointing to may get deleted if
+    // no more sp<> of the same object exist.
     bool remove(int handle);
 
     inline bool hasAnySensor() const { return mHandleMap.size() > 0;}
@@ -57,8 +60,7 @@
     const Vector<Sensor> getVirtualSensors() const;
 
     String8 getName(int handle) const;
-    const Sensor& get(int handle) const;
-    SensorInterface* getInterface(int handle) const;
+    sp<SensorInterface> getInterface(int handle) const;
     bool isNewHandle(int handle) const;
 
     // Iterate through Sensor in sensor list and perform operation f on each Sensor object.
@@ -80,8 +82,7 @@
     virtual ~SensorList();
 private:
     struct Entry {
-        //TODO: use sp<> here
-        SensorInterface * const si;
+        sp<SensorInterface> si;
         const bool isForDebug;
         const bool isVirtual;
         Entry(SensorInterface* si_, bool debug_, bool virtual_) :
@@ -108,7 +109,6 @@
     mutable std::mutex mLock;
     std::map<int, Entry> mHandleMap;
     std::unordered_set<int> mUsedHandle;
-    std::vector<SensorInterface *> mRecycle;
 };
 
 template <typename TF>
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index f334e29..b7a8740 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -33,6 +33,7 @@
 #include "OrientationSensor.h"
 #include "RotationVectorSensor.h"
 #include "SensorFusion.h"
+#include "SensorInterface.h"
 
 #include "SensorService.h"
 #include "SensorEventConnection.h"
@@ -141,8 +142,8 @@
                                !needLinearAcceleration, true);
 
                 // virtual debugging sensors are not for user
-                registerSensor( new CorrectedGyroSensor(list, count), false, true);
-                registerSensor( new GyroDriftSensor(), false, true);
+                registerSensor( new CorrectedGyroSensor(list, count), true, true);
+                registerSensor( new GyroDriftSensor(), true, true);
             }
 
             if (hasAccel && hasGyro) {
@@ -408,10 +409,10 @@
             handle = buffer[i].meta_data.sensor;
         }
         if (connection->hasSensor(handle)) {
-            SensorInterface* si = mSensors.getInterface(handle);
+            sp<SensorInterface> si = getSensorInterfaceFromHandle(handle);
             // If this buffer has an event from a one_shot sensor and this connection is registered
             // for this particular one_shot sensor, try cleaning up the connection.
-            if (si != NULL &&
+            if (si != nullptr &&
                 si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
                 si->autoDisable(connection.get(), handle);
                 cleanupWithoutDisableLocked(connection, handle);
@@ -477,8 +478,7 @@
         // handle virtual sensors
         if (count && vcount) {
             sensors_event_t const * const event = mSensorEventBuffer;
-            const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
-            if (activeVirtualSensorCount) {
+            if (!mActiveVirtualSensors.empty()) {
                 size_t k = 0;
                 SensorFusion& fusion(SensorFusion::getInstance());
                 if (fusion.isEnabled()) {
@@ -487,7 +487,7 @@
                     }
                 }
                 for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
-                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
+                    for (int handle : mActiveVirtualSensors) {
                         if (count + k >= minBufferSize) {
                             ALOGE("buffer too small to hold all events: "
                                     "count=%zd, k=%zu, size=%zu",
@@ -495,7 +495,12 @@
                             break;
                         }
                         sensors_event_t out;
-                        SensorInterface* si = mActiveVirtualSensors.valueAt(j);
+                        sp<SensorInterface> si = mSensors.getInterface(handle);
+                        if (si == nullptr) {
+                            ALOGE("handle %d is not an valid virtual sensor", handle);
+                            continue;
+                        }
+
                         if (si->process(&out, event[i])) {
                             mSensorEventBuffer[count + k] = out;
                             k++;
@@ -698,8 +703,8 @@
 }
 
 bool SensorService::isVirtualSensor(int handle) const {
-    SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-    return sensor != NULL && sensor->isVirtual();
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    return sensor != nullptr && sensor->isVirtual();
 }
 
 bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const {
@@ -707,8 +712,8 @@
     if (event.type == SENSOR_TYPE_META_DATA) {
         handle = event.meta_data.sensor;
     }
-    SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-    return sensor != NULL && sensor->getSensor().isWakeUpSensor();
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    return sensor != nullptr && sensor->getSensor().isWakeUpSensor();
 }
 
 Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
@@ -735,14 +740,15 @@
     Vector<Sensor> accessibleSensorList;
     mSensors.forEachSensor(
             [&opPackageName, &accessibleSensorList] (const Sensor& sensor) -> bool {
-                if (sensor.isDynamicSensor() &&
-                        canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
-                    accessibleSensorList.add(sensor);
-                } else {
-                    ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
-                          sensor.getName().string(),
-                          sensor.getRequiredPermission().string(),
-                          sensor.getRequiredAppOp());
+                if (sensor.isDynamicSensor()) {
+                    if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
+                        accessibleSensorList.add(sensor);
+                    } else {
+                        ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
+                              sensor.getName().string(),
+                              sensor.getRequiredPermission().string(),
+                              sensor.getRequiredAppOp());
+                    }
                 }
                 return true;
             });
@@ -805,10 +811,11 @@
         int handle = mActiveSensors.keyAt(i);
         if (c->hasSensor(handle)) {
             ALOGD_IF(DEBUG_CONNECTIONS, "%zu: disabling handle=0x%08x", i, handle);
-            SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-            ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
-            if (sensor) {
+            sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+            if (sensor != nullptr) {
                 sensor->activate(c, false);
+            } else {
+                ALOGE("sensor interface of handle=0x%08x is null!", handle);
             }
             c->removeSensor(handle);
         }
@@ -821,7 +828,7 @@
         if (rec && rec->removeConnection(connection)) {
             ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
             mActiveSensors.removeItemsAt(i, 1);
-            mActiveVirtualSensors.removeItem(handle);
+            mActiveVirtualSensors.erase(handle);
             delete rec;
             size--;
         } else {
@@ -836,13 +843,10 @@
     }
 }
 
-SensorInterface* SensorService::getSensorInterfaceFromHandle(int handle) const {
+sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
     return mSensors.getInterface(handle);
 }
 
-const Sensor& SensorService::getSensorFromHandle(int handle) const {
-    return mSensors.get(handle);
-}
 
 status_t SensorService::enable(const sp<SensorEventConnection>& connection,
         int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
@@ -850,12 +854,9 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-    if (sensor == NULL) {
-        return BAD_VALUE;
-    }
-
-    if (!canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    if (sensor == nullptr ||
+        !canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
         return BAD_VALUE;
     }
 
@@ -870,7 +871,7 @@
         rec = new SensorRecord(connection);
         mActiveSensors.add(handle, rec);
         if (sensor->isVirtual()) {
-            mActiveVirtualSensors.add(handle, sensor);
+            mActiveVirtualSensors.emplace(handle);
         }
     } else {
         if (rec->addConnection(connection)) {
@@ -983,8 +984,8 @@
     Mutex::Autolock _l(mLock);
     status_t err = cleanupWithoutDisableLocked(connection, handle);
     if (err == NO_ERROR) {
-        SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+        sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+        err = sensor != nullptr ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
 
     }
     if (err == NO_ERROR) {
@@ -1024,7 +1025,7 @@
         // see if this sensor becomes inactive
         if (rec->removeConnection(connection)) {
             mActiveSensors.removeItem(handle);
-            mActiveVirtualSensors.removeItem(handle);
+            mActiveVirtualSensors.erase(handle);
             delete rec;
         }
         return NO_ERROR;
@@ -1037,11 +1038,9 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
-    if (!sensor)
-        return BAD_VALUE;
-
-    if (!canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    if (sensor == nullptr ||
+        !canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
         return BAD_VALUE;
     }
 
@@ -1066,7 +1065,10 @@
     // Loop through all sensors for this connection and call flush on each of them.
     for (size_t i = 0; i < connection->mSensorInfo.size(); ++i) {
         const int handle = connection->mSensorInfo.keyAt(i);
-        SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
+        sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+        if (sensor == nullptr) {
+            continue;
+        }
         if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
             ALOGE("flush called on a one-shot sensor");
             err = INVALID_OPERATION;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index e535339..6473edb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -17,27 +17,25 @@
 #ifndef ANDROID_SENSOR_SERVICE_H
 #define ANDROID_SENSOR_SERVICE_H
 
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/AndroidThreads.h>
-#include <utils/RefBase.h>
-#include <utils/Looper.h>
-#include <utils/String8.h>
+#include "SensorList.h"
 
 #include <binder/BinderService.h>
-
-#include <gui/Sensor.h>
-#include <gui/BitTube.h>
+#include <cutils/compiler.h>
 #include <gui/ISensorServer.h>
 #include <gui/ISensorEventConnection.h>
+#include <gui/Sensor.h>
 
-#include "SensorInterface.h"
-#include "SensorList.h"
+#include <utils/AndroidThreads.h>
+#include <utils/KeyedVector.h>
+#include <utils/Looper.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unordered_set>
 
 #if __clang__
 // Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -57,6 +55,7 @@
 
 namespace android {
 // ---------------------------------------------------------------------------
+class SensorInterface;
 
 class SensorService :
         public BinderService<SensorService>,
@@ -138,7 +137,6 @@
     };
 
     static const char* WAKE_LOCK_NAME;
-
     static char const* getServiceName() ANDROID_API { return "sensorservice"; }
     SensorService() ANDROID_API;
     virtual ~SensorService();
@@ -160,8 +158,7 @@
     static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
-    SensorInterface* getSensorInterfaceFromHandle(int handle) const;
-    const Sensor& getSensorFromHandle(int handle) const;
+    sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
     bool isWakeUpSensor(int type) const;
     void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
@@ -216,12 +213,14 @@
 
     // Socket buffersize used to initialize BitTube. This size depends on whether batching is
     // supported or not.
-    uint32_t mSocketBufferSize; sp<Looper> mLooper; sp<SensorEventAckReceiver> mAckReceiver;
+    uint32_t mSocketBufferSize;
+    sp<Looper> mLooper;
+    sp<SensorEventAckReceiver> mAckReceiver;
 
     // protected by mLock
     mutable Mutex mLock;
     DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
-    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
+    std::unordered_set<int> mActiveVirtualSensors;
     SortedVector< wp<SensorEventConnection> > mActiveConnections;
     bool mWakeLockAcquired;
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 4cf9370..37b6420 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -97,7 +97,6 @@
     virtual bool threadLoop() {
         status_t err;
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-        nsecs_t nextEventTime = 0;
 
         while (true) {
             Vector<CallbackInvocation> callbackInvocations;
@@ -127,16 +126,21 @@
                     continue;
                 }
 
-                nextEventTime = computeNextEventTimeLocked(now);
-                targetTime = nextEventTime;
+                targetTime = computeNextEventTimeLocked(now);
 
                 bool isWakeup = false;
 
                 if (now < targetTime) {
-                    ALOGV("[%s] Waiting until %" PRId64, mName,
-                            ns2us(targetTime));
                     if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
-                    err = mCond.waitRelative(mMutex, targetTime - now);
+
+                    if (targetTime == INT64_MAX) {
+                        ALOGV("[%s] Waiting forever", mName);
+                        err = mCond.wait(mMutex);
+                    } else {
+                        ALOGV("[%s] Waiting until %" PRId64, mName,
+                                ns2us(targetTime));
+                        err = mCond.waitRelative(mMutex, targetTime - now);
+                    }
 
                     if (err == TIMED_OUT) {
                         isWakeup = true;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f7c8473..a67b3ff 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -68,6 +68,8 @@
  *
  */
 
+uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
+
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
@@ -550,10 +552,32 @@
     }
 
     mOrientation = orientation;
+    if (mType == DisplayType::DISPLAY_PRIMARY) {
+        uint32_t transform = 0;
+        switch (mOrientation) {
+            case DisplayState::eOrientationDefault:
+                transform = Transform::ROT_0;
+                break;
+            case DisplayState::eOrientation90:
+                transform = Transform::ROT_90;
+                break;
+            case DisplayState::eOrientation180:
+                transform = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                transform = Transform::ROT_270;
+                break;
+        }
+        sPrimaryDisplayOrientation = transform;
+    }
     mViewport = viewport;
     mFrame = frame;
 }
 
+uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() {
+    return sPrimaryDisplayOrientation;
+}
+
 void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
     result.appendFormat(
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 9ac8a97..dd9b104 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -129,6 +129,7 @@
 
     int                     getOrientation() const { return mOrientation; }
     uint32_t                getOrientationTransform() const;
+    static uint32_t         getPrimaryDisplayOrientationTransform();
     const Transform&        getTransform() const { return mGlobalTransform; }
     const Rect              getViewport() const { return mViewport; }
     const Rect              getFrame() const { return mFrame; }
@@ -238,6 +239,7 @@
 
     uint32_t mLayerStack;
     int mOrientation;
+    static uint32_t sPrimaryDisplayOrientation;
     // user-provided visible area of the layer stack
     Rect mViewport;
     // user-provided rectangle where mViewport gets mapped to
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index d37fcb2..4afd8a2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -926,16 +926,19 @@
 protected:
     HWCTYPE* const mLayerList;
     HWCTYPE* mCurrentLayer;
-    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
+    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
+            mIndex(0) { }
     inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
     inline HWCTYPE* getLayer() { return mCurrentLayer; }
     virtual ~Iterable() { }
+    size_t mIndex;
 private:
     // returns a copy of ourselves
     virtual HWComposer::HWCLayer* dup() {
         return new CONCRETE( static_cast<const CONCRETE&>(*this) );
     }
     virtual status_t setLayer(size_t index) {
+        mIndex = index;
         mCurrentLayer = &mLayerList[index];
         return NO_ERROR;
     }
@@ -948,8 +951,12 @@
 class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
     struct hwc_composer_device_1* mHwc;
 public:
-    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
-        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
+    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer,
+            Vector<Region>* visibleRegions,
+            Vector<Region>* surfaceDamageRegions)
+        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc),
+          mVisibleRegions(visibleRegions),
+          mSurfaceDamageRegions(surfaceDamageRegions) {}
 
     virtual int32_t getCompositionType() const {
         return getLayer()->compositionType;
@@ -1037,9 +1044,10 @@
     }
     virtual void setVisibleRegionScreen(const Region& reg) {
         hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
-        mVisibleRegion = reg;
+        mVisibleRegions->editItemAt(mIndex) = reg;
         visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
-                mVisibleRegion.getArray(&visibleRegion.numRects));
+                mVisibleRegions->itemAt(mIndex).getArray(
+                &visibleRegion.numRects));
     }
     virtual void setSurfaceDamage(const Region& reg) {
         if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
@@ -1053,9 +1061,10 @@
             surfaceDamage.rects = NULL;
             return;
         }
-        mSurfaceDamage = reg;
+        mSurfaceDamageRegions->editItemAt(mIndex) = reg;
         surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
-                mSurfaceDamage.getArray(&surfaceDamage.numRects));
+                mSurfaceDamageRegions->itemAt(mIndex).getArray(
+                &surfaceDamage.numRects));
     }
     virtual void setSidebandStream(const sp<NativeHandle>& stream) {
         ALOG_ASSERT(stream->handle() != NULL);
@@ -1081,11 +1090,10 @@
     }
 
 protected:
-    // We need to hold "copies" of these for memory management purposes. The
-    // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
-    // internally doesn't copy the memory unless one of the copies is modified.
-    Region mVisibleRegion;
-    Region mSurfaceDamage;
+    // Pointers to the vectors of Region backing-memory held in DisplayData.
+    // Only the Region at mIndex corresponds to this Layer.
+    Vector<Region>* mVisibleRegions;
+    Vector<Region>* mSurfaceDamageRegions;
 };
 
 /*
@@ -1095,11 +1103,18 @@
     if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
         return LayerListIterator();
     }
-    const DisplayData& disp(mDisplayData[id]);
+    DisplayData& disp(mDisplayData[id]);
     if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
         return LayerListIterator();
     }
-    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
+    if (disp.visibleRegions.size() < disp.list->numHwLayers) {
+        disp.visibleRegions.resize(disp.list->numHwLayers);
+    }
+    if (disp.surfaceDamageRegions.size() < disp.list->numHwLayers) {
+        disp.surfaceDamageRegions.resize(disp.list->numHwLayers);
+    }
+    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers,
+            &disp.visibleRegions, &disp.surfaceDamageRegions), index);
 }
 
 /*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f5f7d77..c861817 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -346,6 +346,13 @@
 
         // protected by mEventControlLock
         int32_t events;
+
+        // We need to hold "copies" of these for memory management purposes. The
+        // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+        // internally doesn't copy the memory unless one of the copies is
+        // modified.
+        Vector<Region> visibleRegions;
+        Vector<Region> surfaceDamageRegions;
     };
 
     sp<SurfaceFlinger>              mFlinger;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 37b7aba..7e4e797 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -605,6 +605,12 @@
     return INVALID_OPERATION;
 }
 
+status_t VirtualDisplaySurface::getLastQueuedBuffer(
+        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/) {
+    ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
 void VirtualDisplaySurface::updateQueueBufferOutput(
         const QueueBufferOutput& qbo) {
     uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 818d3eb..bd1cfb1 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -126,6 +126,8 @@
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     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;
 
     //
     // Utility methods
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a2c0462..c640f58 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -75,6 +75,7 @@
         mSidebandStreamChanged(false),
         mCurrentTransform(0),
         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+        mOverrideScalingMode(-1),
         mCurrentOpacity(true),
         mCurrentFrameNumber(0),
         mRefreshPending(false),
@@ -250,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;
@@ -435,9 +436,11 @@
     uint32_t invTransform = mCurrentTransform;
     if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
         /*
-         * the code below applies the display's inverse transform to the buffer
+         * the code below applies the primary display's inverse transform to the
+         * buffer
          */
-        uint32_t invTransformOrient = hw->getOrientationTransform();
+        uint32_t invTransformOrient =
+                DisplayDevice::getPrimaryDisplayOrientationTransform();
         // calculate the inverse transform
         if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
             invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
@@ -634,13 +637,12 @@
 
     if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
         /*
-         * the code below applies the display's inverse transform to the buffer
+         * the code below applies the primary display's inverse transform to the
+         * buffer
          */
-#ifdef USE_HWC2
-        uint32_t invTransform = displayDevice->getOrientationTransform();
-#else
-        uint32_t invTransform = hw->getOrientationTransform();
-#endif
+        uint32_t invTransform =
+                DisplayDevice::getPrimaryDisplayOrientationTransform();
+
         uint32_t t_orientation = transform.getOrientation();
         // calculate the inverse transform
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -941,7 +943,8 @@
         if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
 
             /*
-             * the code below applies the display's inverse transform to the texture transform
+             * the code below applies the primary display's inverse transform to
+             * the texture transform
              */
 
             // create a 4x4 transform matrix from the display transform flags
@@ -950,7 +953,8 @@
             const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
 
             mat4 tr;
-            uint32_t transform = hw->getOrientationTransform();
+            uint32_t transform =
+                    DisplayDevice::getPrimaryDisplayOrientationTransform();
             if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
                 tr = tr * rot90;
             if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)
@@ -1244,7 +1248,7 @@
 }
 
 bool Layer::isFixedSize() const {
-    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+    return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
 }
 
 bool Layer::isCropped() const {
@@ -1309,16 +1313,16 @@
     mPendingStates.push_back(mCurrentState);
 }
 
-void Layer::popPendingState() {
-    auto oldFlags = mCurrentState.flags;
-    mCurrentState = mPendingStates[0];
-    mCurrentState.flags = (oldFlags & ~mCurrentState.mask) |
-            (mCurrentState.flags & mCurrentState.mask);
+void Layer::popPendingState(State* stateToCommit) {
+    auto oldFlags = stateToCommit->flags;
+    *stateToCommit = mPendingStates[0];
+    stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
+            (stateToCommit->flags & stateToCommit->mask);
 
     mPendingStates.removeAt(0);
 }
 
-bool Layer::applyPendingStates() {
+bool Layer::applyPendingStates(State* stateToCommit) {
     bool stateUpdateAvailable = false;
     while (!mPendingStates.empty()) {
         if (mPendingStates[0].handle != nullptr) {
@@ -1327,7 +1331,7 @@
                 // will be visually wrong, but it should keep us from getting
                 // into too much trouble.
                 ALOGE("[%s] No local sync point found", mName.string());
-                popPendingState();
+                popPendingState(stateToCommit);
                 stateUpdateAvailable = true;
                 continue;
             }
@@ -1345,7 +1349,7 @@
 
             if (mRemoteSyncPoints.front()->frameIsAvailable()) {
                 // Apply the state update
-                popPendingState();
+                popPendingState(stateToCommit);
                 stateUpdateAvailable = true;
 
                 // Signal our end of the sync point and then dispose of it
@@ -1355,7 +1359,7 @@
                 break;
             }
         } else {
-            popPendingState();
+            popPendingState(stateToCommit);
             stateUpdateAvailable = true;
         }
     }
@@ -1385,12 +1389,12 @@
     ATRACE_CALL();
 
     pushPendingState();
-    if (!applyPendingStates()) {
+    Layer::State c = getCurrentState();
+    if (!applyPendingStates(&c)) {
         return 0;
     }
 
     const Layer::State& s(getDrawingState());
-    const Layer::State& c(getCurrentState());
 
     const bool sizeChanged = (c.requested.w != s.requested.w) ||
                              (c.requested.h != s.requested.h);
@@ -1403,7 +1407,8 @@
                 "            requested={ wh={%4u,%4u} }}\n"
                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                 "            requested={ wh={%4u,%4u} }}\n",
-                this, getName().string(), mCurrentTransform, mCurrentScalingMode,
+                this, getName().string(), mCurrentTransform,
+                getEffectiveScalingMode(),
                 c.active.w, c.active.h,
                 c.crop.left,
                 c.crop.top,
@@ -1454,8 +1459,7 @@
     // this is used by Layer, which special cases resizes.
     if (flags & eDontUpdateGeometryState)  {
     } else {
-        Layer::State& editCurrentState(getCurrentState());
-        editCurrentState.active = c.requested;
+        c.active = c.requested;
     }
 
     if (s.active != c.active) {
@@ -1475,12 +1479,12 @@
     }
 
     // Commit the transaction
-    commitTransaction();
+    commitTransaction(c);
     return flags;
 }
 
-void Layer::commitTransaction() {
-    mDrawingState = mCurrentState;
+void Layer::commitTransaction(const State& stateToCommit) {
+    mDrawingState = stateToCommit;
 }
 
 uint32_t Layer::getTransactionFlags(uint32_t flags) {
@@ -1581,6 +1585,20 @@
     return true;
 }
 
+bool Layer::setOverrideScalingMode(int32_t scalingMode) {
+    if (scalingMode == mOverrideScalingMode)
+        return false;
+    mOverrideScalingMode = scalingMode;
+    return true;
+}
+
+uint32_t Layer::getEffectiveScalingMode() const {
+    if (mOverrideScalingMode >= 0) {
+      return mOverrideScalingMode;
+    }
+    return mCurrentScalingMode;
+}
+
 bool Layer::setLayerStack(uint32_t layerStack) {
     if (mCurrentState.layerStack == layerStack)
         return false;
@@ -1739,14 +1757,17 @@
             bool& recomputeVisibleRegions;
             bool stickyTransformSet;
             const char* name;
+            int32_t overrideScalingMode;
 
             Reject(Layer::State& front, Layer::State& current,
                     bool& recomputeVisibleRegions, bool stickySet,
-                    const char* name)
+                    const char* name,
+                    int32_t overrideScalingMode)
                 : front(front), current(current),
                   recomputeVisibleRegions(recomputeVisibleRegions),
                   stickyTransformSet(stickySet),
-                  name(name) {
+                  name(name),
+                  overrideScalingMode(overrideScalingMode) {
             }
 
             virtual bool reject(const sp<GraphicBuffer>& buf,
@@ -1764,7 +1785,9 @@
                     swap(bufWidth, bufHeight);
                 }
 
-                bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+                int actualScalingMode = overrideScalingMode >= 0 ?
+                        overrideScalingMode : item.mScalingMode;
+                bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
                 if (front.active != front.requested) {
 
                     if (isFixedSize ||
@@ -1840,7 +1863,8 @@
         };
 
         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                getProducerStickyTransform() != 0, mName.string());
+                getProducerStickyTransform() != 0, mName.string(),
+                mOverrideScalingMode);
 
 
         // Check all of our local sync points to ensure that all transactions
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1d73b43..7d085a4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -160,6 +160,7 @@
     bool setFinalCrop(const Rect& crop);
     bool setLayerStack(uint32_t layerStack);
     void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
+    bool setOverrideScalingMode(int32_t overrideScalingMode);
 
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
@@ -431,7 +432,7 @@
     virtual void onFrameReplaced(const BufferItem& item) override;
     virtual void onSidebandStreamChanged() override;
 
-    void commitTransaction();
+    void commitTransaction(const State& stateToCommit);
 
     // needsLinearFiltering - true if this surface's state requires filtering
     bool needsFiltering(const sp<const DisplayDevice>& hw) const;
@@ -500,8 +501,13 @@
     bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
 
     void pushPendingState();
-    void popPendingState();
-    bool applyPendingStates();
+    void popPendingState(State* stateToCommit);
+    bool applyPendingStates(State* stateToCommit);
+
+    // Returns mCurrentScaling mode (originating from the
+    // Client) or mOverrideScalingMode mode (originating from
+    // the Surface Controller) if set.
+    uint32_t getEffectiveScalingMode() const;
 public:
     void notifyAvailableFrames();
 private:
@@ -536,6 +542,8 @@
     Rect mCurrentCrop;
     uint32_t mCurrentTransform;
     uint32_t mCurrentScalingMode;
+    // We encode unset as -1.
+    int32_t mOverrideScalingMode;
     bool mCurrentOpacity;
     std::atomic<uint64_t> mCurrentFrameNumber;
     bool mRefreshPending;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 75559da..e689127 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -143,6 +143,11 @@
     return mProducer->setDequeueTimeout(timeout);
 }
 
+status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence) {
+    return mProducer->getLastQueuedBuffer(outBuffer, outFence);
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return IInterface::asBinder(mProducer).get();
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 441cf50..d2b4b43 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -59,6 +59,8 @@
     virtual String8 getConsumerName() const override;
     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;
     virtual IBinder* onAsBinder();
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a448639..a69b11b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -800,7 +800,8 @@
     if (makeAvailable) {
         mHWVsyncAvailable = true;
     } else if (!mHWVsyncAvailable) {
-        ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
+        // Hardware vsync is not currently available, so abort the resync
+        // attempt for now
         return;
     }
 
@@ -834,7 +835,7 @@
 void SurfaceFlinger::resyncWithRateLimit() {
     static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
     if (systemTime() - mLastSwapTime > kIgnoreDelay) {
-        resyncToHardwareVsync(true);
+        resyncToHardwareVsync(false);
     }
 }
 
@@ -2302,6 +2303,11 @@
             // We don't trigger a traversal here because if no other state is
             // changed, we don't want this to cause any more work
         }
+        if (what & layer_state_t::eOverrideScalingModeChanged) {
+            layer->setOverrideScalingMode(s.overrideScalingMode);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
     }
     return flags;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index ea685e7..00700ab 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -820,7 +820,8 @@
     if (makeAvailable) {
         mHWVsyncAvailable = true;
     } else if (!mHWVsyncAvailable) {
-        ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
+        // Hardware vsync is not currently available, so abort the resync
+        // attempt for now
         return;
     }
 
@@ -854,7 +855,7 @@
 void SurfaceFlinger::resyncWithRateLimit() {
     static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
     if (systemTime() - mLastSwapTime > kIgnoreDelay) {
-        resyncToHardwareVsync(true);
+        resyncToHardwareVsync(false);
     }
 }
 
@@ -2327,6 +2328,11 @@
             // We don't trigger a traversal here because if no other state is
             // changed, we don't want this to cause any more work
         }
+        if (what & layer_state_t::eOverrideScalingModeChanged) {
+            layer->setOverrideScalingMode(s.overrideScalingMode);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
     }
     return flags;
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index d7cb899..320fddb 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -459,4 +459,61 @@
     }
 }
 
+TEST_F(LayerUpdateTest, DeferredTransactionTest) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before anything");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 195,  63,  63);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // set up two deferred transactions on different frames
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
+    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+            mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
+    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+            mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        SCOPED_TRACE("before any trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 195,  63,  63);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // should trigger the first deferred transaction, but not the second one
+    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    {
+        SCOPED_TRACE("after first trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 162,  63,  96);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // should show up immediately since it's not deferred
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    // trigger the second deferred transaction
+    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    {
+        SCOPED_TRACE("after second trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96,  63,  63, 195);
+        sc->checkPixel(160, 160, 195,  63,  63);
+    }
+}
+
 }
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 7830c26..71788a9 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -27,7 +27,6 @@
 	-Wno-undef
 #LOCAL_CFLAGS += -DLOG_NDEBUG=0
 LOCAL_CPPFLAGS := -std=c++14 \
-	-fexceptions \
 	-Wno-c99-extensions \
 	-Wno-c++98-compat-pedantic \
 	-Wno-exit-time-destructors \
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/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 320a2ac..69e8e84 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -15,11 +15,11 @@
  */
 
 #include <algorithm>
-#include <memory>
 
 #include <gui/BufferQueue.h>
 #include <log/log.h>
 #include <sync/sync.h>
+#include <utils/StrongPointer.h>
 
 #include "driver.h"
 
@@ -32,80 +32,6 @@
 
 namespace {
 
-// ----------------------------------------------------------------------------
-// These functions/classes form an adaptor that allows objects to be refcounted
-// by both android::sp<> and std::shared_ptr<> simultaneously, and delegates
-// allocation of the shared_ptr<> control structure to VkAllocationCallbacks.
-// The
-// platform holds a reference to the ANativeWindow using its embedded reference
-// count, and the ANativeWindow implementation holds references to the
-// ANativeWindowBuffers using their embedded reference counts, so the
-// shared_ptr *must* cooperate with these and hold at least one reference to
-// the object using the embedded reference count.
-
-template <typename T>
-struct NativeBaseDeleter {
-    void operator()(T* obj) { obj->common.decRef(&obj->common); }
-};
-
-template <typename Host>
-struct AllocScope {};
-
-template <>
-struct AllocScope<VkInstance> {
-    static const VkSystemAllocationScope kScope =
-        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE;
-};
-
-template <>
-struct AllocScope<VkDevice> {
-    static const VkSystemAllocationScope kScope =
-        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
-};
-
-template <typename T>
-class VulkanAllocator {
-   public:
-    typedef T value_type;
-
-    VulkanAllocator(const VkAllocationCallbacks& allocator,
-                    VkSystemAllocationScope scope)
-        : allocator_(allocator), scope_(scope) {}
-
-    template <typename U>
-    explicit VulkanAllocator(const VulkanAllocator<U>& other)
-        : allocator_(other.allocator_), scope_(other.scope_) {}
-
-    T* allocate(size_t n) const {
-        T* p = static_cast<T*>(allocator_.pfnAllocation(
-            allocator_.pUserData, n * sizeof(T), alignof(T), scope_));
-        if (!p)
-            throw std::bad_alloc();
-        return p;
-    }
-    void deallocate(T* p, size_t) const noexcept {
-        return allocator_.pfnFree(allocator_.pUserData, p);
-    }
-
-   private:
-    template <typename U>
-    friend class VulkanAllocator;
-    const VkAllocationCallbacks& allocator_;
-    const VkSystemAllocationScope scope_;
-};
-
-template <typename T, typename Host>
-std::shared_ptr<T> InitSharedPtr(Host host, T* obj) {
-    try {
-        obj->common.incRef(&obj->common);
-        return std::shared_ptr<T>(obj, NativeBaseDeleter<T>(),
-                                  VulkanAllocator<T>(GetData(host).allocator,
-                                                     AllocScope<Host>::kScope));
-    } catch (std::bad_alloc&) {
-        return nullptr;
-    }
-}
-
 const VkSurfaceTransformFlagsKHR kSupportedTransforms =
     VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
@@ -182,7 +108,7 @@
 // ----------------------------------------------------------------------------
 
 struct Surface {
-    std::shared_ptr<ANativeWindow> window;
+    android::sp<ANativeWindow> window;
 };
 
 VkSurfaceKHR HandleFromSurface(Surface* surface) {
@@ -203,7 +129,7 @@
     struct Image {
         Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
         VkImage image;
-        std::shared_ptr<ANativeWindowBuffer> buffer;
+        android::sp<ANativeWindowBuffer> buffer;
         // The fence is only valid when the buffer is dequeued, and should be
         // -1 any other time. When valid, we own the fd, and must ensure it is
         // closed: either by closing it explicitly when queueing the buffer,
@@ -238,13 +164,7 @@
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     Surface* surface = new (mem) Surface;
 
-    surface->window = InitSharedPtr(instance, pCreateInfo->window);
-    if (!surface->window) {
-        ALOGE("surface creation failed: out of memory");
-        surface->~Surface();
-        allocator->pfnFree(allocator->pUserData, surface);
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
+    surface->window = pCreateInfo->window;
 
     // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
     int err =
@@ -409,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;
 
@@ -428,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;
@@ -531,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;
     }
 
@@ -557,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;
     }
 
@@ -618,14 +572,7 @@
             result = VK_ERROR_INITIALIZATION_FAILED;
             break;
         }
-        img.buffer = InitSharedPtr(device, buffer);
-        if (!img.buffer) {
-            ALOGE("swapchain creation failed: out of memory");
-            surface.window->cancelBuffer(surface.window.get(), buffer,
-                                         img.dequeue_fence);
-            result = VK_ERROR_OUT_OF_HOST_MEMORY;
-            break;
-        }
+        img.buffer = buffer;
         img.dequeued = true;
 
         image_create.extent =
@@ -681,7 +628,7 @@
                          const VkAllocationCallbacks* allocator) {
     const auto& dispatch = GetData(device).driver;
     Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
-    const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window;
+    const android::sp<ANativeWindow>& window = swapchain->surface.window;
 
     for (uint32_t i = 0; i < swapchain->num_images; i++) {
         Swapchain::Image& img = swapchain->images[i];
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"
     };