Merge "Mark Layer as modified when changing zOrderRelativeOf."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index bd3d2d8..5836f11 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -193,10 +193,12 @@
         { REQ,      "events/cpufreq_interactive/enable" },
     } },
     { "sync",       "Synchronization",  0, {
-        // before linux kernel 4.9
+        // linux kernel < 4.9
         { OPT,      "events/sync/enable" },
-        // starting in linux kernel 4.9
+        // linux kernel == 4.9.x
         { OPT,      "events/fence/enable" },
+        // linux kernel > 4.9
+        { OPT,      "events/dma_fence/enable" },
     } },
     { "workq",      "Kernel Workqueues", 0, {
         { REQ,      "events/workqueue/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index a282424..66c9cc6 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -91,6 +91,8 @@
     chmod 0666 /sys/kernel/tracing/events/sync/enable
     chmod 0666 /sys/kernel/debug/tracing/events/fence/enable
     chmod 0666 /sys/kernel/tracing/events/fence/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/dma_fence/enable
+    chmod 0666 /sys/kernel/tracing/events/dma_fence/enable
     chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/enable
     chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/enable
     chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow/enable
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 5b66b92..ccde12a 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -54,4 +54,9 @@
 
     long getVersionCodeForPackage(in String packageName);
 
+    /**
+     * Return if each app, identified by its package name allows its audio to be recorded.
+     * Unknown packages are mapped to false.
+     */
+    boolean[] isAudioPlaybackCaptureAllowed(in @utf8InCpp String[] packageNames);
 }
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index d940752..0571dcc 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -16,6 +16,7 @@
     name: "libgraphicsenv",
 
     srcs: [
+        "GpuStatsInfo.cpp",
         "GraphicsEnv.cpp",
         "IGpuService.cpp"
     ],
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
new file mode 100644
index 0000000..0fa0d9e
--- /dev/null
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2019 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 <inttypes.h>
+
+#include <android-base/stringprintf.h>
+#include <binder/Parcel.h>
+#include <graphicsenv/GpuStatsInfo.h>
+
+namespace android {
+
+using base::StringAppendF;
+
+status_t GpuStatsGlobalInfo::writeToParcel(Parcel* parcel) const {
+    status_t status;
+    if ((status = parcel->writeUtf8AsUtf16(driverPackageName)) != OK) return status;
+    if ((status = parcel->writeUtf8AsUtf16(driverVersionName)) != OK) return status;
+    if ((status = parcel->writeUint64(driverVersionCode)) != OK) return status;
+    if ((status = parcel->writeInt64(driverBuildTime)) != OK) return status;
+    if ((status = parcel->writeInt32(glLoadingCount)) != OK) return status;
+    if ((status = parcel->writeInt32(glLoadingFailureCount)) != OK) return status;
+    if ((status = parcel->writeInt32(vkLoadingCount)) != OK) return status;
+    if ((status = parcel->writeInt32(vkLoadingFailureCount)) != OK) return status;
+    return OK;
+}
+
+status_t GpuStatsGlobalInfo::readFromParcel(const Parcel* parcel) {
+    status_t status;
+    if ((status = parcel->readUtf8FromUtf16(&driverPackageName)) != OK) return status;
+    if ((status = parcel->readUtf8FromUtf16(&driverVersionName)) != OK) return status;
+    if ((status = parcel->readUint64(&driverVersionCode)) != OK) return status;
+    if ((status = parcel->readInt64(&driverBuildTime)) != OK) return status;
+    if ((status = parcel->readInt32(&glLoadingCount)) != OK) return status;
+    if ((status = parcel->readInt32(&glLoadingFailureCount)) != OK) return status;
+    if ((status = parcel->readInt32(&vkLoadingCount)) != OK) return status;
+    if ((status = parcel->readInt32(&vkLoadingFailureCount)) != OK) return status;
+    return OK;
+}
+
+std::string GpuStatsGlobalInfo::toString() const {
+    std::string result;
+    StringAppendF(&result, "driverPackageName = %s\n", driverPackageName.c_str());
+    StringAppendF(&result, "driverVersionName = %s\n", driverVersionName.c_str());
+    StringAppendF(&result, "driverVersionCode = %" PRIu64 "\n", driverVersionCode);
+    StringAppendF(&result, "driverBuildTime = %" PRId64 "\n", driverBuildTime);
+    StringAppendF(&result, "glLoadingCount = %d\n", glLoadingCount);
+    StringAppendF(&result, "glLoadingFailureCount = %d\n", glLoadingFailureCount);
+    StringAppendF(&result, "vkLoadingCount = %d\n", vkLoadingCount);
+    StringAppendF(&result, "vkLoadingFailureCount = %d\n", vkLoadingFailureCount);
+    return result;
+}
+
+status_t GpuStatsAppInfo::writeToParcel(Parcel* parcel) const {
+    status_t status;
+    if ((status = parcel->writeUtf8AsUtf16(appPackageName)) != OK) return status;
+    if ((status = parcel->writeUint64(driverVersionCode)) != OK) return status;
+    if ((status = parcel->writeInt64Vector(glDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->writeInt64Vector(vkDriverLoadingTime)) != OK) return status;
+    return OK;
+}
+
+status_t GpuStatsAppInfo::readFromParcel(const Parcel* parcel) {
+    status_t status;
+    if ((status = parcel->readUtf8FromUtf16(&appPackageName)) != OK) return status;
+    if ((status = parcel->readUint64(&driverVersionCode)) != OK) return status;
+    if ((status = parcel->readInt64Vector(&glDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->readInt64Vector(&vkDriverLoadingTime)) != OK) return status;
+    return OK;
+}
+
+std::string GpuStatsAppInfo::toString() const {
+    std::string result;
+    StringAppendF(&result, "appPackageName = %s\n", appPackageName.c_str());
+    StringAppendF(&result, "driverVersionCode = %" PRIu64 "\n", driverVersionCode);
+    result.append("glDriverLoadingTime:");
+    for (int32_t loadingTime : glDriverLoadingTime) {
+        StringAppendF(&result, " %d", loadingTime);
+    }
+    result.append("\n");
+    result.append("vkDriverLoadingTime:");
+    for (int32_t loadingTime : vkDriverLoadingTime) {
+        StringAppendF(&result, " %d", loadingTime);
+    }
+    result.append("\n");
+    return result;
+}
+
+} // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h b/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h
deleted file mode 100644
index f8b0ad7..0000000
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#pragma once
-
-#include <string>
-#include <vector>
-
-namespace android {
-
-struct GpuStatsGlobalAtom {
-    std::string driverPackageName = "";
-    std::string driverVersionName = "";
-    uint64_t driverVersionCode = 0;
-    int64_t driverBuildTime = 0;
-    int32_t glLoadingCount = 0;
-    int32_t glLoadingFailureCount = 0;
-    int32_t vkLoadingCount = 0;
-    int32_t vkLoadingFailureCount = 0;
-};
-
-struct GpuStatsAppAtom {
-    std::string appPackageName = "";
-    uint64_t driverVersionCode = 0;
-    std::vector<int64_t> glDriverLoadingTime = {};
-    std::vector<int64_t> vkDriverLoadingTime = {};
-};
-
-} // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
new file mode 100644
index 0000000..a92ca70
--- /dev/null
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+/*
+ * class for transporting gpu global stats from GpuService to authorized
+ * recipents. This class is intended to be a data container.
+ */
+class GpuStatsGlobalInfo : public Parcelable {
+public:
+    GpuStatsGlobalInfo() = default;
+    GpuStatsGlobalInfo(const GpuStatsGlobalInfo&) = default;
+    virtual ~GpuStatsGlobalInfo() = default;
+    virtual status_t writeToParcel(Parcel* parcel) const;
+    virtual status_t readFromParcel(const Parcel* parcel);
+    std::string toString() const;
+
+    std::string driverPackageName = "";
+    std::string driverVersionName = "";
+    uint64_t driverVersionCode = 0;
+    int64_t driverBuildTime = 0;
+    int32_t glLoadingCount = 0;
+    int32_t glLoadingFailureCount = 0;
+    int32_t vkLoadingCount = 0;
+    int32_t vkLoadingFailureCount = 0;
+};
+
+/*
+ * class for transporting gpu app stats from GpuService to authorized recipents.
+ * This class is intended to be a data container.
+ */
+class GpuStatsAppInfo : public Parcelable {
+public:
+    GpuStatsAppInfo() = default;
+    GpuStatsAppInfo(const GpuStatsAppInfo&) = default;
+    virtual ~GpuStatsAppInfo() = default;
+    virtual status_t writeToParcel(Parcel* parcel) const;
+    virtual status_t readFromParcel(const Parcel* parcel);
+    std::string toString() const;
+
+    std::string appPackageName = "";
+    uint64_t driverVersionCode = 0;
+    std::vector<int64_t> glDriverLoadingTime = {};
+    std::vector<int64_t> vkDriverLoadingTime = {};
+};
+
+} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index d2f2539..400daf0 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -792,18 +792,18 @@
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
-            ALOGE("addRegionSamplingListener: Failed to write interface token");
+            ALOGE("removeRegionSamplingListener: Failed to write interface token");
             return error;
         }
         error = data.writeStrongBinder(IInterface::asBinder(listener));
         if (error != NO_ERROR) {
-            ALOGE("addRegionSamplingListener: Failed to write listener");
+            ALOGE("removeRegionSamplingListener: Failed to write listener");
             return error;
         }
         error = remote()->transact(BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER, data,
                                    &reply);
         if (error != NO_ERROR) {
-            ALOGE("addRegionSamplingListener: Failed to transact");
+            ALOGE("removeRegionSamplingListener: Failed to transact");
         }
         return error;
     }
@@ -833,6 +833,33 @@
         }
         return reply.readInt32();
     }
