Merge "Add more BufferHubEventFd tests"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 488070d..e33b2a8 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -231,16 +231,16 @@
 }
 
 // OTA slot script
-cc_prebuilt_binary {
+sh_binary {
     name: "otapreopt_slot",
-    srcs: ["otapreopt_slot.sh"],
+    src: "otapreopt_slot.sh",
     init_rc: ["otapreopt.rc"],
 }
 
 // OTA postinstall script
-cc_prebuilt_binary {
+sh_binary {
     name: "otapreopt_script",
-    srcs: ["otapreopt_script.sh"],
+    src: "otapreopt_script.sh",
     // Let this depend on otapreopt, the chroot tool and the slot script,
     // so we just have to mention one in a configuration.
     required: [
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 1c99663..609ddaf 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -41,6 +41,23 @@
 namespace android {
 namespace installd {
 
+// Configuration for bind-mounted Bionic artifacts.
+
+static constexpr const char* kLinkerMountPoint = "/bionic/bin/linker";
+static constexpr const char* kRuntimeLinkerPath = "/apex/com.android.runtime/bin/linker";
+
+static constexpr const char* kBionicLibsMountPointDir = "/bionic/lib/";
+static constexpr const char* kRuntimeBionicLibsDir = "/apex/com.android.runtime/lib/bionic/";
+
+static constexpr const char* kLinkerMountPoint64 = "/bionic/bin/linker64";
+static constexpr const char* kRuntimeLinkerPath64 = "/apex/com.android.runtime/bin/linker64";
+
+static constexpr const char* kBionicLibsMountPointDir64 = "/bionic/lib64/";
+static constexpr const char* kRuntimeBionicLibsDir64 = "/apex/com.android.runtime/lib64/bionic/";
+
+static const std::vector<std::string> kBionicLibFileNames = {"libc.so", "libm.so", "libdl.so"};
+
+
 static void CloseDescriptor(int fd) {
     if (fd >= 0) {
         int result = close(fd);
@@ -79,6 +96,43 @@
     }
 }
 
+// Copied from system/core/init/mount_namespace.cpp.
+static bool BindMount(const std::string& source, const std::string& mount_point,
+                      bool recursive = false) {
+    unsigned long mountflags = MS_BIND;
+    if (recursive) {
+        mountflags |= MS_REC;
+    }
+    if (mount(source.c_str(), mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
+        PLOG(ERROR) << "Could not bind-mount " << source << " to " << mount_point;
+        return false;
+    }
+    return true;
+}
+
+// Copied from system/core/init/mount_namespace.cpp and and adjusted (bind
+// mounts are not made private, as the /postinstall is already private (see
+// `android::installd::otapreopt_chroot`).
+static bool BindMountBionic(const std::string& linker_source, const std::string& lib_dir_source,
+                            const std::string& linker_mount_point,
+                            const std::string& lib_mount_dir) {
+    if (access(linker_source.c_str(), F_OK) != 0) {
+        PLOG(INFO) << linker_source << " does not exist. Skipping mounting Bionic there.";
+        return true;
+    }
+    if (!BindMount(linker_source, linker_mount_point)) {
+        return false;
+    }
+    for (const auto& libname : kBionicLibFileNames) {
+        std::string mount_point = lib_mount_dir + libname;
+        std::string source = lib_dir_source + libname;
+        if (!BindMount(source, mount_point)) {
+            return false;
+        }
+    }
+    return true;
+}
+
 // Entry for otapreopt_chroot. Expected parameters are:
 //   [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
 // The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -222,6 +276,23 @@
     // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
     std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
 
+    // Bind-mount Bionic artifacts from the Runtime APEX.
+    // This logic is copied and adapted from system/core/init/mount_namespace.cpp.
+    if (!BindMountBionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir, kLinkerMountPoint,
+                         kBionicLibsMountPointDir)) {
+        LOG(ERROR) << "Failed to mount 32-bit Bionic artifacts from the Runtime APEX.";
+        // Clean up and exit.
+        DeactivateApexPackages(active_packages);
+        exit(215);
+    }
+    if (!BindMountBionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64, kLinkerMountPoint64,
+                         kBionicLibsMountPointDir64)) {
+        LOG(ERROR) << "Failed to mount 64-bit Bionic artifacts from the Runtime APEX.";
+        // Clean up and exit.
+        DeactivateApexPackages(active_packages);
+        exit(216);
+    }
+
     // Now go on and run otapreopt.
 
     // Incoming:  cmd + status-fd + target-slot + cmd...      | Incoming | = argc
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index e2c5907..cc24ab3 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -451,12 +451,12 @@
 TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
   auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
   auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-  auto fake_package_ce_cache_path = read_path_inode(fake_package_ce_path,
-      "cache", kXattrInodeCache);
-  auto fake_package_ce_code_cache_path = read_path_inode(fake_package_ce_path,
-      "code_cache", kXattrInodeCache);
+  auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
+  auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
   auto fake_package_de_cache_path = fake_package_de_path + "/cache";
   auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
+  auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+  auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
 
   ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
   ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
@@ -464,20 +464,15 @@
   ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 700));
   ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 700));
   ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 700));
+  ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+  ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
 
   auto deleter = [&fake_package_ce_path, &fake_package_de_path,
-          &fake_package_ce_cache_path, &fake_package_ce_code_cache_path,
-          &fake_package_de_cache_path, &fake_package_de_code_cache_path]() {
+          &rollback_ce_dir, &rollback_de_dir]() {
       delete_dir_contents(fake_package_ce_path, true);
       delete_dir_contents(fake_package_de_path, true);
-      delete_dir_contents(fake_package_ce_cache_path, true);
-      delete_dir_contents(fake_package_ce_code_cache_path, true);
-      delete_dir_contents(fake_package_de_cache_path, true);
-      delete_dir_contents(fake_package_de_code_cache_path, true);
-      rmdir(fake_package_ce_cache_path.c_str());
-      rmdir(fake_package_ce_code_cache_path.c_str());
-      rmdir(fake_package_de_cache_path.c_str());
-      rmdir(fake_package_de_code_cache_path.c_str());
+      delete_dir_contents_and_dir(rollback_ce_dir, true);
+      delete_dir_contents_and_dir(rollback_de_dir, true);
   };
   auto scope_guard = android::base::make_scope_guard(deleter);
 
diff --git a/data/etc/android.hardware.biometrics.fingerprint.xml b/data/etc/android.hardware.biometrics.fingerprint.xml
deleted file mode 100644
index e5af541..0000000
--- a/data/etc/android.hardware.biometrics.fingerprint.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<!-- This is the standard set of features for a biometric fingerprint sensor. -->
-<permissions>
-    <feature name="android.hardware.biometrics.fingerprint" />
-</permissions>
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 49592a8..a595c01 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -181,7 +181,10 @@
                 if ((outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
                     int size = ashmem_get_size_region(obj.handle);
                     if (size > 0) {
-                        *outAshmemSize -= size;
+                        // ashmem size might have changed since last time it was accounted for, e.g.
+                        // in acquire_object(). Value of *outAshmemSize is not critical since we are
+                        // releasing the object anyway. Check for integer overflow condition.
+                        *outAshmemSize -= std::min(*outAshmemSize, static_cast<size_t>(size));
                     }
                 }
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index bef68ef..fd30e3b 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -722,42 +722,6 @@
         return error;
     }
 
