Merge "GpuStats: send GpuStats at activity launch hint" into qt-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 5836f11..7ac0eb7 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -62,7 +62,7 @@
 
 using std::string;
 
-#define MAX_SYS_FILES 10
+#define MAX_SYS_FILES 11
 
 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
 const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
@@ -133,7 +133,11 @@
         { OPT,      "events/sched/sched_blocked_reason/enable" },
         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
         { OPT,      "events/sched/sched_pi_setprio/enable" },
+        { OPT,      "events/sched/sched_process_exit/enable" },
         { OPT,      "events/cgroup/enable" },
+        { OPT,      "events/oom/oom_score_adj_update/enable" },
+        { OPT,      "events/task/task_rename/enable" },
+        { OPT,      "events/task/task_newtask/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "events/irq/enable" },
@@ -231,10 +235,6 @@
         { OPT,      "events/kmem/rss_stat/enable" },
         { OPT,      "events/kmem/ion_heap_grow/enable" },
         { OPT,      "events/kmem/ion_heap_shrink/enable" },
-        { OPT,      "events/oom/oom_score_adj_update/enable" },
-        { OPT,      "events/sched/sched_process_exit/enable" },
-        { OPT,      "events/task/task_rename/enable" },
-        { OPT,      "events/task/task_newtask/enable" },
     } },
 };
 
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 7c58a85..032d072 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -33,6 +33,8 @@
     chmod 0666 /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
     chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_pi_setprio/enable
     chmod 0666 /sys/kernel/tracing/events/sched/sched_pi_setprio/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_process_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable
     chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable
     chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 2cc1b32..671c788 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2697,7 +2697,15 @@
             MYLOGI(
                 "Did not receive user consent yet."
                 " Will not copy the bugreport artifacts to caller.\n");
-            // TODO(b/111441001): cancel outstanding requests
+            const String16 incidentcompanion("incidentcompanion");
+            sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
+            if (ics != nullptr) {
+                MYLOGD("Canceling user consent request via incidentcompanion service\n");
+                android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
+                        consent_callback_.get());
+            } else {
+                MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
+            }
         }
     }
 
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c730ab9..59c19d1 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -581,10 +581,6 @@
             // No code cache on shared storage
         } else {
             // Clear everything on shared storage
-            path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
             path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
             if (delete_dir_contents(path, true) != 0) {
                 res = error("Failed to delete contents of " + path);
@@ -668,10 +664,6 @@
         }
 
         auto extPath = findDataMediaPath(uuid, userId);
-        path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname);
-        if (delete_dir_contents_and_dir(path, true) != 0) {
-            res = error("Failed to delete " + path);
-        }
         path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
         if (delete_dir_contents_and_dir(path, true) != 0) {
             res = error("Failed to delete " + path);
@@ -1694,8 +1686,6 @@
             }
 
             ATRACE_BEGIN("external");
-            auto sandboxPath = create_data_media_package_path(uuid_, userId, "sandbox", pkgname);
-            calculate_tree_size(sandboxPath, &extStats.dataSize);
             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
             collectManualStats(extPath, &extStats);
             auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
diff --git a/headers/media_plugin/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
index 59bd292..17b9993 100644
--- a/headers/media_plugin/media/drm/DrmAPI.h
+++ b/headers/media_plugin/media/drm/DrmAPI.h
@@ -115,7 +115,8 @@
             kKeyStatusType_Expired,
             kKeyStatusType_OutputNotAllowed,
             kKeyStatusType_StatusPending,
-            kKeyStatusType_InternalError
+            kKeyStatusType_InternalError,
+            kKeyStatusType_UsableInFuture
         };
 
         // Used by sendKeysChange to report the usability status of each
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index d0642c6..2f5ccb8 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -38,6 +38,7 @@
         RELEASE_PLAYER                        = IBinder::FIRST_CALL_TRANSACTION + 3,
         TRACK_RECORDER                        = IBinder::FIRST_CALL_TRANSACTION + 4,
         RECORDER_EVENT                        = IBinder::FIRST_CALL_TRANSACTION + 5,
+        RELEASE_RECORDER                      = IBinder::FIRST_CALL_TRANSACTION + 6,
     };
 
     DECLARE_META_INTERFACE(AudioManager)
@@ -52,6 +53,7 @@
     /*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
     virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
     /*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
+    /*oneway*/ virtual status_t releaseRecorder(audio_unique_id_t riid) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 70ed80d..90980b8 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -74,4 +74,11 @@
      * LOCATION_PRODUCT: getApplicationInfo(packageName).isProduct()
      */
     int getLocationFlags(in @utf8InCpp String packageName);
+
+    /**
+     * Returns the target SDK version for the given package.
+     * Unknown packages will cause the call to fail. The caller must check the
+     * returned Status before using the result of this function.
+     */
+    int getTargetSdkVersionForPackage(in String packageName);
 }
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index f435d98..34575f5 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -25,50 +25,19 @@
     },
     double_loadable: true,
 
-    clang: true,
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    cppflags: [
-        "-Wextra",
-        "-DDEBUG_ONLY_CODE=0",
-    ],
-
-    product_variables: {
-        eng: {
-            cppflags: [
-                "-UDEBUG_ONLY_CODE",
-                "-DDEBUG_ONLY_CODE=1",
-            ],
-        },
-    },
+    defaults: ["libgui_bufferqueue-defaults"],
 
     srcs: [
         "BitTube.cpp",
         "BufferHubConsumer.cpp",
         "BufferHubProducer.cpp",
-        "BufferItem.cpp",
         "BufferItemConsumer.cpp",
-        "BufferQueue.cpp",
-        "BufferQueueConsumer.cpp",
-        "BufferQueueCore.cpp",
-        "BufferQueueProducer.cpp",
-        "BufferQueueThreadState.cpp",
-        "BufferSlot.cpp",
         "ConsumerBase.cpp",
         "CpuConsumer.cpp",
         "DisplayEventReceiver.cpp",
-        "FrameTimestamps.cpp",
         "GLConsumer.cpp",
-        "GLConsumerUtils.cpp",
         "GuiConfig.cpp",
-        "HdrMetadata.cpp",
         "IDisplayEventConnection.cpp",
-        "IConsumerListener.cpp",
-        "IGraphicBufferConsumer.cpp",
-        "IGraphicBufferProducer.cpp",
-        "IProducerListener.cpp",
         "IRegionSamplingListener.cpp",
         "ISurfaceComposer.cpp",
         "ISurfaceComposerClient.cpp",
@@ -76,50 +45,20 @@
         "LayerDebugInfo.cpp",
         "LayerMetadata.cpp",
         "LayerState.cpp",
-        "OccupancyTracker.cpp",
         "StreamSplitter.cpp",
         "Surface.cpp",
         "SurfaceControl.cpp",
         "SurfaceComposerClient.cpp",
         "SyncFeatures.cpp",
         "view/Surface.cpp",
-        "bufferqueue/1.0/B2HProducerListener.cpp",
-        "bufferqueue/1.0/Conversion.cpp",
-        "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
-        "bufferqueue/1.0/H2BProducerListener.cpp",
-        "bufferqueue/1.0/WProducerListener.cpp",
-        "bufferqueue/2.0/B2HGraphicBufferProducer.cpp",
-        "bufferqueue/2.0/B2HProducerListener.cpp",
-        "bufferqueue/2.0/H2BGraphicBufferProducer.cpp",
-        "bufferqueue/2.0/H2BProducerListener.cpp",
-        "bufferqueue/2.0/types.cpp",
     ],
 
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
-        "android.hardware.graphics.common@1.1",
-        "android.hardware.graphics.common@1.2",
-        "android.hidl.token@1.0-utils",
-        "libbase",
-        "libbinder",
         "libbufferhub",
         "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
-        "libcutils",
-        "libEGL",
-        "libGLESv2",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libinput",
-        "liblog",
-        "libnativewindow",
         "libpdx_default_transport",
-        "libsync",
-        "libui",
-        "libutils",
-        "libvndksupport",
     ],
 
     // bufferhub is not used when building libgui for vendors
@@ -145,43 +84,31 @@
 
     header_libs: [
         "libdvr_headers",
-        "libgui_headers",
-        "libnativebase_headers",
         "libpdx_headers",
     ],
-
-    export_shared_lib_headers: [
-        "libbinder",
-        "libEGL",
-        "libnativewindow",
-        "libui",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
-        "android.hardware.graphics.common@1.1",
-        "android.hardware.graphics.common@1.2",
-        "android.hidl.token@1.0-utils",
-    ],
-
-    export_header_lib_headers: [
-        "libgui_headers",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
 }
 
 // Used by media codec services exclusively as a static lib for
-// core bufferqueuesupport only.
+// core bufferqueue support only.
 cc_library_static {
     name: "libgui_bufferqueue_static",
     vendor_available: true,
 
+    cflags: [
+        "-DNO_BUFFERHUB",
+    ],
+
+    defaults: ["libgui_bufferqueue-defaults"],
+}
+
+// Common build config shared by libgui and libgui_bufferqueue_static.
+cc_defaults {
+    name: "libgui_bufferqueue-defaults",
+
     clang: true,
     cflags: [
         "-Wall",
         "-Werror",
-        "-DNO_BUFFERHUB",
     ],
 
     cppflags: [
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d87228f..5fb3f0b 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -59,13 +59,6 @@
     }
 }
 
-void BufferQueue::ProxyConsumerListener::onBufferAllocated(const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != nullptr) {
-        listener->onBufferAllocated(item);
-    }
-}
-
 void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
     sp<ConsumerListener> listener(mConsumerListener.promote());
     if (listener != nullptr) {
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index e226136..528bfb1 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -94,8 +94,6 @@
         // Skip this if we're in shared buffer mode and the queue is empty,
         // since in that case we'll just return the shared buffer.
         if (expectedPresent != 0 && !mCore->mQueue.empty()) {
-            const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
-
             // The 'expectedPresent' argument indicates when the buffer is expected
             // to be presented on-screen. If the buffer's desired present time is
             // earlier (less) than expectedPresent -- meaning it will be displayed
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index c94c6b3..3928bb9 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -539,13 +539,6 @@
                 return NO_INIT;
             }
 
-            if (mCore->mConsumerListener != nullptr) {
-                BufferItem item;
-                item.mGraphicBuffer = graphicBuffer;
-                item.mSlot = *outSlot;
-                mCore->mConsumerListener->onBufferAllocated(item);
-            }
-
             VALIDATE_CONSISTENCY();
         } // Autolock scope
     }