+
+    virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+                                              std::vector<int32_t>* outAllowedConfigs) {
+        if (!outAllowedConfigs) return BAD_VALUE;
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getAllowedDisplayConfigs failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(displayToken);
+        if (result != NO_ERROR) {
+            ALOGE("getAllowedDisplayConfigs failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_ALLOWED_DISPLAY_CONFIGS, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getAllowedDisplayConfigs failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32Vector(outAllowedConfigs);
+        if (result != NO_ERROR) {
+            ALOGE("getAllowedDisplayConfigs failed to readInt32Vector: %d", result);
+            return result;
+        }
+        return reply.readInt32();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -1354,6 +1381,15 @@
             reply->writeInt32(result);
             return result;
         }
+        case GET_ALLOWED_DISPLAY_CONFIGS: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> displayToken = data.readStrongBinder();
+            std::vector<int32_t> allowedConfigs;
+            status_t result = getAllowedDisplayConfigs(displayToken, &allowedConfigs);
+            reply->writeInt32Vector(allowedConfigs);
+            reply->writeInt32(result);
+            return result;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d583e6d..050ba87 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -189,7 +189,7 @@
 }
 
 void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
-    std::lock_guard lock(mMutex);
+    std::lock_guard<std::mutex> lock(mMutex);
 
     /* This listener knows all the sp<IBinder> to sp<SurfaceControl> for all its registered
      * callbackIds, except for when Transactions are merged together. This probably cannot be
@@ -242,7 +242,7 @@
     }
 
     int32_t getId(const sp<GraphicBuffer>& buffer) {
-        std::lock_guard lock(mMutex);
+        std::lock_guard<std::mutex> lock(mMutex);
 
         auto itr = mBuffers.find(buffer);
         if (itr == mBuffers.end()) {
@@ -253,7 +253,7 @@
     }
 
     int32_t cache(const sp<GraphicBuffer>& buffer) {
-        std::lock_guard lock(mMutex);
+        std::lock_guard<std::mutex> lock(mMutex);
 
         int32_t bufferId = getNextAvailableId();
 
@@ -1388,6 +1388,12 @@
                                                                            allowedConfigs);
 }
 
+status_t SurfaceComposerClient::getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+                                                         std::vector<int32_t>* outAllowedConfigs) {
+    return ComposerService::getComposerService()->getAllowedDisplayConfigs(displayToken,
+                                                                           outAllowedConfigs);
+}
+
 status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
         Vector<ColorMode>* outColorModes) {
     return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index eedd5f5..0e576ca 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -368,6 +368,14 @@
      */
     virtual status_t setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                               const std::vector<int32_t>& allowedConfigs) = 0;
+
+    /*
+     * Returns the allowed display configurations currently set.
+     * The allowedConfigs in a vector of indexes corresponding to the configurations
+     * returned from getDisplayConfigs().
+     */
+    virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+                                              std::vector<int32_t>* outAllowedConfigs) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -416,6 +424,7 @@
         ADD_REGION_SAMPLING_LISTENER,
         REMOVE_REGION_SAMPLING_LISTENER,
         SET_ALLOWED_DISPLAY_CONFIGS,
+        GET_ALLOWED_DISPLAY_CONFIGS,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 4621a34..e062339 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -117,6 +117,12 @@
     static status_t setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                              const std::vector<int32_t>& allowedConfigs);
 
+    // Returns the allowed display configurations currently set.
+    // The allowedConfigs in a vector of indexes corresponding to the configurations
+    // returned from getDisplayConfigs().
+    static status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+                                             std::vector<int32_t>* outAllowedConfigs);
+
     // Gets the list of supported color modes for the given display
     static status_t getDisplayColorModes(const sp<IBinder>& display,
             Vector<ui::ColorMode>* outColorModes);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 7f1dc84..a7599e0 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -683,6 +683,10 @@
                                       const std::vector<int32_t>& /*allowedConfigs*/) override {
         return NO_ERROR;
     }
+    status_t getAllowedDisplayConfigs(const sp<IBinder>& /*displayToken*/,
+                                      std::vector<int32_t>* /*outAllowedConfigs*/) override {
+        return NO_ERROR;
+    }
 
 protected:
     IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 5d0aa1e..8069a1a 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -626,22 +626,13 @@
 }
 
 status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
-                                                     sp<Fence> bufferFence, bool readCache) {
-    return bindExternalTextureBuffer(texName, buffer, bufferFence, readCache,
-                                     /*persistCache=*/false);
-}
-
-status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
-                                                     sp<Fence> bufferFence, bool readCache,
-                                                     bool persistCache) {
+                                                     sp<Fence> bufferFence) {
     ATRACE_CALL();
-    if (readCache) {
-        auto cachedImage = mImageCache.find(buffer->getId());
+    auto cachedImage = mImageCache.find(buffer->getId());
 
-        if (cachedImage != mImageCache.end()) {
-            bindExternalTextureImage(texName, *cachedImage->second);
-            return NO_ERROR;
-        }
+    if (cachedImage != mImageCache.end()) {
+        bindExternalTextureImage(texName, *cachedImage->second);
+        return NO_ERROR;
     }
 
     std::unique_ptr<Image> newImage = createImage();
@@ -678,35 +669,19 @@
             }
         }
     }
-
-    // We don't always want to persist to the cache, e.g. on older devices we
-    // might bind for synchronization purposes, but that might leak if we never
-    // call drawLayers again, so it's just better to recreate the image again
-    // if needed when we draw.
-    if (persistCache) {
-        mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
-    }
+    mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
 
     return NO_ERROR;
 }
 
-void GLESRenderEngine::evictImages(const std::vector<LayerSettings>& layers) {
-    ATRACE_CALL();
-    // destroy old image references that we're not going to draw with.
-    std::unordered_set<uint64_t> bufIds;
-    for (auto layer : layers) {
-        if (layer.source.buffer.buffer != nullptr) {
-            bufIds.emplace(layer.source.buffer.buffer->getId());
-        }
+void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
+    const auto& cachedImage = mImageCache.find(bufferId);
+    if (cachedImage != mImageCache.end()) {
+        ALOGV("Destroying image for buffer: %" PRIu64, bufferId);
+        mImageCache.erase(bufferId);
+        return;
     }
-
-    for (auto it = mImageCache.begin(); it != mImageCache.end();) {
-        if (bufIds.count(it->first) == 0) {
-            it = mImageCache.erase(it);
-        } else {
-            it++;
-        }
-    }
+    ALOGV("Failed to find image for buffer: %" PRIu64, bufferId);
 }
 
 FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
@@ -844,8 +819,6 @@
         return fbo.getStatus();
     }
 
-    evictImages(layers);
-
     // clear the entire buffer, sometimes when we reuse buffers we'd persist
     // ghost images otherwise.
     // we also require a full transparent framebuffer for overlays. This is
@@ -888,10 +861,8 @@
             isOpaque = layer.source.buffer.isOpaque;
 
             sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
-
-            bool readCache = layer.source.buffer.cacheHint == Buffer::CachingHint::USE_CACHE;
             bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
-                                      layer.source.buffer.fence, readCache, /*persistCache=*/true);
+                                      layer.source.buffer.fence);
 
             usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
             Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index e37c91d..728882a 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -74,8 +74,8 @@
     void genTextures(size_t count, uint32_t* names) override;
     void deleteTextures(size_t count, uint32_t const* names) override;
     void bindExternalTextureImage(uint32_t texName, const Image& image) override;