-    virtual status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
-                                 int32_t* outBufferId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-
-        data.writeStrongBinder(token);
-        if (buffer) {
-            data.writeBool(true);
-            data.write(*buffer);
-        } else {
-            data.writeBool(false);
-        }
-
-        status_t result = remote()->transact(BnSurfaceComposer::CACHE_BUFFER, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-
-        int32_t id = -1;
-        result = reply.readInt32(&id);
-        if (result == NO_ERROR) {
-            *outBufferId = id;
-        }
-        return result;
-    }
-
-    virtual status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-
-        data.writeStrongBinder(token);
-        data.writeInt32(bufferId);
-
-        return remote()->transact(BnSurfaceComposer::UNCACHE_BUFFER, data, &reply);
-    }
-
     virtual status_t isWideColorDisplay(const sp<IBinder>& token,
                                         bool* outIsWideColorDisplay) const {
         Parcel data, reply;
@@ -1238,48 +1202,6 @@
             }
             return error;
         }
-        case CACHE_BUFFER: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> token;
-            status_t result = data.readStrongBinder(&token);
-            if (result != NO_ERROR) {
-                ALOGE("cache buffer failure in reading token: %d", result);
-                return result;
-            }
-
-            sp<GraphicBuffer> buffer = new GraphicBuffer();
-            if (data.readBool()) {
-                result = data.read(*buffer);
-                if (result != NO_ERROR) {
-                    ALOGE("cache buffer failure in reading buffer: %d", result);
-                    return result;
-                }
-            }
-            int32_t bufferId = -1;
-            status_t error = cacheBuffer(token, buffer, &bufferId);
-            if (error == NO_ERROR) {
-                reply->writeInt32(bufferId);
-            }
-            return error;
-        }
-        case UNCACHE_BUFFER: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> token;
-            status_t result = data.readStrongBinder(&token);
-            if (result != NO_ERROR) {
-                ALOGE("uncache buffer failure in reading token: %d", result);
-                return result;
-            }
-
-            int32_t bufferId = -1;
-            result = data.readInt32(&bufferId);
-            if (result != NO_ERROR) {
-                ALOGE("uncache buffer failure in reading buffer id: %d", result);
-                return result;
-            }
-
-            return uncacheBuffer(token, bufferId);
-        }
         case IS_WIDE_COLOR_DISPLAY: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = nullptr;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 51385b8..92b5588 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -48,6 +48,9 @@
 
 #include <private/gui/ComposerService.h>
 
+// This server size should always be smaller than the server cache size
+#define BUFFER_CACHE_MAX_SIZE 64
+
 namespace android {
 
 using ui::ColorMode;
@@ -230,6 +233,113 @@
 
 // ---------------------------------------------------------------------------
 
+class BufferCache : public Singleton<BufferCache> {
+public:
+    BufferCache() : token(new BBinder()) {}
+
+    sp<IBinder> getToken() {
+        return IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    }
+
+    int32_t getId(const sp<GraphicBuffer>& buffer) {
+        std::lock_guard lock(mMutex);
+
+        auto itr = mBuffers.find(buffer);
+        if (itr == mBuffers.end()) {
+            return -1;
+        }
+        itr->second.counter = getCounter();
+        return itr->second.id;
+    }
+
+    int32_t cache(const sp<GraphicBuffer>& buffer) {
+        std::lock_guard lock(mMutex);
+
+        int32_t bufferId = getNextAvailableId();
+
+        mBuffers[buffer].id = bufferId;
+        mBuffers[buffer].counter = getCounter();
+        return bufferId;
+    }
+
+private:
+    int32_t evictDestroyedBuffer() REQUIRES(mMutex) {
+        auto itr = mBuffers.begin();
+        while (itr != mBuffers.end()) {
+            auto& buffer = itr->first;
+            if (buffer == nullptr || buffer.promote() == nullptr) {
+                int32_t bufferId = itr->second.id;
+                mBuffers.erase(itr);
+                return bufferId;
+            }
+            itr++;
+        }
+        return -1;
+    }
+
+    int32_t evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
+        if (mBuffers.size() < 0) {
+            return -1;
+        }
+        auto itr = mBuffers.begin();
+        uint64_t minCounter = itr->second.counter;
+        auto minBuffer = itr;
+        itr++;
+
+        while (itr != mBuffers.end()) {
+            uint64_t counter = itr->second.counter;
+            if (counter < minCounter) {
+                minCounter = counter;
+                minBuffer = itr;
+            }
+            itr++;
+        }
+        int32_t minBufferId = minBuffer->second.id;
+        mBuffers.erase(minBuffer);
+        return minBufferId;
+    }
+
+    int32_t getNextAvailableId() REQUIRES(mMutex) {
+        static int32_t id = 0;
+        if (id + 1 < BUFFER_CACHE_MAX_SIZE) {
+            return id++;
+        }
+
+        // There are no more valid cache ids. To set additional buffers, evict existing buffers
+        // and reuse their cache ids.
+        int32_t bufferId = evictDestroyedBuffer();
+        if (bufferId > 0) {
+            return bufferId;
+        }
+        return evictLeastRecentlyUsedBuffer();
+    }
+
+    uint64_t getCounter() REQUIRES(mMutex) {
+        static uint64_t counter = 0;
+        return counter++;
+    }
+
+    struct Metadata {
+        // The cache id of a buffer that can be set to ISurfaceComposer. When ISurfaceComposer
+        // recieves this id, it can retrieve the buffer from its cache. Caching GraphicBuffers
+        // is important because sending them across processes is expensive.
+        int32_t id = 0;
+        // When a buffer is set, a counter is incremented and stored in the cache's metadata.
+        // When an buffer must be evicted, the entry with the lowest counter value is chosen.
+        uint64_t counter = 0;
+    };
+
+    std::mutex mMutex;
+    std::map<wp<GraphicBuffer>, Metadata> mBuffers GUARDED_BY(mMutex);
+
+    // Used by ISurfaceComposer to identify which process is sending the cached buffer.
+    sp<IBinder> token;
+};
+
+ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache);
+
+// ---------------------------------------------------------------------------
+
 SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
       : mForceSynchronous(other.mForceSynchronous),
         mTransactionNestCount(other.mTransactionNestCount),
@@ -759,22 +869,17 @@
         mStatus = BAD_INDEX;
         return *this;
     }
-    s->what |= layer_state_t::eBufferChanged;
-    s->buffer = buffer;
 
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
+    int32_t bufferId = BufferCache::getInstance().getId(buffer);
+    if (bufferId < 0) {
+        bufferId = BufferCache::getInstance().cache(buffer);
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCachedBuffer(
-        const sp<SurfaceControl>& sc, int32_t bufferId) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
+        s->what |= layer_state_t::eBufferChanged;
+        s->buffer = buffer;
     }