@@ -975,9 +968,6 @@
         item.mGraphicBuffer.clear();
     }
 
-    // Don't send the slot number through the callback since the consumer shouldn't need it
-    item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
-
     // Call back without the main BufferQueue lock held, but with the callback
     // lock held so we can ensure that callbacks occur in order
 
@@ -1433,13 +1423,6 @@
                 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
                         *slot);
 
-                if (mCore->mConsumerListener != nullptr) {
-                    BufferItem item;
-                    item.mGraphicBuffer = buffers[i];
-                    item.mSlot = *slot;
-                    mCore->mConsumerListener->onBufferAllocated(item);
-                }
-
                 // Make sure the erase is done after all uses of the slot
                 // iterator since it will be invalid after this point.
                 mCore->mFreeSlots.erase(slot);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 1e94cc1..abd9921 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -131,8 +131,6 @@
     }
 }
 
-void ConsumerBase::onBufferAllocated(const BufferItem& /*item*/) {}
-
 void ConsumerBase::onBuffersReleased() {
     Mutex::Autolock lock(mMutex);
 
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index ea9045c..85ac304 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -28,8 +28,7 @@
     ON_FRAME_REPLACED,
     ON_BUFFERS_RELEASED,
     ON_SIDEBAND_STREAM_CHANGED,
-    ON_BUFFER_ALLOCATED,
-    LAST = ON_BUFFER_ALLOCATED,
+    LAST = ON_SIDEBAND_STREAM_CHANGED,
 };
 
 } // Anonymous namespace
@@ -55,11 +54,6 @@
                                                                        item);
     }
 
-    void onBufferAllocated(const BufferItem& item) override {
-        callRemoteAsync<decltype(&IConsumerListener::onBufferAllocated)>(Tag::ON_BUFFER_ALLOCATED,
-                                                                         item);
-    }
-
     void onBuffersReleased() override {
         callRemoteAsync<decltype(&IConsumerListener::onBuffersReleased)>(Tag::ON_BUFFERS_RELEASED);
     }
@@ -95,8 +89,6 @@
             return callLocalAsync(data, reply, &IConsumerListener::onFrameAvailable);
         case Tag::ON_FRAME_REPLACED:
             return callLocalAsync(data, reply, &IConsumerListener::onFrameReplaced);
-        case Tag::ON_BUFFER_ALLOCATED:
-            return callLocalAsync(data, reply, &IConsumerListener::onBufferAllocated);
         case Tag::ON_BUFFERS_RELEASED:
             return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased);
         case Tag::ON_SIDEBAND_STREAM_CHANGED:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a8b1a4c..4372e16 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -142,6 +142,28 @@
         return result;
     }
 
+    virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeUint64(displayOrLayerStack);
+        status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_BY_ID, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("captureScreen failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result != NO_ERROR) {
+            ALOGE("captureScreen failed to readInt32: %d", result);
+            return result;
+        }
+
+        *outDataspace = static_cast<ui::Dataspace>(reply.readInt32());
+        *outBuffer = new GraphicBuffer();
+        reply.read(**outBuffer);
+        return result;
+    }
+
     virtual status_t captureLayers(
             const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
             const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
@@ -1042,6 +1064,19 @@
             }
             return NO_ERROR;
         }
+        case CAPTURE_SCREEN_BY_ID: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            uint64_t displayOrLayerStack = data.readUint64();
+            ui::Dataspace outDataspace = ui::Dataspace::V0_SRGB;
+            sp<GraphicBuffer> outBuffer;
+            status_t res = captureScreen(displayOrLayerStack, &outDataspace, &outBuffer);
+            reply->writeInt32(res);
+            if (res == NO_ERROR) {
+                reply->writeInt32(static_cast<int32_t>(outDataspace));
+                reply->write(*outBuffer);
+            }
+            return NO_ERROR;
+        }
         case CAPTURE_LAYERS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> layerHandleBinder = data.readStrongBinder();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 437cdd7..5d4367d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1572,6 +1572,13 @@
                    useIdentityTransform, rotation, false, outBuffer, ignored);
 }
 
