Merge "[SurfaceFlinger] add getDisplayedContentSamplingAttributes i/f"
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index bab87ac..280c14a 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -22,8 +22,9 @@
     cflags: ["-Wall", "-Werror"],
 
     shared_libs: [
-        "liblog",
+        "libbase",
         "libcutils",
+        "liblog",
     ],
 
     export_include_dirs: ["include"],
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index afa32b6..c2a6764 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -18,32 +18,99 @@
 #define LOG_TAG "GraphicsEnv"
 #include <graphicsenv/GraphicsEnv.h>
 
+#include <dlfcn.h>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/dlext.h>
+#include <cutils/properties.h>
+#include <log/log.h>
 #include <sys/prctl.h>
 
 #include <mutex>
 
-#include <android/dlext.h>
-#include <cutils/properties.h>
-#include <log/log.h>
-
 // TODO(b/37049319) Get this from a header once one exists
 extern "C" {
-  android_namespace_t* android_get_exported_namespace(const char*);
-  android_namespace_t* android_create_namespace(const char* name,
-                                                const char* ld_library_path,
-                                                const char* default_library_path,
-                                                uint64_t type,
-                                                const char* permitted_when_isolated_path,
-                                                android_namespace_t* parent);
+android_namespace_t* android_get_exported_namespace(const char*);
+android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
+                                              const char* default_library_path, uint64_t type,
+                                              const char* permitted_when_isolated_path,
+                                              android_namespace_t* parent);
+bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to,
+                             const char* shared_libs_sonames);
 
-  enum {
-     ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
-     ANDROID_NAMESPACE_TYPE_SHARED = 2,
-  };
+enum {
+    ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+    ANDROID_NAMESPACE_TYPE_SHARED = 2,
+};
 }
 
 namespace android {
 
+enum NativeLibrary {
+    LLNDK = 0,
+    VNDKSP = 1,
+};
+
+static constexpr const char* kNativeLibrariesSystemConfigPath[] = {"/etc/llndk.libraries.txt",
+                                                                   "/etc/vndksp.libraries.txt"};
+
+static std::string vndkVersionStr() {
+#ifdef __BIONIC__
+    std::string version = android::base::GetProperty("ro.vndk.version", "");
+    if (version != "" && version != "current") {
+        return "." + version;
+    }
+#endif
+    return "";
+}
+
+static void insertVndkVersionStr(std::string* fileName) {
+    LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
+    size_t insertPos = fileName->find_last_of(".");
+    if (insertPos == std::string::npos) {
+        insertPos = fileName->length();
+    }
+    fileName->insert(insertPos, vndkVersionStr());
+}
+
+static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
+    // Read list of public native libraries from the config file.
+    std::string fileContent;
+    if (!base::ReadFileToString(configFile, &fileContent)) {
+        return false;
+    }
+
+    std::vector<std::string> lines = base::Split(fileContent, "\n");
+
+    for (auto& line : lines) {
+        auto trimmedLine = base::Trim(line);
+        if (!trimmedLine.empty()) {
+            soNames->push_back(trimmedLine);
+        }
+    }
+
+    return true;
+}
+
+static const std::string getSystemNativeLibraries(NativeLibrary type) {
+    static const char* androidRootEnv = getenv("ANDROID_ROOT");
+    static const std::string rootDir = androidRootEnv != nullptr ? androidRootEnv : "/system";
+
+    std::string nativeLibrariesSystemConfig = rootDir + kNativeLibrariesSystemConfigPath[type];
+
+    insertVndkVersionStr(&nativeLibrariesSystemConfig);
+
+    std::vector<std::string> soNames;
+    if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
+        ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
+        return "";
+    }
+
+    return base::Join(soNames, ':');
+}
+
 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
     static GraphicsEnv env;
     return env;
@@ -59,8 +126,8 @@
 
 void GraphicsEnv::setDriverPath(const std::string path) {
     if (!mDriverPath.empty()) {
-        ALOGV("ignoring attempt to change driver path from '%s' to '%s'",
-                mDriverPath.c_str(), path.c_str());
+        ALOGV("ignoring attempt to change driver path from '%s' to '%s'", mDriverPath.c_str(),
+              path.c_str());
         return;
     }
     ALOGV("setting driver path to '%s'", path.c_str());
@@ -102,7 +169,7 @@
         mAppNamespace = appNamespace;
     } else {
         ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
-                layerPaths.c_str(), appNamespace);
+              layerPaths.c_str(), appNamespace);
     }
 }
 
@@ -154,20 +221,41 @@
 android_namespace_t* GraphicsEnv::getDriverNamespace() {
     static std::once_flag once;
     std::call_once(once, [this]() {
-        if (mDriverPath.empty())
-            return;
-        // If the sphal namespace isn't configured for a device, don't support updatable drivers.
-        // We need a parent namespace to inherit the default search path from.
-        auto sphalNamespace = android_get_exported_namespace("sphal");
-        if (!sphalNamespace) return;
+        if (mDriverPath.empty()) return;
+
+        auto vndkNamespace = android_get_exported_namespace("vndk");
+        if (!vndkNamespace) return;
+
         mDriverNamespace = android_create_namespace("gfx driver",
                                                     mDriverPath.c_str(), // ld_library_path
                                                     mDriverPath.c_str(), // default_library_path
-                                                    ANDROID_NAMESPACE_TYPE_SHARED |
-                                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
                                                     nullptr, // permitted_when_isolated_path
-                                                    sphalNamespace);
+                                                    nullptr);
+
+        const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+        if (llndkLibraries.empty()) {
+            mDriverNamespace = nullptr;
+            return;
+        }
+        if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+            ALOGE("Failed to link default namespace[%s]", dlerror());
+            mDriverNamespace = nullptr;
+            return;
+        }
+
+        const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+        if (vndkspLibraries.empty()) {
+            mDriverNamespace = nullptr;
+            return;
+        }
+        if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+            ALOGE("Failed to link vndk namespace[%s]", dlerror());
+            mDriverNamespace = nullptr;
+            return;
+        }
     });