+
     s->what |= layer_state_t::eCachedBufferChanged;
-    s->cachedBuffer.token = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    s->cachedBuffer.token = BufferCache::getInstance().getToken();
     s->cachedBuffer.bufferId = bufferId;
 
     registerSurfaceControlForCallback(sc);
@@ -1217,26 +1322,6 @@
 
 // ----------------------------------------------------------------------------
 
-status_t SurfaceComposerClient::cacheBuffer(const sp<GraphicBuffer>& buffer, int32_t* outBufferId) {
-    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-    if (buffer == nullptr || outBufferId == nullptr) {
-        return BAD_VALUE;
-    }
-    return sf->cacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()),
-                           buffer, outBufferId);
-}
-
-status_t SurfaceComposerClient::uncacheBuffer(int32_t bufferId) {
-    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-    if (bufferId < 0) {
-        return BAD_VALUE;
-    }
-    return sf->uncacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()),
-                             bufferId);
-}
-
-// ----------------------------------------------------------------------------
-
 status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     return sf->enableVSyncInjections(enable);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3899f6a..7146b7d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -320,11 +320,6 @@
      */
     virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
 
-    virtual status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
-                                 int32_t* outBufferId) = 0;
-
-    virtual status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) = 0;
-
     /*
      * Queries whether the given display is a wide color display.
      * Requires the ACCESS_SURFACE_FLINGER permission.
@@ -373,8 +368,6 @@
         SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
         GET_DISPLAYED_CONTENT_SAMPLE,
         GET_PROTECTED_CONTENT_SUPPORT,
-        CACHE_BUFFER,
-        UNCACHE_BUFFER,
         IS_WIDE_COLOR_DISPLAY,
         GET_DISPLAY_NATIVE_PRIMARIES,
         // Always append new enum to the end.
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index a95664b..044106d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -152,12 +152,6 @@
     static void doDropReferenceTransaction(const sp<IBinder>& handle,
             const sp<ISurfaceComposerClient>& client);
 
-    // Caches a buffer with the ISurfaceComposer so the buffer does not need to be resent across
-    // processes
-    static status_t cacheBuffer(const sp<GraphicBuffer>& buffer, int32_t* outBufferId);
-    // Uncaches a buffer set by cacheBuffer
-    static status_t uncacheBuffer(int32_t bufferId);
-
     // Queries whether a given display is wide color display.
     static status_t isWideColorDisplay(const sp<IBinder>& display, bool* outIsWideColorDisplay);
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 1705fd7..8bd589d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -664,11 +664,6 @@
     status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
     status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
 
-    status_t cacheBuffer(const sp<IBinder>& /*token*/, const sp<GraphicBuffer>& /*buffer*/,
-                         int32_t* /*outBufferId*/) {
-        return NO_ERROR;
-    }
-    status_t uncacheBuffer(const sp<IBinder>& /*token*/, int32_t /*bufferId*/) { return NO_ERROR; }
     status_t isWideColorDisplay(const sp<IBinder>&, bool*) const override { return NO_ERROR; }
 
 protected:
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 92ea07c..5dc4530 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -351,6 +351,12 @@
     return releaseFence;
 }
 
+status_t Gralloc2Mapper::isSupported(uint32_t /*width*/, uint32_t /*height*/,
+                                     android::PixelFormat /*format*/, uint32_t /*layerCount*/,
+                                     uint64_t /*usage*/, bool* /*outSupported*/) const {
+    return INVALID_OPERATION;
+}
+
 Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) {
     mAllocator = IAllocator::getService();
     if (mAllocator == nullptr) {
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index 306a74b..7f8e57c 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -314,6 +314,36 @@
     return releaseFence;
 }
 
+status_t Gralloc3Mapper::isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
+                                     uint32_t layerCount, uint64_t usage,
+                                     bool* outSupported) const {
+    IMapper::BufferDescriptorInfo descriptorInfo;
+    sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
+
+    Error error;
+    auto ret = mMapper->isSupported(descriptorInfo,
+                                    [&](const auto& tmpError, const auto& tmpSupported) {
+                                        error = tmpError;
+                                        if (error != Error::NONE) {
+                                            return;
+                                        }
+                                        if (outSupported) {
+                                            *outSupported = tmpSupported;
+                                        }
+                                    });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+
+    if (error != Error::NONE) {
+        ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount,
+              error);
+    }
+
+    return static_cast<status_t>(error);
+}
+
 Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {
     mAllocator = IAllocator::getService();
     if (mAllocator == nullptr) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 15597eb..e678c58 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -344,6 +344,13 @@
     return res;
 }
 
+status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+                                    uint32_t inLayerCount, uint64_t inUsage,
+                                    bool* outSupported) const {
+    return mBufferMapper.isSupported(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+                                     outSupported);
+}
+
 size_t GraphicBuffer::getFlattenedSize() const {
     return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
 }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 79c333f..06981c3 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -161,5 +161,10 @@
     return NO_ERROR;
 }
 
+status_t GraphicBufferMapper::isSupported(uint32_t width, uint32_t height,
+                                          android::PixelFormat format, uint32_t layerCount,
+                                          uint64_t usage, bool* outSupported) {
+    return mMapper->isSupported(width, height, format, layerCount, usage, outSupported);
+}
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h
index 1b8a930..6cc23f0 100644
--- a/libs/ui/include/ui/Gralloc.h
+++ b/libs/ui/include/ui/Gralloc.h
@@ -67,6 +67,15 @@
     // unlock returns a fence sync object (or -1) and the fence sync object is
     // owned by the caller
     virtual int unlock(buffer_handle_t bufferHandle) const = 0;
+
+    // isSupported queries whether or not a buffer with the given width, height,
+    // format, layer count, and usage can be allocated on the device.  If
+    // *outSupported is set to true, a buffer with the given specifications may be successfully
+    // allocated if resources are available.  If false, a buffer with the given specifications will
+    // never successfully allocate on this device. Note that this function is not guaranteed to be
+    // supported on all devices, in which case a status_t of INVALID_OPERATION will be returned.
+    virtual status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
+                                 uint32_t layerCount, uint64_t usage, bool* outSupported) const = 0;
 };
 
 // A wrapper to IAllocator
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 4ef9b51..948f597 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -61,6 +61,9 @@
 
     int unlock(buffer_handle_t bufferHandle) const override;
 
+    status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
+                         uint32_t layerCount, uint64_t usage, bool* outSupported) const override;
+
 private:
     // Determines whether the passed info is compatible with the mapper.
     status_t validateBufferDescriptorInfo(
diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h
index 879e96e..0965f52 100644
--- a/libs/ui/include/ui/Gralloc3.h
+++ b/libs/ui/include/ui/Gralloc3.h
@@ -60,6 +60,9 @@
 
     int unlock(buffer_handle_t bufferHandle) const override;
 
+    status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
+                         uint32_t layerCount, uint64_t usage, bool* outSupported) const override;
+
 private:
     // Determines whether the passed info is compatible with the mapper.
     status_t validateBufferDescriptorInfo(
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 18a27a0..7d88c58 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -191,6 +191,9 @@
             android_ycbcr *ycbcr, int fenceFd);
     status_t unlockAsync(int *fenceFd);
 