+status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (s == nullptr) return NO_INIT;
+    return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer);
+}
+
 status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
                                          const ui::Dataspace reqDataSpace,
                                          const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index e64ba9b..cee1b81 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -1061,7 +1061,7 @@
 
 status_t H2BGraphicBufferProducer::attachBuffer(
         int* outSlot, const sp<GraphicBuffer>& buffer) {
-    AnwBuffer tBuffer;
+    AnwBuffer tBuffer{};
     wrapAs(&tBuffer, *buffer);
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->attachBuffer(tBuffer,
@@ -1076,7 +1076,7 @@
         int slot,
         const QueueBufferInput& input,
         QueueBufferOutput* output) {
-    HGraphicBufferProducer::QueueBufferInput tInput;
+    HGraphicBufferProducer::QueueBufferInput tInput{};
     native_handle_t* nh;
     if (!wrapAs(&tInput, &nh, input)) {
         ALOGE("H2BGraphicBufferProducer::queueBuffer - "
diff --git a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
index e039593..e891ec5 100644
--- a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "H2BGraphicBufferProducer@2.0"
+#define LOG_TAG "B2HGraphicBufferProducer@2.0"
 
 #include <android-base/logging.h>
 
@@ -30,13 +30,38 @@
 #include <vndk/hardware_buffer.h>
 
 namespace android {
-
 namespace hardware {
 namespace graphics {
 namespace bufferqueue {
 namespace V2_0 {
 namespace utils {
 
+namespace /* unnamed */ {
+
+using BQueueBufferInput = ::android::
+        IGraphicBufferProducer::QueueBufferInput;
+using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferInput;
+using BQueueBufferOutput = ::android::
+        IGraphicBufferProducer::QueueBufferOutput;
+using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferOutput;
+
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
+
+bool b2h(BQueueBufferOutput const& from, HQueueBufferOutput* to) {
+    to->width = from.width;
+    to->height = from.height;
+    to->transformHint = static_cast<int32_t>(from.transformHint);
+    to->numPendingBuffers = from.numPendingBuffers;
+    to->nextFrameNumber = from.nextFrameNumber;
+    to->bufferReplaced = from.bufferReplaced;
+    return true;
+}
+
+} // unnamed namespace
+
 // B2HGraphicBufferProducer
 // ========================
 
@@ -161,11 +186,7 @@
         int32_t slot,
         QueueBufferInput const& hInput,
         queueBuffer_cb _hidl_cb) {
-    using HOutput = QueueBufferOutput;
-    using BInput = BGraphicBufferProducer::QueueBufferInput;
-    using BOutput = BGraphicBufferProducer::QueueBufferOutput;
-
-    BInput bInput{
+    BQueueBufferInput bInput{
             hInput.timestamp,
             hInput.isAutoTimestamp,
             static_cast<android_dataspace>(hInput.dataSpace),
@@ -178,35 +199,32 @@
 
     // Convert crop.
     if (!h2b(hInput.crop, &bInput.crop)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
     // Convert surfaceDamage.
     if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
     // Convert fence.
     if (!h2b(hInput.fence, &bInput.fence)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
-    BOutput bOutput{};
+    BQueueBufferOutput bOutput{};
     HStatus hStatus{};
-    bool converted = b2h(
-            mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
-            &hStatus);
+    QueueBufferOutput hOutput{};
+    bool converted =
+            b2h(
+                mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
+                &hStatus) &&
+            b2h(bOutput, &hOutput);
 
-    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
-             HOutput{bOutput.width,
-                     bOutput.height,
-                     static_cast<int32_t>(bOutput.transformHint),
-                     bOutput.numPendingBuffers,
-                     bOutput.nextFrameNumber,
-                     bOutput.bufferReplaced});
+    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
     return {};
 }
 
@@ -236,33 +254,23 @@
         HConnectionType hConnectionType,
         bool producerControlledByApp,
         connect_cb _hidl_cb) {
-    using BOutput = BGraphicBufferProducer::QueueBufferOutput;
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     sp<BProducerListener> bListener = new H2BProducerListener(hListener);
-    if (!bListener) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+    int bConnectionType{};
+    if (!bListener || !h2b(hConnectionType, &bConnectionType)) {
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
-    int bConnectionType;
-    if (!h2b(hConnectionType, &bConnectionType)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
-        return {};
-    }
-    BOutput bOutput{};
+    BQueueBufferOutput bOutput{};
     HStatus hStatus{};
-    bool converted = b2h(
-            mBase->connect(bListener,
-                           bConnectionType,
-                           producerControlledByApp,
-                           &bOutput),
-            &hStatus);
-    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
-             HOutput{bOutput.width,
-                     bOutput.height,
-                     static_cast<int32_t>(bOutput.transformHint),
-                     bOutput.numPendingBuffers,
-                     bOutput.nextFrameNumber,
-                     bOutput.bufferReplaced});
+    QueueBufferOutput hOutput{};
+    bool converted =
+            b2h(mBase->connect(bListener,
+                               bConnectionType,
+                               producerControlledByApp,
+                               &bOutput),
+                &hStatus) &&
+            b2h(bOutput, &hOutput);
+    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
     return {};
 }
 
diff --git a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
index 1023ef1..2f5b73c 100644
--- a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
@@ -29,13 +29,54 @@
 #include <vndk/hardware_buffer.h>
 
 namespace android {
-
 namespace hardware {
 namespace graphics {
 namespace bufferqueue {
 namespace V2_0 {
 namespace utils {
 
+namespace /* unnamed */ {
+
+using BQueueBufferInput = ::android::
+        IGraphicBufferProducer::QueueBufferInput;
+using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferInput;
+using BQueueBufferOutput = ::android::
+        IGraphicBufferProducer::QueueBufferOutput;
+using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferOutput;
+
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
+
+bool b2h(BQueueBufferInput const& from, HQueueBufferInput* to,
+         HFenceWrapper* hFenceWrapper) {
+    to->timestamp = from.timestamp;
+    to->isAutoTimestamp = static_cast<bool>(from.isAutoTimestamp);
+    to->dataSpace = static_cast<int32_t>(from.dataSpace);
+    to->transform = static_cast<int32_t>(from.transform);
+    to->stickyTransform = static_cast<int32_t>(from.stickyTransform);
+    if (!b2h(from.crop, &to->crop) ||
+            !b2h(from.surfaceDamage, &to->surfaceDamage) ||
+            !b2h(from.fence, hFenceWrapper)) {
+        return false;
+    }
+    to->fence = hFenceWrapper->getHandle();
+    return true;
+}
+
+bool h2b(HQueueBufferOutput const& from, BQueueBufferOutput* to) {
+    to->width = from.width;
+    to->height = from.height;
+    to->transformHint = static_cast<uint32_t>(from.transformHint);
+    to->numPendingBuffers = from.numPendingBuffers;
+    to->nextFrameNumber = from.nextFrameNumber;
+    to->bufferReplaced = from.bufferReplaced;
+    return true;
+}
+
+} // unnamed namespace
+
 // H2BGraphicBufferProducer
 // ========================
 
@@ -209,47 +250,13 @@
         int slot,
         QueueBufferInput const& input,
         QueueBufferOutput* output) {
-    HRect hCrop{};
-    (void)b2h(input.crop, &hCrop);
-
-    using HInput = HGraphicBufferProducer::QueueBufferInput;
-    HInput hInput{
-            input.timestamp,
-            static_cast<bool>(input.isAutoTimestamp),
-            static_cast<int32_t>(input.dataSpace),
-            {}, // crop
-            static_cast<int32_t>(input.transform),
-            static_cast<int32_t>(input.stickyTransform),
-            {}, // fence
-            {}  // surfaceDamage
-            };
-
-    // Convert crop.
-    if (!b2h(input.crop, &hInput.crop)) {
-        LOG(ERROR) << "queueBuffer: corrupted input crop rectangle.";
-        return UNKNOWN_ERROR;
-    }
-
-    // Convert surfaceDamage.
-    size_t numRects;
-    Rect const* rectArray = input.surfaceDamage.getArray(&numRects);
-    hInput.surfaceDamage.resize(numRects);
-    for (size_t i = 0; i < numRects; ++i) {
-        if (!b2h(rectArray[i], &hInput.surfaceDamage[i])) {
-            LOG(ERROR) << "queueBuffer: corrupted input surface damage.";
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    // Convert fence.
+    HQueueBufferInput hInput{};
     HFenceWrapper hFenceWrapper;
-    if (!b2h(input.fence, &hFenceWrapper)) {
-        LOG(ERROR) << "queueBuffer: corrupted input fence.";
+    if (!b2h(input, &hInput, &hFenceWrapper)) {
+        LOG(ERROR) << "queueBuffer: corrupted input.";
         return UNKNOWN_ERROR;
     }
-    hInput.fence = hFenceWrapper.getHandle();
 
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     bool converted{};
     status_t bStatus{};
     Return<void> transResult = mBase->queueBuffer(
@@ -257,15 +264,8 @@
             hInput,
             [&converted, &bStatus, output](
                     HStatus hStatus,
-                    HOutput const& hOutput) {
-                converted = h2b(hStatus, &bStatus);
-                output->width = hOutput.width;
-                output->height = hOutput.height;
-                output->transformHint =
-                        static_cast<uint32_t>(hOutput.transformHint);
-                output->numPendingBuffers = hOutput.numPendingBuffers;
-                output->nextFrameNumber = hOutput.nextFrameNumber;
-                output->bufferReplaced = hOutput.bufferReplaced;
+                    HQueueBufferOutput const& hOutput) {
+                converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
             });
 
     if (!transResult.isOk()) {
@@ -332,7 +332,6 @@
         }
     }
 
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     bool converted{};
     status_t bStatus{};
     Return<void> transResult = mBase->connect(
@@ -341,15 +340,8 @@
             producerControlledByApp,
             [&converted, &bStatus, output](
                     HStatus hStatus,
-                    HOutput hOutput) {
-                converted = h2b(hStatus, &bStatus);
-                output->width = hOutput.width;
-                output->height = hOutput.height;
-                output->transformHint =
-                        static_cast<uint32_t>(hOutput.transformHint);
-                output->numPendingBuffers = hOutput.numPendingBuffers;
-                output->nextFrameNumber = hOutput.nextFrameNumber;
-                output->bufferReplaced = hOutput.bufferReplaced;
+                    HQueueBufferOutput const& hOutput) {
+                converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
             });
     if (!transResult.isOk()) {
         LOG(ERROR) << "connect: transaction failed.";
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index 721427b..da95274 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -61,7 +61,6 @@
         void onDisconnect() override;
         void onFrameAvailable(const BufferItem& item) override;
         void onFrameReplaced(const BufferItem& item) override;
-        void onBufferAllocated(const BufferItem& item) override;
         void onBuffersReleased() override;
         void onSidebandStreamChanged() override;
         void addAndGetFrameTimestamps(
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index aa13c0c..7db69ec 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -171,6 +171,9 @@
 
     // End functions required for backwards compatibility
 
+    // Value used to determine if present time is valid.
+    constexpr static int MAX_REASONABLE_NSEC = 1'000'000'000ULL; // 1 second
+
 private:
     sp<BufferQueueCore> mCore;
 
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 7c26482..366ced3 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -141,7 +141,6 @@
     // classes if they want the notification.
     virtual void onFrameAvailable(const BufferItem& item) override;
     virtual void onFrameReplaced(const BufferItem& item) override;
-    virtual void onBufferAllocated(const BufferItem& item) override;
     virtual void onBuffersReleased() override;
     virtual void onSidebandStreamChanged() override;
 
diff --git a/libs/gui/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
index 03fefbe..c082882 100644
--- a/libs/gui/include/gui/IConsumerListener.h
+++ b/libs/gui/include/gui/IConsumerListener.h
@@ -61,13 +61,6 @@
     // This is called without any lock held and can be called concurrently by multiple threads.
     virtual void onFrameReplaced(const BufferItem& /* item */) {} /* Asynchronous */
 
-    // onBufferAllocated is called to notify the buffer consumer that the BufferQueue has allocated
-    // a GraphicBuffer for a particular slot. Only the GraphicBuffer pointer and the slot ID will
-    // be populated.
-    //
-    // This is called without any lock held and can be called concurrently by multiple threads.
-    virtual void onBufferAllocated(const BufferItem& /* item */) {} /* Asynchronous */
-
     // onBuffersReleased is called to notify the buffer consumer that the BufferQueue has released
     // its references to one or more GraphicBuffers contained in its slots. The buffer consumer
     // should then call BufferQueue::getReleasedBuffers to retrieve the list of buffers.
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e8c7a39..fd67754 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -247,6 +247,9 @@
                              useIdentityTransform, rotation);
     }
 
+    virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) = 0;
+
     template <class AA>
     struct SpHash {
         size_t operator()(const sp<AA>& k) const { return std::hash<AA*>()(k.get()); }
@@ -473,6 +476,7 @@
         GET_ALLOWED_DISPLAY_CONFIGS,
         GET_DISPLAY_BRIGHTNESS_SUPPORT,
         SET_DISPLAY_BRIGHTNESS,
+        CAPTURE_SCREEN_BY_ID,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 9d34468..a038838 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -515,6 +515,8 @@
                             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                             uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
                             uint32_t rotation, sp<GraphicBuffer>* outBuffer);
+    static status_t capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                            sp<GraphicBuffer>* outBuffer);
     static status_t captureLayers(const sp<IBinder>& layerHandle, const ui::Dataspace reqDataSpace,
                                   const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                   float frameScale, sp<GraphicBuffer>* outBuffer);
diff --git a/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
index 0e57f20..029dcc0 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
@@ -68,7 +68,7 @@
     Return<void> requestBuffer(int32_t slot, HGraphicBufferProducer::requestBuffer_cb _hidl_cb) override {
         sp<GraphicBuffer> buf;
         status_t status = mBase->requestBuffer(slot, &buf);
-        AnwBuffer anwBuffer;
+        AnwBuffer anwBuffer{};
         if (buf != nullptr) {
             ::android::conversion::wrapAs(&anwBuffer, *buf);
         }
@@ -89,15 +89,15 @@
             uint32_t width, uint32_t height,
             ::android::hardware::graphics::common::V1_0::PixelFormat format, uint32_t usage,
             bool getFrameTimestamps, HGraphicBufferProducer::dequeueBuffer_cb _hidl_cb) override {
-        int slot;
+        int slot{};
         sp<Fence> fence;
         ::android::FrameEventHistoryDelta outTimestamps;
         status_t status = mBase->dequeueBuffer(
             &slot, &fence, width, height,
             static_cast<::android::PixelFormat>(format), usage, nullptr,
             getFrameTimestamps ? &outTimestamps : nullptr);
-        hidl_handle tFence;
-        HGraphicBufferProducer::FrameEventHistoryDelta tOutTimestamps;
+        hidl_handle tFence{};
+        HGraphicBufferProducer::FrameEventHistoryDelta tOutTimestamps{};
 
         native_handle_t* nh = nullptr;
         if ((fence == nullptr) || !::android::conversion::wrapAs(&tFence, &nh, *fence)) {
@@ -144,8 +144,8 @@
         sp<GraphicBuffer> outBuffer;
         sp<Fence> outFence;
         status_t status = mBase->detachNextBuffer(&outBuffer, &outFence);
-        AnwBuffer tBuffer;
-        hidl_handle tFence;
+        AnwBuffer tBuffer{};
+        hidl_handle tFence{};
 
         if (outBuffer == nullptr) {
             LOG(ERROR) << "TWGraphicBufferProducer::detachNextBuffer - "
@@ -185,7 +185,7 @@
     Return<void> queueBuffer(
             int32_t slot, const HGraphicBufferProducer::QueueBufferInput& input,
             HGraphicBufferProducer::queueBuffer_cb _hidl_cb) override {
-        HGraphicBufferProducer::QueueBufferOutput tOutput;
+        HGraphicBufferProducer::QueueBufferOutput tOutput{};
         BGraphicBufferProducer::QueueBufferInput lInput(
                 0, false, HAL_DATASPACE_UNKNOWN,
                 ::android::Rect(0, 0, 1, 1),
@@ -246,7 +246,7 @@
                 producerControlledByApp,
                 &lOutput);
 
-        HGraphicBufferProducer::QueueBufferOutput tOutput;
+        HGraphicBufferProducer::QueueBufferOutput tOutput{};
         std::vector<std::vector<native_handle_t*> > nhAA;
         if (!::android::conversion::wrapAs(&tOutput, &nhAA, lOutput)) {
             LOG(ERROR) << "TWGraphicBufferProducer::connect - "
@@ -320,11 +320,11 @@
         status_t status = mBase->getLastQueuedBuffer(
                 &lOutBuffer, &lOutFence, lOutTransformMatrix);
 
-        AnwBuffer tOutBuffer;
+        AnwBuffer tOutBuffer{};
         if (lOutBuffer != nullptr) {
             ::android::conversion::wrapAs(&tOutBuffer, *lOutBuffer);
         }
-        hidl_handle tOutFence;
+        hidl_handle tOutFence{};
         native_handle_t* nh = nullptr;
         if ((lOutFence == nullptr) || !::android::conversion::wrapAs(&tOutFence, &nh, *lOutFence)) {
             LOG(ERROR) << "TWGraphicBufferProducer::getLastQueuedBuffer - "
@@ -346,7 +346,7 @@
         ::android::FrameEventHistoryDelta lDelta;
         mBase->getFrameTimestamps(&lDelta);
 
-        HGraphicBufferProducer::FrameEventHistoryDelta tDelta;
+        HGraphicBufferProducer::FrameEventHistoryDelta tDelta{};
         std::vector<std::vector<native_handle_t*> > nhAA;
         if (!::android::conversion::wrapAs(&tDelta, &nhAA, lDelta)) {
             LOG(ERROR) << "TWGraphicBufferProducer::getFrameTimestamps - "
@@ -365,7 +365,7 @@
     }
 
     Return<void> getUniqueId(HGraphicBufferProducer::getUniqueId_cb _hidl_cb) override {
-        uint64_t outId;
+        uint64_t outId{};
         status_t status = mBase->getUniqueId(&outId);
         _hidl_cb(static_cast<int32_t>(status), outId);
         return Void();
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 014b1fa..db97fae 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -623,6 +623,10 @@
                            bool /*captureSecureLayers*/) override {
         return NO_ERROR;
     }
+    status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/,
+                           sp<GraphicBuffer>* /*outBuffer*/) override {
+        return NO_ERROR;
+    }
     virtual status_t captureLayers(
             const sp<IBinder>& /*parentHandle*/, sp<GraphicBuffer>* /*outBuffer*/,
             const ui::Dataspace /*reqDataspace*/, const ui::PixelFormat /*reqPixelFormat*/,
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index efe4bdf..46a8e9e 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -271,13 +271,6 @@
     extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
                                  glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
 
-    // In order to have protected contents in GPU composition, the OpenGL ES extension
-    // GL_EXT_protected_textures must be supported. If it's not supported, reset
-    // protected context to EGL_NO_CONTEXT to indicate that protected contents is not supported.
-    if (!extensions.hasProtectedTexture()) {
-        protectedContext = EGL_NO_CONTEXT;
-    }
-
     EGLSurface protectedDummy = EGL_NO_SURFACE;
     if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
         protectedDummy =
@@ -616,10 +609,6 @@
     const GLenum target = GL_TEXTURE_EXTERNAL_OES;
 
     glBindTexture(target, texName);
-    if (supportsProtectedContent()) {
-        glTexParameteri(target, GL_TEXTURE_PROTECTED_EXT,
-                        glImage.isProtected() ? GL_TRUE : GL_FALSE);
-    }
     if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
         glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
     }
@@ -799,10 +788,6 @@
 
     // Bind the texture and turn our EGLImage into a texture
     glBindTexture(GL_TEXTURE_2D, textureName);
-    if (supportsProtectedContent()) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PROTECTED_EXT,
-                        mInProtectedContext ? GL_TRUE : GL_FALSE);
-    }
     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
 
     // Bind the Framebuffer to render into
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index d9a986e..139987e 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -22,6 +22,13 @@
 #include <binder/IPermissionController.h>
 #include <binder/IServiceManager.h>
 
+/*
+ * The permission to use for activity recognition sensors (like step counter).
+ * See sensor types for more details on what sensors should require this
+ * permission.
+ */
+#define SENSOR_PERMISSION_ACTIVITY_RECOGNITION "android.permission.ACTIVITY_RECOGNITION"
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -116,7 +123,7 @@
         mStringType = SENSOR_STRING_TYPE_HEART_RATE;
         mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
         AppOpsManager appOps;
-        mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
+        mRequiredAppOp = appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         } break;
     case SENSOR_TYPE_LIGHT:
@@ -165,14 +172,22 @@
             mFlags |= SENSOR_FLAG_WAKE_UP;
         }
         break;
-    case SENSOR_TYPE_STEP_COUNTER:
+    case SENSOR_TYPE_STEP_COUNTER: {
         mStringType = SENSOR_STRING_TYPE_STEP_COUNTER;
+        mRequiredPermission = SENSOR_PERMISSION_ACTIVITY_RECOGNITION;
+        AppOpsManager appOps;
+        mRequiredAppOp =
+                appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
-        break;
-    case SENSOR_TYPE_STEP_DETECTOR:
+        } break;
+    case SENSOR_TYPE_STEP_DETECTOR: {
         mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR;
+        mRequiredPermission = SENSOR_PERMISSION_ACTIVITY_RECOGNITION;
+        AppOpsManager appOps;
+        mRequiredAppOp =
+                appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
-        break;
+        } break;
     case SENSOR_TYPE_TEMPERATURE:
         mStringType = SENSOR_STRING_TYPE_TEMPERATURE;
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 95c41bc..d5c46c6 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -173,8 +173,10 @@
     }
 }
 
+static const char* DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
+
 static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
-    "ro.hardware.egl",
+    DRIVER_SUFFIX_PROPERTY,
     "ro.board.platform",
 };
 
@@ -198,6 +200,8 @@
         // Secondly, try to load from driver apk.
         hnd = attempt_to_load_updated_driver(cnx);
     }
+
+    bool failToLoadFromDriverSuffixProperty = false;
     if (!hnd) {
         // Finally, try to load system driver, start by searching for the library name appended by
         // the system properties of the GLES userspace driver in both locations.
@@ -209,9 +213,11 @@
             if (property_get(key, prop, nullptr) <= 0) {
                 continue;
             }
-            hnd = attempt_to_load_system_driver(cnx, prop);
+            hnd = attempt_to_load_system_driver(cnx, prop, true);
             if (hnd) {
                 break;
+            } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+                failToLoadFromDriverSuffixProperty = true;
             }
         }
     }
@@ -222,7 +228,11 @@
         // i.e.:
         //      libGLES.so, or:
         //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
-        hnd = attempt_to_load_system_driver(cnx, nullptr);
+        hnd = attempt_to_load_system_driver(cnx, nullptr, true);
+    }
+
+    if (!hnd && !failToLoadFromDriverSuffixProperty) {
+        hnd = attempt_to_load_system_driver(cnx, nullptr, false);
     }
 
     if (!hnd) {
@@ -340,11 +350,11 @@
     }
 }
 
-static void* load_system_driver(const char* kind, const char* suffix) {
+static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
     ATRACE_CALL();
     class MatchFile {
     public:
-        static std::string find(const char* libraryName) {
+        static std::string find(const char* libraryName, const bool exact) {
             const char* const searchPaths[] = {
 #if defined(__LP64__)
                     "/vendor/lib64/egl",
@@ -356,8 +366,8 @@
             };
 
             for (auto dir : searchPaths) {
-                std::string absolutePath = dir + std::string("/") + libraryName + ".so";
-                if (!access(absolutePath.c_str(), R_OK)) {
+                std::string absolutePath;
+                if (find(absolutePath, libraryName, dir, exact)) {
                     return absolutePath;
                 }
             }
@@ -365,13 +375,53 @@
             // Driver not found. gah.
             return std::string();
         }
+    private:
+        static bool find(std::string& result,
+                const std::string& pattern, const char* const search, bool exact) {
+            if (exact) {
+                std::string absolutePath = std::string(search) + "/" + pattern + ".so";
+                if (!access(absolutePath.c_str(), R_OK)) {
+                    result = absolutePath;
+                    return true;
+                }
+                return false;
+            }
+
+            DIR* d = opendir(search);
+            if (d != nullptr) {
+                struct dirent* e;
+                while ((e = readdir(d)) != nullptr) {
+                    if (e->d_type == DT_DIR) {
+                        continue;
+                    }
+                    if (!strcmp(e->d_name, "libGLES_android.so")) {
+                        // always skip the software renderer
+                        continue;
+                    }
+                    if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
+                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
+                            result = std::string(search) + "/" + e->d_name;
+                            closedir(d);
+                            return true;
+                        }
+                    }
+                }
+                closedir(d);
+            }
+            return false;
+        }
     };
 
     std::string libraryName = std::string("lib") + kind;
     if (suffix) {
         libraryName += std::string("_") + suffix;
+    } else if (!exact) {
+        // Deprecated: we look for files that match
+        //      libGLES_*.so, or:
+        //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+        libraryName += std::string("_");
     }
-    std::string absolutePath = MatchFile::find(libraryName.c_str());
+    std::string absolutePath = MatchFile::find(libraryName.c_str(), exact);
     if (absolutePath.empty()) {
         // this happens often, we don't want to log an error
         return nullptr;
@@ -458,14 +508,14 @@
                 if (property_get(key, prop, nullptr) <= 0) {
                     continue;
                 }
-                void* dso = load_system_driver("EGL", prop);
+                void* dso = load_system_driver("EGL", prop, true);
                 if (dso) {
                     cnx->vendorEGL = dso;
                     break;
                 }
             }
             if (!cnx->vendorEGL) {
-                cnx->vendorEGL = load_system_driver("EGL", nullptr);
+                cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
             }
         }
     } else {
@@ -562,26 +612,27 @@
 #endif
 }
 
-Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix) {
+Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
+                                                        const bool exact) {
     ATRACE_CALL();
     android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
     driver_t* hnd = nullptr;
-    void* dso = load_system_driver("GLES", suffix);
+    void* dso = load_system_driver("GLES", suffix, exact);
     if (dso) {
         initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
         hnd = new driver_t(dso);
         return hnd;
     }
-    dso = load_system_driver("EGL", suffix);
+    dso = load_system_driver("EGL", suffix, exact);
     if (dso) {
         initialize_api(dso, cnx, EGL);
         hnd = new driver_t(dso);
 
-        dso = load_system_driver("GLESv1_CM", suffix);
+        dso = load_system_driver("GLESv1_CM", suffix, exact);
         initialize_api(dso, cnx, GLESv1_CM);
         hnd->set(dso, GLESv1_CM);
 
-        dso = load_system_driver("GLESv2", suffix);
+        dso = load_system_driver("GLESv2", suffix, exact);
         initialize_api(dso, cnx, GLESv2);
         hnd->set(dso, GLESv2);
     }
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index f6b67ab..0292d02 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -57,7 +57,7 @@
     Loader();
     driver_t* attempt_to_load_angle(egl_connection_t* cnx);
     driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
-    driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix);
+    driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
     void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index f5d4826..6235f06 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -122,6 +122,13 @@
         data.writeInt32((int32_t) event);
         return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual status_t releaseRecorder(audio_unique_id_t riid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32((int32_t) riid);
+        return remote()->transact(RELEASE_RECORDER, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index b874411..31a2dab 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3611,8 +3611,9 @@
 }
 
 void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
-    dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
-    dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
+    dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
+    dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
+    dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
     dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
 
     if (!mFocusedApplicationHandlesByDisplay.empty()) {
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 659329e..be75c64 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -467,11 +467,6 @@
                               asBaseType(INTERNAL_WAKE), &eventFlagState);
         availableEvents = mEventQueue->availableToRead();
 
-        if ((eventFlagState & asBaseType(EventQueueFlagBits::READ_AND_PROCESS)) &&
-                availableEvents == 0) {
-            ALOGW("Event FMQ wake without any events");
-        }
-
         if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
             ALOGD("Event FMQ internal wake, returning from poll with no events");
             return DEAD_OBJECT;
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c4cfdc6..0e40940 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -285,8 +285,9 @@
                         scratch[count++] = buffer[i];
                     }
                 } else {
-                    // Regular sensor event, just copy it to the scratch buffer.
-                    if (hasSensorAccess()) {
+                    // Regular sensor event, just copy it to the scratch buffer after checking
+                    // the AppOp.
+                    if (hasSensorAccess() && noteOpIfRequired(buffer[i])) {
                         scratch[count++] = buffer[i];
                     }
                 }
@@ -386,6 +387,16 @@
     return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
 }
 
+bool SensorService::SensorEventConnection::noteOpIfRequired(const sensors_event_t& event) {
+    bool success = true;
+    const auto iter = mHandleToAppOp.find(event.sensor);
+    if (iter != mHandleToAppOp.end()) {
+        int32_t appOpMode = mService->sAppOpsManager.noteOp((*iter).second, mUid, mOpPackageName);
+        success = (appOpMode == AppOpsManager::MODE_ALLOWED);
+    }
+    return success;
+}
+
 void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
                                                                  int count) {
     sensors_event_t *eventCache_new;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 7077880..fd881cb 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <unordered_map>
 
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
@@ -134,6 +135,9 @@
     // privacy not being enabled.
     bool hasSensorAccess();
 
+    // Call noteOp for the sensor if the sensor requires a permission
+    bool noteOpIfRequired(const sensors_event_t& event);
+
     sp<SensorService> const mService;
     sp<BitTube> mChannel;
     uid_t mUid;
@@ -181,6 +185,10 @@
     mutable Mutex mDestroyLock;
     bool mDestroyed;
     bool mHasSensorAccess;
+
+    // Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
+    // valid mapping for sensors that require a permission in order to reduce the lookup time.
+    std::unordered_map<int32_t, int32_t> mHandleToAppOp;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 0269990..fa1e232 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,8 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <android/content/pm/IPackageManagerNative.h>
 #include <binder/ActivityManager.h>
-#include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
@@ -75,6 +75,9 @@
 const char* SensorService::WAKE_LOCK_NAME = "SensorService_wakelock";
 uint8_t SensorService::sHmacGlobalKey[128] = {};
 bool SensorService::sHmacGlobalKeyIsValid = false;
+std::map<String16, int> SensorService::sPackageTargetVersion;
+Mutex SensorService::sPackageTargetVersionLock;
+AppOpsManager SensorService::sAppOpsManager;
 
 #define SENSOR_SERVICE_DIR "/data/system/sensor_service"
 #define SENSOR_SERVICE_HMAC_KEY_FILE  SENSOR_SERVICE_DIR "/hmac_key"
@@ -1394,6 +1397,14 @@
         checkWakeLockStateLocked();
     }
 
+    {
+        Mutex::Autolock packageLock(sPackageTargetVersionLock);
+        auto iter = sPackageTargetVersion.find(c->mOpPackageName);
+        if (iter != sPackageTargetVersion.end()) {
+            sPackageTargetVersion.erase(iter);
+        }
+    }
+
     SensorDevice& dev(SensorDevice::getInstance());
     dev.notifyConnectionDestroyed(c);
 }
@@ -1539,6 +1550,10 @@
     if (err == NO_ERROR) {
         connection->updateLooperRegistration(mLooper);
 
+        if (sensor->getSensor().getRequiredPermission().size() > 0) {
+            connection->mHandleToAppOp[handle] = sensor->getSensor().getRequiredAppOp();
+        }
+
         mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex) =
                 SensorRegistrationInfo(handle, connection->getPackageName(),
                                        samplingPeriodNs, maxBatchReportLatencyNs, true);
@@ -1663,13 +1678,53 @@
 
 bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
         const String16& opPackageName) {
-    const String8& requiredPermission = sensor.getRequiredPermission();
-
-    if (requiredPermission.length() <= 0) {
+    // Check if a permission is required for this sensor
+    if (sensor.getRequiredPermission().length() <= 0) {
         return true;
     }
 
+    const int32_t opCode = sensor.getRequiredAppOp();
+    const int32_t appOpMode = sAppOpsManager.checkOp(opCode,
+            IPCThreadState::self()->getCallingUid(), opPackageName);
+    bool appOpAllowed = appOpMode == AppOpsManager::MODE_ALLOWED;
+
+    bool canAccess = false;
+    if (hasPermissionForSensor(sensor)) {
+        // Ensure that the AppOp is allowed, or that there is no necessary app op for the sensor
+        if (opCode < 0 || appOpAllowed) {
+            canAccess = true;
+        }
+    } else if (sensor.getType() == SENSOR_TYPE_STEP_COUNTER ||
+            sensor.getType() == SENSOR_TYPE_STEP_DETECTOR) {
+        int targetSdkVersion = getTargetSdkVersion(opPackageName);
+        // Allow access to the sensor if the application targets pre-Q, which is before the
+        // requirement to hold the AR permission to access Step Counter and Step Detector events
+        // was introduced, and the user hasn't revoked the app op.
+        //
+        // Verifying the app op is required to ensure that the user hasn't revoked the necessary
+        // permissions to access the Step Detector and Step Counter when the application targets
+        // pre-Q. Without this check, if the user revokes the pre-Q install-time GMS Core AR
+        // permission, the app would still be able to receive Step Counter and Step Detector events.
+        if (appOpAllowed &&
+                targetSdkVersion > 0 &&
+                targetSdkVersion <= __ANDROID_API_P__) {
+            canAccess = true;
+        }
+    }
+
+    if (canAccess) {
+        sAppOpsManager.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName);
+    } else {
+        ALOGE("%s a sensor (%s) without holding its required permission: %s",
+                operation, sensor.getName().string(), sensor.getRequiredPermission().string());
+    }
+
+    return canAccess;
+}
+
+bool SensorService::hasPermissionForSensor(const Sensor& sensor) {
     bool hasPermission = false;
+    const String8& requiredPermission = sensor.getRequiredPermission();
 
     // Runtime permissions can't use the cache as they may change.
     if (sensor.isRequiredPermissionRuntime()) {
@@ -1678,25 +1733,31 @@
     } else {
         hasPermission = PermissionCache::checkCallingPermission(String16(requiredPermission));
     }
+    return hasPermission;
+}
 
-    if (!hasPermission) {
-        ALOGE("%s a sensor (%s) without holding its required permission: %s",
-                operation, sensor.getName().string(), sensor.getRequiredPermission().string());
-        return false;
-    }
-
-    const int32_t opCode = sensor.getRequiredAppOp();
-    if (opCode >= 0) {
-        AppOpsManager appOps;
-        if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName)
-                        != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("%s a sensor (%s) without enabled required app op: %d",
-                    operation, sensor.getName().string(), opCode);
-            return false;
+int SensorService::getTargetSdkVersion(const String16& opPackageName) {
+    Mutex::Autolock packageLock(sPackageTargetVersionLock);
+    int targetSdkVersion = -1;
+    auto entry = sPackageTargetVersion.find(opPackageName);
+    if (entry != sPackageTargetVersion.end()) {
+        targetSdkVersion = entry->second;
+    } else {
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("package_native"));
+        if (binder != nullptr) {
+            sp<content::pm::IPackageManagerNative> packageManager =
+                    interface_cast<content::pm::IPackageManagerNative>(binder);
+            if (packageManager != nullptr) {
+                binder::Status status = packageManager->getTargetSdkVersionForPackage(
+                        opPackageName, &targetSdkVersion);
+                if (!status.isOk()) {
+                    targetSdkVersion = -1;
+                }
+            }
         }
+        sPackageTargetVersion[opPackageName] = targetSdkVersion;
     }
-
-    return true;
+    return targetSdkVersion;
 }
 
 void SensorService::checkWakeLockState() {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 5076967..e6ec96d 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -20,6 +20,7 @@
 #include "SensorList.h"
 #include "RecentEventLogger.h"
 
+#include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IUidObserver.h>
 #include <cutils/compiler.h>
@@ -243,6 +244,8 @@
             sensors_event_t const* buffer, const int count);
     static bool canAccessSensor(const Sensor& sensor, const char* operation,
             const String16& opPackageName);
+    static bool hasPermissionForSensor(const Sensor& sensor);
+    static int getTargetSdkVersion(const String16& opPackageName);
     // SensorService acquires a partial wakelock for delivering events from wake up sensors. This
     // method checks whether all the events from these wake up sensors have been delivered to the
     // corresponding applications, if yes the wakelock is released.
@@ -343,6 +346,10 @@
 
     sp<UidPolicy> mUidPolicy;
     sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
+    static AppOpsManager sAppOpsManager;
+    static std::map<String16, int> sPackageTargetVersion;
+    static Mutex sPackageTargetVersionLock;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 4ea587d..06caf1e 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -534,11 +534,13 @@
 
 // transaction
 void BufferLayer::notifyAvailableFrames() {
-    auto headFrameNumber = getHeadFrameNumber();
-    bool headFenceSignaled = fenceHasSignaled();
+    const auto headFrameNumber = getHeadFrameNumber();
+    const bool headFenceSignaled = fenceHasSignaled();
+    const bool presentTimeIsCurrent = framePresentTimeIsCurrent();
     Mutex::Autolock lock(mLocalSyncPointMutex);
     for (auto& point : mLocalSyncPoints) {
-        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
+        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
+            presentTimeIsCurrent) {
             point->setFrameAvailable();
         }
     }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index dc103cb..b679380 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -114,6 +114,7 @@
     // -----------------------------------------------------------------------
 private:
     virtual bool fenceHasSignaled() const = 0;
+    virtual bool framePresentTimeIsCurrent() const = 0;
 
     virtual nsecs_t getDesiredPresentTime() = 0;
     virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index fc98dc8..6709fb4 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -478,20 +478,15 @@
     }
 }
 
-void BufferLayerConsumer::onBufferAllocated(const BufferItem& item) {
-    if (item.mGraphicBuffer != nullptr) {
-        std::shared_ptr<Image> image = std::make_shared<Image>(item.mGraphicBuffer, mRE);
-        std::shared_ptr<Image> oldImage;
-        {
-            std::lock_guard<std::mutex> lock(mImagesMutex);
-            oldImage = mImages[item.mSlot];
-            if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr ||
-                oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) {
-                mImages[item.mSlot] = std::make_shared<Image>(item.mGraphicBuffer, mRE);
-            }
-            image = mImages[item.mSlot];
+void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) {
+    if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
+        std::lock_guard<std::mutex> lock(mImagesMutex);
+        const std::shared_ptr<Image>& oldImage = mImages[item.mSlot];
+        if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr ||
+            oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) {
+            mImages[item.mSlot] = std::make_shared<Image>(item.mGraphicBuffer, mRE);
+            mRE.cacheExternalTextureBuffer(item.mGraphicBuffer);
         }
-        mRE.cacheExternalTextureBuffer(image->graphicBuffer());
     }
 }
 