+
     return mDriverNamespace;
 }
 
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 2871302..86e9c23 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -59,9 +59,8 @@
 class InputSurface {
 public:
     InputSurface(const sp<SurfaceComposerClient>& scc, int width, int height) {
-        mSurfaceControl = scc->createSurface(String8("Test Surface"),
-                width, height, PIXEL_FORMAT_RGBA_8888,
-                ISurfaceComposerClient::eFXSurfaceColor);
+        mSurfaceControl = scc->createSurface(String8("Test Surface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+                                             ISurfaceComposerClient::eFXSurfaceColor);
 
         InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
         mServerChannel->setToken(new BBinder());
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 8cc1a4e..dd79775 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -36,10 +36,12 @@
 #include <private/dvr/bufferhub_rpc.h>
 #pragma clang diagnostic pop
 
-#include <ui/BufferHubBuffer.h>
-
 #include <poll.h>
 
+#include <android-base/unique_fd.h>
+#include <ui/BufferHubBuffer.h>
+
+using android::base::unique_fd;
 using android::dvr::BufferTraits;
 using android::dvr::DetachedBufferRPC;
 using android::dvr::NativeHandleWrapper;
@@ -132,7 +134,9 @@
     const int bufferId = bufferTraits.id();
 
     // Import the metadata.
-    mMetadata = BufferHubMetadata::Import(bufferTraits.take_metadata_handle());
+    LocalHandle metadataHandle = bufferTraits.take_metadata_handle();
+    unique_fd metadataFd(metadataHandle.Release());
+    mMetadata = BufferHubMetadata::Import(std::move(metadataFd));
 
     if (!mMetadata.IsValid()) {
         ALOGE("BufferHubBuffer::ImportGraphicBuffer: invalid metadata.");
diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp
index 1e08ed1..18d9a2c 100644
--- a/libs/ui/BufferHubMetadata.cpp
+++ b/libs/ui/BufferHubMetadata.cpp
@@ -48,47 +48,47 @@
         return {};
     }
 
-    // Hand over the ownership of the fd to a pdx::LocalHandle immediately after the successful
-    // return of ashmem_create_region. The ashmemHandle is going to own the fd and to prevent fd
+    // Hand over the ownership of the fd to a unique_fd immediately after the successful
+    // return of ashmem_create_region. The ashmemFd is going to own the fd and to prevent fd
     // leaks during error handling.
-    pdx::LocalHandle ashmemHandle{fd};
+    unique_fd ashmemFd{fd};
 
-    if (ashmem_set_prot_region(ashmemHandle.Get(), kAshmemProt) != 0) {
+    if (ashmem_set_prot_region(ashmemFd.get(), kAshmemProt) != 0) {
         ALOGE("BufferHubMetadata::Create: failed to set protect region.");
         return {};
     }
 
-    return BufferHubMetadata::Import(std::move(ashmemHandle));
+    return BufferHubMetadata::Import(std::move(ashmemFd));
 }
 
 /* static */
-BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmemHandle) {
-    if (!ashmem_valid(ashmemHandle.Get())) {
+BufferHubMetadata BufferHubMetadata::Import(unique_fd ashmemFd) {
+    if (!ashmem_valid(ashmemFd.get())) {
         ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
         return {};
     }
 
-    size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemHandle.Get()));
+    size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemFd.get()));
     size_t userMetadataSize = metadataSize - kMetadataHeaderSize;
 
     // Note that here the buffer state is mapped from shared memory as an atomic object. The
     // std::atomic's constructor will not be called so that the original value stored in the memory
     // region can be preserved.
     auto metadataHeader = static_cast<MetadataHeader*>(mmap(nullptr, metadataSize, kAshmemProt,
-                                                            MAP_SHARED, ashmemHandle.Get(),
+                                                            MAP_SHARED, ashmemFd.get(),
                                                             /*offset=*/0));
     if (metadataHeader == nullptr) {
         ALOGE("BufferHubMetadata::Import: failed to map region.");
         return {};
     }
 
-    return BufferHubMetadata(userMetadataSize, std::move(ashmemHandle), metadataHeader);
+    return BufferHubMetadata(userMetadataSize, std::move(ashmemFd), metadataHeader);
 }
 
-BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle,
+BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd,
                                      MetadataHeader* metadataHeader)
       : mUserMetadataSize(userMetadataSize),