-    status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence,
-                                       bool readCache);
+    status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence);
+    void unbindExternalTextureBuffer(uint64_t bufferId);
     status_t bindFrameBuffer(Framebuffer* framebuffer) override;
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
     void checkErrors() const override;
@@ -143,8 +143,6 @@
     // Defines the viewport, and sets the projection matrix to the projection
     // defined by the clip.
     void setViewportAndProjection(Rect viewport, Rect clip);
-    status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence,
-                                       bool readCache, bool persistCache);
     // Evicts stale images from the buffer cache.
     void evictImages(const std::vector<LayerSettings>& layers);
     // Computes the cropping window for the layer and sets up cropping
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index aa45ed8..b8bf801 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -32,16 +32,6 @@
 
 // Metadata describing the input buffer to render from.
 struct Buffer {
-    // Hint for whether to use the Image cache or not.
-    // If NO_CACHE is specified, then upload the contents of the GraphicBuffer
-    // to the GPU, without checking against any implementation defined cache.
-    // If USE_CACHE is specified, then check against an implementation defined
-    // cache first. If there is an Image cached for the given GraphicBuffer id,
-    // then use that instead of the provided buffer contents. If there is no
-    // cached image or the RenderEngine implementation does not support caching,
-    // then use the GraphicBuffer contents.
-    enum class CachingHint { NO_CACHE, USE_CACHE };
-
     // Buffer containing the image that we will render.
     // If buffer == nullptr, then the rest of the fields in this struct will be
     // ignored.
@@ -50,9 +40,6 @@
     // Fence that will fire when the buffer is ready to be bound.
     sp<Fence> fence = nullptr;
 
-    // Caching hint to use when uploading buffer contents.
-    CachingHint cacheHint = CachingHint::NO_CACHE;
-
     // Texture identifier to bind the external texture to.
     // TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
     uint32_t textureName = 0;
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 2a2b48f..ab34274 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -110,7 +110,11 @@
     virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
     virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
     virtual status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
-                                               sp<Fence> fence, bool cleanCache) = 0;
+                                               sp<Fence> fence) = 0;
+    // Removes internal resources referenced by the bufferId. This method should be
+    // invoked when the caller will no longer hold a reference to a GraphicBuffer
+    // and needs to clean up its resources.
+    virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0;
     // When binding a native buffer, it must be done before setViewportAndProjection
     // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 5956c46..ddf7420 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -53,7 +53,8 @@
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
     MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
-    MOCK_METHOD4(bindExternalTextureBuffer, status_t(uint32_t, sp<GraphicBuffer>, sp<Fence>, bool));
+    MOCK_METHOD3(bindExternalTextureBuffer, status_t(uint32_t, sp<GraphicBuffer>, sp<Fence>));
+    MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t));
     MOCK_CONST_METHOD0(checkErrors, void());
     MOCK_METHOD4(setViewportAndProjection,
                  void(size_t, size_t, Rect, ui::Transform::orientation_flags));
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 00e227f..4ca1781 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,6 +45,8 @@
 
         // Don't warn about struct padding
         "-Wno-padded",
+
+        "-Wno-switch-enum",
     ],
 
     sanitize: {
@@ -68,6 +70,7 @@
         "GraphicBufferMapper.cpp",
         "HdrCapabilities.cpp",
         "PixelFormat.cpp",
+        "PublicFormat.cpp",
         "Rect.cpp",
         "Region.cpp",
         "Size.cpp",
@@ -87,8 +90,6 @@
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@3.0",
-        "android.hardware.configstore@1.2",
-        "android.hardware.configstore-utils",
         "libbase",
         "libcutils",
         "libhardware",
@@ -102,7 +103,6 @@
     ],
 
     export_shared_lib_headers: [
-        "android.hardware.configstore@1.2",
         "android.hardware.graphics.common@1.2",
     ],
 
diff --git a/libs/ui/PublicFormat.cpp b/libs/ui/PublicFormat.cpp
new file mode 100644
index 0000000..70e3ce7
--- /dev/null
+++ b/libs/ui/PublicFormat.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 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 <ui/GraphicTypes.h> // ui::Dataspace
+#include <ui/PublicFormat.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+using ui::Dataspace;
+
+int mapPublicFormatToHalFormat(PublicFormat f) {
+    switch (f) {
+        case PublicFormat::JPEG:
+        case PublicFormat::DEPTH_POINT_CLOUD:
+        case PublicFormat::DEPTH_JPEG:
+        case PublicFormat::HEIC:
+            return HAL_PIXEL_FORMAT_BLOB;
+        case PublicFormat::DEPTH16:
+            return HAL_PIXEL_FORMAT_Y16;
+        case PublicFormat::RAW_SENSOR:
+        case PublicFormat::RAW_DEPTH:
+            return HAL_PIXEL_FORMAT_RAW16;
+        default:
+            // Most formats map 1:1
+            return static_cast<int>(f);
+    }
+}
+
+android_dataspace mapPublicFormatToHalDataspace(PublicFormat f) {
+    Dataspace dataspace;
+    switch (f) {
+        case PublicFormat::JPEG:
+            dataspace = Dataspace::V0_JFIF;
+            break;
+        case PublicFormat::DEPTH_POINT_CLOUD:
+        case PublicFormat::DEPTH16:
+        case PublicFormat::RAW_DEPTH:
+            dataspace = Dataspace::DEPTH;
+            break;
+        case PublicFormat::RAW_SENSOR:
+        case PublicFormat::RAW_PRIVATE:
+        case PublicFormat::RAW10:
+        case PublicFormat::RAW12:
+            dataspace = Dataspace::ARBITRARY;
+            break;
+        case PublicFormat::YUV_420_888:
+        case PublicFormat::NV21:
+        case PublicFormat::YV12:
+            dataspace = Dataspace::V0_JFIF;
+            break;
+        case PublicFormat::DEPTH_JPEG:
+            dataspace = Dataspace::DYNAMIC_DEPTH;
+            break;
+        case PublicFormat::HEIC:
+            dataspace = Dataspace::HEIF;
+            break;
+        default:
+            // Most formats map to UNKNOWN
+            dataspace = Dataspace::UNKNOWN;
+            break;
+    }
+    return static_cast<android_dataspace>(dataspace);
+}
+
+PublicFormat mapHalFormatDataspaceToPublicFormat(int format, android_dataspace dataSpace) {
+    Dataspace ds = static_cast<Dataspace>(dataSpace);
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_Y8:
+        case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW12:
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        case HAL_PIXEL_FORMAT_YV12:
+            // Enums overlap in both name and value
+            return static_cast<PublicFormat>(format);
+        case HAL_PIXEL_FORMAT_RAW16:
+            switch (ds) {
+                case Dataspace::DEPTH:
+                    return PublicFormat::RAW_DEPTH;
+                default:
+                    return PublicFormat::RAW_SENSOR;
+            }
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+            // Name differs, though value is the same
+            return PublicFormat::RAW_PRIVATE;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            // Name differs, though the value is the same
+            return PublicFormat::NV16;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            // Name differs, though the value is the same
+            return PublicFormat::NV21;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            // Name differs, though the value is the same
+            return PublicFormat::YUY2;
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+            // Name differs, though the value is the same
+            return PublicFormat::PRIVATE;
+        case HAL_PIXEL_FORMAT_Y16:
+            // Dataspace-dependent
+            switch (ds) {
+                case Dataspace::DEPTH:
+                    return PublicFormat::DEPTH16;
+                default:
+                    // Assume non-depth Y16 is just Y16.
+                    return PublicFormat::Y16;
+            }
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Dataspace-dependent
+            switch (ds) {
+                case Dataspace::DEPTH:
+                    return PublicFormat::DEPTH_POINT_CLOUD;
+                case Dataspace::V0_JFIF:
+                    return PublicFormat::JPEG;
+                case Dataspace::HEIF:
+                    return PublicFormat::HEIC;
+                default:
+                    if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
+                        return PublicFormat::DEPTH_JPEG;
+                    } else {
+                        // Assume otherwise-marked blobs are also JPEG
+                        return PublicFormat::JPEG;
+                    }
+            }
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            // Not defined in public API
+            return PublicFormat::UNKNOWN;
+
+        default:
+            return PublicFormat::UNKNOWN;
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/libs/ui/include/ui/ConfigStoreTypes.h b/libs/ui/include/ui/ConfigStoreTypes.h
index 37a2bd5..4445ae9 100644
--- a/libs/ui/include/ui/ConfigStoreTypes.h
+++ b/libs/ui/include/ui/ConfigStoreTypes.h
@@ -16,14 +16,22 @@
 
 #pragma once
 