@@ -533,5 +528,4 @@
         mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId());
     }
 }
-
 }; // namespace android
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 0f0655d..e3f6100 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -176,6 +176,7 @@
     // setConsumerUsageBits overrides the ConsumerBase method to OR
     // DEFAULT_USAGE_FLAGS to usage.
     status_t setConsumerUsageBits(uint64_t usage);
+    void onBufferAvailable(const BufferItem& item) EXCLUDES(mImagesMutex);
 
 protected:
     // abandonLocked overrides the ConsumerBase method to clear
@@ -241,7 +242,6 @@
 
     // IConsumerListener interface
     void onDisconnect() override;
-    void onBufferAllocated(const BufferItem& item) override EXCLUDES(mImagesMutex);
     void onSidebandStreamChanged() override;
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
                                   FrameEventHistoryDelta* outDelta) override;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index ff5f271..3d51ec3 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
+#undef LOG_TAG
+#define LOG_TAG "BufferQueueLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/LayerCompositionState.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <gui/BufferQueueConsumer.h>
 #include <system/window.h>
 
 #include "BufferQueueLayer.h"
@@ -133,6 +137,15 @@
     return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
 }
 
+bool BufferQueueLayer::framePresentTimeIsCurrent() const {
+    if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
+        return true;
+    }
+
+    Mutex::Autolock lock(mQueueItemLock);
+    return mQueueItems[0].mTimestamp <= mFlinger->mScheduler->expectedPresentTime();
+}
+
 nsecs_t BufferQueueLayer::getDesiredPresentTime() {
     return mConsumer->getTimestamp();
 }