-        mAshmemHandle(std::move(ashmemHandle)),
+        mAshmemFd(std::move(ashmemFd)),
         mMetadataHeader(metadataHeader) {}
 
 BufferHubMetadata::~BufferHubMetadata() {
diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h
index 94a9000..4261971 100644
--- a/libs/ui/include/ui/BufferHubMetadata.h
+++ b/libs/ui/include/ui/BufferHubMetadata.h
@@ -33,12 +33,17 @@
 #pragma clang diagnostic ignored "-Wundefined-func-template"
 #pragma clang diagnostic ignored "-Wunused-template"
 #pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_defs.h>
 #pragma clang diagnostic pop
 
+#include <android-base/unique_fd.h>
+
 namespace android {
 
+namespace {
+using base::unique_fd;
+} // namespace
+
 class BufferHubMetadata {
 public:
     // Creates a new BufferHubMetadata backed by an ashmem region.
@@ -50,11 +55,8 @@
 
     // Imports an existing BufferHubMetadata from an ashmem FD.
     //
-    // TODO(b/112338294): Refactor BufferHub to use Binder as its internal IPC backend instead of
-    // UDS.
-    //
-    // @param ashmemHandle Ashmem file handle representing an ashmem region.
-    static BufferHubMetadata Import(pdx::LocalHandle ashmemHandle);
+    // @param ashmemFd Ashmem file descriptor representing an ashmem region.
+    static BufferHubMetadata Import(unique_fd ashmemFd);
 
     BufferHubMetadata() = default;
 
@@ -67,7 +69,7 @@
             mUserMetadataSize = other.mUserMetadataSize;
             other.mUserMetadataSize = 0;
 
-            mAshmemHandle = std::move(other.mAshmemHandle);
+            mAshmemFd = std::move(other.mAshmemFd);
 
             // The old raw mMetadataHeader pointer must be cleared, otherwise the destructor will
             // automatically mummap() the shared memory.
@@ -79,25 +81,25 @@
 
     // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem
     // has been mapped into virtual address space.
-    bool IsValid() const { return mAshmemHandle.IsValid() && mMetadataHeader != nullptr; }
+    bool IsValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; }
 
     size_t user_metadata_size() const { return mUserMetadataSize; }
     size_t metadata_size() const {
         return mUserMetadataSize + dvr::BufferHubDefs::kMetadataHeaderSize;
     }
 
-    const pdx::LocalHandle& ashmem_handle() const { return mAshmemHandle; }
+    const unique_fd& ashmem_fd() const { return mAshmemFd; }
     dvr::BufferHubDefs::MetadataHeader* metadata_header() { return mMetadataHeader; }
 
 private:
-    BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle,
+    BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd,
                       dvr::BufferHubDefs::MetadataHeader* metadataHeader);
 
     BufferHubMetadata(const BufferHubMetadata&) = delete;
     void operator=(const BufferHubMetadata&) = delete;
 
     size_t mUserMetadataSize = 0;
-    pdx::LocalHandle mAshmemHandle;
+    unique_fd mAshmemFd;
     dvr::BufferHubDefs::MetadataHeader* mMetadataHeader = nullptr;
 };
 
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 6af8033..d30636f 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -156,20 +156,25 @@
     memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
 
     sp<IBufferClient> client;
+    BufferHubStatus ret;
     IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& outClient, const auto& status) {
-        ASSERT_EQ(status, BufferHubStatus::NO_ERROR);
-        ASSERT_NE(nullptr, outClient.get());
         client = outClient;
+        ret = status;
     };
     ASSERT_TRUE(bufferhub->allocateBuffer(desc, kUserMetadataSize, alloc_cb).isOk());
+    EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+    ASSERT_NE(nullptr, client.get());
 
-    IBufferClient::duplicate_cb dup_cb = [](const auto& token, const auto& status) {
-        ASSERT_EQ(status, BufferHubStatus::NO_ERROR);
-        ASSERT_NE(token.getNativeHandle(), nullptr);
-        EXPECT_EQ(token->numInts, 1);
-        EXPECT_EQ(token->numFds, 0);
+    hidl_handle token;
+    IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+        token = outToken;
+        ret = status;
     };
     EXPECT_TRUE(client->duplicate(dup_cb).isOk());
+    EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+    ASSERT_NE(token.getNativeHandle(), nullptr);
+    EXPECT_EQ(token->numInts, 1);
+    EXPECT_EQ(token->numFds, 0);
 }
 
 } // namespace
diff --git a/libs/ui/tests/BufferHubMetadata_test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp
index 4209392..70f86b3 100644
--- a/libs/ui/tests/BufferHubMetadata_test.cpp
+++ b/libs/ui/tests/BufferHubMetadata_test.cpp
@@ -43,11 +43,11 @@
   EXPECT_TRUE(m1.IsValid());
   EXPECT_NE(m1.metadata_header(), nullptr);
 
-  pdx::LocalHandle h2 = m1.ashmem_handle().Duplicate();
-  EXPECT_TRUE(h2.IsValid());
+  unique_fd h2 = unique_fd(dup(m1.ashmem_fd().get()));
+  EXPECT_NE(h2.get(), -1);
 
   BufferHubMetadata m2 = BufferHubMetadata::Import(std::move(h2));
-  EXPECT_FALSE(h2.IsValid());
+  EXPECT_EQ(h2.get(), -1);
   EXPECT_TRUE(m1.IsValid());
   BufferHubDefs::MetadataHeader* mh1 = m1.metadata_header();
   EXPECT_NE(mh1, nullptr);
@@ -71,31 +71,29 @@
   BufferHubMetadata m1 = BufferHubMetadata::Create(sizeof(int));
   EXPECT_TRUE(m1.IsValid());
   EXPECT_NE(m1.metadata_header(), nullptr);
-  EXPECT_TRUE(m1.ashmem_handle().IsValid());
+  EXPECT_NE(m1.ashmem_fd().get(), -1);
   EXPECT_EQ(m1.user_metadata_size(), sizeof(int));
 
   BufferHubMetadata m2 = std::move(m1);
 
-  // After the move, the metadata header (a raw pointer) should be reset in the
-  // older buffer.
+  // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
   EXPECT_EQ(m1.metadata_header(), nullptr);
   EXPECT_NE(m2.metadata_header(), nullptr);
 
-  EXPECT_FALSE(m1.ashmem_handle().IsValid());
-  EXPECT_TRUE(m2.ashmem_handle().IsValid());
+  EXPECT_EQ(m1.ashmem_fd().get(), -1);
+  EXPECT_NE(m2.ashmem_fd().get(), -1);
 
   EXPECT_EQ(m1.user_metadata_size(), 0U);
   EXPECT_EQ(m2.user_metadata_size(), sizeof(int));
 
   BufferHubMetadata m3{std::move(m2)};
 
-  // After the move, the metadata header (a raw pointer) should be reset in the
-  // older buffer.
+  // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
   EXPECT_EQ(m2.metadata_header(), nullptr);
   EXPECT_NE(m3.metadata_header(), nullptr);
 