+    status_t isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+                         uint32_t inLayerCount, uint64_t inUsage, bool* outSupported) const;
+
     ANativeWindowBuffer* getNativeBuffer() const;
 
     // for debugging
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 072926f..77c99cc 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -78,6 +78,9 @@
 
     status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
 
+    status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
+                         uint32_t layerCount, uint64_t usage, bool* outSupported);
+
     const GrallocMapper& getGrallocMapper() const {
         return reinterpret_cast<const GrallocMapper&>(*mMapper);
     }
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index b6027e6..fa39d08 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -21,16 +21,6 @@
   // a file descriptor for the new channel or a negative error code.
   Status<LocalChannelHandle> CreateConsumer();
 
-  // Locks the area specified by (x, y, width, height) for a specific usage. If
-  // the usage is software then |addr| will be updated to point to the address
-  // of the buffer in virtual memory. The caller should only access/modify the
-  // pixels in the specified area. anything else is undefined behavior.
-  int Lock(int usage, int x, int y, int width, int height, void** addr);
-
-  // Must be called after Lock() when the caller has finished changing the
-  // buffer.
-  int Unlock();
-
   // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
   // Locking and Unlocking is handled internally. There's no need to Unlock
   // after calling this method.
@@ -128,6 +118,16 @@
   int UpdateSharedFence(const LocalHandle& new_fence,
                         const LocalHandle& shared_fence);
 
+  // Locks the area specified by (x, y, width, height) for a specific usage. If
+  // the usage is software then |addr| will be updated to point to the address
+  // of the buffer in virtual memory. The caller should only access/modify the
+  // pixels in the specified area. anything else is undefined behavior.
+  int Lock(int usage, int x, int y, int width, int height, void** addr);
+
+  // Must be called after Lock() when the caller has finished changing the
+  // buffer.
+  int Unlock();
+
   // IonBuffer that is shared between bufferhubd, producer, and consumers.
   size_t metadata_buf_size_{0};
   size_t user_metadata_size_{0};
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
index 0eb7fec..7075e88 100644
--- a/libs/vr/libvrflinger/tests/vrflinger_test.cpp
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
@@ -205,9 +205,9 @@
     ASSERT_EQ(buffer.get()->height(), metrics.get().display_height);
 
     void* raw_buf = nullptr;
-    ASSERT_GE(buffer.get()->Lock(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
-                                 /*x=*/0, /*y=*/0, buffer.get()->width(),
-                                 buffer.get()->height(), &raw_buf),
+    ASSERT_GE(buffer.get()->buffer()->Lock(
+                  AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, /*x=*/0, /*y=*/0,
+                  buffer.get()->width(), buffer.get()->height(), &raw_buf),
               0);
     ASSERT_NE(raw_buf, nullptr);
     uint32_t* pixels = static_cast<uint32_t*>(raw_buf);
@@ -216,7 +216,7 @@
       pixels[i] = 0x0000ff00;
     }
 
-    ASSERT_GE(buffer.get()->Unlock(), 0);
+    ASSERT_GE(buffer.get()->buffer()->Unlock(), 0);
 
     ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle()), 0);
 
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 4c4ee06..734ed6c 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -228,24 +228,6 @@
     ],
 }
 