@@ -185,7 +198,37 @@
 
 uint64_t BufferQueueLayer::getFrameNumber() const {
     Mutex::Autolock lock(mQueueItemLock);
-    return mQueueItems[0].mFrameNumber;
+    uint64_t frameNumber = mQueueItems[0].mFrameNumber;
+
+    // The head of the queue will be dropped if there are signaled and timely frames behind it
+    nsecs_t expectedPresentTime = mFlinger->mScheduler->expectedPresentTime();
+
+    if (isRemovedFromCurrentState()) {
+        expectedPresentTime = 0;
+    }
+
+    for (int i = 1; i < mQueueItems.size(); i++) {
+        const bool fenceSignaled =
+                mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+        if (!fenceSignaled) {
+            break;
+        }
+
+        // We don't drop frames without explicit timestamps
+        if (mQueueItems[i].mIsAutoTimestamp) {
+            break;
+        }
+
+        const nsecs_t desiredPresent = mQueueItems[i].mTimestamp;
+        if (desiredPresent < expectedPresentTime - BufferQueueConsumer::MAX_REASONABLE_NSEC ||
+            desiredPresent > expectedPresentTime) {
+            break;
+        }
+
+        frameNumber = mQueueItems[i].mFrameNumber;
+    }
+
+    return frameNumber;
 }
 
 bool BufferQueueLayer::getAutoRefresh() const {
@@ -395,6 +438,7 @@
 }
 
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
+    ATRACE_CALL();
     // Add this buffer from our internal queue tracker
     { // Autolock scope
         if (mFlinger->mUseSmart90ForVideo) {
@@ -435,9 +479,11 @@
     } else {
         mFlinger->signalLayerUpdate();
     }
+    mConsumer->onBufferAvailable(item);
 }
 
 void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