-  EXPECT_FALSE(m2.ashmem_handle().IsValid());
-  EXPECT_TRUE(m3.ashmem_handle().IsValid());
+  EXPECT_EQ(m2.ashmem_fd().get(), -1);
+  EXPECT_NE(m3.ashmem_fd().get(), -1);
 
   EXPECT_EQ(m2.user_metadata_size(), 0U);
   EXPECT_EQ(m3.user_metadata_size(), sizeof(int));
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 0fb4ac6..8dc80cc 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -315,32 +315,7 @@
     if (mCacheSize != 0) {
         // There are some events in the cache which need to be sent first. Copy this buffer to
         // the end of cache.
-        if (mCacheSize + count <= mMaxCacheSize) {
-            memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
-            mCacheSize += count;
-        } else {
-            // Check if any new sensors have registered on this connection which may have increased
-            // the max cache size that is desired.
-            if (mCacheSize + count < computeMaxCacheSizeLocked()) {
-                reAllocateCacheLocked(scratch, count);
-                return status_t(NO_ERROR);
-            }
-            // Some events need to be dropped.
-            int remaningCacheSize = mMaxCacheSize - mCacheSize;
-            if (remaningCacheSize != 0) {
-                memcpy(&mEventCache[mCacheSize], scratch,
-                                                remaningCacheSize * sizeof(sensors_event_t));
-            }
-            int numEventsDropped = count - remaningCacheSize;
-            countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
-            // Drop the first "numEventsDropped" in the cache.
-            memmove(mEventCache, &mEventCache[numEventsDropped],
-                    (mCacheSize - numEventsDropped) * sizeof(sensors_event_t));
-
-            // Copy the remainingEvents in scratch buffer to the end of cache.
-            memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
-                                            numEventsDropped * sizeof(sensors_event_t));
-        }
+        appendEventsToCacheLocked(scratch, count);
         return status_t(NO_ERROR);
     }
 
@@ -376,8 +351,8 @@
             mEventCache = new sensors_event_t[mMaxCacheSize];
             mCacheSize = 0;
         }
-        memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
-        mCacheSize += count;
+        // Save the events so that they can be written later
+        appendEventsToCacheLocked(scratch, count);
 
         // Add this file descriptor to the looper to get a callback when this fd is available for
         // writing.
@@ -417,6 +392,51 @@
     mMaxCacheSize = new_cache_size;
 }
 
+void SensorService::SensorEventConnection::appendEventsToCacheLocked(sensors_event_t const* events,
+                                                                     int count) {
+    if (count <= 0) {
+        return;
+    } else if (mCacheSize + count <= mMaxCacheSize) {
+        // The events fit within the current cache: add them
+        memcpy(&mEventCache[mCacheSize], events, count * sizeof(sensors_event_t));
+        mCacheSize += count;
+    } else if (mCacheSize + count <= computeMaxCacheSizeLocked()) {
+        // The events fit within a resized cache: resize the cache and add the events
+        reAllocateCacheLocked(events, count);
+    } else {
+        // The events do not fit within the cache: drop the oldest events.
+        ALOGW("Dropping events from cache (%d / %d) to save %d newer events", mCacheSize,
+                mMaxCacheSize, count);
+
+        int freeSpace = mMaxCacheSize - mCacheSize;
+
+        // Drop up to the currently cached number of events to make room for new events
+        int cachedEventsToDrop = std::min(mCacheSize, count - freeSpace);
+
+        // New events need to be dropped if there are more new events than the size of the cache
+        int newEventsToDrop = std::max(0, count - mMaxCacheSize);
+
+        // Determine the number of new events to copy into the cache
+        int eventsToCopy = std::min(mMaxCacheSize, count);
+
+        // Check for any flush complete events in the events that will be dropped
+        countFlushCompleteEventsLocked(mEventCache, cachedEventsToDrop);
+        countFlushCompleteEventsLocked(events, newEventsToDrop);
+
+        // Only shift the events if they will not all be overwritten
+        if (eventsToCopy != mMaxCacheSize) {
+            memmove(mEventCache, &mEventCache[cachedEventsToDrop],
+                    (mCacheSize - cachedEventsToDrop) * sizeof(sensors_event_t));
+        }
+        mCacheSize -= cachedEventsToDrop;
+
+        // Copy the events into the cache
+        memcpy(&mEventCache[mCacheSize], &events[newEventsToDrop],
+                eventsToCopy * sizeof(sensors_event_t));
+        mCacheSize += eventsToCopy;
+    }
+}
+
 void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
     ASensorEvent flushCompleteEvent;
     memset(&flushCompleteEvent, 0, sizeof(flushCompleteEvent));
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 40c21ff..eefd81a 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -108,6 +108,10 @@
     // size, reallocate memory and copy over events from the older cache.
     void reAllocateCacheLocked(sensors_event_t const* scratch, int count);
 
+    // Add the events to the cache. If the cache would be exceeded, drop events at the beginning of
+    // the cache.
+    void appendEventsToCacheLocked(sensors_event_t const* events, int count);
+
     // LooperCallback method. If there is data to read on this fd, it is an ack from the app that it
     // has read events from a wake up sensor, decrement mWakeLockRefCount.  If this fd is available
     // for writing send the data from the cache.
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index ade62bf..7caae98 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -501,7 +501,7 @@
 
     // FIXME: postedRegion should be dirty & bounds
     // transform the dirty region to window-manager space
-    return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s))));
+    return getTransform().transform(Region(getBufferSize(s)));
 }
 
 // transaction
@@ -624,11 +624,13 @@
 
     ui::Transform t = getTransform();
     Rect win = bounds;
+    const int bufferWidth = getBufferSize(s).getWidth();
+    const int bufferHeight = getBufferSize(s).getHeight();
 
-    float left = float(win.left) / float(getActiveWidth(s));
-    float top = float(win.top) / float(getActiveHeight(s));
-    float right = float(win.right) / float(getActiveWidth(s));
-    float bottom = float(win.bottom) / float(getActiveHeight(s));
+    const float left = float(win.left) / float(bufferWidth);
+    const float top = float(win.top) / float(bufferHeight);
+    const float right = float(win.right) / float(bufferWidth);
+    const float bottom = float(win.bottom) / float(bufferHeight);
 
     // TODO: we probably want to generate the texture coords with the mesh
     // here we assume that we only have 4 vertices
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6ac0901..3b444f7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -367,27 +367,24 @@
     // layerstack space, and convert-back to layer space.
     // if there are no window scaling involved, this operation will map to full
     // pixels in the buffer.