-#include <android/hardware/configstore/1.2/types.h>
-
 // android::ui::* in this header file will alias different types as
 // the HIDL interface is updated.
 namespace android {
 namespace ui {
 
-using android::hardware::configstore::V1_2::DisplayPrimaries;
+struct CieXyz {
+    float X;
+    float Y;
+    float Z;
+};
+struct DisplayPrimaries {
+    CieXyz red;
+    CieXyz green;
+    CieXyz blue;
+    CieXyz white;
+};
 
 }  // namespace ui
 }  // namespace android
diff --git a/libs/ui/include/ui/PublicFormat.h b/libs/ui/include/ui/PublicFormat.h
new file mode 100644
index 0000000..1152cc5
--- /dev/null
+++ b/libs/ui/include/ui/PublicFormat.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 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 UI_PUBLICFORMAT_H
+#define UI_PUBLICFORMAT_H
+
+#include <system/graphics.h>
+
+namespace android {
+
+/**
+ * Enum mirroring the public API definitions for image and pixel formats.
+ * Some of these are hidden in the public API
+ *
+ * Keep up to date with android.graphics.ImageFormat and
+ * android.graphics.PixelFormat
+ *
+ * TODO: PublicFormat is going to be deprecated(b/126594675)
+ */
+enum class PublicFormat {
+    UNKNOWN = 0x0,
+    RGBA_8888 = 0x1,
+    RGBX_8888 = 0x2,
+    RGB_888 = 0x3,
+    RGB_565 = 0x4,
+    NV16 = 0x10,
+    NV21 = 0x11,
+    YUY2 = 0x14,
+    RGBA_FP16 = 0x16,
+    RAW_SENSOR = 0x20,
+    PRIVATE = 0x22,
+    YUV_420_888 = 0x23,
+    RAW_PRIVATE = 0x24,
+    RAW10 = 0x25,
+    RAW12 = 0x26,
+    RGBA_1010102 = 0x2b,
+    JPEG = 0x100,
+    DEPTH_POINT_CLOUD = 0x101,
+    RAW_DEPTH = 0x1002, // @hide
+    YV12 = 0x32315659,
+    Y8 = 0x20203859,
+    Y16 = 0x20363159, // @hide
+    DEPTH16 = 0x44363159,
+    DEPTH_JPEG = 0x69656963,
+    HEIC = 0x48454946,
+};
+
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * format */
+extern int mapPublicFormatToHalFormat(PublicFormat f);
+
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * dataspace */
+extern android_dataspace mapPublicFormatToHalDataspace(PublicFormat f);
+
+/* Convert from HAL format, dataspace pair to
+ * android.graphics.ImageFormat/PixelFormat.
+ * For unknown/unspecified pairs, returns PublicFormat::UNKNOWN */
+extern PublicFormat mapHalFormatDataspaceToPublicFormat(int format, android_dataspace dataSpace);
+
+}; // namespace android
+
+#endif // UI_PUBLICFORMAT_H
diff --git a/libs/ui/include_vndk/ui/ConfigStoreTypes.h b/libs/ui/include_vndk/ui/ConfigStoreTypes.h
index 37a2bd5..4445ae9 100644
--- a/libs/ui/include_vndk/ui/ConfigStoreTypes.h
+++ b/libs/ui/include_vndk/ui/ConfigStoreTypes.h
@@ -16,14 +16,22 @@
 
 #pragma once
 
-#include <android/hardware/configstore/1.2/types.h>
-
 // android::ui::* in this header file will alias different types as
 // the HIDL interface is updated.
 namespace android {
 namespace ui {
 
-using android::hardware::configstore::V1_2::DisplayPrimaries;
+struct CieXyz {
+    float X;
+    float Y;
+    float Z;
+};
+struct DisplayPrimaries {
+    CieXyz red;
+    CieXyz green;
+    CieXyz blue;
+    CieXyz white;
+};
 
 }  // namespace ui
 }  // namespace android
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index d7696f9..a73705b 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -23,6 +23,7 @@
 #include <binder/IResultReceiver.h>
 #include <binder/Parcel.h>
 #include <binder/PermissionCache.h>
+#include <cutils/properties.h>
 #include <private/android_filesystem_config.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
@@ -38,6 +39,7 @@
 namespace {
 status_t cmdHelp(int out);
 status_t cmdVkjson(int out, int err);
+void dumpGameDriverInfo(std::string* result);
 } // namespace
 
 const String16 sDump("android.permission.DUMP");
@@ -96,7 +98,11 @@
         }
 
         if (dumpAll) {
+            dumpGameDriverInfo(&result);
+            result.append("\n");
+
             mGpuStats->dump(Vector<String16>(), &result);
+            result.append("\n");
         }
     }
 
@@ -137,6 +143,18 @@
     return NO_ERROR;
 }
 
+void dumpGameDriverInfo(std::string* result) {
+    if (!result) return;
+
+    char stableGameDriver[PROPERTY_VALUE_MAX] = {};
+    property_get("ro.gfx.driver.0", stableGameDriver, "unsupported");
+    StringAppendF(result, "Stable Game Driver: %s\n", stableGameDriver);
+
+    char preReleaseGameDriver[PROPERTY_VALUE_MAX] = {};
+    property_get("ro.gfx.driver.1", preReleaseGameDriver, "unsupported");
+    StringAppendF(result, "Pre-release Game Driver: %s\n", preReleaseGameDriver);
+}
+
 } // anonymous namespace
 
 } // namespace android
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 43c9492..c4256df 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -19,28 +19,25 @@
 
 #include "GpuStats.h"
 
-#include <android-base/stringprintf.h>
+#include <unordered_set>
+
 #include <log/log.h>
 #include <utils/Trace.h>
 
-#include <unordered_set>
-
 namespace android {
 
-using base::StringAppendF;
-
 static bool addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
-                            GpuStatsGlobalAtom* const outGlobalAtom) {
+                            GpuStatsGlobalInfo* const outGlobalInfo) {
     switch (driver) {
         case GraphicsEnv::Driver::GL:
         case GraphicsEnv::Driver::GL_UPDATED:
-            outGlobalAtom->glLoadingCount++;
-            if (!isDriverLoaded) outGlobalAtom->glLoadingFailureCount++;
+            outGlobalInfo->glLoadingCount++;
+            if (!isDriverLoaded) outGlobalInfo->glLoadingFailureCount++;
             break;
         case GraphicsEnv::Driver::VULKAN:
         case GraphicsEnv::Driver::VULKAN_UPDATED:
-            outGlobalAtom->vkLoadingCount++;
-            if (!isDriverLoaded) outGlobalAtom->vkLoadingFailureCount++;
+            outGlobalInfo->vkLoadingCount++;
+            if (!isDriverLoaded) outGlobalInfo->vkLoadingFailureCount++;
             break;
         default:
             // Currently we don't support GraphicsEnv::Driver::ANGLE because the
@@ -52,15 +49,15 @@
 }
 
 static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
-                           GpuStatsAppAtom* const outAppAtom) {
+                           GpuStatsAppInfo* const outAppInfo) {
     switch (driver) {
         case GraphicsEnv::Driver::GL:
         case GraphicsEnv::Driver::GL_UPDATED:
-            outAppAtom->glDriverLoadingTime.emplace_back(driverLoadingTime);
+            outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
             break;
         case GraphicsEnv::Driver::VULKAN:
         case GraphicsEnv::Driver::VULKAN_UPDATED:
-            outAppAtom->vkDriverLoadingTime.emplace_back(driverLoadingTime);
+            outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
             break;
         default:
             break;
@@ -87,31 +84,31 @@
           appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
 
     if (!mGlobalStats.count(driverVersionCode)) {
-        GpuStatsGlobalAtom globalAtom;
-        if (!addLoadingCount(driver, isDriverLoaded, &globalAtom)) {
+        GpuStatsGlobalInfo globalInfo;
+        if (!addLoadingCount(driver, isDriverLoaded, &globalInfo)) {
             return;
         }
-        globalAtom.driverPackageName = driverPackageName;
-        globalAtom.driverVersionName = driverVersionName;
-        globalAtom.driverVersionCode = driverVersionCode;
-        globalAtom.driverBuildTime = driverBuildTime;
-        mGlobalStats.insert({driverVersionCode, globalAtom});
+        globalInfo.driverPackageName = driverPackageName;
+        globalInfo.driverVersionName = driverVersionName;
+        globalInfo.driverVersionCode = driverVersionCode;
+        globalInfo.driverBuildTime = driverBuildTime;
+        mGlobalStats.insert({driverVersionCode, globalInfo});
     } else if (!addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode])) {
         return;
     }
 
     if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
-        ALOGV("GpuStatsAppAtom has reached maximum size. Ignore new stats.");
+        ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
         return;
     }
 
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
     if (!mAppStats.count(appStatsKey)) {
-        GpuStatsAppAtom appAtom;
-        addLoadingTime(driver, driverLoadingTime, &appAtom);
-        appAtom.appPackageName = appPackageName;
-        appAtom.driverVersionCode = driverVersionCode;
-        mAppStats.insert({appStatsKey, appAtom});
+        GpuStatsAppInfo appInfo;
+        addLoadingTime(driver, driverLoadingTime, &appInfo);
+        appInfo.appPackageName = appPackageName;
+        appInfo.driverVersionCode = driverVersionCode;
+        mAppStats.insert({appStatsKey, appInfo});
         return;
     }
 