+    ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mQueueItemLock);
 
@@ -459,6 +505,7 @@
         mLastFrameNumberReceived = item.mFrameNumber;
         mQueueItemCondition.broadcast();
     }
+    mConsumer->onBufferAvailable(item);
 }
 
 void BufferQueueLayer::onSidebandStreamChanged() {
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index a2aad17..7def33a 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -61,6 +61,7 @@
     // -----------------------------------------------------------------------
 public:
     bool fenceHasSignaled() const override;
+    bool framePresentTimeIsCurrent() const override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 6ef4518..a740afb 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -374,6 +374,14 @@
     return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
 }
 
+bool BufferStateLayer::framePresentTimeIsCurrent() const {
+    if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
+        return true;
+    }
+
+    return mDesiredPresentTime <= mFlinger->mScheduler->expectedPresentTime();
+}
+
 nsecs_t BufferStateLayer::getDesiredPresentTime() {
     return mDesiredPresentTime;
 }
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 13186dd..4e2bc45 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -101,6 +101,7 @@
     // Interface implementation for BufferLayer
     // -----------------------------------------------------------------------
     bool fenceHasSignaled() const override;
+    bool framePresentTimeIsCurrent() const override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index e69b99f..e21128c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -50,6 +50,9 @@
     // Returns the bounds of the surface
     virtual const ui::Size& getSize() const = 0;
 
+    // Returns whether the surface is protected.
+    virtual bool isProtected() const = 0;
+
     // Gets the latest fence to pass to the HWC to signal that the surface
     // buffer is done rendering
     virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 3c79084..0f57315 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -45,6 +45,7 @@
     bool isValid() const override;
     void initialize() override;
     const ui::Size& getSize() const override;
+    bool isProtected() const override { return mProtected; }
 
     const sp<Fence>& getClientTargetAcquireFence() const override;
     void setBufferDataspace(ui::Dataspace) override;
@@ -78,6 +79,7 @@
     sp<GraphicBuffer> mGraphicBuffer;
     const sp<DisplaySurface> mDisplaySurface;
     ui::Size mSize;
+    bool mProtected{false};
     std::uint32_t mPageFlipCount{0};
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index 1562f58..ca2299a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -31,6 +31,7 @@
     MOCK_CONST_METHOD0(isValid, bool());
     MOCK_METHOD0(initialize, void());
     MOCK_CONST_METHOD0(getSize, const ui::Size&());