-cc_library_shared {
-    name: "libsurfaceflinger_ddmconnection",
-    defaults: ["surfaceflinger_defaults"],
-    srcs: ["DdmConnection.cpp"],
-    shared_libs: [
-        "libcutils",
-        "libdl",
-        "liblog",
-        "libprocessgroup",
-    ],
-    product_variables: {
-        // uses jni which may not be available in PDK
-        pdk: {
-            enabled: false,
-        },
-    },
-}
-
 subdirs = [
     "layerproto",
     "TimeStats/timestatsproto",
diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp
index c82ad7b..cb02d16 100644
--- a/services/surfaceflinger/BufferStateLayerCache.cpp
+++ b/services/surfaceflinger/BufferStateLayerCache.cpp
@@ -19,81 +19,84 @@
 #define LOG_TAG "BufferStateLayerCache"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <cinttypes>
+
 #include "BufferStateLayerCache.h"
 
-#define MAX_CACHE_SIZE 64
+#define VALID_CACHE_ID(id) ((id) >= 0 || (id) < (BUFFER_CACHE_MAX_SIZE))
 
 namespace android {
 
-int32_t BufferStateLayerCache::add(const sp<IBinder>& processToken,
-                                   const sp<GraphicBuffer>& buffer) {
-    std::lock_guard lock(mMutex);
+ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache);
 
-    auto& processCache = getProccessCache(processToken);
+BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {}
 
-    int32_t slot = findSlot(processCache);
-    if (slot < 0) {
-        return slot;
+void BufferStateLayerCache::add(sp<IBinder> processToken, int32_t id,
+                                const sp<GraphicBuffer>& buffer) {
+    if (!VALID_CACHE_ID(id)) {
+        ALOGE("failed to cache buffer: invalid buffer id");
+        return;
     }
 
-    processCache[slot] = buffer;
+    if (!processToken) {
+        ALOGE("failed to cache buffer: invalid process token");
+        return;
+    }
 
-    return slot;
-}
-
-void BufferStateLayerCache::release(const sp<IBinder>& processToken, int32_t id) {
-    if (id < 0) {
-        ALOGE("invalid buffer id");
+    if (!buffer) {
+        ALOGE("failed to cache buffer: invalid buffer");
         return;
     }
 
     std::lock_guard lock(mMutex);
-    auto& processCache = getProccessCache(processToken);
 
-    if (id >= processCache.size()) {
-        ALOGE("invalid buffer id");
-        return;
-    }
-    processCache[id] = nullptr;
-}
-
-sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, int32_t id) {
-    if (id < 0) {
-        ALOGE("invalid buffer id");
-        return nullptr;
-    }
-
-    std::lock_guard lock(mMutex);
-    auto& processCache = getProccessCache(processToken);
-
-    if (id >= processCache.size()) {
-        ALOGE("invalid buffer id");
-        return nullptr;
-    }
-    return processCache[id];
-}
-
-std::vector<sp<GraphicBuffer>>& BufferStateLayerCache::getProccessCache(
-        const sp<IBinder>& processToken) {
-    return mBuffers[processToken];
-}
-
-int32_t BufferStateLayerCache::findSlot(std::vector<sp<GraphicBuffer>>& processCache) {
-    int32_t slot = 0;
-
-    for (const sp<GraphicBuffer> buffer : processCache) {
-        if (!buffer) {
-            return slot;
+    // If this is a new process token, set a death recipient. If the client process dies, we will
+    // get a callback through binderDied.
+    if (mBuffers.find(processToken) == mBuffers.end()) {
+        status_t err = processToken->linkToDeath(mDeathRecipient);
+        if (err != NO_ERROR) {
+            ALOGE("failed to cache buffer: could not link to death");
+            return;
         }
-        slot++;
     }
 
-    if (processCache.size() < MAX_CACHE_SIZE) {
-        processCache.push_back(nullptr);
-        return slot;
+    auto& processBuffers = mBuffers[processToken];
+    processBuffers[id] = buffer;
+}
+
+sp<GraphicBuffer> BufferStateLayerCache::get(sp<IBinder> processToken, int32_t id) {
+    if (!VALID_CACHE_ID(id)) {
+        ALOGE("failed to get buffer: invalid buffer id");
+        return nullptr;
     }
 
-    return -1;
+    if (!processToken) {
+        ALOGE("failed to cache buffer: invalid process token");
+        return nullptr;
+    }
+
+    std::lock_guard lock(mMutex);
+    auto itr = mBuffers.find(processToken);
+    if (itr == mBuffers.end()) {
+        ALOGE("failed to get buffer: process token not found");
+        return nullptr;
+    }
+
+    if (id >= itr->second.size()) {
+        ALOGE("failed to get buffer: id outside the bounds of the cache");
+        return nullptr;
+    }
+
+    return itr->second[id];
+}
+
+void BufferStateLayerCache::removeProcess(const wp<IBinder>& processToken) {
+    std::lock_guard lock(mMutex);
+    mBuffers.erase(processToken);
+}
+
+void BufferStateLayerCache::CacheDeathRecipient::binderDied(const wp<IBinder>& who) {
+    BufferStateLayerCache::getInstance().removeProcess(who);
 }
 
 }; // namespace android
diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h
index 623f0c6..ede3feb 100644
--- a/services/surfaceflinger/BufferStateLayerCache.h
+++ b/services/surfaceflinger/BufferStateLayerCache.h
@@ -20,36 +20,36 @@
 #include <binder/IBinder.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/RefBase.h>
+#include <utils/Singleton.h>
 
+#include <array>
+#include <map>
 #include <mutex>
-#include <unordered_map>
-#include <vector>
+
+#define BUFFER_CACHE_MAX_SIZE 64
 
 namespace android {
 
-class BufferStateLayerCache {
+class BufferStateLayerCache : public Singleton<BufferStateLayerCache> {
 public:
-    int32_t add(const sp<IBinder>& processToken, const sp<GraphicBuffer>& buffer);
-    void release(const sp<IBinder>& processToken, int32_t id);
+    BufferStateLayerCache();
 
-    sp<GraphicBuffer> get(const sp<IBinder>& processToken, int32_t id);
+    void add(sp<IBinder> processToken, int32_t id, const sp<GraphicBuffer>& buffer);
+    sp<GraphicBuffer> get(sp<IBinder> processToken, int32_t id);
+
+    void removeProcess(const wp<IBinder>& processToken);
 
 private:
     std::mutex mMutex;
+    std::map<wp<IBinder> /*caching process*/, std::array<sp<GraphicBuffer>, BUFFER_CACHE_MAX_SIZE>>
+            mBuffers GUARDED_BY(mMutex);
 
-    std::vector<sp<GraphicBuffer>>& getProccessCache(const sp<IBinder>& processToken)
-            REQUIRES(mMutex);
-
-    int32_t findSlot(std::vector<sp<GraphicBuffer>>& proccessCache) REQUIRES(mMutex);
-
-    struct IBinderHash {
-        std::size_t operator()(const sp<IBinder>& strongPointer) const {
-            return std::hash<IBinder*>{}(strongPointer.get());
-        }
+    class CacheDeathRecipient : public IBinder::DeathRecipient {
+    public:
+        void binderDied(const wp<IBinder>& who) override;
     };
 
-    std::unordered_map<sp<IBinder> /*caching process*/, std::vector<sp<GraphicBuffer>>, IBinderHash>
-            mBuffers GUARDED_BY(mMutex);
+    sp<CacheDeathRecipient> mDeathRecipient;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
deleted file mode 100644
index 35d55f5..0000000
--- a/services/surfaceflinger/DdmConnection.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <dlfcn.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include "jni.h"
-#include "DdmConnection.h"
-
-namespace android {
-
-void DdmConnection_start(const char* name) {
-    ALOGI("DdmConnection_start");
-    DdmConnection::start(name);
-}
-
-void DdmConnection::start(const char* name) {
-    JavaVM* vm;
-    JNIEnv* env;
-
-    // start a VM
-    JavaVMInitArgs args;
-    JavaVMOption opt;
-
-    opt.optionString =
-        "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
-
-    args.version = JNI_VERSION_1_4;
-    args.options = &opt;
-    args.nOptions = 1;
-    args.ignoreUnrecognized = JNI_FALSE;
-
-
-    // TODO: Should this just link against libnativehelper and use its
-    // JNI_CreateJavaVM wrapper that essential does this dlopen/dlsym
-    // work based on the current system default runtime?
-    void* libart_dso = dlopen("libart.so", RTLD_NOW);
-    ALOGE_IF(!libart_dso, "DdmConnection: %s", dlerror());
-
-    void* libandroid_runtime_dso = dlopen("libandroid_runtime.so", RTLD_NOW);
-    ALOGE_IF(!libandroid_runtime_dso, "DdmConnection: %s", dlerror());
-
-    if (!libart_dso || !libandroid_runtime_dso) {
-        goto error;
-    }
-
-    jint (*JNI_CreateJavaVM)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
-    JNI_CreateJavaVM = reinterpret_cast<decltype(JNI_CreateJavaVM)>(
-            dlsym(libart_dso, "JNI_CreateJavaVM"));
-    ALOGE_IF(!JNI_CreateJavaVM, "DdmConnection: %s", dlerror());
-
-    jint (*registerNatives)(JNIEnv* env, jclass clazz);
-    registerNatives = reinterpret_cast<decltype(registerNatives)>(
-            dlsym(libandroid_runtime_dso,
-                "Java_com_android_internal_util_WithFramework_registerNatives"));
-    ALOGE_IF(!registerNatives, "DdmConnection: %s", dlerror());
-
-    if (!JNI_CreateJavaVM || !registerNatives) {
-        goto error;
-    }
-
-    if (JNI_CreateJavaVM(&vm, &env, &args) == 0) {
-        jclass startClass;
-        jmethodID startMeth;
-
-        // register native code
-        if (registerNatives(env, 0) == 0) {
-            // set our name by calling DdmHandleAppName.setAppName()
-            startClass = env->FindClass("android/ddm/DdmHandleAppName");
-            if (startClass) {
-                startMeth = env->GetStaticMethodID(startClass,
-                        "setAppName", "(Ljava/lang/String;I)V");
-                if (startMeth) {
-                    jstring str = env->NewStringUTF(name);
-                    env->CallStaticVoidMethod(startClass, startMeth, str, getuid());
-                    env->DeleteLocalRef(str);
-                }
-            }
-
-            // initialize DDMS communication by calling
-            // DdmRegister.registerHandlers()
-            startClass = env->FindClass("android/ddm/DdmRegister");
-            if (startClass) {
-                startMeth = env->GetStaticMethodID(startClass,
-                        "registerHandlers", "()V");
-                if (startMeth) {
-                    env->CallStaticVoidMethod(startClass, startMeth);
-                }
-            }
-        }
-    }
-    return;
-
-error:
-    if (libandroid_runtime_dso) {
-        dlclose(libandroid_runtime_dso);
-    }
-    if (libart_dso) {
-        dlclose(libart_dso);
-    }
-}
-
-}; // namespace android
diff --git a/services/surfaceflinger/DdmConnection.h b/services/surfaceflinger/DdmConnection.h
deleted file mode 100644
index 938d14b..0000000
--- a/services/surfaceflinger/DdmConnection.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_DDM_CONNECTION
-#define ANDROID_SF_DDM_CONNECTION
-
-namespace android {
-
-// wrapper for dlsym
-extern "C" void DdmConnection_start(const char* name);
-
-class DdmConnection {
-public:
-    // Creates a JVM and registers all handlers to DDMS.
-    // This allows tools relying on DDMS to find surfaceflinger
-    // (e.g: Memory Leak finder, heap analyzer, ...)
-    static void start(const char* name);
-};
-
-}; // namespace android
-
-#endif /* ANDROID_SF_DDM_CONNECTION */
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 96496f0..d54a1d5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -78,7 +78,6 @@
 #include "ColorLayer.h"
 #include "Colorizer.h"
 #include "ContainerLayer.h"
-#include "DdmConnection.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
 #include "LayerVector.h"
@@ -279,7 +278,6 @@
         mAnimCompositionPending(false),
         mBootStage(BootStage::BOOTLOADER),
         mDebugRegion(0),
-        mDebugDDMS(0),
         mDebugDisableHWC(0),
         mDebugDisableTransformHint(0),
         mDebugInTransaction(0),
@@ -370,16 +368,12 @@
     property_get("debug.sf.showupdates", value, "0");
     mDebugRegion = atoi(value);
 
-    property_get("debug.sf.ddms", value, "0");
-    mDebugDDMS = atoi(value);
-    if (mDebugDDMS) {
-        if (!startDdmConnection()) {
-            // start failed, and DDMS debugging not enabled
-            mDebugDDMS = 0;
-        }
-    }
     ALOGI_IF(mDebugRegion, "showupdates enabled");
-    ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+    // DDMS debugging deprecated (b/120782499)
+    property_get("debug.sf.ddms", value, "0");
+    int debugDdms = atoi(value);
+    ALOGI_IF(debugDdms, "DDMS debugging not supported");
 
     property_get("debug.sf.disable_backpressure", value, "0");
     mPropagateBackpressure = !atoi(value);
@@ -1165,20 +1159,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
-                                     int32_t* outBufferId) {
-    if (!outBufferId) {
-        return BAD_VALUE;
-    }
-    *outBufferId = mBufferStateLayerCache.add(token, buffer);
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) {
-    mBufferStateLayerCache.release(token, bufferId);
-    return NO_ERROR;
-}
-
 status_t SurfaceFlinger::isWideColorDisplay(const sp<IBinder>& displayToken,
                                             bool* outIsWideColorDisplay) const {
     if (!displayToken || !outIsWideColorDisplay) {
@@ -2356,10 +2336,12 @@
                 break;
             case Dataspace::BT2020_PQ:
             case Dataspace::BT2020_ITU_PQ:
+                bestDataSpace = Dataspace::DISPLAY_P3;
                 *outHdrDataSpace = Dataspace::BT2020_PQ;
                 break;
             case Dataspace::BT2020_HLG:
             case Dataspace::BT2020_ITU_HLG:
+                bestDataSpace = Dataspace::DISPLAY_P3;
                 // When there's mixed PQ content and HLG content, we set the HDR
                 // data space to be BT2020_PQ and convert HLG to PQ.
                 if (*outHdrDataSpace == Dataspace::UNKNOWN) {
@@ -4005,9 +3987,6 @@
     if (what & layer_state_t::eFrameChanged) {
         if (layer->setFrame(s.frame)) flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eBufferChanged) {
-        if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded;
-    }
     if (what & layer_state_t::eAcquireFenceChanged) {
         if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded;
     }
@@ -4044,9 +4023,16 @@
             callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
         }
     }
+
+    if (what & layer_state_t::eBufferChanged) {
+        // Add the new buffer to the cache. This should always come before eCachedBufferChanged.
+        BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.bufferId,
+                                                 s.buffer);
+    }
     if (what & layer_state_t::eCachedBufferChanged) {
         sp<GraphicBuffer> buffer =
-                mBufferStateLayerCache.get(s.cachedBuffer.token, s.cachedBuffer.bufferId);
+                BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
+                                                         s.cachedBuffer.bufferId);
         if (layer->setBuffer(buffer)) flags |= eTraversalNeeded;
     }
     if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded;
@@ -4945,24 +4931,6 @@
     return empty;
 }
 
-bool SurfaceFlinger::startDdmConnection()
-{
-    void* libddmconnection_dso =
-            dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
-    if (!libddmconnection_dso) {
-        return false;
-    }
-    void (*DdmConnection_start)(const char* name);
-    DdmConnection_start =
-            (decltype(DdmConnection_start))dlsym(libddmconnection_dso, "DdmConnection_start");
-    if (!DdmConnection_start) {
-        dlclose(libddmconnection_dso);
-        return false;
-    }
-    (*DdmConnection_start)(getServiceName());
-    return true;
-}
-
 void SurfaceFlinger::updateColorMatrixLocked() {
     mat4 colorMatrix;
     if (mGlobalSaturationFactor != 1.0f) {
@@ -5046,8 +5014,6 @@
         case GET_COLOR_MANAGEMENT:
         case GET_COMPOSITION_PREFERENCE:
         case GET_PROTECTED_CONTENT_SUPPORT:
-        case CACHE_BUFFER:
-        case UNCACHE_BUFFER:
         case IS_WIDE_COLOR_DISPLAY: {
             return OK;
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d108ad1..a127550 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -467,9 +467,6 @@
                                        uint64_t timestamp,
                                        DisplayedFrameStats* outStats) const override;
     status_t getProtectedContentSupport(bool* outSupported) const override;
-    status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
-                         int32_t* outBufferId) override;
-    status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) override;
     status_t isWideColorDisplay(const sp<IBinder>& displayToken,
                                 bool* outIsWideColorDisplay) const override;
 
@@ -831,8 +828,6 @@
     /*
      * Debugging & dumpsys
      */
-    bool startDdmConnection();
-
     using DumpArgs = Vector<String16>;
     using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
 
@@ -984,7 +979,6 @@
 
     // don't use a lock for these, we don't care
     int mDebugRegion;
-    int mDebugDDMS;
     int mDebugDisableHWC;
     int mDebugDisableTransformHint;
     volatile nsecs_t mDebugInSwapBuffers;
@@ -1092,8 +1086,6 @@
 
     InputWindowCommands mInputWindowCommands;
 
-    BufferStateLayerCache mBufferStateLayerCache;
-
     ui::DisplayPrimaries mInternalDisplayPrimaries;
 };
 }; // namespace android
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4f0ded3..1ae7008 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1625,7 +1625,7 @@
     bool bufferFill = true;
     float alpha = 1.0f;
     Color finalColor = Color::RED;
-    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
                                                      priorColor, bufferFill, alpha, finalColor));
 }
 
@@ -1635,7 +1635,7 @@
     bool bufferFill = false;
     float alpha = 1.0f;
     Color finalColor = Color::GREEN;
-    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
                                                      priorColor, bufferFill, alpha, finalColor));
 }
 