@@ -174,39 +171,16 @@
 }
 
 void GpuStats::dumpGlobalLocked(std::string* result) {
-    result->append("GpuStats global:\n");
-
     for (const auto& ele : mGlobalStats) {
-        StringAppendF(result, "  driverPackageName = %s\n", ele.second.driverPackageName.c_str());
-        StringAppendF(result, "  driverVersionName = %s\n", ele.second.driverVersionName.c_str());
-        StringAppendF(result, "  driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode);
-        StringAppendF(result, "  driverBuildTime = %" PRId64 "\n", ele.second.driverBuildTime);
-        StringAppendF(result, "  glLoadingCount = %d\n", ele.second.glLoadingCount);
-        StringAppendF(result, "  glLoadingFailureCount = %d\n", ele.second.glLoadingFailureCount);
-        StringAppendF(result, "  vkLoadingCount = %d\n", ele.second.vkLoadingCount);
-        StringAppendF(result, "  vkLoadingFailureCount = %d\n", ele.second.vkLoadingFailureCount);
+        result->append(ele.second.toString());
         result->append("\n");
     }
 }
 
 void GpuStats::dumpAppLocked(std::string* result) {
-    result->append("GpuStats app:\n");
-
     for (const auto& ele : mAppStats) {
-        StringAppendF(result, "  appPackageName = %s\n", ele.second.appPackageName.c_str());
-        StringAppendF(result, "  driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode);
-
-        result->append("  glDriverLoadingTime:");
-        for (int32_t loadingTime : ele.second.glDriverLoadingTime) {
-            StringAppendF(result, " %d", loadingTime);
-        }
+        result->append(ele.second.toString());
         result->append("\n");
-
-        result->append("  vkDriverLoadingTime:");
-        for (int32_t loadingTime : ele.second.vkDriverLoadingTime) {
-            StringAppendF(result, " %d", loadingTime);
-        }
-        result->append("\n\n");
     }
 }
 
diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h
index 8837c39..da7fd33 100644
--- a/services/gpuservice/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/GpuStats.h
@@ -20,7 +20,7 @@
 #include <unordered_map>
 #include <vector>
 
-#include <graphicsenv/GpuStatsAtoms.h>
+#include <graphicsenv/GpuStatsInfo.h>
 #include <graphicsenv/GraphicsEnv.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
@@ -52,9 +52,9 @@
     // GpuStats access should be guarded by mLock.
     std::mutex mLock;
     // Key is driver version code.
-    std::unordered_map<uint64_t, GpuStatsGlobalAtom> mGlobalStats;
+    std::unordered_map<uint64_t, GpuStatsGlobalInfo> mGlobalStats;
     // Key is <app package name>+<driver version code>.
-    std::unordered_map<std::string, GpuStatsAppAtom> mAppStats;
+    std::unordered_map<std::string, GpuStatsAppInfo> mAppStats;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/AllowedDisplayConfigs.h b/services/surfaceflinger/AllowedDisplayConfigs.h
index e3b9c1f..7ca62ea 100644
--- a/services/surfaceflinger/AllowedDisplayConfigs.h
+++ b/services/surfaceflinger/AllowedDisplayConfigs.h
@@ -54,6 +54,12 @@
         return (std::find(mConfigs.begin(), mConfigs.end(), config) != mConfigs.end());
     }
 
+    void getAllowedConfigs(std::vector<int32_t>* outConfigs) const {
+        if (outConfigs) {
+            *outConfigs = mConfigs;
+        }
+    }
+
 private:
     // add a config to the allowed config set
     void addConfig(int32_t config) { mConfigs.push_back(config); }
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 9bf499b..ac1d492 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -23,7 +23,6 @@
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore@1.1",
-        "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.2",
@@ -57,7 +56,6 @@
         "libui",
         "libinput",
         "libutils",
-        "libutilscallstack",
         "libSurfaceFlingerProperties",
     ],
     static_libs: [
@@ -189,7 +187,6 @@
         "android.frameworks.displayservice@1.0",
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
-        "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "libbinder",
@@ -244,13 +241,15 @@
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore@1.1",
-        "android.hardware.configstore@1.2",
+        "android.hardware.graphics.common@1.2",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
+        "libui",
         "libutils",
     ],
     export_shared_lib_headers: [
+        "android.hardware.graphics.common@1.2",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 6badc73..756ca42 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -163,9 +163,6 @@
         layer.source.buffer.buffer = mActiveBuffer;
         layer.source.buffer.isOpaque = isOpaque(s);
         layer.source.buffer.fence = mActiveBufferFence;
-        layer.source.buffer.cacheHint = useCachedBufferForClientComposition()
-                ? renderengine::Buffer::CachingHint::USE_CACHE
-                : renderengine::Buffer::CachingHint::NO_CACHE;
         layer.source.buffer.textureName = mTextureName;
         layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
         layer.source.buffer.isY410BT2020 = isHdrY410();
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index c48146f..e9dbdea 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -161,10 +161,6 @@
 
     bool mRefreshPending{false};
 
-    // Returns true if, when drawing the active buffer during gpu compositon, we
-    // should use a cached buffer or not.
-    virtual bool useCachedBufferForClientComposition() const = 0;
-
     // prepareClientLayer - constructs a RenderEngine layer for GPU composition.
     bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
                             bool useIdentityTransform, Region& clearRegion,
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 6866e5c..7d2dcba 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -178,7 +178,8 @@
         return;
     }
 
-    auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer : mCurrentTextureBuffer;
+    auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
+                                            : mCurrentTextureBuffer->graphicBuffer();
     auto err = addReleaseFence(slot, buffer, fence);
     if (err != OK) {
         BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
@@ -214,9 +215,9 @@
     }
 
     // If item->mGraphicBuffer is not null, this buffer has not been acquired
-    // before.
+    // before, so we need to clean up old references.
     if (item->mGraphicBuffer != nullptr) {
-        mImages[item->mSlot] = nullptr;
+        mImages[item->mSlot] = std::make_shared<Image>(item->mGraphicBuffer, mRE);
     }
 
     return NO_ERROR;
@@ -229,18 +230,21 @@
     int slot = item.mSlot;
 
     BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
-             mCurrentTextureBuffer != nullptr ? mCurrentTextureBuffer->handle : 0, slot,
-             mSlots[slot].mGraphicBuffer->handle);
+             (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr)
+                     ? mCurrentTextureBuffer->graphicBuffer()->handle
+                     : 0,
+             slot, mSlots[slot].mGraphicBuffer->handle);
 
     // Hang onto the pointer so that it isn't freed in the call to
     // releaseBufferLocked() if we're in shared buffer mode and both buffers are
     // the same.
-    sp<GraphicBuffer> nextTextureBuffer = mSlots[slot].mGraphicBuffer;
+    std::shared_ptr<Image> nextTextureBuffer = mImages[slot];
 
     // release old buffer
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
         if (pendingRelease == nullptr) {
-            status_t status = releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer);
+            status_t status =
+                    releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer());
             if (status < NO_ERROR) {
                 BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
                          status);
@@ -249,7 +253,7 @@
             }
         } else {
             pendingRelease->currentTexture = mCurrentTexture;
-            pendingRelease->graphicBuffer = mCurrentTextureBuffer;
+            pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer();
             pendingRelease->isPending = true;
         }
     }
@@ -257,8 +261,6 @@
     // Update the BufferLayerConsumer state.
     mCurrentTexture = slot;
     mCurrentTextureBuffer = nextTextureBuffer;
-    mCurrentTextureBufferStaleForGpu = false;
-    mCurrentTextureImageFreed = nullptr;
     mCurrentCrop = item.mCrop;
     mCurrentTransform = item.mTransform;
     mCurrentScalingMode = item.mScalingMode;
@@ -280,7 +282,12 @@
 status_t BufferLayerConsumer::bindTextureImageLocked() {
     ATRACE_CALL();
 
-    return mRE.bindExternalTextureBuffer(mTexName, mCurrentTextureBuffer, mCurrentFence, false);
+    if (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr) {
+        return mRE.bindExternalTextureBuffer(mTexName, mCurrentTextureBuffer->graphicBuffer(),
+                                             mCurrentFence);
+    }
+
+    return NO_INIT;
 }
 
 void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