+    MOCK_CONST_METHOD0(isProtected, bool());
     MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
     MOCK_METHOD1(setDisplaySize, void(const ui::Size&));
     MOCK_METHOD1(setProtected, void(bool));
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b5a6678..3fcd9d1 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -101,6 +101,9 @@
     }
     const int status = native_window_set_usage(mNativeWindow.get(), usageFlags);
     ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status);
+    if (status == NO_ERROR) {
+        mProtected = useProtected;
+    }
 }
 
 status_t RenderSurface::beginFrame(bool mustRecompose) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 9960478..f75a4dc 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -143,16 +143,40 @@
  */
 
 TEST_F(RenderSurfaceTest, setProtectedTrueEnablesProtection) {
+    EXPECT_FALSE(mSurface.isProtected());
     EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
             .WillOnce(Return(NO_ERROR));
 
     mSurface.setProtected(true);
+    EXPECT_TRUE(mSurface.isProtected());
 }
 
 TEST_F(RenderSurfaceTest, setProtectedFalseDisablesProtection) {
+    EXPECT_FALSE(mSurface.isProtected());
     EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR));
 
     mSurface.setProtected(false);
+    EXPECT_FALSE(mSurface.isProtected());
+}
+
+TEST_F(RenderSurfaceTest, setProtectedEnableAndDisable) {
+    EXPECT_FALSE(mSurface.isProtected());
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
+            .WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR));
+
+    mSurface.setProtected(true);
+    EXPECT_TRUE(mSurface.isProtected());
+    mSurface.setProtected(false);
+    EXPECT_FALSE(mSurface.isProtected());
+}
+
+TEST_F(RenderSurfaceTest, setProtectedEnableWithError) {
+    EXPECT_FALSE(mSurface.isProtected());
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
+            .WillOnce(Return(INVALID_OPERATION));
+    mSurface.setProtected(true);
+    EXPECT_FALSE(mSurface.isProtected());
 }
 
 /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index fcde8da..1e5c25f 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -38,7 +38,7 @@
     }
 
     mLayer = mClient->getLayerUser(mIBinder);
-    mLayer->setCrop_legacy(Rect(0, 0, 200, 100), true);
+    mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true);
     mLayer->setLayer(INT32_MAX - 2);
 
     return true;
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 252ff0d..3684260 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -168,11 +168,8 @@
         mPhaseCallback(std::make_unique<SamplingOffsetCallback>(*this, mScheduler,
                                                                 tunables.mSamplingOffset)),
         lastSampleTime(0ns) {
-    {
-        std::lock_guard threadLock(mThreadMutex);
-        mThread = std::thread([this]() { threadMain(); });
-        pthread_setname_np(mThread.native_handle(), "RegionSamplingThread");
-    }
+    mThread = std::thread([this]() { threadMain(); });
+    pthread_setname_np(mThread.native_handle(), "RegionSamplingThread");
     mIdleTimer.start();
 }
 
@@ -186,12 +183,11 @@
     mIdleTimer.stop();
 
     {
-        std::lock_guard lock(mMutex);
+        std::lock_guard lock(mThreadControlMutex);
         mRunning = false;
         mCondition.notify_one();
     }
 
-    std::lock_guard threadLock(mThreadMutex);
     if (mThread.joinable()) {
         mThread.join();
     }
@@ -205,17 +201,17 @@
 
     sp<IBinder> asBinder = IInterface::asBinder(listener);
     asBinder->linkToDeath(this);
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.emplace(wp<IBinder>(asBinder), Descriptor{samplingArea, stopLayer, listener});
 }
 
 void RegionSamplingThread::removeListener(const sp<IRegionSamplingListener>& listener) {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.erase(wp<IBinder>(IInterface::asBinder(listener)));
 }
 
 void RegionSamplingThread::checkForStaleLuma() {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mThreadControlMutex);
 
     if (mDiscardedFrames) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForZeroPhase));
@@ -233,7 +229,7 @@
 }
 
 void RegionSamplingThread::doSample() {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mThreadControlMutex);
     auto now = std::chrono::nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     if (lastSampleTime + mTunables.mSamplingPeriod > now) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::idleTimerWaiting));
@@ -254,7 +250,7 @@
 }
 
 void RegionSamplingThread::binderDied(const wp<IBinder>& who) {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.erase(who);
 }
 
@@ -315,6 +311,7 @@
 
 void RegionSamplingThread::captureSample() {
     ATRACE_CALL();
+    std::lock_guard lock(mSamplingMutex);
 
     if (mDescriptors.empty()) {
         return;
@@ -377,24 +374,18 @@
         mFlinger.traverseLayersInDisplay(device, filterVisitor);
     };
 
-    const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(),
-                              PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+    sp<GraphicBuffer> buffer = nullptr;
+    if (mCachedBuffer && mCachedBuffer->getWidth() == sampledArea.getWidth() &&
+        mCachedBuffer->getHeight() == sampledArea.getHeight()) {
+        buffer = mCachedBuffer;
+    } else {
+        const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
+        buffer = new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(),
+                                   PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+    }
 
-    // When calling into SF, we post a message into the SF message queue (so the
-    // screen capture runs on the main thread). This message blocks until the
-    // screenshot is actually captured, but before the capture occurs, the main
-    // thread may perform a normal refresh cycle. At the end of this cycle, it
-    // can request another sample (because layers changed), which triggers a
-    // call into sampleNow. When sampleNow attempts to grab the mutex, we can
-    // deadlock.
-    //
-    // To avoid this, we drop the mutex while we call into SF.
-    mMutex.unlock();
     bool ignored;
     mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false, ignored);
-    mMutex.lock();
 
     std::vector<Descriptor> activeDescriptors;
     for (const auto& descriptor : descriptors) {
@@ -415,18 +406,28 @@
     for (size_t d = 0; d < activeDescriptors.size(); ++d) {
         activeDescriptors[d].listener->onSampleCollected(lumas[d]);
     }
+
+    // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that:
+    // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer
+    // happens in this thread, as opposed to the main thread.
+    // 2) The listener(s) receive their notifications prior to freeing the buffer.
+    mCachedBuffer = buffer;
     ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::noWorkNeeded));
 }
 
-void RegionSamplingThread::threadMain() {
-    std::lock_guard lock(mMutex);
+// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
+void RegionSamplingThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
+    std::unique_lock<std::mutex> lock(mThreadControlMutex);
     while (mRunning) {
         if (mSampleRequested) {
             mSampleRequested = false;
+            lock.unlock();
             captureSample();
+            lock.lock();
         }
-        mCondition.wait(mMutex,
-                        [this]() REQUIRES(mMutex) { return mSampleRequested || !mRunning; });
+        mCondition.wait(lock, [this]() REQUIRES(mThreadControlMutex) {
+            return mSampleRequested || !mRunning;
+        });
     }
 }
 
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 9796429..08134e6 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -24,13 +24,13 @@
 
 #include <android-base/thread_annotations.h>
 #include <binder/IBinder.h>
+#include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/StrongPointer.h>
 #include "Scheduler/IdleTimer.h"
 
 namespace android {
 
-class GraphicBuffer;
 class IRegionSamplingListener;
 class Layer;
 class Scheduler;
@@ -100,7 +100,7 @@
     void binderDied(const wp<IBinder>& who) override;
     void checkForStaleLuma();
 
-    void captureSample() REQUIRES(mMutex);
+    void captureSample();
     void threadMain();
 
     SurfaceFlinger& mFlinger;
@@ -110,17 +110,18 @@
 
     std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback;
 
-    std::mutex mThreadMutex;
-    std::thread mThread GUARDED_BY(mThreadMutex);
+    std::thread mThread;
 
-    std::mutex mMutex;
+    std::mutex mThreadControlMutex;
     std::condition_variable_any mCondition;
-    bool mRunning GUARDED_BY(mMutex) = true;
-    bool mSampleRequested GUARDED_BY(mMutex) = false;
+    bool mRunning GUARDED_BY(mThreadControlMutex) = true;
+    bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false;
+    bool mDiscardedFrames GUARDED_BY(mThreadControlMutex) = false;
+    std::chrono::nanoseconds lastSampleTime GUARDED_BY(mThreadControlMutex);
 
-    std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mMutex);
-    std::chrono::nanoseconds lastSampleTime GUARDED_BY(mMutex);
-    bool mDiscardedFrames GUARDED_BY(mMutex) = false;
+    std::mutex mSamplingMutex;
+    std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex);
+    sp<GraphicBuffer> mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 871f556..abf7b71 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -210,17 +210,14 @@
             const nsecs_t baseTime = now - mReferenceTime;
             const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
             const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