@@ -1645,7 +1645,7 @@
     bool bufferFill = false;
     float alpha = 1.0f;
     Color finalColor = Color::GREEN;
-    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
                                                      priorColor, bufferFill, alpha, finalColor));
 }
 
@@ -1655,7 +1655,7 @@
     bool bufferFill = false;
     float alpha = 0;
     Color finalColor = Color::BLACK;
-    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
                                                      priorColor, bufferFill, alpha, finalColor));
 }
 
@@ -1665,7 +1665,7 @@
     bool bufferFill = false;
     float alpha = 0;
     Color finalColor = Color::BLACK;
-    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
                                                      priorColor, bufferFill, alpha, finalColor));
 }
 
@@ -2405,6 +2405,117 @@
     }
 }
 
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+    std::array<sp<GraphicBuffer>, 10> buffers;
+
+    size_t idx = 0;
+    for (auto& buffer : buffers) {
+        buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                                   BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                           BufferUsage::COMPOSER_OVERLAY,
+                                   "test");
+        Color color = colors[idx % colors.size()];
+        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        idx++;
+    }
+
+    // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+    // cache is working.
+    idx = 0;
+    for (auto& buffer : buffers) {
+        for (int i = 0; i < 2; i++) {
+            Transaction().setBuffer(layer, buffer).apply();
+
+            Color color = colors[idx % colors.size()];
+            auto shot = screenshot();
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+        }
+        idx++;
+    }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_BufferState) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+    std::array<sp<GraphicBuffer>, 70> buffers;
+
+    size_t idx = 0;
+    for (auto& buffer : buffers) {
+        buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                                   BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                           BufferUsage::COMPOSER_OVERLAY,
+                                   "test");
+        Color color = colors[idx % colors.size()];
+        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        idx++;
+    }
+
+    // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+    // cache is working.
+    idx = 0;
+    for (auto& buffer : buffers) {
+        for (int i = 0; i < 2; i++) {
+            Transaction().setBuffer(layer, buffer).apply();
+
+            Color color = colors[idx % colors.size()];
+            auto shot = screenshot();
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+        }
+        idx++;
+    }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferState) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+    std::array<sp<GraphicBuffer>, 65> buffers;
+
+    size_t idx = 0;
+    for (auto& buffer : buffers) {
+        buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                                   BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                           BufferUsage::COMPOSER_OVERLAY,
+                                   "test");
+        Color color = colors[idx % colors.size()];
+        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        idx++;
+    }
+
+    // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+    // cache is working.
+    idx = 0;
+    for (auto& buffer : buffers) {
+        for (int i = 0; i < 2; i++) {
+            Transaction().setBuffer(layer, buffer).apply();
+
+            Color color = colors[idx % colors.size()];
+            auto shot = screenshot();
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+        }
+        if (idx == 0) {
+            buffers[0].clear();
+        }
+        idx++;
+    }
+}
+
 TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