-    // FIXME: the 3 lines below can produce slightly incorrect clipping when we have
-    // a viewport clipping and a window transform. we should use floating point to fix this.
 
-    Rect activeCrop(getActiveWidth(s), getActiveHeight(s));
-    Rect crop = getCrop(s);
-    if (!crop.isEmpty()) {
-        activeCrop.intersect(crop, &activeCrop);
-    }
-
+    FloatRect activeCropFloat = computeBounds();
     ui::Transform t = getTransform();
-    activeCrop = t.transform(activeCrop);
-    if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
+    // Transform to screen space.
+    activeCropFloat = t.transform(activeCropFloat);
+    activeCropFloat = activeCropFloat.intersect(display->getViewport().toFloatRect());
+    // Back to layer space to work with the content crop.
+    activeCropFloat = t.inverse().transform(activeCropFloat);
+    // This needs to be here as transform.transform(Rect) computes the
+    // transformed rect and then takes the bounding box of the result before
+    // returning. This means
+    // transform.inverse().transform(transform.transform(Rect)) != Rect
+    // in which case we need to make sure the final rect is clipped to the
+    // display bounds.
+    Rect activeCrop{activeCropFloat};
+    if (!activeCrop.intersect(getBufferSize(s), &activeCrop)) {
         activeCrop.clear();
     }
-
-    const auto& p = mDrawingParent.promote();
-    if (p != nullptr) {
-        auto parentCrop = p->computeInitialCrop(display);
-        activeCrop.intersect(parentCrop, &activeCrop);
-    }
-
     return activeCrop;
 }
 
@@ -399,24 +396,8 @@
     // In addition there is a WM-specified crop we pull from our drawing state.
     const State& s(getDrawingState());
 
-    // Screen space to make reduction to parent crop clearer.
     Rect activeCrop = computeInitialCrop(display);
-    ui::Transform t = getTransform();
-    // Back to layer space to work with the content crop.
-    activeCrop = t.inverse().transform(activeCrop);
-
-    // This needs to be here as transform.transform(Rect) computes the
-    // transformed rect and then takes the bounding box of the result before
-    // returning. This means
-    // transform.inverse().transform(transform.transform(Rect)) != Rect
-    // in which case we need to make sure the final rect is clipped to the
-    // display bounds.
-    if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) {
-        activeCrop.clear();
-    }
-
-    // subtract the transparent region and snap to the bounds
-    activeCrop = reduce(activeCrop, getActiveTransparentRegion(s));
+    Rect bufferSize = getBufferSize(s);
 
     // Transform the window crop to match the buffer coordinate system,
     // which means using the inverse of the current transform set on the
@@ -437,8 +418,8 @@
                         ui::Transform(invTransform)).getOrientation();
     }
 
-    int winWidth = getActiveWidth(s);
-    int winHeight = getActiveHeight(s);
+    int winWidth = bufferSize.getWidth();
+    int winHeight = bufferSize.getHeight();
     if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
         // If the activeCrop has been rotate the ends are rotated but not
         // the space itself so when transforming ends back we can't rely on
@@ -450,10 +431,10 @@
         if (is_h_flipped == is_v_flipped) {
             invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
         }
-        winWidth = getActiveHeight(s);
-        winHeight = getActiveWidth(s);
+        std::swap(winWidth, winHeight);
     }
-    const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s));
+    const Rect winCrop =
+            activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
 
     // below, crop is intersected with winCrop expressed in crop's coordinate space
     float xScale = crop.getWidth() / float(winWidth);
@@ -489,6 +470,8 @@
 
     // this gives us only the "orientation" component of the transform
     const State& s(getDrawingState());
+    const int bufferWidth = getBufferSize(s).getWidth();
+    const int bufferHeight = getBufferSize(s).getHeight();
     auto blendMode = HWC2::BlendMode::None;
     if (!isOpaque(s) || getAlpha() != 1.0f) {
         blendMode =
@@ -519,16 +502,15 @@
         // transform.inverse().transform(transform.transform(Rect)) != Rect
         // in which case we need to make sure the final rect is clipped to the
         // display bounds.
-        if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) {
+        if (!activeCrop.intersect(Rect(bufferWidth, bufferHeight), &activeCrop)) {
             activeCrop.clear();
         }
         // mark regions outside the crop as transparent
-        activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top));
-        activeTransparentRegion.orSelf(
-                Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s)));
+        activeTransparentRegion.orSelf(Rect(0, 0, bufferWidth, activeCrop.top));
+        activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, bufferWidth, bufferHeight));
         activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
         activeTransparentRegion.orSelf(
-                Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), activeCrop.bottom));
+                Rect(activeCrop.right, activeCrop.top, bufferWidth, activeCrop.bottom));
     }
 
     // computeBounds returns a FloatRect to provide more accuracy during the
@@ -664,11 +646,7 @@
 
     // Apply the layer's transform, followed by the display's global transform
     // Here we're guaranteed that the layer's transform preserves rects
-    Rect win(getActiveWidth(s), getActiveHeight(s));
-    Rect crop = getCrop(s);
-    if (!crop.isEmpty()) {
-        win.intersect(crop, &win);
-    }
+    Rect win = getCroppedBufferSize(s);
     // Subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, getActiveTransparentRegion(s));
     Rect frame(getTransform().transform(bounds));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index fe8d5a9..00a6bbe 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -596,6 +596,12 @@
     int32_t getZ() const;
     virtual void pushPendingState();
 
+    /**
+     * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
+     * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
+     */
+    virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -819,12 +825,6 @@
      * bounds are constrained by its parent bounds.
      */
     Rect getCroppedBufferSize(const Layer::State& s) const;