@@ -308,12 +315,15 @@
 
 void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
     BLC_LOGV("computeCurrentTransformMatrixLocked");
-    if (mCurrentTextureBuffer == nullptr) {
+    if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->graphicBuffer() == nullptr) {
         BLC_LOGD("computeCurrentTransformMatrixLocked: "
                  "mCurrentTextureBuffer is nullptr");
     }
-    GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer, mCurrentCrop,
-                                       mCurrentTransform, mFilteringEnabled);
+    GLConsumer::computeTransformMatrix(mCurrentTransformMatrix,
+                                       mCurrentTextureBuffer == nullptr
+                                               ? nullptr
+                                               : mCurrentTextureBuffer->graphicBuffer(),
+                                       mCurrentCrop, mCurrentTransform, mFilteringEnabled);
 }
 
 nsecs_t BufferLayerConsumer::getTimestamp() {
@@ -365,16 +375,7 @@
         *outFence = mCurrentFence;
     }
 
-    return mCurrentTextureBuffer;
-}
-
-bool BufferLayerConsumer::getAndSetCurrentBufferCacheHint() {
-    Mutex::Autolock lock(mMutex);
-    bool useCache = mCurrentTextureBufferStaleForGpu;
-    // Set the staleness bit here, as this function is only called during a
-    // client composition path.
-    mCurrentTextureBufferStaleForGpu = true;
-    return useCache;
+    return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer();
 }
 
 Rect BufferLayerConsumer::getCurrentCrop() const {
@@ -432,10 +433,8 @@
     BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     if (slotIndex == mCurrentTexture) {
         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
-        mCurrentTextureImageFreed = std::move(mImages[slotIndex]);
-    } else {
-        mImages[slotIndex] = nullptr;
     }
+    mImages[slotIndex] = nullptr;
     ConsumerBase::freeBufferLocked(slotIndex);
 }
 
@@ -474,7 +473,10 @@
 
 void BufferLayerConsumer::abandonLocked() {
     BLC_LOGV("abandonLocked");
-    mCurrentTextureBuffer.clear();
+    mCurrentTextureBuffer = nullptr;
+    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        mImages[i] = nullptr;
+    }
     ConsumerBase::abandonLocked();
 }
 
@@ -492,4 +494,11 @@
     ConsumerBase::dumpLocked(result, prefix);
 }
 
+BufferLayerConsumer::Image::~Image() {
+    if (mGraphicBuffer != nullptr) {
+        ALOGE("Destroying buffer: %" PRId64, mGraphicBuffer->getId());
+        mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId());
+    }
+}
+
 }; // namespace android
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index e2a6d2e..32ccfbb 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -149,11 +149,6 @@
     // for use with bilinear filtering.
     void setFilteringEnabled(bool enabled);
 
-    // Sets mCurrentTextureBufferStaleForGpu to true to indicate that the
-    // buffer is now "stale" for GPU composition, and returns the old staleness
-    // bit as a caching hint.
-    bool getAndSetCurrentBufferCacheHint();
-
     // getCurrentBuffer returns the buffer associated with the current image.
     // When outSlot is not nullptr, the current buffer slot index is also
     // returned. Simiarly, when outFence is not nullptr, the current output
@@ -218,6 +213,22 @@
     status_t bindTextureImageLocked();
 
 private:
+    // Utility class for managing GraphicBuffer references into renderengine
+    class Image {
+    public:
+        Image(sp<GraphicBuffer> graphicBuffer, renderengine::RenderEngine& engine)
+              : mGraphicBuffer(graphicBuffer), mRE(engine) {}
+        virtual ~Image();
+        const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
+
+    private:
+        // mGraphicBuffer is the buffer that was used to create this image.
+        sp<GraphicBuffer> mGraphicBuffer;
+        // Back-reference into renderengine to initiate cleanup.
+        renderengine::RenderEngine& mRE;
+        DISALLOW_COPY_AND_ASSIGN(Image);
+    };
+
     // freeBufferLocked frees up the given buffer slot. If the slot has been
     // initialized this will release the reference to the GraphicBuffer in
     // that slot.  Otherwise it has no effect.
@@ -248,14 +259,10 @@
     // consume buffers as hardware textures.
     static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
 
-    // mCurrentTextureImage is the buffer containing the current texture. It's
+    // mCurrentTextureBuffer is the buffer containing the current texture. It's
     // possible that this buffer is not associated with any buffer slot, so we
     // must track it separately in order to support the getCurrentBuffer method.
-    sp<GraphicBuffer> mCurrentTextureBuffer;
-
-    // True if the buffer was used for the previous client composition frame,
-    // and false otherwise.
-    bool mCurrentTextureBufferStaleForGpu;
+    std::shared_ptr<Image> mCurrentTextureBuffer;
 
     // mCurrentCrop is the crop rectangle that applies to the current texture.
     // It gets set each time updateTexImage is called.
@@ -333,16 +340,8 @@
     // reset mCurrentTexture to INVALID_BUFFER_SLOT.
     int mCurrentTexture;
 
-    // Cached image used for rendering the current texture through GPU
-    // composition, which contains the cached image after freeBufferLocked is
-    // called on the current buffer. Whenever latchBuffer is called, this is
-    // expected to be cleared. Then, if bindTexImage is called before the next
-    // buffer is acquired, then this image is bound.
-    std::unique_ptr<renderengine::Image> mCurrentTextureImageFreed;
-
-    // Cached images used for rendering the current texture through GPU
-    // composition.
-    std::unique_ptr<renderengine::Image> mImages[BufferQueueDefs::NUM_BUFFER_SLOTS];
+    // Shadow buffer cache for cleaning up renderengine references.
+    std::shared_ptr<Image> mImages[BufferQueueDefs::NUM_BUFFER_SLOTS];
 
     // A release that is pending on the receipt of a new release fence from
     // presentDisplay
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 215dea1..16e8e95 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -342,10 +342,6 @@
     return NO_ERROR;
 }
 
-bool BufferQueueLayer::useCachedBufferForClientComposition() const {
-    return mConsumer->getAndSetCurrentBufferCacheHint();
-}
-
 status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) {
     mPreviousFrameNumber = mCurrentFrameNumber;
     mCurrentFrameNumber = mConsumer->getFrameNumber();
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index fbb8c14..a2aad17 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -62,9 +62,6 @@
 public:
     bool fenceHasSignaled() const override;
 
-protected:
-    bool useCachedBufferForClientComposition() const override;
-
 private:
     nsecs_t getDesiredPresentTime() override;
     std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index f6b69eb..6390e85 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -48,7 +48,12 @@
     mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
     mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
 }
-BufferStateLayer::~BufferStateLayer() = default;
+BufferStateLayer::~BufferStateLayer() {
+    if (mActiveBuffer != nullptr) {
+        auto& engine(mFlinger->getRenderEngine());
+        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
+    }
+}
 
 // -----------------------------------------------------------------------
 // Interface implementation for Layer
@@ -468,7 +473,7 @@
     const State& s(getDrawingState());
     auto& engine(mFlinger->getRenderEngine());
 
-    return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence, false);
+    return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence);
 }
 
 status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
@@ -542,6 +547,11 @@
         return BAD_VALUE;
     }
 
+    if (mActiveBuffer != nullptr) {
+        // todo: get this to work with BufferStateLayerCache
+        auto& engine(mFlinger->getRenderEngine());
+        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
+    }
     mActiveBuffer = s.buffer;
     mActiveBufferFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
@@ -551,11 +561,6 @@
     return NO_ERROR;
 }
 