@@ -2623,143 +2734,6 @@
     Transaction().setSidebandStream(layer, nullptr).apply();
 }
 
-TEST_F(LayerTransactionTest, CacheBuffer_BufferState) {
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY,
-                              "test");
-
-    int32_t bufferId = -1;
-    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
-    ASSERT_GE(bufferId, 0);
-
-    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
-}
-
-TEST_F(LayerTransactionTest, CacheBuffers_BufferState) {
-    std::vector<int32_t> bufferIds;
-    int32_t bufferCount = 20;
-
-    for (int i = 0; i < bufferCount; i++) {
-        sp<GraphicBuffer> buffer =
-                new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                                  BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                          BufferUsage::COMPOSER_OVERLAY,
-                                  "test");
-        int32_t bufferId = -1;
-        ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
-        if (bufferId < 0) {
-            EXPECT_GE(bufferId, 0);
-            break;
-        }
-        bufferIds.push_back(bufferId);
-    }
-
-    for (int32_t bufferId : bufferIds) {
-        ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
-    }
-}
-
-TEST_F(LayerTransactionTest, CacheBufferInvalid_BufferState) {
-    sp<GraphicBuffer> buffer = nullptr;
-
-    int32_t bufferId = -1;
-    ASSERT_NE(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
-    ASSERT_LT(bufferId, 0);
-}
-
-TEST_F(LayerTransactionTest, UncacheBufferTwice_BufferState) {
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY,
-                              "test");
-
-    int32_t bufferId = -1;
-    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
-    ASSERT_GE(bufferId, 0);
-
-    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
-    mClient->uncacheBuffer(bufferId);
-}
-
-TEST_F(LayerTransactionTest, UncacheBufferInvalidId_BufferState) {
-    mClient->uncacheBuffer(-1);
-    mClient->uncacheBuffer(0);
-    mClient->uncacheBuffer(1);
-    mClient->uncacheBuffer(5);
-    mClient->uncacheBuffer(1000);
-}
-
-TEST_F(LayerTransactionTest, SetCachedBuffer_BufferState) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY,
-                              "test");
-
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
-    int32_t bufferId = -1;
-    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
-    ASSERT_GE(bufferId, 0);
-
-    Transaction().setCachedBuffer(layer, bufferId).apply();
-
-    auto shot = screenshot();
-    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-
-    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
-}
-
-TEST_F(LayerTransactionTest, SetCachedBufferDelayed_BufferState) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
-    sp<GraphicBuffer> cachedBuffer =
-            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY,
-                              "test");
-    int32_t bufferId = -1;
-    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(cachedBuffer, &bufferId));
-    ASSERT_GE(bufferId, 0);
-
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY,
-                              "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::BLUE);
-    Transaction().setBuffer(layer, buffer).apply();
-    {
-        SCOPED_TRACE("Uncached buffer");
-
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
-
-    fillGraphicBufferColor(cachedBuffer, Rect(0, 0, 32, 32), Color::RED);
-    Transaction().setCachedBuffer(layer, bufferId).apply();
-    {
-        SCOPED_TRACE("Cached buffer");
-
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
-
-    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
-}
-
 TEST_F(LayerTransactionTest, ReparentToSelf) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ab9aadc..e092aed 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -95,6 +95,7 @@
         EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
         EXPECT_CALL(*mPrimaryDispSync, getPeriod())
                 .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+        EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
@@ -238,16 +239,23 @@
     static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
 
     static void setupPreconditions(CompositionTest* test) {
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                                Return(Error::NONE)));
 
         FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical,
                                true /* isPrimary */)
                 .setCapabilities(&test->mDefaultCapabilities)
                 .inject(&test->mFlinger, test->mComposer);