-
-    /**
-     * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
-     * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
-     */
-    virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6bd43aa..75dd828 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3724,11 +3724,24 @@
             result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer);
             break;
         case ISurfaceComposerClient::eFXSurfaceColor:
+            // check if buffer size is set for color layer.
+            if (w > 0 || h > 0) {
+                ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)",
+                      int(w), int(h));
+                return BAD_VALUE;
+            }
+
             result = createColorLayer(client,
                     uniqueName, w, h, flags,
                     handle, &layer);
             break;
         case ISurfaceComposerClient::eFXSurfaceContainer:
+            // check if buffer size is set for container layer.
+            if (w > 0 || h > 0) {
+                ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)",
+                      int(w), int(h));
+                return BAD_VALUE;
+            }
             result = createContainerLayer(client,
                     uniqueName, w, h, flags,
                     handle, &layer);
@@ -5179,12 +5192,14 @@
         const ui::Transform& getTransform() const override { return mTransform; }
         Rect getBounds() const override {
             const Layer::State& layerState(mLayer->getDrawingState());
-            return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState));
+            return mLayer->getBufferSize(layerState);
         }
         int getHeight() const override {
-            return mLayer->getActiveHeight(mLayer->getDrawingState());
+            return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
         }
-        int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); }
+        int getWidth() const override {
+            return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth();
+        }
         bool isSecure() const override { return false; }
         bool needsFiltering() const override { return mNeedsFiltering; }
         Rect getSourceCrop() const override {
@@ -5258,12 +5273,12 @@
     Rect crop(sourceCrop);
     if (sourceCrop.width() <= 0) {
         crop.left = 0;
-        crop.right = parent->getActiveWidth(parent->getCurrentState());
+        crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
     }
 
     if (sourceCrop.height() <= 0) {
         crop.top = 0;
-        crop.bottom = parent->getActiveHeight(parent->getCurrentState());
+        crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
     }
 
     int32_t reqWidth = crop.width() * frameScale;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a600a0a..7e95d99 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -334,16 +334,10 @@
     virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client,
                                            const char* name, uint32_t width, uint32_t height,
                                            uint32_t flags = 0) {
-        auto layer =
-                client->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags);
-        EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
+        auto layer = createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags);
 
         Transaction t;
         t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
-        // If we are creating a color layer, set its crop since its size will be ignored.
-        if (flags == ISurfaceComposerClient::eFXSurfaceColor) {
-            t.setCrop_legacy(layer, Rect(0, 0, width, height));
-        }
 
         status_t error = t.apply();
         if (error != NO_ERROR) {
@@ -354,6 +348,15 @@
         return layer;
     }
 
+    virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client,
+                                             const char* name, uint32_t width, uint32_t height,
+                                             PixelFormat format, uint32_t flags,
+                                             SurfaceControl* parent = nullptr) {
+        auto layer = client->createSurface(String8(name), width, height, format, flags, parent);
+        EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
+        return layer;
+    }
+
     virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
                                            uint32_t flags = 0) {
         return createLayer(mClient, name, width, height, flags);
@@ -509,9 +512,9 @@
 
         mDisplayLayerStack = 0;
 
-        mBlackBgSurface = mClient->createSurface(String8("BaseSurface"), mDisplayWidth,
-                                                 mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
-                                                 ISurfaceComposerClient::eFXSurfaceColor);
+        mBlackBgSurface =
+                createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */,
+                              PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
 
         // set layer stack (b/68888219)
         Transaction t;
@@ -834,8 +837,9 @@
 
 TEST_P(LayerTypeTransactionTest, SetZNegative) {
     sp<SurfaceControl> parent =
-            LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight,
+            LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
                                               ISurfaceComposerClient::eFXSurfaceContainer);
+    Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
     sp<SurfaceControl> layerR;
     sp<SurfaceControl> layerG;
     ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
@@ -892,8 +896,9 @@
 
 TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
     sp<SurfaceControl> parent =
-            LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight,
+            LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
                                               ISurfaceComposerClient::eFXSurfaceContainer);
+    Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
     sp<SurfaceControl> layerR;
     sp<SurfaceControl> layerG;
     sp<SurfaceControl> layerB;
@@ -1225,10 +1230,15 @@
     sp<SurfaceControl> colorLayer;
     ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+    ASSERT_NO_FATAL_FAILURE(colorLayer =
+                                    createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+                                                ISurfaceComposerClient::eFXSurfaceColor));
 
-    Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+    Transaction()
+            .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+            .setLayer(colorLayer, mLayerZBase + 1)
+            .apply();
+
     {
         SCOPED_TRACE("default color");
         screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
@@ -1248,10 +1258,14 @@
 
 TEST_F(LayerTransactionTest, SetColorClamped) {
     sp<SurfaceControl> colorLayer;
-    ASSERT_NO_FATAL_FAILURE(
-            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+    ASSERT_NO_FATAL_FAILURE(colorLayer =
+                                    createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+                                                ISurfaceComposerClient::eFXSurfaceColor));
+    Transaction()
+            .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+            .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f))
+            .apply();
 
-    Transaction().setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)).apply();
     screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
 }
 
@@ -1260,8 +1274,10 @@
     sp<SurfaceControl> colorLayer;
     ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+    ASSERT_NO_FATAL_FAILURE(colorLayer =
+                                    createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+                                                ISurfaceComposerClient::eFXSurfaceColor));
+    Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
 
     const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
     const float alpha = 0.25f;
@@ -1285,9 +1301,10 @@
     ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
     ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32));
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
-    ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer(
-            "childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
-
+    ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */,
+                                                     0 /* buffer height */,
+                                                     ISurfaceComposerClient::eFXSurfaceColor));
+    Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
     const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
     const float alpha = 0.25f;
     const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