-bool BufferStateLayer::useCachedBufferForClientComposition() const {
-    // TODO: Store a proper staleness bit to support EGLImage caching.
-    return false;
-}
-
 status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) {
     // TODO(marissaw): support frame history events
     mCurrentFrameNumber = mFrameNumber;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 0b03f49..97662e8 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -96,9 +96,6 @@
     // -----------------------------------------------------------------------
     bool fenceHasSignaled() const override;
 
-protected:
-    bool useCachedBufferForClientComposition() const override;
-
 private:
     nsecs_t getDesiredPresentTime() override;
     std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 02383a6..2d6d33c 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -49,8 +49,6 @@
     Region::const_iterator const tail = region.end();
     // Use a lambda do avoid writing the object header when the object is empty
     RegionProto* regionProto = getRegionProto();
-    uint64_t address = reinterpret_cast<uint64_t>(&region);
-    regionProto->set_id(address);
     while (head != tail) {
         std::function<RectProto*()> getProtoRect = [&]() { return regionProto->add_rect(); };
         writeToProto(*head, getProtoRect);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 990318a..5b4af4a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -26,7 +26,6 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
-#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <ui/DisplayStatInfo.h>
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 81f148a..e50dd08 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -62,7 +62,6 @@
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/UiConfig.h>
-#include <utils/CallStack.h>
 #include <utils/StopWatch.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
@@ -110,7 +109,6 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
-#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/types.h>
 #include <configstore/Utils.h>
 
@@ -949,9 +947,11 @@
     }
 
     // Don't check against the current mode yet. Worst case we set the desired
-    // config twice.
+    // config twice. However event generation config might have changed so we need to update it
+    // accordingly
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
-    mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, event};
+    const ConfigEvent desiredConfig = mDesiredActiveConfig.event | event;
+    mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, desiredConfig};
 
     if (!mDesiredActiveConfigChanged) {
         // This is the first time we set the desired
@@ -1309,7 +1309,7 @@
 status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea,
                                                    const sp<IBinder>& stopLayerHandle,
                                                    const sp<IRegionSamplingListener>& listener) {
-    if (!listener) {
+    if (!listener || samplingArea == Rect::INVALID_RECT) {
         return BAD_VALUE;
     }
     mRegionSamplingThread->addListener(samplingArea, stopLayerHandle, listener);
@@ -1317,6 +1317,9 @@
 }
 
 status_t SurfaceFlinger::removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) {
+    if (!listener) {
+        return BAD_VALUE;
+    }
     mRegionSamplingThread->removeListener(listener);
     return NO_ERROR;
 }
@@ -1968,78 +1971,22 @@
     getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
 }
 
-// debug patch for b/119477596 - add stack guards to catch stack
-// corruptions and disable clang optimizations.
-// The code below is temporary and planned to be removed once stack
-// corruptions are found.
-#pragma clang optimize off
-class StackGuard {
-public:
-    StackGuard(const char* name, const char* func, int line) {
-        guarders.reserve(MIN_CAPACITY);
-        guarders.push_back({this, name, func, line});
-        validate();
-    }
-    ~StackGuard() {
-        for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) {
-            if (i->guard == this) {
-                guarders.erase(i);
-                break;
-            }
-        }
-    }
-
-    static void validate() {
-        for (const auto& guard : guarders) {
-            if (guard.guard->cookie != COOKIE_VALUE) {
-                ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name);
-                CallStack stack(LOG_TAG);
-                abort();
-            }
-        }
-    }
-
-private:
-    uint64_t cookie = COOKIE_VALUE;
-    static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef;
-    static constexpr size_t MIN_CAPACITY = 16;
-
-    struct GuarderElement {
-        StackGuard* guard;
-        const char* name;
-        const char* func;
-        int line;
-    };
-
-    static std::vector<GuarderElement> guarders;
-};
-std::vector<StackGuard::GuarderElement> StackGuard::guarders;
-
-#define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__);
-
-#define ASSERT_ON_STACK_GUARD() StackGuard::validate();
 void SurfaceFlinger::postComposition()
 {
-    DEFINE_STACK_GUARD(begin);
     ATRACE_CALL();
     ALOGV("postComposition");
 
     // Release any buffers which were replaced this frame
     nsecs_t dequeueReadyTime = systemTime();
-    DEFINE_STACK_GUARD(dequeueReadyTime);
     for (auto& layer : mLayersWithQueuedFrames) {
         layer->releasePendingBuffer(dequeueReadyTime);
     }
-    ASSERT_ON_STACK_GUARD();
 
     // |mStateLock| not needed as we are on the main thread
     const auto displayDevice = getDefaultDisplayDeviceLocked();
-    DEFINE_STACK_GUARD(displayDevice);
 
     getBE().mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
-    DEFINE_STACK_GUARD(glCompositionDoneFenceTime);
-
     if (displayDevice && getHwComposer().hasClientComposition(displayDevice->getId())) {
         glCompositionDoneFenceTime =
                 std::make_shared<FenceTime>(displayDevice->getCompositionDisplay()
@@ -2050,52 +1997,37 @@
         glCompositionDoneFenceTime = FenceTime::NO_FENCE;
     }
 
-    ASSERT_ON_STACK_GUARD();
-
     getBE().mDisplayTimeline.updateSignalTimes();
     mPreviousPresentFence = displayDevice ? getHwComposer().getPresentFence(*displayDevice->getId())
                                           : Fence::NO_FENCE;
     auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
-    DEFINE_STACK_GUARD(presentFenceTime);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
     DisplayStatInfo stats;
-    DEFINE_STACK_GUARD(stats);
     mScheduler->getDisplayStatInfo(&stats);
 
-    ASSERT_ON_STACK_GUARD();
-
     // We use the mRefreshStartTime which might be sampled a little later than
     // when we started doing work for this frame, but that should be okay
     // since updateCompositorTiming has snapping logic.
     updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
     CompositorTiming compositorTiming;
-    DEFINE_STACK_GUARD(compositorTiming);
-
     {
         std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
-        DEFINE_STACK_GUARD(lock);
         compositorTiming = getBE().mCompositorTiming;
-
-        ASSERT_ON_STACK_GUARD();
     }
 
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         bool frameLatched =
                 layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime,
                                          presentFenceTime, compositorTiming);
-        DEFINE_STACK_GUARD(frameLatched);
         if (frameLatched) {
             recordBufferingStats(layer->getName().string(),
                     layer->getOccupancyHistory(false));
         }
-        ASSERT_ON_STACK_GUARD();
     });
 
     if (presentFenceTime->isValid()) {
-        ASSERT_ON_STACK_GUARD();
         mScheduler->addPresentFence(presentFenceTime);
-        ASSERT_ON_STACK_GUARD();
     }
 
     if (!hasSyncFramework) {
@@ -2105,80 +2037,58 @@
         }
     }
 
-    ASSERT_ON_STACK_GUARD();
-
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
         if (presentFenceTime->isValid()) {
             mAnimFrameTracker.setActualPresentFence(
                     std::move(presentFenceTime));
-
-            ASSERT_ON_STACK_GUARD();
         } else if (displayDevice && getHwComposer().isConnected(*displayDevice->getId())) {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
             const nsecs_t presentTime =
                     getHwComposer().getRefreshTimestamp(*displayDevice->getId());
-            DEFINE_STACK_GUARD(presentTime);
-
             mAnimFrameTracker.setActualPresentTime(presentTime);
-            ASSERT_ON_STACK_GUARD();
         }
         mAnimFrameTracker.advanceFrame();
     }
 
-    ASSERT_ON_STACK_GUARD();
-
     mTimeStats->incrementTotalFrames();
     if (mHadClientComposition) {
         mTimeStats->incrementClientCompositionFrames();
     }
 
-    ASSERT_ON_STACK_GUARD();
-
     mTimeStats->setPresentFenceGlobal(presentFenceTime);
 
-    ASSERT_ON_STACK_GUARD();
-
     if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
         !displayDevice->isPoweredOn()) {
         return;
     }
 
     nsecs_t currentTime = systemTime();
-    DEFINE_STACK_GUARD(currentTime);
     if (mHasPoweredOff) {
         mHasPoweredOff = false;
     } else {
         nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
-        DEFINE_STACK_GUARD(elapsedTime);
         size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
-        DEFINE_STACK_GUARD(numPeriods);
         if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
             getBE().mFrameBuckets[numPeriods] += elapsedTime;
         } else {
             getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
         }
         getBE().mTotalTime += elapsedTime;
-
-        ASSERT_ON_STACK_GUARD();
     }
     getBE().mLastSwapTime = currentTime;
-    ASSERT_ON_STACK_GUARD();
 
     {
         std::lock_guard lock(mTexturePoolMutex);
-        DEFINE_STACK_GUARD(lock);
         const size_t refillCount = mTexturePoolSize - mTexturePool.size();
-        DEFINE_STACK_GUARD(refillCount);
         if (refillCount > 0) {
             const size_t offset = mTexturePool.size();
             mTexturePool.resize(mTexturePoolSize);
             getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
             ATRACE_INT("TexturePoolSize", mTexturePool.size());
         }
-        ASSERT_ON_STACK_GUARD();
     }
 
     mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
@@ -2187,10 +2097,7 @@
     if (mLumaSampling) {
         mRegionSamplingThread->sampleNow();
     }
-
-    ASSERT_ON_STACK_GUARD();
 }