+        Mock::VerifyAndClear(test->mComposer);
 
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
         test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
                                                    false /* isVirtual */, true /* isPrimary */)
                                  .setDisplaySurface(test->mDisplaySurface)
@@ -255,6 +263,7 @@
                                  .setSecure(Derived::IS_SECURE)
                                  .setPowerMode(Derived::INIT_POWER_MODE)
                                  .inject();
+        Mock::VerifyAndClear(test->mNativeWindow);
         test->mDisplay->setLayerStack(DEFAULT_LAYER_STACK);
     }
 
@@ -405,6 +414,8 @@
 
     template <typename Case>
     static void setupCommonCompositionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
+
         // TODO: This seems like an unnecessary call if display is powered off.
         EXPECT_CALL(*test->mComposer,
                     setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
@@ -417,6 +428,8 @@
     static void setupHwcCompositionCallExpectations(CompositionTest*) {}
 
     static void setupRECompositionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
+
         // TODO: This seems like an unnecessary call if display is powered off.
         EXPECT_CALL(*test->mDisplaySurface, getClientTargetAcquireFence())
                 .WillRepeatedly(ReturnRef(test->mClientTargetAcquireFence));
@@ -575,7 +588,6 @@
                     setLayerColor(HWC_DISPLAY, HWC_LAYER,
                                   IComposerClient::Color({0xff, 0xff, 0xff, 0xff})))
                 .Times(1);
-
     }
 
     static void setupHwcSetPerFrameBufferCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 4cb79ab..b7464d2 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -335,11 +335,17 @@
         injector.setNativeWindow(test->mNativeWindow);
 
         // Creating a DisplayDevice requires getting default dimensions from the
-        // native window.
+        // native window along with some other initial setup.
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
+                .WillRepeatedly(Return(0));
         return injector;
     }
 
@@ -352,6 +358,12 @@
                 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
+                .WillRepeatedly(Return(0));
     }
 
     static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
@@ -389,7 +401,7 @@
     }
 
     // Called by tests to inject a HWC display setup
-    static void injectHwcDisplay(DisplayTransactionTest* test) {
+    static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
         const auto displayId = DisplayVariant::DISPLAY_ID::get();
         ASSERT_TRUE(displayId);
         FakeHwcDisplayInjector(*displayId, HWC_DISPLAY_TYPE,
@@ -401,6 +413,14 @@
                 .inject(&test->mFlinger, test->mComposer);
     }
 
+    // Called by tests to inject a HWC display setup
+    static void injectHwcDisplay(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                                Return(Error::NONE)));
+        injectHwcDisplayWithNoDefaultCapabilities(test);
+    }
+
     static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
         EXPECT_CALL(*test->mComposer, getDisplayType(HWC_DISPLAY_ID, _))
                 .WillOnce(DoAll(SetArgPointee<1>(static_cast<IComposerClient::DisplayType>(
@@ -430,6 +450,9 @@
                     getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
                                         IComposerClient::Attribute::DPI_Y, _))
                 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                                Return(Error::NONE)));
 
         if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
             EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
@@ -482,6 +505,8 @@
 
 struct TertiaryDisplay {
     static constexpr Primary PRIMARY = Primary::FALSE;
+    static constexpr uint8_t PORT = 253;
+    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
 };
 
 // A primary display is a physical display that is critical
@@ -577,6 +602,8 @@
     }
 
     static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_DATASPACE)).Times(1);
+
         EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>({ColorMode::DISPLAY_P3})),
                                 Return(Error::NONE)));
@@ -1156,9 +1183,9 @@
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1080 /* arbitrary */), Return(0)));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1920 /* arbitrary */), Return(0)));
-        EXPECT_CALL(*mNativeWindow, perform(9)).Times(1);
-        EXPECT_CALL(*mNativeWindow, perform(13)).Times(1);
-        EXPECT_CALL(*mNativeWindow, perform(30)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
         auto displayDevice = mInjector.inject();
 
         displayDevice->getCompositionDisplay()
@@ -1705,6 +1732,13 @@
     PrimaryDisplayVariant::injectHwcDisplay(this);
     ExternalDisplayVariant::injectHwcDisplay(this);
 
+    // TODO: This is an unnecessary call.
+    EXPECT_CALL(*mComposer,
+                getDisplayIdentificationData(TertiaryDisplayVariant::HWC_DISPLAY_ID, _, _))
+            .WillOnce(DoAll(SetArgPointee<1>(TertiaryDisplay::PORT),
+                            SetArgPointee<2>(TertiaryDisplay::GET_IDENTIFICATION_DATA()),
+                            Return(Error::NONE)));
+
     EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
 
     ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
@@ -1852,6 +1886,10 @@
     Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
     Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
 
+    EXPECT_CALL(*mComposer, getDisplayCapabilities(Case::Display::HWC_DISPLAY_ID, _))
+            .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                            Return(Error::NONE)));
+
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
             .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
@@ -1864,6 +1902,7 @@
 
     EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
 
+    EXPECT_CALL(*mProducer, connect(_, NATIVE_WINDOW_API_EGL, false, _)).Times(1);
     EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
 
     Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -2096,9 +2135,9 @@
             .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
     EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
             .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(9)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(30)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -2140,9 +2179,9 @@
             .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
     EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
             .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(9)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(30)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -2656,6 +2695,8 @@
     // processing.
     EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
 
+    EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+
     // --------------------------------------------------------------------
     // Invocation
 
@@ -2950,7 +2991,7 @@
     using Transition = TransitionVariant;
 
     static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, int mode) {
-        Display::injectHwcDisplay(test);
+        Display::injectHwcDisplayWithNoDefaultCapabilities(test);
         auto display = Display::makeFakeExistingDisplayInjector(test);
         display.inject();
         display.mutableDisplayDevice()->setPowerMode(mode);
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 8601373..47334f6 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -416,7 +416,7 @@
         case VK_FORMAT_R16G16B16A16_SFLOAT:
             native_format = HAL_PIXEL_FORMAT_RGBA_FP16;
             break;
-        case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+        case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
             native_format = HAL_PIXEL_FORMAT_RGBA_1010102;
             break;
         default:
@@ -570,6 +570,7 @@
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGB_565:
         case HAL_PIXEL_FORMAT_RGBA_FP16:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
             format_supported = true;
             break;
         default:
@@ -700,6 +701,8 @@
          VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT},
         {VK_FORMAT_R16G16B16A16_SFLOAT,
          VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT},
+        {VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+         VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
     };
     const uint32_t kNumWideColorFormats =
         sizeof(kWideColorFormats) / sizeof(kWideColorFormats[0]);