@@ -2129,10 +2146,13 @@
 
 TEST_F(LayerTransactionTest, SetColorTransformBasic) {
     sp<SurfaceControl> colorLayer;
-    ASSERT_NO_FATAL_FAILURE(
-            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
-
-    Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+    ASSERT_NO_FATAL_FAILURE(colorLayer =
+                                    createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+                                                ISurfaceComposerClient::eFXSurfaceColor));
+    Transaction()
+            .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+            .setLayer(colorLayer, mLayerZBase + 1)
+            .apply();
     {
         SCOPED_TRACE("default color");
         screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
@@ -3024,11 +3044,10 @@
     std::unique_ptr<ScreenCapture> sc;
 
     sp<SurfaceControl> childNoBuffer =
-            mClient->createSurface(String8("Bufferless child"), 10, 10,
-                                           PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    sp<SurfaceControl> childBuffer =
-            mClient->createSurface(String8("Buffered child"), 20, 20,
-                                           PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
+            createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */,
+                          PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20,
+                                                   PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
     fillSurfaceRGBA8(childBuffer, 200, 200, 200);
     SurfaceComposerClient::Transaction{}
             .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10))
@@ -3078,8 +3097,8 @@
 protected:
     void SetUp() override {
         LayerUpdateTest::SetUp();
-        mChild = mClient->createSurface(String8("Child surface"), 10, 10,
-                                                PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+        mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
+                               mFGSurfaceControl.get());
         fillSurfaceRGBA8(mChild, 200, 200, 200);
 
         {
@@ -3254,8 +3273,7 @@
 
 TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
     sp<SurfaceControl> mGrandChild =
-        mClient->createSurface(String8("Grand Child"), 10, 10,
-                PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+            createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
     fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
 
     {
@@ -3318,10 +3336,9 @@
 TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
     sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
     sp<SurfaceControl> mChildNewClient =
-            mNewComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
-                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+            createSurface(mNewComposerClient, "New Child Test Surface", 10, 10,
+                          PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
 
-    ASSERT_TRUE(mChildNewClient != nullptr);
     ASSERT_TRUE(mChildNewClient->isValid());
 
     fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
@@ -3482,9 +3499,8 @@
     mChild.clear();
 
     // Now recreate it as hidden
-    mChild = mClient->createSurface(String8("Child surface"), 10, 10,
-                                            PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eHidden,
-                                            mFGSurfaceControl.get());
+    mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888,
+                           ISurfaceComposerClient::eHidden, mFGSurfaceControl.get());
 
     // Show the child layer in a deferred transaction
     asTransaction([&](Transaction& t) {
@@ -3600,9 +3616,8 @@
 }
 
 TEST_F(ChildLayerTest, NestedChildren) {
-    sp<SurfaceControl> grandchild =
-            mClient->createSurface(String8("Grandchild surface"), 10, 10,
-                                           PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+    sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10,
+                                                  PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
     fillSurfaceRGBA8(grandchild, 50, 50, 50);
 
     {
@@ -3640,9 +3655,8 @@
 // Verify setting a size on a buffer layer has no effect.
 TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) {
     sp<SurfaceControl> bufferLayer =
-            mClient->createSurface(String8("BufferLayer"), 45, 45, PIXEL_FORMAT_RGBA_8888, 0,
-                                   mFGSurfaceControl.get());
-    ASSERT_TRUE(bufferLayer != nullptr);
+            createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0,
+                          mFGSurfaceControl.get());
     ASSERT_TRUE(bufferLayer->isValid());
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30));
     asTransaction([&](Transaction& t) { t.show(bufferLayer); });
@@ -3661,10 +3675,8 @@
 // which will crop the color layer.
 TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) {
     sp<SurfaceControl> colorLayer =
-            mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceColor,
-                                   mFGSurfaceControl.get());
-    ASSERT_TRUE(colorLayer != nullptr);
+            createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
     ASSERT_TRUE(colorLayer->isValid());
     asTransaction([&](Transaction& t) {
         t.setColor(colorLayer, half3{0, 0, 0});
@@ -3684,15 +3696,12 @@
 // Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has
 // a crop which will be used to crop the color layer.
 TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) {
-    sp<SurfaceControl> cropLayer =
-            mClient->createSurface(String8("CropLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   0 /* flags */, mFGSurfaceControl.get());
-    ASSERT_TRUE(cropLayer != nullptr);
+    sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                                                 0 /* flags */, mFGSurfaceControl.get());
     ASSERT_TRUE(cropLayer->isValid());
     sp<SurfaceControl> colorLayer =
-            mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get());
-    ASSERT_TRUE(colorLayer != nullptr);
+            createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get());
     ASSERT_TRUE(colorLayer->isValid());
     asTransaction([&](Transaction& t) {
         t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10));
@@ -3716,10 +3725,8 @@
 // Verify for boundless layer with no children, their transforms have no effect.
 TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) {
     sp<SurfaceControl> colorLayer =
-            mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceColor,
-                                   mFGSurfaceControl.get());
-    ASSERT_TRUE(colorLayer != nullptr);
+            createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
     ASSERT_TRUE(colorLayer->isValid());
     asTransaction([&](Transaction& t) {
         t.setPosition(colorLayer, 320, 320);
@@ -3741,20 +3748,16 @@
 // Verify for boundless layer with children, their transforms have an effect.
 TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) {
     sp<SurfaceControl> boundlessLayerRightShift =
-            mClient->createSurface(String8("BoundlessLayerRightShift"), 0, 0,
-                                   PIXEL_FORMAT_RGBA_8888, 0 /* flags */, mFGSurfaceControl.get());
-    ASSERT_TRUE(boundlessLayerRightShift != nullptr);
+            createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          0 /* flags */, mFGSurfaceControl.get());
     ASSERT_TRUE(boundlessLayerRightShift->isValid());
     sp<SurfaceControl> boundlessLayerDownShift =
-            mClient->createSurface(String8("BoundlessLayerLeftShift"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   0 /* flags */, boundlessLayerRightShift.get());
-    ASSERT_TRUE(boundlessLayerDownShift != nullptr);
+            createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          0 /* flags */, boundlessLayerRightShift.get());
     ASSERT_TRUE(boundlessLayerDownShift->isValid());
     sp<SurfaceControl> colorLayer =
-            mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceColor,
-                                   boundlessLayerDownShift.get());
-    ASSERT_TRUE(colorLayer != nullptr);
+            createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get());
     ASSERT_TRUE(colorLayer->isValid());
     asTransaction([&](Transaction& t) {
         t.setPosition(boundlessLayerRightShift, 32, 0);
@@ -3815,16 +3818,13 @@
 
 // Verify for boundless root layers with children, their transforms have an effect.
 TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) {
-    sp<SurfaceControl> rootBoundlessLayer =
-            mClient->createSurface(String8("RootBoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   0 /* flags */);
-    ASSERT_TRUE(rootBoundlessLayer != nullptr);
+    sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0,
+                                                          PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
     ASSERT_TRUE(rootBoundlessLayer->isValid());
     sp<SurfaceControl> colorLayer =
-            mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceColor,
-                                   rootBoundlessLayer.get());
-    ASSERT_TRUE(colorLayer != nullptr);
+            createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+                          ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get());
+
     ASSERT_TRUE(colorLayer->isValid());
     asTransaction([&](Transaction& t) {
         t.setLayer(rootBoundlessLayer, INT32_MAX - 1);
@@ -3864,9 +3864,8 @@
 TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
     auto fgHandle = mFGSurfaceControl->getHandle();
 
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
@@ -3880,9 +3879,8 @@
 TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
     auto fgHandle = mFGSurfaceControl->getHandle();
 
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
@@ -3894,9 +3892,8 @@
 }
 
 TEST_F(ScreenCaptureTest, CaptureTransparent) {
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
 
     fillSurfaceRGBA8(child, 200, 200, 200);
 
@@ -3914,9 +3911,9 @@
 TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
     auto fgHandle = mFGSurfaceControl->getHandle();
 
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    ASSERT_NE(nullptr, child.get()) << "failed to create surface";
     sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
     fillSurfaceRGBA8(child, 200, 200, 200);
     fillSurfaceRGBA8(relative, 100, 100, 100);
@@ -3937,12 +3934,10 @@
 TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
     auto fgHandle = mFGSurfaceControl->getHandle();
 
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
-    sp<SurfaceControl> relative =
-            mClient->createSurface(String8("Relative surface"), 10, 10,
-                                           PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
+                                                PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
     fillSurfaceRGBA8(relative, 100, 100, 100);
 
@@ -3971,9 +3966,8 @@
     void SetUp() override {
         LayerUpdateTest::SetUp();
 
-        mChild =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                    0, mFGSurfaceControl.get());
+        mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
+                               mFGSurfaceControl.get());
         fillSurfaceRGBA8(mChild, 200, 200, 200);
 
         SurfaceComposerClient::Transaction().show(mChild).apply(true);
@@ -4029,14 +4023,12 @@
 TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
     auto fgHandle = mFGSurfaceControl->getHandle();
 
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
 
-    sp<SurfaceControl> grandchild =
-            mClient->createSurface(String8("Grandchild surface"), 5, 5,
-                                           PIXEL_FORMAT_RGBA_8888, 0, child.get());
+    sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+                                                  PIXEL_FORMAT_RGBA_8888, 0, child.get());
 
     fillSurfaceRGBA8(grandchild, 50, 50, 50);
     SurfaceComposerClient::Transaction()
@@ -4053,9 +4045,8 @@
 }
 
 TEST_F(ScreenCaptureTest, CaptureChildOnly) {
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
     auto childHandle = child->getHandle();
 
@@ -4068,15 +4059,13 @@
 }
 
 TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
-    sp<SurfaceControl> child =
-            mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
-                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     fillSurfaceRGBA8(child, 200, 200, 200);
     auto childHandle = child->getHandle();
 
-    sp<SurfaceControl> grandchild =
-            mClient->createSurface(String8("Grandchild surface"), 5, 5,
-                                           PIXEL_FORMAT_RGBA_8888, 0, child.get());
+    sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+                                                  PIXEL_FORMAT_RGBA_8888, 0, child.get());
     fillSurfaceRGBA8(grandchild, 50, 50, 50);
 
     SurfaceComposerClient::Transaction()
@@ -4095,9 +4084,8 @@
 
 TEST_F(ScreenCaptureTest, CaptureCrop) {
     sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
-    sp<SurfaceControl> blueLayer =
-            mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
-                                           0, redLayer.get());
+    sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+                                                 PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
 
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
@@ -4128,9 +4116,8 @@
 
 TEST_F(ScreenCaptureTest, CaptureSize) {
     sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
-    sp<SurfaceControl> blueLayer =
-            mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
-                                           0, redLayer.get());
+    sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+                                                 PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
 
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp
index 589b31a..6c64bcd 100644
--- a/services/vr/bufferhubd/buffer_channel.cpp
+++ b/services/vr/bufferhubd/buffer_channel.cpp
@@ -83,10 +83,13 @@
   ATRACE_NAME("BufferChannel::OnImport");
   ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.", buffer_id());
 
+  BorrowedHandle ashmem_handle =
+      BorrowedHandle(buffer_node_->metadata().ashmem_fd().get());
+
   // TODO(b/112057680) Move away from the GraphicBuffer-based IonBuffer.
   return BufferTraits<BorrowedHandle>{
       /*buffer_handle=*/buffer_node_->buffer_handle(),
-      /*metadata_handle=*/buffer_node_->metadata().ashmem_handle().Borrow(),
+      /*metadata_handle=*/ashmem_handle,
       /*id=*/buffer_id(),
       /*client_state_mask=*/client_state_mask_,
       /*metadata_size=*/buffer_node_->metadata().metadata_size(),