-#pragma clang optimize on // b/119477596
 
 void SurfaceFlinger::computeLayerBounds() {
     for (const auto& pair : mDisplays) {
@@ -4912,6 +4819,7 @@
         case GET_HDR_CAPABILITIES:
         case SET_ACTIVE_CONFIG:
         case SET_ALLOWED_DISPLAY_CONFIGS:
+        case GET_ALLOWED_DISPLAY_CONFIGS:
         case SET_ACTIVE_COLOR_MODE:
         case INJECT_VSYNC:
         case SET_POWER_MODE:
@@ -5808,6 +5716,36 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getAllowedDisplayConfigs(const android::sp<android::IBinder>& displayToken,
+                                                  std::vector<int32_t>* outAllowedConfigs) {
+    ATRACE_CALL();
+
+    if (!displayToken) {
+        ALOGE("getAllowedDisplayConfigs: displayToken is null");
+        return BAD_VALUE;
+    }
+
+    if (!outAllowedConfigs) {
+        ALOGE("getAllowedDisplayConfigs: outAllowedConfigs is null");
+        return BAD_VALUE;
+    }
+
+    ConditionalLock stateLock(mStateLock, std::this_thread::get_id() != mMainThreadId);
+    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+    if (!displayId) {
+        ALOGE("getAllowedDisplayConfigs: display not found");
+        return NAME_NOT_FOUND;
+    }
+
+    std::lock_guard allowedConfigLock(mAllowedConfigsLock);
+    auto allowedConfigIterator = mAllowedConfigs.find(displayId.value());
+    if (allowedConfigIterator != mAllowedConfigs.end()) {
+        allowedConfigIterator->second->getAllowedConfigs(outAllowedConfigs);
+    }
+
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 void SetInputWindowsListener::onSetInputWindowsFinished() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0bf6ac5..3eaaaea 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -489,6 +489,8 @@
     status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
     status_t setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                       const std::vector<int32_t>& allowedConfigs) override;
+    status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+                                      std::vector<int32_t>* outAllowedConfigs) override;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
@@ -521,6 +523,13 @@
 
     enum class ConfigEvent { None, Changed };
 
+    // logical or operator with the semantics of at least one of the events is Changed
+    friend ConfigEvent operator|(const ConfigEvent& first, const ConfigEvent& second) {
+        if (first == ConfigEvent::Changed) return ConfigEvent::Changed;
+        if (second == ConfigEvent::Changed) return ConfigEvent::Changed;
+        return ConfigEvent::None;
+    }
+
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays() REQUIRES(mStateLock);
     // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index e676d20..f2881f5 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -4,7 +4,6 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/types.h>
-#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 
 #include <cstdlib>
@@ -16,9 +15,9 @@
 namespace sysprop {
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
-using ::android::hardware::configstore::V1_2::DisplayPrimaries;
-using ::android::hardware::graphics::common::V1_2::Dataspace;
-using ::android::hardware::graphics::common::V1_2::PixelFormat;
+using android::hardware::graphics::common::V1_2::Dataspace;
+using android::hardware::graphics::common::V1_2::PixelFormat;
+using android::ui::DisplayPrimaries;
 
 int64_t vsync_event_phase_offset_ns(int64_t defaultValue) {
     auto temp = SurfaceFlingerProperties::vsync_event_phase_offset_ns();
@@ -171,40 +170,14 @@
         tmpHasWideColorDisplay.has_value()) {
         return *tmpuseColorManagement || *tmpHasHDRDisplay || *tmpHasWideColorDisplay;
     }
-    auto surfaceFlingerConfigsServiceV1_2 = ISurfaceFlingerConfigs::getService();
-    if (surfaceFlingerConfigsServiceV1_2) {
-        return getBool<V1_2::ISurfaceFlingerConfigs,
-                       &V1_2::ISurfaceFlingerConfigs::useColorManagement>(defaultValue);
-    }
     return defaultValue;
 }
 
-auto getCompositionPreference(sp<V1_2::ISurfaceFlingerConfigs> configsServiceV1_2) {
-    Dataspace defaultCompositionDataspace = Dataspace::V0_SRGB;
-    PixelFormat defaultCompositionPixelFormat = PixelFormat::RGBA_8888;
-    Dataspace wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
-    PixelFormat wideColorGamutCompositionPixelFormat = PixelFormat::RGBA_8888;
-    configsServiceV1_2->getCompositionPreference(
-            [&](auto tmpDefaultDataspace, auto tmpDefaultPixelFormat,
-                auto tmpWideColorGamutDataspace, auto tmpWideColorGamutPixelFormat) {
-                defaultCompositionDataspace = tmpDefaultDataspace;
-                defaultCompositionPixelFormat = tmpDefaultPixelFormat;
-                wideColorGamutCompositionDataspace = tmpWideColorGamutDataspace;
-                wideColorGamutCompositionPixelFormat = tmpWideColorGamutPixelFormat;
-            });
-    return std::tuple(defaultCompositionDataspace, defaultCompositionPixelFormat,
-                      wideColorGamutCompositionDataspace, wideColorGamutCompositionPixelFormat);
-}
-
 int64_t default_composition_dataspace(Dataspace defaultValue) {
     auto temp = SurfaceFlingerProperties::default_composition_dataspace();
     if (temp.has_value()) {
         return *temp;
     }
-    auto configsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
-    if (configsServiceV1_2) {
-        return static_cast<int64_t>(get<0>(getCompositionPreference(configsServiceV1_2)));
-    }
     return static_cast<int64_t>(defaultValue);
 }
 
@@ -213,10 +186,6 @@
     if (temp.has_value()) {
         return *temp;
     }
-    auto configsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
-    if (configsServiceV1_2) {
-        return static_cast<int32_t>(get<1>(getCompositionPreference(configsServiceV1_2)));
-    }
     return static_cast<int32_t>(defaultValue);
 }
 
@@ -225,10 +194,6 @@
     if (temp.has_value()) {
         return *temp;
     }
-    auto configsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
-    if (configsServiceV1_2) {
-        return static_cast<int64_t>(get<2>(getCompositionPreference(configsServiceV1_2)));
-    }
     return static_cast<int64_t>(defaultValue);
 }
 
@@ -237,10 +202,6 @@
     if (temp.has_value()) {
         return *temp;
     }
-    auto configsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
-    if (configsServiceV1_2) {
-        return static_cast<int32_t>(get<3>(getCompositionPreference(configsServiceV1_2)));
-    }
     return static_cast<int32_t>(defaultValue);
 }
 
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index c86880e..9917683 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -3,8 +3,9 @@
 #define SURFACEFLINGERPROPERTIES_H_
 
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
-#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
+#include <android/hardware/graphics/common/1.2/types.h>
 #include <sysprop/SurfaceFlingerProperties.sysprop.h>
+#include <ui/ConfigStoreTypes.h>
 
 #include <cstdint>
 #include <optional>
@@ -54,7 +55,7 @@
 int32_t wcg_composition_pixel_format(
         android::hardware::graphics::common::V1_2::PixelFormat defaultValue);
 
-android::hardware::configstore::V1_2::DisplayPrimaries getDisplayNativePrimaries();
+android::ui::DisplayPrimaries getDisplayNativePrimaries();
 } // namespace sysprop
 } // namespace android
 #endif // SURFACEFLINGERPROPERTIES_H_
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 7ab57f9..7288232 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -132,7 +132,6 @@
 
 LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) {
     LayerProtoParser::Region region;
-    region.id = regionProto.id();
     for (int i = 0; i < regionProto.rect_size(); i++) {
         const RectProto& rectProto = regionProto.rect(i);
         region.rects.push_back(generateRect(rectProto));
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index a0fb0a0..fd4695e 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -117,7 +117,7 @@
 }
 
 message RegionProto {
-  uint64 id = 1;
+  reserved 1;  // Previously: uint64 id
   repeated RectProto rect = 2;
 }
 
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 6deec29..30ae764 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -592,8 +592,6 @@
                     renderengine::LayerSettings layer = layerSettings.back();
                     EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull()));
                     EXPECT_THAT(layer.source.buffer.fence, Not(IsNull()));
-                    EXPECT_EQ(renderengine::Buffer::CachingHint::NO_CACHE,
-                              layer.source.buffer.cacheHint);
                     EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName);
                     EXPECT_EQ(false, layer.source.buffer.isY410BT2020);
                     EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 1487d47..9bf29a2 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -1926,6 +1926,10 @@
     EXPECT_CALL(*mComposer, destroyVirtualDisplay(Case::Display::HWC_DISPLAY_ID))
             .WillOnce(Return(Error::NONE));
     EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
+
+    // Cleanup
+    mFlinger.mutableCurrentState().displays.removeItem(displayToken);
+    mFlinger.mutableDrawingState().displays.removeItem(displayToken);
 }
 
 TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) {