-            listener.mLastEventTime = predictedReference + mPhase + listener.mPhase;
-            // If we're very close in time to the predicted last event time,
-            // and we're not very close to the next predicted last event time
-            // then we need to back up the last event time so that we can
-            // attempt to fire an event immediately.
-            //
-            // Otherwise, keep the last event time that we predicted so that
-            // we don't wake up early.
-            if (isShorterThanPeriod(now - listener.mLastEventTime) &&
-                !isShorterThanPeriod(listener.mLastEventTime + mPeriod - now)) {
-                listener.mLastEventTime -= mPeriod;
+            const nsecs_t phaseCorrection = mPhase + listener.mPhase;
+            const nsecs_t predictedLastEventTime = predictedReference + phaseCorrection;
+            if (predictedLastEventTime >= now) {
+                // Make sure that the last event time does not exceed the current time.
+                // If it would, then back the last event time by a period.
+                listener.mLastEventTime = predictedLastEventTime - mPeriod;
+            } else {
+                listener.mLastEventTime = predictedLastEventTime;
             }
         } else {
             listener.mLastEventTime = now + mPhase - mWakeupLatency;
@@ -316,7 +313,7 @@
 
     // Sanity check that the duration is close enough in length to a period without
     // falling into double-rate vsyncs.
-    bool isShorterThanPeriod(nsecs_t duration) {
+    bool isCloseToPeriod(nsecs_t duration) {
         // Ratio of 3/5 is arbitrary, but it must be greater than 1/2.
         return duration < (3 * mPeriod) / 5;
     }
@@ -332,7 +329,7 @@
             nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo);
 
             if (t < now) {
-                if (isShorterThanPeriod(now - eventListener.mLastCallbackTime)) {
+                if (isCloseToPeriod(now - eventListener.mLastCallbackTime)) {
                     eventListener.mLastEventTime = t;
                     ALOGV("[%s] [%s] Skipping event due to model error", mName,
                           eventListener.mName);
@@ -392,7 +389,7 @@
 
         // Check that it's been slightly more than half a period since the last
         // event so that we don't accidentally fall into double-rate vsyncs
-        if (isShorterThanPeriod(t - listener.mLastEventTime)) {
+        if (isCloseToPeriod(t - listener.mLastEventTime)) {
             t += mPeriod;
             ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2ca5c02..23c6e89 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -590,7 +590,11 @@
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
-    postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
+    std::lock_guard lock(mTexturePoolMutex);
+    // We don't change the pool size, so the fix-up logic in postComposition will decide whether
+    // to actually delete this or not based on mTexturePoolSize
+    mTexturePool.push_back(texture);
+    ATRACE_INT("TexturePoolSize", mTexturePool.size());
 }
 
 // Do not call property_set on main thread which will be blocked by init
@@ -1632,7 +1636,7 @@
             }
 
             // For now, only propagate backpressure when missing a hwc frame.
-            if (hwcFrameMissed) {
+            if (hwcFrameMissed && !gpuFrameMissed) {
                 if (mPropagateBackpressure) {
                     signalLayerUpdate();
                     break;
@@ -2078,12 +2082,18 @@
 
     {
         std::lock_guard lock(mTexturePoolMutex);
-        const size_t refillCount = mTexturePoolSize - mTexturePool.size();
-        if (refillCount > 0) {
+        if (mTexturePool.size() < mTexturePoolSize) {
+            const size_t refillCount = mTexturePoolSize - mTexturePool.size();
             const size_t offset = mTexturePool.size();
             mTexturePool.resize(mTexturePoolSize);
             getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
             ATRACE_INT("TexturePoolSize", mTexturePool.size());
+        } else if (mTexturePool.size() > mTexturePoolSize) {
+            const size_t deleteCount = mTexturePool.size() - mTexturePoolSize;
+            const size_t offset = mTexturePoolSize;
+            getRenderEngine().deleteTextures(deleteCount, mTexturePool.data() + offset);
+            mTexturePool.resize(mTexturePoolSize);
+            ATRACE_INT("TexturePoolSize", mTexturePool.size());
         }
     }
 
@@ -3301,8 +3311,11 @@
                     break;
                 }
             }
-            if (needsProtected != renderEngine.isProtected() &&
-                renderEngine.useProtectedContext(needsProtected)) {
+            if (needsProtected != renderEngine.isProtected()) {
+                renderEngine.useProtectedContext(needsProtected);
+            }
+            if (needsProtected != display->getRenderSurface()->isProtected() &&
+                needsProtected == renderEngine.isProtected()) {
                 display->getRenderSurface()->setProtected(needsProtected);
             }
         }
@@ -3520,33 +3533,41 @@
 }
 
 bool SurfaceFlinger::flushTransactionQueues() {
-    Mutex::Autolock _l(mStateLock);
+    // to prevent onHandleDestroyed from being called while the lock is held,
+    // we must keep a copy of the transactions (specifically the composer
+    // states) around outside the scope of the lock
+    std::vector<const TransactionState> transactions;
     bool flushedATransaction = false;
+    {
+        Mutex::Autolock _l(mStateLock);
 
-    auto it = mTransactionQueues.begin();
-    while (it != mTransactionQueues.end()) {
-        auto& [applyToken, transactionQueue] = *it;
+        auto it = mTransactionQueues.begin();
+        while (it != mTransactionQueues.end()) {
+            auto& [applyToken, transactionQueue] = *it;
 
-        while (!transactionQueue.empty()) {
-            const auto&
-                    [states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks,
-                     postTime, privileged] = transactionQueue.front();
-            if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
-                setTransactionFlags(eTransactionFlushNeeded);
-                break;
+            while (!transactionQueue.empty()) {
+                const auto& transaction = transactionQueue.front();
+                if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+                                                   transaction.states)) {
+                    setTransactionFlags(eTransactionFlushNeeded);
+                    break;
+                }
+                transactions.push_back(transaction);
+                applyTransactionState(transaction.states, transaction.displays, transaction.flags,
+                                      mPendingInputWindowCommands, transaction.desiredPresentTime,
+                                      transaction.buffer, transaction.callback,
+                                      transaction.postTime, transaction.privileged,
+                                      /*isMainThread*/ true);
+                transactionQueue.pop();
+                flushedATransaction = true;
             }
-            applyTransactionState(states, displays, flags, mPendingInputWindowCommands,
-                                  desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime,
-                                  privileged, /*isMainThread*/ true);
-            transactionQueue.pop();
-            flushedATransaction = true;
-        }
 
-        if (transactionQueue.empty()) {
-            it = mTransactionQueues.erase(it);
-            mTransactionCV.broadcast();
-        } else {
-            std::next(it, 1);
+            if (transactionQueue.empty()) {
+                it = mTransactionQueues.erase(it);
+                mTransactionCV.broadcast();
+            } else {
+                std::next(it, 1);
+            }
         }
     }
     return flushedATransaction;
@@ -5078,6 +5099,14 @@
             ALOGE("Attempting to access SurfaceFlinger with unused code: %u", code);
             return PERMISSION_DENIED;
         }
+        case CAPTURE_SCREEN_BY_ID: {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int uid = ipc->getCallingUid();
+            if ((uid == AID_GRAPHICS) || (uid == AID_SYSTEM) || (uid == AID_SHELL)) {
+                return OK;
+            }
+            return PERMISSION_DENIED;
+        }
     }
 
     // These codes are used for the IBinder protocol to either interrogate the recipient
@@ -5492,6 +5521,66 @@
                                useIdentityTransform, outCapturedSecureLayers);
 }
 
+static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) {
+    switch (colorMode) {
+        case ColorMode::DISPLAY_P3:
+        case ColorMode::BT2100_PQ:
+        case ColorMode::BT2100_HLG:
+        case ColorMode::DISPLAY_BT2020:
+            return Dataspace::DISPLAY_P3;
+        default:
+            return Dataspace::V0_SRGB;
+    }
+}
+
+const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
+    const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
+    if (displayToken) {
+        return getDisplayDeviceLocked(displayToken);
+    }
+    // Couldn't find display by displayId. Try to get display by layerStack since virtual displays
+    // may not have a displayId.
+    for (const auto& [token, display] : mDisplays) {
+        if (display->getLayerStack() == displayOrLayerStack) {
+            return display;
+        }
+    }
+    return nullptr;
+}
+
+status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace,
+                                       sp<GraphicBuffer>* outBuffer) {
+    sp<DisplayDevice> display;
+    uint32_t width;
+    uint32_t height;
+    ui::Transform::orientation_flags captureOrientation;
+    {
+        Mutex::Autolock _l(mStateLock);
+        display = getDisplayByIdOrLayerStack(displayOrLayerStack);
+        if (!display) {
+            return BAD_VALUE;
+        }
+
+        width = uint32_t(display->getViewport().width());
+        height = uint32_t(display->getViewport().height());
+
+        captureOrientation = fromSurfaceComposerRotation(
+                static_cast<ISurfaceComposer::Rotation>(display->getOrientation()));
+        *outDataspace =
+                pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode);
+    }
+
+    DisplayRenderArea renderArea(display, Rect(), width, height, *outDataspace, captureOrientation,
+                                 false /* captureSecureLayers */);
+
+    auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
+                                    std::placeholders::_1);
+    bool ignored = false;
+    return captureScreenCommon(renderArea, traverseLayers, outBuffer, ui::PixelFormat::RGBA_8888,
+                               false /* useIdentityTransform */,
+                               ignored /* outCapturedSecureLayers */);
+}
+
 status_t SurfaceFlinger::captureLayers(
         const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
         const Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5871774..d9de07b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -405,6 +405,8 @@
             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
             uint32_t reqWidth, uint32_t reqHeight,
             bool useIdentityTransform, ISurfaceComposer::Rotation rotation, bool captureSecureLayers) override;
+    status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                           sp<GraphicBuffer>* outBuffer) override;
     status_t captureLayers(
             const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
             const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
@@ -636,6 +638,7 @@
     status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
                                  const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
                                  bool& outCapturedSecureLayers);
+    const sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack);
     status_t captureScreenImplLocked(const RenderArea& renderArea,
                                      TraverseLayersFunction traverseLayers,
                                      ANativeWindowBuffer* buffer, bool useIdentityTransform,
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 4e040a3..2bcb568 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -41,7 +41,7 @@
 
     virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
     virtual bool isEnabled() = 0;
-    virtual std::string miniDump();
+    virtual std::string miniDump() = 0;
 
     virtual void incrementTotalFrames() = 0;
     virtual void incrementMissedFrames() = 0;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index bebfa6c..7c0ecb3 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -856,7 +856,7 @@
     }
 
     static void cleanupInjectedLayers(CompositionTest* test) {
-        EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(2);
+        EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(1);
         Base::cleanupInjectedLayers(test);
     }
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index bc00190..a22f60e 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -222,6 +222,15 @@
             window,
             &refresh_duration);
     }
+    uint64_t get_refresh_duration()
+    {
+        ANativeWindow* window = surface.window.get();
+        native_window_get_refresh_cycle_duration(
+            window,
+            &refresh_duration);
+        return static_cast<uint64_t>(refresh_duration);
+
+    }
 
     Surface& surface;
     uint32_t num_images;
@@ -1730,8 +1739,7 @@
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
     VkResult result = VK_SUCCESS;
 
-    pDisplayTimingProperties->refreshDuration =
-            static_cast<uint64_t>(swapchain.refresh_duration);
+    pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration();
 
     return result;
 }