Merge "Adding SkiaGL RE information to dumpsys" into sc-dev
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 0e366cb..c62d302 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -310,8 +310,12 @@
     // FS/proc/*/mountinfo size > 0
     FileExists("FS/proc/1/mountinfo", 0U, 100000U);
 
-    // FS/data/misc/profiles/cur/0/*/primary.prof size > 0
-    FileExists("FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", 0U, 100000U);
+    // FS/data/misc/profiles/cur/0/*/primary.prof should exist. Also, since dumpstate only adds
+    // profiles to the zip in the non-user build, a build checking is necessary here.
+    if (!PropertiesHelper::IsUserBuild()) {
+        ZipEntry entry;
+        GetEntry(handle, "FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", &entry);
+    }
 }
 
 /**
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..4dfd1d0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1130,23 +1130,6 @@
     return true;
 }
 
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
-    struct stat input_stat;
-    memset(&input_stat, 0, sizeof(input_stat));
-    if (stat(apk_path, &input_stat) != 0) {
-        PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
-        return;
-    }
-
-    struct utimbuf ut;
-    ut.actime = input_stat.st_atime;
-    ut.modtime = input_stat.st_mtime;
-    if (utime(out_oat_path, &ut) != 0) {
-        PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
-    }
-}
-
 // Runs (execv) dexoptanalyzer on the given arguments.
 // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
 // If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1843,8 +1826,6 @@
         }
     }
 
-    update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
     // We've been successful, don't delete output.
     out_oat.DisableCleanup();
     out_vdex.DisableCleanup();
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index b21010d..0dbab4e 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -623,4 +623,21 @@
     return Status::ok();
 }
 
+Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
+    if (!mAccess->canList(mAccess->getCallingContext())) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    outReturn->reserve(mNameToService.size());
+    for (auto const& [name, service] : mNameToService) {
+        ServiceDebugInfo info;
+        info.name = name;
+        info.debugPid = service.debugPid;
+
+        outReturn->push_back(std::move(info));
+    }
+
+    return Status::ok();
+}
+
 }  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 9f43eb4..c089115 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -26,6 +26,7 @@
 
 using os::IClientCallback;
 using os::IServiceCallback;
+using os::ServiceDebugInfo;
 
 class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
 public:
@@ -48,6 +49,7 @@
     binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                           const sp<IClientCallback>& cb) override;
     binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
+    binder::Status getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) override;
     void binderDied(const wp<IBinder>& who) override;
     void handleClientCallbacks();
 
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c6f656b..79aab82 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -50,11 +50,10 @@
         CornerRadiusChange          corner_radius           = 16;
         ReparentChange              reparent                = 17;
         RelativeParentChange        relative_parent         = 18;
-        DetachChildrenChange        detach_children         = 19;
-        ReparentChildrenChange      reparent_children       = 20;
-        BackgroundBlurRadiusChange  background_blur_radius  = 21;
-        ShadowRadiusChange          shadow_radius           = 22;
-        BlurRegionsChange           blur_regions            = 23;
+        ReparentChildrenChange      reparent_children       = 19;
+        BackgroundBlurRadiusChange  background_blur_radius  = 20;
+        ShadowRadiusChange          shadow_radius           = 21;
+        BlurRegionsChange           blur_regions            = 22;
     }
 }
 
@@ -200,10 +199,6 @@
     required int32 z = 2;
 }
 
-message DetachChildrenChange {
-    required bool detach_children = 1;
-}
-
 message ShadowRadiusChange {
     required float radius = 1;
 }
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 5849212..58d6582 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -417,9 +417,6 @@
             case SurfaceChange::SurfaceChangeCase::kRelativeParent:
                 setRelativeParentChange(transaction, change.id(), change.relative_parent());
                 break;
-            case SurfaceChange::SurfaceChangeCase::kDetachChildren:
-                setDetachChildrenChange(transaction, change.id(), change.detach_children());
-                break;
             case SurfaceChange::SurfaceChangeCase::kShadowRadius:
                 setShadowRadiusChange(transaction, change.id(), change.shadow_radius());
                 break;
@@ -713,11 +710,6 @@
     t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
 }
 
-void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const DetachChildrenChange& c) {
-    t.detachChildren(mLayers[id]);
-}
-
 void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
         layer_id id, const ReparentChildrenChange& c) {
     if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index a22262a..324d591 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -116,8 +116,6 @@
             layer_id id, const ReparentChange& c);
     void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
             layer_id id, const RelativeParentChange& c);
-    void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
-            layer_id id, const DetachChildrenChange& c);
     void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
             layer_id id, const ReparentChildrenChange& c);
     void setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+     in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+    <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+     in hardware with max usage count equals to 1. -->
+<permissions>
+    <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.telephony.ims.singlereg.xml b/data/etc/android.hardware.telephony.ims.singlereg.xml
new file mode 100644
index 0000000..9a6cec0
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.singlereg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices that have an IMS service that supports all IMS
+     applications using a single IMS registration. -->
+<permissions>
+  <feature name="android.hardware.telephony.ims" />
+  <feature name="android.hardware.telephony.ims.singlereg" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index ccf4dc8..adfd6e2 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -34,6 +34,8 @@
     <feature name="android.hardware.microphone" />
     <!-- Feature to specify if the device is a car -->
     <feature name="android.hardware.type.automotive" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.connectionservice" />
@@ -45,6 +47,12 @@
     <feature name="android.software.secure_lock_screen" />
     <feature name="android.software.input_methods" />
 
+
+    <!-- Feature to support device admins -->
+    <!-- TODO(b/178412797): not fully supported yet, CTS tests are still
+         failing. -->
+    <feature name="android.software.device_admin" />
+
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or
diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
index 915e579..e6db4ad 100644
--- a/data/etc/go_handheld_core_hardware.xml
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -33,6 +33,8 @@
     <feature name="android.hardware.microphone" />
     <feature name="android.hardware.screen.portrait" />
     <feature name="android.hardware.screen.landscape" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.connectionservice" />
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 2c34047..c3c3a7f 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -37,6 +37,8 @@
     <feature name="android.hardware.microphone" />
     <feature name="android.hardware.screen.portrait" />
     <feature name="android.hardware.screen.landscape" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.app_widgets" />
diff --git a/data/etc/pc_core_hardware.xml b/data/etc/pc_core_hardware.xml
index c62da0a..b490ba0 100644
--- a/data/etc/pc_core_hardware.xml
+++ b/data/etc/pc_core_hardware.xml
@@ -33,6 +33,8 @@
     <feature name="android.hardware.screen.landscape" />
     <feature name="android.hardware.location" />
     <feature name="android.hardware.location.network" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.app_widgets" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 873b5b7..4b565fd 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -38,6 +38,8 @@
     <feature name="android.hardware.microphone" />
     <feature name="android.hardware.screen.portrait" />
     <feature name="android.hardware.screen.landscape" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.app_widgets" />
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 0f364c1..855b110 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -32,6 +32,8 @@
     <feature name="android.hardware.bluetooth" />
     <feature name="android.hardware.touchscreen" />
     <feature name="android.hardware.microphone" />
+    <!-- Indicate support for the Android security model per the CDD. -->
+    <feature name="android.hardware.security.model.compatible" />
 
     <!-- basic system services -->
     <feature name="android.software.home_screen" />
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index d7f25e1..2362c9e 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -132,8 +132,6 @@
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info);
 
-#if __ANDROID_API__ >= 30
-
 /**
  * Given a java bitmap object, return its {@link ADataSpace}.
  *
@@ -145,8 +143,6 @@
  */
 int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap)  __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 /**
  * Given a java bitmap object, attempt to lock the pixel address.
  * Locking will ensure that the memory for the pixels will not move
@@ -216,8 +212,6 @@
                                                 const void* data,
                                                 size_t size) __INTRODUCED_IN(30);
 
-#if __ANDROID_API__ >= 30
-
 /**
  *  Compress |pixels| as described by |info|.
  *
@@ -269,8 +263,6 @@
 int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
         AHardwareBuffer** outBuffer) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index e9f559c..8039bb0 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -61,8 +61,6 @@
  */
 typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
 
-#if __ANDROID_API__ >= 24
-
 /**
  * Get the AChoreographer instance for the current thread. This must be called
  * on an ALooper thread.
@@ -86,10 +84,6 @@
                                              long delayMillis) __INTRODUCED_IN(24)
         __DEPRECATED_IN(29);
 
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Power a callback to be run on the next frame.  The data pointer provided will
  * be passed to the callback function when it's called.
@@ -111,10 +105,6 @@
                                                AChoreographer_frameCallback64 callback, void* data,
                                                uint32_t delayMillis) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
-
 /**
  * Registers a callback to be run when the display refresh rate changes. The
  * data pointer provided will be passed to the callback function when it's
@@ -160,7 +150,6 @@
 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
                                                   AChoreographer_refreshRateCallback, void* data)
         __INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
 
 __END_DECLS
 
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ccf3e59..88019ae 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -645,14 +645,12 @@
  */
 void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
 
-#if __ANDROID_API__ >= 30
 /**
  * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
  *
  * Available since API level 30.
  */
 int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30);
-#endif
 
 /**
  * Set the current screen round in the configuration.
@@ -712,7 +710,6 @@
  */
 void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
 
-#if __ANDROID_API__ >= 17
 /**
  * Return the configuration's layout direction, or
  * ACONFIGURATION_LAYOUTDIR_ANY if not set.
@@ -727,7 +724,6 @@
  * Available since API level 17.
  */
 void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
-#endif /* __ANDROID_API__ >= 17 */
 
 /**
  * Perform a diff between two configurations.  Returns a bit mask of
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..a172618 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -51,8 +51,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 enum {
     /** The minimum value fot the font weight value. */
     AFONT_WEIGHT_MIN = 0,
@@ -297,8 +295,6 @@
 float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
       __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_FONT_H
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..49e478c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -97,8 +97,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 enum {
     /** A family variant value for the system default variant. */
     AFAMILY_VARIANT_DEFAULT = 0,
@@ -217,8 +215,6 @@
         const uint32_t textLength,
         uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_FONT_MATCHER_H
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index c7a8939..819a6a4 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -139,8 +139,6 @@
     ANDROID_IMAGE_DECODER_INVALID_STATE = -11,
 };
 
-#if __ANDROID_API__ >= 31
-
 /**
  * Return a constant string value representing the error code.
  *
@@ -155,8 +153,6 @@
  */
 const char* _Nullable AImageDecoder_resultToString(int)__INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 struct AImageDecoder;
 
 /**
@@ -179,8 +175,6 @@
  */
 typedef struct AImageDecoder AImageDecoder;
 
-#if __ANDROID_API__ >= 30
-
 /**
  * Create a new {@link AImageDecoder} from an {@link AAsset}.
  *
@@ -469,8 +463,6 @@
  */
 int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 struct AImageDecoderHeaderInfo;
 /**
  * Opaque handle for representing information about the encoded image.
@@ -483,8 +475,6 @@
  */
 typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;
 
-#if __ANDROID_API__ >= 30
-
 /**
  * Return an opaque handle for reading header info.
  *
@@ -672,10 +662,6 @@
                               void* _Nonnull pixels, size_t stride,
                               size_t size) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
 /**
  * Return true iff the image is animated - i.e. has multiple frames.
  *
@@ -690,8 +676,6 @@
 bool AImageDecoder_isAnimated(AImageDecoder* _Nonnull decoder)
         __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 enum {
     /*
      * Reported by {@link AImageDecoder_getRepeatCount} if the
@@ -702,8 +686,6 @@
     ANDROID_IMAGE_DECODER_INFINITE = INT32_MAX,
 };
 
-#if __ANDROID_API__ >= 31
-
 /**
  * Report how many times the animation should repeat.
  *
@@ -793,8 +775,6 @@
 int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder)
         __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 struct AImageDecoderFrameInfo;
 
 /**
@@ -810,8 +790,6 @@
  */
 typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo;
 
-#if __ANDROID_API__ >= 31
-
 /**
  * Create an uninitialized AImageDecoderFrameInfo.
  *
@@ -922,8 +900,6 @@
 bool AImageDecoderFrameInfo_hasAlphaWithinBounds(
         const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 /**
  * How a frame is “disposed” before showing the next one.
  *
@@ -947,8 +923,6 @@
     ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3,
 };
 
-#if __ANDROID_API__ >= 31
-
 /**
  * Return how this frame is “disposed” before showing the next one.
  *
@@ -969,8 +943,6 @@
 int32_t AImageDecoderFrameInfo_getDisposeOp(
         const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 /**
  * How a frame is blended with the previous frame.
  *
@@ -989,8 +961,6 @@
     ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2,
 };
 
-#if __ANDROID_API__ >= 31
-
 /**
  * Return how this frame is blended with the previous frame.
  *
@@ -1047,8 +1017,6 @@
         __INTRODUCED_IN(31);
 
 
-#endif // __ANDROID_API__ >= 31
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/android/input.h b/include/android/input.h
index b5d399e..b70d424 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -856,8 +856,10 @@
     AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
     /** joystick */
     AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+    /** HDMI */
+    AINPUT_SOURCE_HDMI = 0x02000000 | AINPUT_SOURCE_CLASS_BUTTON,
     /** sensor */
-    AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+    AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_UNKNOWN,
     /** rotary encoder */
     AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
 
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index c6d1c94..424299d 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
  * on failure with an appropriate errno value set.
  */
 
-#if __ANDROID_API__ >= 23
-
 /**
  * Set the network to be used by the given socket file descriptor.
  *
@@ -111,10 +109,6 @@
         const char *node, const char *service,
         const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
 
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Possible values of the flags argument to android_res_nsend and android_res_nquery.
  * Values are ORed together.
@@ -187,8 +181,6 @@
  */
 void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
 __END_DECLS
 
 #endif  // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..071ec79 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
  */
 ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
 
-#if __ANDROID_API__ >= 26
 /**
  * Return a Java Surface object derived from the ANativeWindow, for interacting
  * with it through Java code. The returned Java object acquires a reference on
@@ -55,7 +54,6 @@
  * Available since API level 26.
  */
 jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
-#endif
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sensor.h b/include/android/sensor.h
index eb40779..6447844 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -52,6 +52,13 @@
 #include <math.h>
 #include <stdint.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -553,13 +560,8 @@
  *     ASensorManager* sensorManager = ASensorManager_getInstance();
  *
  */
-#if __ANDROID_API__ >= 26
-__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
-#else
-ASensorManager* ASensorManager_getInstance();
-#endif
+ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
 
-#if __ANDROID_API__ >= 26
 /**
  * Get a reference to the sensor manager. ASensorManager is a singleton
  * per package as different packages may have access to different sensors.
@@ -571,7 +573,6 @@
  * Available since API level 26.
  */
 ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
-#endif
 
 /**
  * Returns the list of available sensors.
@@ -584,7 +585,6 @@
  */
 ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
 
-#if __ANDROID_API__ >= 21
 /**
  * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
  * of this type and wakeUp properties exists.
@@ -592,7 +592,6 @@
  * Available since API level 21.
  */
 ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
-#endif
 
 /**
  * Creates a new sensor event queue and associate it with a looper.
@@ -609,7 +608,6 @@
  */
 int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
 
-#if __ANDROID_API__ >= 26
 /**
  * Create direct channel based on shared memory
  *
@@ -706,7 +704,6 @@
  */
 int ASensorManager_configureDirectReport(ASensorManager* manager,
         ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
 
 /*****************************************************************************/
 
@@ -795,7 +792,6 @@
  */
 ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
 
-#if __ANDROID_API__ >= 29
 /**
  * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
  * the given {@link ASensorEventQueue}.
@@ -819,7 +815,6 @@
  * \return 0 on success or a negative error code on failure
  */
 int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
 
 /*****************************************************************************/
 
@@ -850,7 +845,6 @@
  */
 int ASensor_getMinDelay(ASensor const* sensor);
 
-#if __ANDROID_API__ >= 21
 /**
  * Returns the maximum size of batches for this sensor. Batches will often be
  * smaller, as the hardware fifo might be used for other sensors.
@@ -886,9 +880,7 @@
  * Available since API level 21.
  */
 bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
 
-#if __ANDROID_API__ >= 26
 /**
  * Test if sensor supports a certain type of direct channel.
  *
@@ -914,9 +906,7 @@
  *         does not support direct report.
  */
 int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
 
-#if __ANDROID_API__ >= 29
 /**
  * Returns the sensor's handle.
  *
@@ -934,7 +924,6 @@
  * Available since API level 29.
  */
 int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 5f74682..7994aa9 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -50,8 +50,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Create a shared memory region.
  *
@@ -121,8 +119,6 @@
  */
 int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 13e56e6..bbac785 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -52,8 +52,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 27
-
 /**
  * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
  * descriptor has all the same properties & capabilities as the FD returned from
@@ -72,8 +70,6 @@
  */
 int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
 
-#endif // __ANDROID_API__ >= 27
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 7a74248..98fd875 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -35,8 +35,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 struct ASurfaceControl;
 
 /**
@@ -409,10 +407,6 @@
                                                  struct AHdrMetadata_cta861_3* metadata)
                                                  __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
 /**
  * Same as ASurfaceTransaction_setFrameRateWithSeamlessness(transaction, surface_control,
  * frameRate, compatibility, true).
@@ -425,10 +419,6 @@
                                       ASurfaceControl* surface_control, float frameRate,
                                       int8_t compatibility) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
 /**
  * Sets the intended frame rate for \a surface_control.
  *
@@ -462,7 +452,6 @@
                                       int8_t compatibility, bool shouldBeSeamless)
                                       __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
 __END_DECLS
 
 #endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..b227b32 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -59,8 +59,6 @@
  */
 typedef struct ASurfaceTexture ASurfaceTexture;
 
-#if __ANDROID_API__ >= 28
-
 /**
  * Release the reference to the native ASurfaceTexture acquired with
  * ASurfaceTexture_fromSurfaceTexture().
@@ -175,8 +173,6 @@
  */
 int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
-#endif /* __ANDROID_API__ >= 28 */
-
 __END_DECLS
 
 #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..e40686d 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 28
-
 /**
  * Get a reference to the native ASurfaceTexture from the corresponding java object.
  *
@@ -52,8 +50,6 @@
  */
 ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
 
-#endif
-
 __END_DECLS
 
 #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..b0bbb95 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -87,8 +87,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 /**
  * ASystemFontIterator provides access to the system font configuration.
  *
@@ -128,8 +126,6 @@
  */
 AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_SYSTEM_FONTS_H
diff --git a/include/android/trace.h b/include/android/trace.h
index dbad6f6..dcefffb 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -40,8 +40,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 23
-
 /**
  * Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
  * when tracing is enabled.
@@ -72,10 +70,6 @@
  */
 void ATrace_endSection() __INTRODUCED_IN(23);
 
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Writes a trace message to indicate that a given section of code has
  * begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
@@ -112,8 +106,6 @@
  */
 void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 23692e9..2bd7bd2 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -213,6 +213,9 @@
     inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
     inline bool hasVibrator() const { return mHasVibrator; }
 
+    inline void setHasBattery(bool hasBattery) { mHasBattery = hasBattery; }
+    inline bool hasBattery() const { return mHasBattery; }
+
     inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; }
     inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; }
 
@@ -239,6 +242,7 @@
     int32_t mKeyboardType;
     std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
     bool mHasVibrator;
+    bool mHasBattery;
     bool mHasButtonUnderPad;
     bool mHasSensor;
 
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 9ea9732..2c0cca1 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -212,6 +212,7 @@
         "aidl/android/os/IClientCallback.aidl",
         "aidl/android/os/IServiceCallback.aidl",
         "aidl/android/os/IServiceManager.aidl",
+        "aidl/android/os/ServiceDebugInfo.aidl",
     ],
     path: "aidl",
 }
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5c34069..79a11d2 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -611,6 +611,12 @@
     mPostWriteStrongDerefs.clear();
 }
 
+void IPCThreadState::createTransactionReference(RefBase* ref)
+{
+    ref->incStrong(mProcess.get());
+    mPostWriteStrongDerefs.push(ref);
+}
+
 void IPCThreadState::joinThreadPool(bool isMain)
 {
     LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d62266..4edc493 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -24,12 +24,10 @@
 #include <log/log.h>
 #include <utils/Errors.h>
 
-using android::BAD_TYPE;
 using android::BAD_VALUE;
 using android::NO_ERROR;
 using android::Parcel;
 using android::status_t;
-using android::UNEXPECTED_NULL;
 
 namespace android {
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 440c98c..b9d00fe 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2291,7 +2291,7 @@
         ssize_t written = TEMP_FAILURE_RETRY(
             ::write(comm, &message, sizeof(message)));
 
-        if (written == -1 || written != sizeof(message)) {
+        if (written != sizeof(message)) {
             ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
                 written, strerror(errno));
             return BAD_TYPE;
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c807cfe..406fee0 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -31,7 +31,6 @@
 using android::BAD_VALUE;
 using android::NO_ERROR;
 using android::Parcel;
-using android::sp;
 using android::status_t;
 using android::UNEXPECTED_NULL;
 
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 2b1e492..ce30050 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -18,6 +18,7 @@
 
 import android.os.IClientCallback;
 import android.os.IServiceCallback;
+import android.os.ServiceDebugInfo;
 
 /**
  * Basic interface for finding and publishing system services.
@@ -116,4 +117,9 @@
      * Attempt to unregister and remove a service. Will fail if the service is still in use.
      */
     void tryUnregisterService(@utf8InCpp String name, IBinder service);
+
+    /**
+     * Get debug information for all currently registered services.
+     */
+    ServiceDebugInfo[] getServiceDebugInfo();
 }
diff --git a/libs/binder/aidl/android/os/ServiceDebugInfo.aidl b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl
new file mode 100644
index 0000000..b95d222
--- /dev/null
+++ b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Debug information associated with a registered service
+ * @hide
+ */
+parcelable ServiceDebugInfo {
+    /**
+     * Service name (see IServiceManager.addService/checkService/getService)
+     */
+    @utf8InCpp String name;
+    /**
+     * PID of service at the time of registration (may no longer be valid).
+     */
+    int debugPid;
+}
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 0183324..23a0cb0 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -162,6 +162,12 @@
             // This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
             // side.
             static const int32_t kUnsetWorkSource = -1;
+
+            // Create a temp reference until commands in queue flushed to driver
+            // Internal only.
+            // @internal
+            void                 createTransactionReference(RefBase* ref);
+
 private:
                                 IPCThreadState();
                                 ~IPCThreadState();
diff --git a/libs/binder/include/binder/ParcelRef.h b/libs/binder/include/binder/ParcelRef.h
new file mode 100644
index 0000000..497da2d
--- /dev/null
+++ b/libs/binder/include/binder/ParcelRef.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+
+#include <binder/Parcel.h>
+#include <utils/RefBase.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+/**
+ * internal use only
+ * @internal
+ */
+class ParcelRef : public Parcel, public RefBase
+{
+public:
+    static sp<ParcelRef> create() {
+        return new ParcelRef();
+    }
+
+private:
+    ParcelRef() = default;
+};
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 454fbd0..3c90681 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -597,13 +597,6 @@
         return STATUS_INVALID_OPERATION;
     }
 
-    if (!binder->isRemote()) {
-        LOG(WARNING) << "A binder object at " << binder
-                     << " is being transacted on, however, this object is in the same process as "
-                        "its proxy. Transacting with this binder is expensive compared to just "
-                        "calling the corresponding functionality in the same process.";
-    }
-
     *in = new AParcel(binder);
     status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
     binder_status_t ret = PruneStatusT(status);
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2ae13f4..2bf3d03 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -25,7 +25,6 @@
 use binder::parcel::ParcelFileDescriptor;
 
 use std::ffi::{c_void, CStr, CString};
-use std::panic::{self, AssertUnwindSafe};
 use std::sync::Once;
 
 #[allow(
@@ -73,22 +72,9 @@
 
 impl ReadParcelTest for () {}
 
-fn on_transact(
-    _service: &dyn ReadParcelTest,
-    code: TransactionCode,
-    parcel: &Parcel,
-    reply: &mut Parcel,
-) -> Result<()> {
-    panic::catch_unwind(AssertUnwindSafe(|| transact_inner(code, parcel, reply))).unwrap_or_else(
-        |e| {
-            eprintln!("Failure in Rust: {:?}", e.downcast_ref::<String>());
-            Err(StatusCode::FAILED_TRANSACTION)
-        },
-    )
-}
-
 #[allow(clippy::float_cmp)]
-fn transact_inner(code: TransactionCode, parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
+fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode,
+               parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
     match code {
         bindings::Transaction_TEST_BOOL => {
             assert_eq!(parcel.read::<bool>()?, true);
@@ -296,7 +282,7 @@
             ))?;
         }
         bindings::Transaction_TEST_FAIL => {
-            panic!("Testing expected failure");
+            return Err(StatusCode::FAILED_TRANSACTION)
         }
         _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
     }
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 462f0db..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -155,10 +155,14 @@
     return true;
 }
 
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
     std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
                                     eventType.c_str(), eventName.c_str());
-    int prog_fd = retrieveProgram(path.c_str());
+    return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+    int prog_fd = retrieveProgramFd(eventType, eventName);
     if (prog_fd < 0) return false;
     return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
 }
@@ -174,6 +178,17 @@
     return {};
 }
 
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+    auto freqs = getCpuFreqs();
+    if (!freqs || freqs->empty()) return false;
+    if (gTracking) return true;
+    if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+    if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+    if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+    return true;
+}
+
 // Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
 // Returns true on success, false otherwise.
 // Tracking is active only once a live process has successfully called this function; if the calling
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 46de669..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,6 +22,7 @@
 namespace android {
 namespace bpf {
 
+bool isTrackingUidTimesSupported();
 bool startTrackingUidTimes();
 std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
 std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d25b2e9..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,11 @@
 
 using std::vector;
 
+TEST(TimeInStateTest, IsTrackingSupported) {
+    isTrackingUidTimesSupported();
+    SUCCEED();
+}
+
 TEST(TimeInStateTest, TotalTimeInState) {
     auto times = getTotalCpuFreqTimes();
     ASSERT_TRUE(times.has_value());
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 143fa13..8a82c2a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -53,7 +53,6 @@
 
 /* list of hal interface to dump containing process during native dumps */
 static const char* hal_interfaces_to_dump[] {
-        "android.hardware.audio@2.0::IDevicesFactory",
         "android.hardware.audio@4.0::IDevicesFactory",
         "android.hardware.audio@5.0::IDevicesFactory",
         "android.hardware.audio@6.0::IDevicesFactory",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 38ae353..fa5044c 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -49,6 +49,7 @@
 
     srcs: [
         ":framework_native_aidl",
+        ":inputconstants_aidl",
         ":libgui_aidl",
         ":libgui_bufferqueue_sources",
 
@@ -62,6 +63,7 @@
         "DebugEGLImageTracker.cpp",
         "DisplayEventDispatcher.cpp",
         "DisplayEventReceiver.cpp",
+        "FrameTimelineInfo.cpp",
         "GLConsumer.cpp",
         "IConsumerListener.cpp",
         "IDisplayEventConnection.cpp",
@@ -154,6 +156,7 @@
     defaults: ["libgui_bufferqueue-defaults"],
 
     srcs: [
+        ":inputconstants_aidl",
         ":libgui_aidl",
         ":libgui_bufferqueue_sources",
     ],
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 0a3d44d..c62d9ad 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -146,6 +146,10 @@
 
     mTransformHint = mSurfaceControl->getTransformHint();
     mBufferItemConsumer->setTransformHint(mTransformHint);
+    SurfaceComposerClient::Transaction()
+            .setFlags(surface, layer_state_t::eEnableBackpressure,
+                      layer_state_t::eEnableBackpressure)
+            .apply();
 
     mNumAcquired = 0;
     mNumFrameAvailable = 0;
@@ -169,13 +173,20 @@
 void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
                               int32_t format) {
     std::unique_lock _lock{mMutex};
-    mSurfaceControl = surface;
-
     if (mFormat != format) {
         mFormat = format;
         mBufferItemConsumer->setDefaultBufferFormat(format);
     }
 
+    SurfaceComposerClient::Transaction t;
+    bool applyTransaction = false;
+    if (!SurfaceControl::isSameSurface(mSurfaceControl, surface)) {
+        mSurfaceControl = surface;
+        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
+                   layer_state_t::eEnableBackpressure);
+        applyTransaction = true;
+    }
+
     ui::Size newSize(width, height);
     if (mRequestedSize != newSize) {
         mRequestedSize.set(newSize);
@@ -184,13 +195,15 @@
             // If the buffer supports scaling, update the frame immediately since the client may
             // want to scale the existing buffer to the new size.
             mSize = mRequestedSize;
-            SurfaceComposerClient::Transaction t;
             t.setFrame(mSurfaceControl,
                        {0, 0, static_cast<int32_t>(mSize.width),
                         static_cast<int32_t>(mSize.height)});
-            t.apply();
+            applyTransaction = true;
         }
     }
+    if (applyTransaction) {
+        t.apply();
+    }
 }
 
 static void transactionCallbackThunk(void* context, nsecs_t latchTime,
@@ -248,7 +261,7 @@
         mPendingReleaseItem.item = std::move(mSubmitted.front());
         mSubmitted.pop();
 
-        processNextBufferLocked(false);
+        processNextBufferLocked(false /* useNextTransaction */);
 
         currFrameNumber = mPendingReleaseItem.item.mFrameNumber;
         if (mTransactionCompleteCallback && mTransactionCompleteFrameNumber == currFrameNumber) {
@@ -269,9 +282,10 @@
     ATRACE_CALL();
     BQA_LOGV("processNextBufferLocked useNextTransaction=%s", toString(useNextTransaction));
 
-    // Wait to acquire a buffer if there are no frames available or we have acquired the max
-    // number of buffers.
-    if (mNumFrameAvailable == 0 || maxBuffersAcquired()) {
+    // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't
+    // include the extra buffer when checking if we can acquire the next buffer.
+    const bool includeExtraAcquire = !useNextTransaction;
+    if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) {
         BQA_LOGV("processNextBufferLocked waiting for frame available or callback");
         mCallbackCV.notify_all();
         return;
@@ -295,7 +309,10 @@
 
     status_t status =
             mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
-    if (status != OK) {
+    if (status == BufferQueue::NO_BUFFER_AVAILABLE) {
+        BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE");
+        return;
+    } else if (status != OK) {
         BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str());
         return;
     }
@@ -353,9 +370,9 @@
     }
     t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
 
-    if (!mNextFrameTimelineVsyncIdQueue.empty()) {
-        t->setFrameTimelineVsync(mSurfaceControl, mNextFrameTimelineVsyncIdQueue.front());
-        mNextFrameTimelineVsyncIdQueue.pop();
+    if (!mNextFrameTimelineInfoQueue.empty()) {
+        t->setFrameTimelineInfo(mSurfaceControl, mNextFrameTimelineInfoQueue.front());
+        mNextFrameTimelineInfoQueue.pop();
     }
 
     if (mAutoRefresh != bufferItem.mAutoRefresh) {
@@ -414,7 +431,7 @@
              item.mFrameNumber, toString(nextTransactionSet), toString(mFlushShadowQueue));
 
     if (nextTransactionSet || mFlushShadowQueue) {
-        while (mNumFrameAvailable > 0 || maxBuffersAcquired()) {
+        while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) {
             BQA_LOGV("waiting in onFrameAvailable...");
             mCallbackCV.wait(_lock);
         }
@@ -422,7 +439,7 @@
     mFlushShadowQueue = false;
     // add to shadow queue
     mNumFrameAvailable++;
-    processNextBufferLocked(true);
+    processNextBufferLocked(nextTransactionSet /* useNextTransaction */);
 }
 
 void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) {
@@ -482,9 +499,12 @@
 // Check if we have acquired the maximum number of buffers.
 // As a special case, we wait for the first callback before acquiring the second buffer so we
 // can ensure the first buffer is presented if multiple buffers are queued in succession.
-bool BLASTBufferQueue::maxBuffersAcquired() const {
-    return mNumAcquired == MAX_ACQUIRED_BUFFERS + 1 ||
-            (!mInitialCallbackReceived && mNumAcquired == 1);
+// Consumer can acquire an additional buffer if that buffer is not droppable. Set
+// includeExtraAcquire is true to include this buffer to the count. Since this depends on the state
+// of the buffer, the next acquire may return with NO_BUFFER_AVAILABLE.
+bool BLASTBufferQueue::maxBuffersAcquired(bool includeExtraAcquire) const {
+    int maxAcquiredBuffers = MAX_ACQUIRED_BUFFERS + (includeExtraAcquire ? 2 : 1);
+    return mNumAcquired == maxAcquiredBuffers || (!mInitialCallbackReceived && mNumAcquired == 1);
 }
 
 class BBQSurface : public Surface {
@@ -514,8 +534,8 @@
         return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless);
     }
 
-    status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override {
-        return mBbq->setFrameTimelineVsync(frameTimelineVsyncId);
+    status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override {
+        return mBbq->setFrameTimelineInfo(frameTimelineInfo);
     }
 };
 
@@ -529,9 +549,9 @@
     return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
 }
 
-status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
+status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
     std::unique_lock _lock{mMutex};
-    mNextFrameTimelineVsyncIdQueue.push(frameTimelineVsyncId);
+    mNextFrameTimelineInfoQueue.push(frameTimelineInfo);
     return OK;
 }
 
@@ -654,7 +674,8 @@
     LOG_ALWAYS_FATAL_IF(producer == nullptr,
                         "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
 
-    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
+    sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
+    consumer->setAllowExtraAcquire(true);
     LOG_ALWAYS_FATAL_IF(consumer == nullptr,
                         "BLASTBufferQueue: failed to create BufferQueueConsumer");
 
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index da6143c..7f7a043 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -94,7 +94,10 @@
                 ++numAcquiredBuffers;
             }
         }
-        if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
+        const bool acquireNonDroppableBuffer = mCore->mAllowExtraAcquire &&
+                numAcquiredBuffers == mCore->mMaxAcquiredBufferCount + 1;
+        if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1 &&
+            !acquireNonDroppableBuffer) {
             BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
                     numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
             return INVALID_OPERATION;
@@ -254,6 +257,9 @@
             outBuffer->mIsStale = false;
             outBuffer->mAutoRefresh = mCore->mSharedBufferMode &&
                     mCore->mAutoRefresh;
+        } else if (acquireNonDroppableBuffer && front->mIsDroppable) {
+            BQ_LOGV("acquireBuffer: front buffer is not droppable");
+            return NO_BUFFER_AVAILABLE;
         } else {
             slot = front->mSlot;
             *outBuffer = *front;
@@ -824,4 +830,9 @@
     return NO_ERROR;
 }
 
+void BufferQueueConsumer::setAllowExtraAcquire(bool allow) {
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+    mCore->mAllowExtraAcquire = allow;
+}
+
 } // namespace android
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c6c9a8f..2ad484a 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,7 +36,9 @@
 DisplayEventDispatcher::DisplayEventDispatcher(
         const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
         ISurfaceComposer::EventRegistrationFlags eventRegistration)
-      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
+      : mLooper(looper),
+        mReceiver(vsyncSource, eventRegistration),
+        mVsyncState(VsyncState::Unregistered) {
     ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
 }
 
@@ -66,26 +68,37 @@
 }
 
 status_t DisplayEventDispatcher::scheduleVsync() {
-    if (!mWaitingForVsync) {
-        ALOGV("dispatcher %p ~ Scheduling vsync.", this);
+    switch (mVsyncState) {
+        case VsyncState::Unregistered: {
+            ALOGV("dispatcher %p ~ Scheduling vsync.", this);
 
-        // Drain all pending events.
-        nsecs_t vsyncTimestamp;
-        PhysicalDisplayId vsyncDisplayId;
-        uint32_t vsyncCount;
-        VsyncEventData vsyncEventData;
-        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
-            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
-                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+            // Drain all pending events.
+            nsecs_t vsyncTimestamp;
+            PhysicalDisplayId vsyncDisplayId;
+            uint32_t vsyncCount;
+            VsyncEventData vsyncEventData;
+            if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount,
+                                     &vsyncEventData)) {
+                ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
+                      this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+            }
+
+            status_t status = mReceiver.setVsyncRate(1);
+            if (status) {
+                ALOGW("Failed to set vsync rate, status=%d", status);
+                return status;
+            }
+
+            mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+            break;
         }
-
-        status_t status = mReceiver.requestNextVsync();
-        if (status) {
-            ALOGW("Failed to request next vsync, status=%d", status);
-            return status;
+        case VsyncState::Registered: {
+            mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+            break;
         }
-
-        mWaitingForVsync = true;
+        case VsyncState::RegisteredAndWaitingForVsync: {
+            break;
+        }
     }
     return OK;
 }
@@ -123,8 +136,23 @@
               ", displayId=%s, count=%d, vsyncId=%" PRId64,
               this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
               vsyncEventData.id);
-        mWaitingForVsync = false;
-        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+        switch (mVsyncState) {
+            case VsyncState::Unregistered:
+                ALOGW("Received unexpected VSYNC event");
+                break;
+            case VsyncState::RegisteredAndWaitingForVsync:
+                mVsyncState = VsyncState::Registered;
+                dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+                break;
+            case VsyncState::Registered:
+                status_t status = mReceiver.setVsyncRate(0);
+                if (status) {
+                    ALOGW("Failed to reset vsync rate, status=%d", status);
+                    return status;
+                }
+                mVsyncState = VsyncState::Unregistered;
+                break;
+        }
     }
 
     return 1; // keep the callback
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
new file mode 100644
index 0000000..f400774
--- /dev/null
+++ b/libs/gui/FrameTimelineInfo.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FrameTimelineInfo"
+
+#include <inttypes.h>
+
+#include <android/os/IInputConstants.h>
+#include <gui/FrameTimelineInfo.h>
+#include <gui/LayerState.h>
+#include <utils/Errors.h>
+
+#include <cmath>
+
+using android::os::IInputConstants;
+
+namespace android {
+
+status_t FrameTimelineInfo::write(Parcel& output) const {
+    SAFE_PARCEL(output.writeInt64, vsyncId);
+    SAFE_PARCEL(output.writeInt32, inputEventId);
+    return NO_ERROR;
+}
+
+status_t FrameTimelineInfo::read(const Parcel& input) {
+    SAFE_PARCEL(input.readInt64, &vsyncId);
+    SAFE_PARCEL(input.readInt32, &inputEventId);
+    return NO_ERROR;
+}
+
+void FrameTimelineInfo::merge(const FrameTimelineInfo& other) {
+    // When merging vsync Ids we take the oldest valid one
+    if (vsyncId != INVALID_VSYNC_ID && other.vsyncId != INVALID_VSYNC_ID) {
+        if (other.vsyncId > vsyncId) {
+            vsyncId = other.vsyncId;
+            inputEventId = other.inputEventId;
+        }
+    } else if (vsyncId == INVALID_VSYNC_ID) {
+        vsyncId = other.vsyncId;
+        inputEventId = other.inputEventId;
+    }
+}
+
+void FrameTimelineInfo::clear() {
+    vsyncId = INVALID_VSYNC_ID;
+    inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
+}
+
+}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a8d6832..f68f3e1 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -68,16 +68,19 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
-    virtual status_t setTransactionState(
-            int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
-            const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp,
-            const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
-            const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+    status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+                                 const Vector<ComposerState>& state,
+                                 const Vector<DisplayState>& displays, uint32_t flags,
+                                 const sp<IBinder>& applyToken, const InputWindowCommands& commands,
+                                 int64_t desiredPresentTime, bool isAutoTimestamp,
+                                 const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+                                 const std::vector<ListenerCallbacks>& listenerCallbacks,
+                                 uint64_t transactionId) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
 
-        SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId);
+        SAFE_PARCEL(frameTimelineInfo.write, data);
+
         SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size()));
         for (const auto& s : state) {
             SAFE_PARCEL(s.write, data);
@@ -108,15 +111,14 @@
         return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
-    virtual void bootFinished()
-    {
+    void bootFinished() override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t captureDisplay(const DisplayCaptureArgs& args,
-                                    const sp<IScreenCaptureListener>& captureListener) {
+    status_t captureDisplay(const DisplayCaptureArgs& args,
+                            const sp<IScreenCaptureListener>& captureListener) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         SAFE_PARCEL(args.write, data);
@@ -125,8 +127,8 @@
         return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
     }
 
-    virtual status_t captureDisplay(uint64_t displayOrLayerStack,
-                                    const sp<IScreenCaptureListener>& captureListener) {
+    status_t captureDisplay(uint64_t displayOrLayerStack,
+                            const sp<IScreenCaptureListener>& captureListener) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         SAFE_PARCEL(data.writeUint64, displayOrLayerStack);
@@ -135,8 +137,8 @@
         return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
     }
 
-    virtual status_t captureLayers(const LayerCaptureArgs& args,
-                                   const sp<IScreenCaptureListener>& captureListener) {
+    status_t captureLayers(const LayerCaptureArgs& args,
+                           const sp<IScreenCaptureListener>& captureListener) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         SAFE_PARCEL(args.write, data);
@@ -145,9 +147,8 @@
         return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
     }
 
-    virtual bool authenticateSurfaceTexture(
-            const sp<IGraphicBufferProducer>& bufferProducer) const
-    {
+    bool authenticateSurfaceTexture(
+            const sp<IGraphicBufferProducer>& bufferProducer) const override {
         Parcel data, reply;
         int err = NO_ERROR;
         err = data.writeInterfaceToken(
@@ -180,8 +181,7 @@
         return result != 0;
     }
 
-    virtual status_t getSupportedFrameTimestamps(
-            std::vector<FrameEvent>* outSupported) const {
+    status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override {
         if (!outSupported) {
             return UNEXPECTED_NULL;
         }
@@ -224,8 +224,8 @@
         return NO_ERROR;
     }
 
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override {
         Parcel data, reply;
         sp<IDisplayEventConnection> result;
         int err = data.writeInterfaceToken(
@@ -247,8 +247,7 @@
         return result;
     }
 
-    virtual sp<IBinder> createDisplay(const String8& displayName, bool secure)
-    {
+    sp<IBinder> createDisplay(const String8& displayName, bool secure) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t status = data.writeString8(displayName);
@@ -272,15 +271,14 @@
         return display;
     }
 
-    virtual void destroyDisplay(const sp<IBinder>& display)
-    {
+    void destroyDisplay(const sp<IBinder>& display) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
         remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply);
     }
 
-    virtual std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const {
+    std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) ==
@@ -297,7 +295,7 @@
         return {};
     }
 
-    virtual sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
+    sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeUint64(displayId.value);
@@ -305,8 +303,7 @@
         return reply.readStrongBinder();
     }
 
-    virtual void setPowerMode(const sp<IBinder>& display, int mode)
-    {
+    void setPowerMode(const sp<IBinder>& display, int mode) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -314,7 +311,7 @@
         remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply);
     }
 
-    virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) {
+    status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -326,7 +323,7 @@
         return result;
     }
 
-    virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
+    status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -336,7 +333,8 @@
         return reply.read(*info);
     }
 
-    virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>* configs) {
+    status_t getDisplayConfigs(const sp<IBinder>& display,
+                               Vector<DisplayConfig>* configs) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -354,9 +352,7 @@
         return result;
     }
 
-    virtual status_t getDisplayStats(const sp<IBinder>& display,
-            DisplayStatInfo* stats)
-    {
+    status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -370,8 +366,7 @@
         return result;
     }
 
-    virtual int getActiveConfig(const sp<IBinder>& display)
-    {
+    int getActiveConfig(const sp<IBinder>& display) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -379,8 +374,8 @@
         return reply.readInt32();
     }
 
-    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ColorMode>* outColorModes) {
+    status_t getDisplayColorModes(const sp<IBinder>& display,
+                                  Vector<ColorMode>* outColorModes) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -409,8 +404,8 @@
         return result;
     }
 
-    virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
-            ui::DisplayPrimaries& primaries) {
+    status_t getDisplayNativePrimaries(const sp<IBinder>& display,
+                                       ui::DisplayPrimaries& primaries) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -435,7 +430,7 @@
         return result;
     }
 
-    virtual ColorMode getActiveColorMode(const sp<IBinder>& display) {
+    ColorMode getActiveColorMode(const sp<IBinder>& display) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -455,8 +450,7 @@
         return static_cast<ColorMode>(reply.readInt32());
     }
 
-    virtual status_t setActiveColorMode(const sp<IBinder>& display,
-            ColorMode colorMode) {
+    status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -481,8 +475,8 @@
         return static_cast<status_t>(reply.readInt32());
     }
 
-    virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
-                                                  bool* outSupport) const {
+    status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
+                                          bool* outSupport) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t result = data.writeStrongBinder(display);
@@ -499,7 +493,7 @@
         return reply.readBool(outSupport);
     }
 
-    virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
+    void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -524,7 +518,8 @@
         }
     }
 
-    virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, bool* outSupport) const {
+    status_t getGameContentTypeSupport(const sp<IBinder>& display,
+                                       bool* outSupport) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t result = data.writeStrongBinder(display);
@@ -540,7 +535,7 @@
         return reply.readBool(outSupport);
     }
 
-    virtual void setGameContentType(const sp<IBinder>& display, bool on) {
+    void setGameContentType(const sp<IBinder>& display, bool on) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -563,7 +558,7 @@
         }
     }
 
-    virtual status_t clearAnimationFrameStats() {
+    status_t clearAnimationFrameStats() override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -578,7 +573,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t getAnimationFrameStats(FrameStats* outStats) const {
+    status_t getAnimationFrameStats(FrameStats* outStats) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
@@ -586,8 +581,8 @@
         return reply.readInt32();
     }
 
-    virtual status_t getHdrCapabilities(const sp<IBinder>& display,
-            HdrCapabilities* outCapabilities) const {
+    status_t getHdrCapabilities(const sp<IBinder>& display,
+                                HdrCapabilities* outCapabilities) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t result = data.writeStrongBinder(display);
@@ -608,7 +603,7 @@
         return result;
     }
 
-    virtual status_t enableVSyncInjections(bool enable) {
+    status_t enableVSyncInjections(bool enable) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -629,7 +624,7 @@
         return result;
     }
 
-    virtual status_t injectVSync(nsecs_t when) {
+    status_t injectVSync(nsecs_t when) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -650,7 +645,7 @@
         return result;
     }
 
-    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
+    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override {
         if (!outLayers) {
             return UNEXPECTED_NULL;
         }
@@ -680,10 +675,10 @@
         return reply.readParcelableVector(outLayers);
     }
 
-    virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
-                                              ui::PixelFormat* defaultPixelFormat,
-                                              ui::Dataspace* wideColorGamutDataspace,
-                                              ui::PixelFormat* wideColorGamutPixelFormat) const {
+    status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
+                                      ui::PixelFormat* defaultPixelFormat,
+                                      ui::Dataspace* wideColorGamutDataspace,
+                                      ui::PixelFormat* wideColorGamutPixelFormat) const override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -703,7 +698,7 @@
         return error;
     }
 
-    virtual status_t getColorManagement(bool* outGetColorManagement) const {
+    status_t getColorManagement(bool* outGetColorManagement) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply);
@@ -715,10 +710,10 @@
         return err;
     }
 
-    virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
-                                                           ui::PixelFormat* outFormat,
-                                                           ui::Dataspace* outDataspace,
-                                                           uint8_t* outComponentMask) const {
+    status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+                                                   ui::PixelFormat* outFormat,
+                                                   ui::Dataspace* outDataspace,
+                                                   uint8_t* outComponentMask) const override {
         if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE;
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -752,8 +747,8 @@
         return error;
     }
 
-    virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
-                                                      uint8_t componentMask, uint64_t maxFrames) {
+    status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+                                              uint8_t componentMask, uint64_t maxFrames) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
@@ -766,9 +761,9 @@
         return result;
     }
 
-    virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
-                                               uint64_t timestamp,
-                                               DisplayedFrameStats* outStats) const {
+    status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+                                       uint64_t timestamp,
+                                       DisplayedFrameStats* outStats) const override {
         if (!outStats) return BAD_VALUE;
 
         Parcel data, reply;
@@ -805,7 +800,7 @@
         return result;
     }
 
-    virtual status_t getProtectedContentSupport(bool* outSupported) const {
+    status_t getProtectedContentSupport(bool* outSupported) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t error =
@@ -817,8 +812,8 @@
         return error;
     }
 
-    virtual status_t isWideColorDisplay(const sp<IBinder>& token,
-                                        bool* outIsWideColorDisplay) const {
+    status_t isWideColorDisplay(const sp<IBinder>& token,
+                                bool* outIsWideColorDisplay) const override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -837,9 +832,8 @@
         return error;
     }
 
-    virtual status_t addRegionSamplingListener(const Rect& samplingArea,
-                                               const sp<IBinder>& stopLayerHandle,
-                                               const sp<IRegionSamplingListener>& listener) {
+    status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+                                       const sp<IRegionSamplingListener>& listener) override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -868,7 +862,7 @@
         return error;
     }
 
-    virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) {
+    status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -888,12 +882,11 @@
         return error;
     }
 
-    virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
-                                                  int32_t defaultConfig, bool allowGroupSwitching,
-                                                  float primaryRefreshRateMin,
-                                                  float primaryRefreshRateMax,
-                                                  float appRequestRefreshRateMin,
-                                                  float appRequestRefreshRateMax) {
+    status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t defaultConfig,
+                                          bool allowGroupSwitching, float primaryRefreshRateMin,
+                                          float primaryRefreshRateMax,
+                                          float appRequestRefreshRateMin,
+                                          float appRequestRefreshRateMax) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (result != NO_ERROR) {
@@ -947,13 +940,12 @@
         return reply.readInt32();
     }
 
-    virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
-                                                  int32_t* outDefaultConfig,
-                                                  bool* outAllowGroupSwitching,
-                                                  float* outPrimaryRefreshRateMin,
-                                                  float* outPrimaryRefreshRateMax,
-                                                  float* outAppRequestRefreshRateMin,
-                                                  float* outAppRequestRefreshRateMax) {
+    status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+                                          int32_t* outDefaultConfig, bool* outAllowGroupSwitching,
+                                          float* outPrimaryRefreshRateMin,
+                                          float* outPrimaryRefreshRateMax,
+                                          float* outAppRequestRefreshRateMin,
+                                          float* outAppRequestRefreshRateMax) override {
         if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
             !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin ||
             !outAppRequestRefreshRateMax) {
@@ -1011,8 +1003,8 @@
         return reply.readInt32();
     }
 
-    virtual status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
-                                                 bool* outSupport) const {
+    status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
+                                         bool* outSupport) const override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -1039,7 +1031,7 @@
         return NO_ERROR;
     }
 
-    virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) {
+    status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -1064,7 +1056,7 @@
         return NO_ERROR;
     }
 
-    virtual status_t notifyPowerBoost(int32_t boostId) {
+    status_t notifyPowerBoost(int32_t boostId) override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -1085,8 +1077,8 @@
         return NO_ERROR;
     }
 
-    virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
-                                             float lightPosY, float lightPosZ, float lightRadius) {
+    status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
+                                     float lightPosY, float lightPosZ, float lightRadius) override {
         Parcel data, reply;
         status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (error != NO_ERROR) {
@@ -1114,8 +1106,8 @@
         return NO_ERROR;
     }
 
-    virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
-                                  int8_t compatibility, bool shouldBeSeamless) {
+    status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+                          int8_t compatibility, bool shouldBeSeamless) override {
         Parcel data, reply;
         status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (err != NO_ERROR) {
@@ -1156,7 +1148,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
+    status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override {
         if (!outToken) return BAD_VALUE;
 
         Parcel data, reply;
@@ -1191,40 +1183,34 @@
         return NO_ERROR;
     }
 
-    virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
-                                           int64_t frameTimelineVsyncId) {
+    status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+                                  const FrameTimelineInfo& frameTimelineInfo) override {
         Parcel data, reply;
         status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         if (err != NO_ERROR) {
-            ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err),
-                  -err);
+            ALOGE("%s: failed writing interface token: %s (%d)", __func__, strerror(-err), -err);
             return err;
         }
 
         err = data.writeStrongBinder(IInterface::asBinder(surface));
         if (err != NO_ERROR) {
-            ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err),
-                  -err);
+            ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err);
             return err;
         }
 
-        err = data.writeInt64(frameTimelineVsyncId);
-        if (err != NO_ERROR) {
-            ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err);
-            return err;
-        }
+        SAFE_PARCEL(frameTimelineInfo.write, data);
 
-        err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply);
+        err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply);
         if (err != NO_ERROR) {
-            ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err);
+            ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err);
             return err;
         }
 
         return reply.readInt32();
     }
 
-    virtual status_t addTransactionTraceListener(
-            const sp<gui::ITransactionTraceListener>& listener) {
+    status_t addTransactionTraceListener(
+            const sp<gui::ITransactionTraceListener>& listener) override {
         Parcel data, reply;
         SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
         SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
@@ -1235,7 +1221,7 @@
     /**
      * Get priority of the RenderEngine in surface flinger.
      */
-    virtual int getGPUContextPriority() {
+    int getGPUContextPriority() override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         status_t err =
@@ -1269,8 +1255,9 @@
         case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
 
-            int64_t frameTimelineVsyncId;
-            SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId);
+            FrameTimelineInfo frameTimelineInfo;
+            SAFE_PARCEL(frameTimelineInfo.read, data);
+
             uint32_t count = 0;
             SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
             Vector<ComposerState> state;
@@ -1324,10 +1311,10 @@
             uint64_t transactionId = -1;
             SAFE_PARCEL(data.readUint64, &transactionId);
 
-            return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags,
-                                       applyToken, inputWindowCommands, desiredPresentTime,
-                                       isAutoTimestamp, uncachedBuffer, hasListenerCallbacks,
-                                       listenerCallbacks, transactionId);
+            return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
+                                       inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+                                       uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
+                                       transactionId);
         }
         case BOOT_FINISHED: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -2078,30 +2065,26 @@
             }
             return NO_ERROR;
         }
-        case SET_FRAME_TIMELINE_VSYNC: {
+        case SET_FRAME_TIMELINE_INFO: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> binder;
             status_t err = data.readStrongBinder(&binder);
             if (err != NO_ERROR) {
-                ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)",
-                      strerror(-err), -err);
+                ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err),
+                      -err);
                 return err;
             }
             sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
             if (!surface) {
-                ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)",
+                ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)",
                       strerror(-err), -err);
                 return err;
             }
-            int64_t frameTimelineVsyncId;
-            err = data.readInt64(&frameTimelineVsyncId);
-            if (err != NO_ERROR) {
-                ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err),
-                      -err);
-                return err;
-            }
 
-            status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId);
+            FrameTimelineInfo frameTimelineInfo;
+            SAFE_PARCEL(frameTimelineInfo.read, data);
+
+            status_t result = setFrameTimelineInfo(surface, frameTimelineInfo);
             reply->writeInt32(result);
             return NO_ERROR;
         }
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 1808571..0ded936 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -92,10 +92,8 @@
     return err;
 }
 
-JankData::JankData() :
-        frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
-        jankType(JankType::None) {
-}
+JankData::JankData()
+      : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {}
 
 status_t JankData::writeToParcel(Parcel* output) const {
     SAFE_PARCEL(output->writeInt64, frameVsyncId);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e5e10a0..fff3305 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -63,7 +63,7 @@
         shouldBeSeamless(true),
         fixedTransformHint(ui::Transform::ROT_INVALID),
         frameNumber(0),
-        frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
+        frameTimelineInfo(),
         autoRefresh(false) {
     matrix.dsdx = matrix.dtdy = 1.0f;
     matrix.dsdy = matrix.dtdx = 0.0f;
@@ -151,7 +151,7 @@
     SAFE_PARCEL(output.writeBool, shouldBeSeamless);
     SAFE_PARCEL(output.writeUint32, fixedTransformHint);
     SAFE_PARCEL(output.writeUint64, frameNumber);
-    SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId);
+    SAFE_PARCEL(frameTimelineInfo.write, output);
     SAFE_PARCEL(output.writeBool, autoRefresh);
 
     SAFE_PARCEL(output.writeUint32, blurRegions.size());
@@ -183,12 +183,9 @@
     SAFE_PARCEL(input.readUint32, &layerStack);
     SAFE_PARCEL(input.readFloat, &alpha);
 
-    uint32_t tmpUint32 = 0;
-    SAFE_PARCEL(input.readUint32, &tmpUint32);
-    flags = static_cast<uint8_t>(tmpUint32);
+    SAFE_PARCEL(input.readUint32, &flags);
 
-    SAFE_PARCEL(input.readUint32, &tmpUint32);
-    mask = static_cast<uint8_t>(tmpUint32);
+    SAFE_PARCEL(input.readUint32, &mask);
 
     SAFE_PARCEL(matrix.read, input);
     SAFE_PARCEL(input.read, crop_legacy);
@@ -229,6 +226,7 @@
         SAFE_PARCEL(input.read, *acquireFence);
     }
 
+    uint32_t tmpUint32 = 0;
     SAFE_PARCEL(input.readUint32, &tmpUint32);
     dataspace = static_cast<ui::Dataspace>(tmpUint32);
 
@@ -272,7 +270,7 @@
     SAFE_PARCEL(input.readUint32, &tmpUint32);
     fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
     SAFE_PARCEL(input.readUint64, &frameNumber);
-    SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId);
+    SAFE_PARCEL(frameTimelineInfo.read, input);
     SAFE_PARCEL(input.readBool, &autoRefresh);
 
     uint32_t numRegions = 0;
@@ -428,9 +426,6 @@
         what |= eReparentChildren;
         reparentSurfaceControl = other.reparentSurfaceControl;
     }
-    if (other.what & eDetachChildren) {
-        what |= eDetachChildren;
-    }
     if (other.what & eRelativeLayerChanged) {
         what |= eRelativeLayerChanged;
         what &= ~eLayerChanged;
@@ -539,15 +534,9 @@
         what |= eFrameNumberChanged;
         frameNumber = other.frameNumber;
     }
-    if (other.what & eFrameTimelineVsyncChanged) {
-        // When merging vsync Ids we take the oldest valid one
-        if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
-            other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
-            frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId);
-        } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
-            frameTimelineVsyncId = other.frameTimelineVsyncId;
-        }
-        what |= eFrameTimelineVsyncChanged;
+    if (other.what & eFrameTimelineInfoChanged) {
+        what |= eFrameTimelineInfoChanged;
+        frameTimelineInfo.merge(other.frameTimelineInfo);
     }
     if (other.what & eAutoRefreshChanged) {
         what |= eAutoRefreshChanged;
@@ -646,11 +635,13 @@
 status_t CaptureArgs::write(Parcel& output) const {
     SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(pixelFormat));
     SAFE_PARCEL(output.write, sourceCrop);
-    SAFE_PARCEL(output.writeFloat, frameScale);
+    SAFE_PARCEL(output.writeFloat, frameScaleX);
+    SAFE_PARCEL(output.writeFloat, frameScaleY);
     SAFE_PARCEL(output.writeBool, captureSecureLayers);
     SAFE_PARCEL(output.writeInt32, uid);
     SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace));
     SAFE_PARCEL(output.writeBool, allowProtected);
+    SAFE_PARCEL(output.writeBool, grayscale);
     return NO_ERROR;
 }
 
@@ -659,12 +650,14 @@
     SAFE_PARCEL(input.readInt32, &value);
     pixelFormat = static_cast<ui::PixelFormat>(value);
     SAFE_PARCEL(input.read, sourceCrop);
-    SAFE_PARCEL(input.readFloat, &frameScale);
+    SAFE_PARCEL(input.readFloat, &frameScaleX);
+    SAFE_PARCEL(input.readFloat, &frameScaleY);
     SAFE_PARCEL(input.readBool, &captureSecureLayers);
     SAFE_PARCEL(input.readInt32, &uid);
     SAFE_PARCEL(input.readInt32, &value);
     dataspace = static_cast<ui::Dataspace>(value);
     SAFE_PARCEL(input.readBool, &allowProtected);
+    SAFE_PARCEL(input.readBool, &grayscale);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/ScreenCaptureResults.cpp b/libs/gui/ScreenCaptureResults.cpp
index 2b29487..f3849bc 100644
--- a/libs/gui/ScreenCaptureResults.cpp
+++ b/libs/gui/ScreenCaptureResults.cpp
@@ -25,6 +25,14 @@
     } else {
         SAFE_PARCEL(parcel->writeBool, false);
     }
+
+    if (fence != Fence::NO_FENCE) {
+        SAFE_PARCEL(parcel->writeBool, true);
+        SAFE_PARCEL(parcel->write, *fence);
+    } else {
+        SAFE_PARCEL(parcel->writeBool, false);
+    }
+
     SAFE_PARCEL(parcel->writeBool, capturedSecureLayers);
     SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(capturedDataspace));
     SAFE_PARCEL(parcel->writeInt32, result);
@@ -39,6 +47,13 @@
         SAFE_PARCEL(parcel->read, *buffer);
     }
 
+    bool hasFence;
+    SAFE_PARCEL(parcel->readBool, &hasFence);
+    if (hasFence) {
+        fence = new Fence();
+        SAFE_PARCEL(parcel->read, *fence);
+    }
+
     SAFE_PARCEL(parcel->readBool, &capturedSecureLayers);
     uint32_t dataspace = 0;
     SAFE_PARCEL(parcel->readUint32, &dataspace);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e82f0cc..59ad8d2 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1496,8 +1496,8 @@
     case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER:
         res = dispatchGetLastQueuedBuffer(args);
         break;
-    case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC:
-        res = dispatchSetFrameTimelineVsync(args);
+    case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
+        res = dispatchSetFrameTimelineInfo(args);
         break;
     default:
         res = NAME_NOT_FOUND;
@@ -1806,12 +1806,13 @@
     return result;
 }
 
-int Surface::dispatchSetFrameTimelineVsync(va_list args) {
+int Surface::dispatchSetFrameTimelineInfo(va_list args) {
     ATRACE_CALL();
     auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
+    auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
 
-    ALOGV("Surface::dispatchSetFrameTimelineVsync");
-    return setFrameTimelineVsync(frameTimelineVsyncId);
+    ALOGV("Surface::%s", __func__);
+    return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
 }
 
 bool Surface::transformToDisplayInverse() {
@@ -2579,9 +2580,8 @@
                                            shouldBeSeamless);
 }
 
-status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
-    return composerService()->setFrameTimelineVsync(mGraphicBufferProducer,
-        frameTimelineVsyncId);
+status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
+    return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
 }
 
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 78f655a..550803d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -396,7 +396,7 @@
         mContainsBuffer(other.mContainsBuffer),
         mDesiredPresentTime(other.mDesiredPresentTime),
         mIsAutoTimestamp(other.mIsAutoTimestamp),
-        mFrameTimelineVsyncId(other.mFrameTimelineVsyncId),
+        mFrameTimelineInfo(other.mFrameTimelineInfo),
         mApplyToken(other.mApplyToken) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
@@ -427,7 +427,9 @@
     const bool containsBuffer = parcel->readBool();
     const int64_t desiredPresentTime = parcel->readInt64();
     const bool isAutoTimestamp = parcel->readBool();
-    const int64_t frameTimelineVsyncId = parcel->readInt64();
+    FrameTimelineInfo frameTimelineInfo;
+    SAFE_PARCEL(frameTimelineInfo.read, *parcel);
+
     sp<IBinder> applyToken;
     parcel->readNullableStrongBinder(&applyToken);
     size_t count = static_cast<size_t>(parcel->readUint32());
@@ -502,7 +504,7 @@
     mContainsBuffer = containsBuffer;
     mDesiredPresentTime = desiredPresentTime;
     mIsAutoTimestamp = isAutoTimestamp;
-    mFrameTimelineVsyncId = frameTimelineVsyncId;
+    mFrameTimelineInfo = frameTimelineInfo;
     mDisplayStates = displayStates;
     mListenerCallbacks = listenerCallbacks;
     mComposerStates = composerStates;
@@ -534,7 +536,7 @@
     parcel->writeBool(mContainsBuffer);
     parcel->writeInt64(mDesiredPresentTime);
     parcel->writeBool(mIsAutoTimestamp);
-    parcel->writeInt64(mFrameTimelineVsyncId);
+    SAFE_PARCEL(mFrameTimelineInfo.write, *parcel);
     parcel->writeStrongBinder(mApplyToken);
     parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
     for (auto const& displayState : mDisplayStates) {
@@ -613,13 +615,7 @@
     mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd;
     mApplyToken = other.mApplyToken;
 
-    // When merging vsync Ids we take the oldest one
-    if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
-        other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
-        mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId);
-    } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
-        mFrameTimelineVsyncId = other.mFrameTimelineVsyncId;
-    }
+    mFrameTimelineInfo.merge(other.mFrameTimelineInfo);
 
     other.clear();
     return *this;
@@ -639,7 +635,7 @@
     mExplicitEarlyWakeupEnd = false;
     mDesiredPresentTime = 0;
     mIsAutoTimestamp = true;
-    mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+    mFrameTimelineInfo.clear();
     mApplyToken = nullptr;
 }
 
@@ -651,9 +647,8 @@
     uncacheBuffer.id = cacheId;
 
     sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
-    sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {},
-                            systemTime(), true, uncacheBuffer, false, {},
-                            0 /* Undefined transactionId */);
+    sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true,
+                            uncacheBuffer, false, {}, 0 /* Undefined transactionId */);
 }
 
 void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -773,7 +768,7 @@
             ? mApplyToken
             : IInterface::asBinder(TransactionCompletedListener::getIInstance());
 
-    sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken,
+    sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
                             mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
                             {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
                             hasListenerCallbacks, listenerCallbacks, mId);
@@ -934,7 +929,8 @@
         return *this;
     }
     if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) ||
-        (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot)) {
+        (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) ||
+        (mask & layer_state_t::eEnableBackpressure)) {
         s->what |= layer_state_t::eFlagsChanged;
     }
     s->flags &= ~mask;
@@ -1390,19 +1386,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
-        const sp<SurfaceControl>& sc) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eDetachChildren;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
 #ifndef NO_INPUT
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
         const sp<SurfaceControl>& sc,
@@ -1548,22 +1531,22 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
-        int64_t frameTimelineVsyncId) {
-    mFrameTimelineVsyncId = frameTimelineVsyncId;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+        const FrameTimelineInfo& frameTimelineInfo) {
+    mFrameTimelineInfo = frameTimelineInfo;
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
-        const sp<SurfaceControl>& sc, int64_t frameTimelineVsyncId) {
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+        const sp<SurfaceControl>& sc, const FrameTimelineInfo& frameTimelineInfo) {
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
         return *this;
     }
 
-    s->what |= layer_state_t::eFrameTimelineVsyncChanged;
-    s->frameTimelineVsyncId = frameTimelineVsyncId;
+    s->what |= layer_state_t::eFrameTimelineInfoChanged;
+    s->frameTimelineInfo = frameTimelineInfo;
     return *this;
 }
 
diff --git a/libs/gui/aidl/android/gui/IScreenCaptureListener.aidl b/libs/gui/aidl/android/gui/IScreenCaptureListener.aidl
index f490118..e0f66cd 100644
--- a/libs/gui/aidl/android/gui/IScreenCaptureListener.aidl
+++ b/libs/gui/aidl/android/gui/IScreenCaptureListener.aidl
@@ -20,5 +20,5 @@
 
 /** @hide */
 oneway interface IScreenCaptureListener {
-    void onScreenCaptureComplete(in ScreenCaptureResults captureResults);
+    void onScreenCaptureCompleted(in ScreenCaptureResults captureResults);
 }
\ No newline at end of file
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 411526e..fa3efe1 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -92,7 +92,7 @@
     void flushShadowQueue() { mFlushShadowQueue = true; }
 
     status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
-    status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+    status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
 
     virtual ~BLASTBufferQueue();
 
@@ -109,7 +109,7 @@
     Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
     // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
     bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
-    bool maxBuffersAcquired() const REQUIRES(mMutex);
+    bool maxBuffersAcquired(bool includeExtraAcquire) const REQUIRES(mMutex);
 
     std::string mName;
     sp<SurfaceControl> mSurfaceControl;
@@ -156,7 +156,7 @@
     // This is only relevant for shared buffer mode.
     bool mAutoRefresh GUARDED_BY(mMutex) = false;
 
-    std::queue<int64_t> mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex);
+    std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex);
 
     // Last acquired buffer's scaling mode. This is used to check if we should update the blast
     // layer size immediately or wait until we get the next buffer. This will support scenarios
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index 7db69ec..6aa801a 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -174,6 +174,10 @@
     // Value used to determine if present time is valid.
     constexpr static int MAX_REASONABLE_NSEC = 1'000'000'000ULL; // 1 second
 
+    // This allows the consumer to acquire an additional buffer if that buffer is not droppable and
+    // will eventually be released or acquired by the consumer.
+    void setAllowExtraAcquire(bool /* allow */);
+
 private:
     sp<BufferQueueCore> mCore;
 
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 557c28b..8d0828d 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -354,6 +354,9 @@
     // mTransformHintInUse is to cache the mTransformHint used by the producer.
     uint32_t mTransformHintInUse;
 
+    // This allows the consumer to acquire an additional buffer if that buffer is not droppable and
+    // will eventually be released or acquired by the consumer.
+    bool mAllowExtraAcquire = false;
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 5587acf..4175a49 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -25,7 +25,7 @@
     // The Vsync Id corresponsing to this vsync event. This will be used to
     // populate ISurfaceComposer::setFrameTimelineVsync and
     // SurfaceComposerClient::setFrameTimelineVsync
-    int64_t id = ISurfaceComposer::INVALID_VSYNC_ID;
+    int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
 
     // The deadline in CLOCK_MONOTONIC that the app needs to complete its
     // frame by (both on the CPU and the GPU)
@@ -52,7 +52,20 @@
 private:
     sp<Looper> mLooper;
     DisplayEventReceiver mReceiver;
-    bool mWaitingForVsync;
+    // The state of vsync event registration and whether the client is expecting
+    // an event or not.
+    enum class VsyncState {
+        // The dispatcher is not registered for vsync events.
+        Unregistered,
+        // The dispatcher is registered to receive vsync events but should not dispatch it to the
+        // client as the client is not expecting a vsync event.
+        Registered,
+
+        // The dispatcher is registered to receive vsync events and supposed to dispatch it to
+        // the client.
+        RegisteredAndWaitingForVsync,
+    };
+    VsyncState mVsyncState;
 
     std::vector<FrameRateOverride> mFrameRateOverrides;
 
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
new file mode 100644
index 0000000..3b4c009
--- /dev/null
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <android/os/IInputConstants.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+struct FrameTimelineInfo {
+    // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
+    static constexpr int64_t INVALID_VSYNC_ID = -1;
+
+    // The vsync id that was used to start the transaction
+    int64_t vsyncId = INVALID_VSYNC_ID;
+
+    // The id of the input event that caused this buffer
+    int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+
+    status_t write(Parcel& output) const;
+    status_t read(const Parcel& input);
+
+    void merge(const FrameTimelineInfo& other);
+    void clear();
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 86f3c60..81ff6b0 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -24,6 +24,7 @@
 
 #include <android/gui/IScreenCaptureListener.h>
 #include <android/gui/ITransactionTraceListener.h>
+#include <gui/FrameTimelineInfo.h>
 #include <gui/ITransactionCompletedListener.h>
 
 #include <input/Flags.h>
@@ -117,9 +118,6 @@
 
     using EventRegistrationFlags = Flags<EventRegistration>;
 
-    // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
-    static constexpr int64_t INVALID_VSYNC_ID = -1;
-
     /*
      * Create a connection with SurfaceFlinger.
      */
@@ -164,7 +162,7 @@
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
     virtual status_t setTransactionState(
-            int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+            const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
             const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
             bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
@@ -494,11 +492,11 @@
     virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
 
     /*
-     * Sets the frame timeline vsync id received from choreographer that corresponds to next
+     * Sets the frame timeline vsync info received from choreographer that corresponds to next
      * buffer submitted on that surface.
      */
-    virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
-                                           int64_t frameTimelineVsyncId) = 0;
+    virtual status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+                                          const FrameTimelineInfo& frameTimelineInfo) = 0;
 
     /*
      * Adds a TransactionTraceListener to listen for transaction tracing state updates.
@@ -569,7 +567,7 @@
         SET_GAME_CONTENT_TYPE,
         SET_FRAME_RATE,
         ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
-        SET_FRAME_TIMELINE_VSYNC,
+        SET_FRAME_TIMELINE_INFO,
         ADD_TRANSACTION_TRACE_LISTENER,
         GET_GPU_CONTEXT_PRIORITY,
         // Always append new enum to the end.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 83a9d33..2f9a0c0 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -82,6 +82,10 @@
         eLayerOpaque = 0x02,         // SURFACE_OPAQUE
         eLayerSkipScreenshot = 0x40, // SKIP_SCREENSHOT
         eLayerSecure = 0x80,         // SECURE
+        // Queue up BufferStateLayer buffers instead of dropping the oldest buffer when this flag is
+        // set. This blocks the client until all the buffers have been presented. If the buffers
+        // have presentation timestamps, then we may drop buffers.
+        eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE
     };
 
     enum {
@@ -98,7 +102,7 @@
         /* was ScalingModeChanged, now available 0x00000400, */
         eShadowRadiusChanged = 0x00000800,
         eReparentChildren = 0x00001000,
-        eDetachChildren = 0x00002000,
+        /* was eDetachChildren, now available 0x00002000, */
         eRelativeLayerChanged = 0x00004000,
         eReparent = 0x00008000,
         eColorChanged = 0x00010000,
@@ -128,7 +132,7 @@
         eProducerDisconnect = 0x100'00000000,
         eFixedTransformHintChanged = 0x200'00000000,
         eFrameNumberChanged = 0x400'00000000,
-        eFrameTimelineVsyncChanged = 0x800'00000000,
+        eFrameTimelineInfoChanged = 0x800'00000000,
         eBlurRegionsChanged = 0x1000'00000000,
         eAutoRefreshChanged = 0x2000'00000000,
     };
@@ -157,8 +161,8 @@
     uint32_t h;
     uint32_t layerStack;
     float alpha;
-    uint8_t flags;
-    uint8_t mask;
+    uint32_t flags;
+    uint32_t mask;
     uint8_t reserved;
     matrix22_t matrix;
     Rect crop_legacy;
@@ -234,7 +238,7 @@
     // graphics producer.
     uint64_t frameNumber;
 
-    int64_t frameTimelineVsyncId;
+    FrameTimelineInfo frameTimelineInfo;
 
     // Indicates that the consumer should acquire the next frame as soon as it
     // can and not wait for a frame to become available. This is only relevant
@@ -324,7 +328,8 @@
 
     ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
     Rect sourceCrop;
-    float frameScale{1};
+    float frameScaleX{1};
+    float frameScaleY{1};
     bool captureSecureLayers{false};
     int32_t uid{UNSET_UID};
     // Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
@@ -342,6 +347,8 @@
     // the contents being accessed/captured by screenshot or unsecure display.
     bool allowProtected = false;
 
+    bool grayscale = false;
+
     virtual status_t write(Parcel& output) const;
     virtual status_t read(const Parcel& input);
 };
diff --git a/libs/gui/include/gui/ScreenCaptureResults.h b/libs/gui/include/gui/ScreenCaptureResults.h
index fdb4b69..0ccc6e8 100644
--- a/libs/gui/include/gui/ScreenCaptureResults.h
+++ b/libs/gui/include/gui/ScreenCaptureResults.h
@@ -27,6 +27,7 @@
 
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
+#include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 
 namespace android::gui {
@@ -39,6 +40,7 @@
     status_t readFromParcel(const android::Parcel* parcel) override;
 
     sp<GraphicBuffer> buffer;
+    sp<Fence> fence = Fence::NO_FENCE;
     bool capturedSecureLayers{false};
     ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB};
     status_t result = OK;
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 43b5dcd..b6b5c7c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -18,6 +18,7 @@
 #define ANDROID_GUI_SURFACE_H
 
 #include <gui/BufferQueueDefs.h>
+#include <gui/FrameTimelineInfo.h>
 #include <gui/HdrMetadata.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/IProducerListener.h>
@@ -187,7 +188,7 @@
     status_t getConsumerUsage(uint64_t* outUsage) const;
 
     virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
-    virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+    virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
 
 protected:
     virtual ~Surface();
@@ -273,7 +274,7 @@
     int dispatchAddQueueInterceptor(va_list args);
     int dispatchAddQueryInterceptor(va_list args);
     int dispatchGetLastQueuedBuffer(va_list args);
-    int dispatchSetFrameTimelineVsync(va_list args);
+    int dispatchSetFrameTimelineInfo(va_list args);
     bool transformToDisplayInverse();
 
 protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 11db658..e7abfe6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -385,8 +385,8 @@
         int64_t mDesiredPresentTime = 0;
         bool mIsAutoTimestamp = true;
 
-        // The vsync Id provided by Choreographer.getVsyncId
-        int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+        // The vsync id provided by Choreographer.getVsyncId and the input event id
+        FrameTimelineInfo mFrameTimelineInfo;
 
         // If not null, transactions will be queued up using this token otherwise a common token
         // per process will be used.
@@ -508,18 +508,6 @@
         // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
         Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
 
-        // Detaches all child surfaces (and their children recursively)
-        // from their SurfaceControl.
-        // The child SurfaceControls will not throw exceptions or return errors,
-        // but transactions will have no effect.
-        // The child surfaces will continue to follow their parent surfaces,
-        // and remain eligible for rendering, but their relative state will be
-        // frozen. We use this in the WindowManager, in app shutdown/relaunch
-        // scenarios, where the app would otherwise clean up its child Surfaces.
-        // Sometimes the WindowManager needs to extend their lifetime slightly
-        // in order to perform an exit animation or prevent flicker.
-        Transaction& detachChildren(const sp<SurfaceControl>& sc);
-
 #ifndef NO_INPUT
         Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
         Transaction& setFocusedWindow(const FocusRequest& request);
@@ -546,11 +534,12 @@
         Transaction& setFixedTransformHint(const sp<SurfaceControl>& sc, int32_t transformHint);
 
         // Sets the frame timeline vsync id received from choreographer that corresponds
-        // to the transaction.
-        Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+        // to the transaction, and the input event id that identifies the input event that caused
+        // the current frame.
+        Transaction& setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo);
         // Variant that only applies to a specific SurfaceControl.
-        Transaction& setFrameTimelineVsync(const sp<SurfaceControl>& sc,
-                int64_t frameTimelineVsyncId);
+        Transaction& setFrameTimelineInfo(const sp<SurfaceControl>& sc,
+                                          const FrameTimelineInfo& frameTimelineInfo);
 
         // Indicates that the consumer should acquire the next frame as soon as it
         // can and not wait for a frame to become available. This is only relevant
diff --git a/libs/gui/include/gui/SyncScreenCaptureListener.h b/libs/gui/include/gui/SyncScreenCaptureListener.h
index 8620b77..0784fbc 100644
--- a/libs/gui/include/gui/SyncScreenCaptureListener.h
+++ b/libs/gui/include/gui/SyncScreenCaptureListener.h
@@ -26,14 +26,16 @@
 
 struct SyncScreenCaptureListener : gui::BnScreenCaptureListener {
 public:
-    binder::Status onScreenCaptureComplete(const ScreenCaptureResults& captureResults) override {
+    binder::Status onScreenCaptureCompleted(const ScreenCaptureResults& captureResults) override {
         resultsPromise.set_value(captureResults);
         return binder::Status::ok();
     }
 
     ScreenCaptureResults waitForResults() {
         std::future<ScreenCaptureResults> resultsFuture = resultsPromise.get_future();
-        return resultsFuture.get();
+        const auto screenCaptureResults = resultsFuture.get();
+        screenCaptureResults.fence->waitForever("");
+        return screenCaptureResults;
     }
 
 private:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 63db9a7..3f7a5b1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -695,7 +695,7 @@
     void destroyDisplay(const sp<IBinder>& /*display */) override {}
     std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override { return {}; }
     sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; }
-    status_t setTransactionState(int64_t /*frameTimelineVsyncId*/,
+    status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/,
                                  const Vector<ComposerState>& /*state*/,
                                  const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
                                  const sp<IBinder>& /*applyToken*/,
@@ -877,8 +877,8 @@
         return NO_ERROR;
     }
 
-    status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& /*surface*/,
-                                   int64_t /*frameTimelineVsyncId*/) override {
+    status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& /*surface*/,
+                                  const FrameTimelineInfo& /*frameTimelineInfo*/) override {
         return NO_ERROR;
     }
 
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 2ed441d..698cf6e 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -166,6 +166,7 @@
         mKeyboardType(other.mKeyboardType),
         mKeyCharacterMap(other.mKeyCharacterMap),
         mHasVibrator(other.mHasVibrator),
+        mHasBattery(other.mHasBattery),
         mHasButtonUnderPad(other.mHasButtonUnderPad),
         mHasSensor(other.mHasSensor),
         mMotionRanges(other.mMotionRanges),
@@ -187,6 +188,7 @@
     mSources = 0;
     mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
     mHasVibrator = false;
+    mHasBattery = false;
     mHasButtonUnderPad = false;
     mHasSensor = false;
     mMotionRanges.clear();
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 6316b59..bce0ec8 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -28,4 +28,13 @@
       * to identify apps that are using this flag.
       */
     const long BLOCK_FLAG_SLIPPERY = 157929241;
+
+    // Indicate invalid battery capacity
+    const int INVALID_BATTERY_CAPACITY = -1;
+
+    /**
+     * Every input event has an id. This constant value is used when a valid input event id is not
+     * available.
+     */
+    const int INVALID_INPUT_EVENT_ID = 0;
 }
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 6d91916..6b085a3 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
 #include <gui/DisplayEventDispatcher.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 #include <private/android/choreographer.h>
 #include <utils/Looper.h>
 #include <utils/Timers.h>
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6574ae6 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -53,15 +53,13 @@
         "libcutils",
         "libEGL",
         "libGLESv2",
-        "libnativehelper",
     ],
 
-    export_shared_lib_headers: [
-        "libnativehelper",
-    ],
+    export_header_lib_headers: ["jni_headers"],
 
     header_libs: [
+        "jni_headers",
         "libnativedisplay_headers",
+        "libnativehelper_header_only",
     ],
-
 }
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index d3a4a66..0f4fd45 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
 
 #include <apex/choreographer.h>
 #include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 
 namespace android {
 
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 #include <system/graphics.h>
 
 // This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
 #include <mutex>
 
 #include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
 
 struct ASurfaceTexture {
     android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 4fcca9e..20a1f74 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -334,8 +334,6 @@
 
 // clang-format on
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Allocates a buffer that matches the passed AHardwareBuffer_Desc.
  *
@@ -478,10 +476,6 @@
                                              AHardwareBuffer* _Nullable* _Nonnull outBuffer)
         __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
  *
@@ -551,10 +545,6 @@
                                    int32_t* _Nonnull outBytesPerPixel,
                                    int32_t* _Nonnull outBytesPerStride) __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 31
-
 /**
  * Get the system wide unique id for an AHardwareBuffer.
  *
@@ -566,8 +556,6 @@
 int AHardwareBuffer_getId(const AHardwareBuffer* _Nonnull buffer, uint64_t* _Nonnull outId)
         __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 __END_DECLS
 
 #endif // ANDROID_HARDWARE_BUFFER_H
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index deea59b..285f2fb 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -186,8 +186,6 @@
  */
 int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Set a transform that will be applied to future buffers posted to the window.
  *
@@ -198,10 +196,6 @@
  */
 int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 28
-
 /**
  * All buffers queued after this call will be associated with the dataSpace
  * parameter specified.
@@ -230,10 +224,6 @@
  */
 int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
 
-#endif // __ANDROID_API__ >= 28
-
-#if __ANDROID_API__ >= 30
-
 /** Compatibility value for ANativeWindow_setFrameRate. */
 enum ANativeWindow_FrameRateCompatibility {
     /**
@@ -275,11 +265,7 @@
  *
  * Available since API level 30.
  */
-void ANativeWindow_tryAllocateBuffers(ANativeWindow* window);
-
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
+void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) __INTRODUCED_IN(30);
 
 /**
  * Sets the intended frame rate for this window.
@@ -322,8 +308,6 @@
 int32_t ANativeWindow_setFrameRateWithSeamlessness(ANativeWindow* window, float frameRate,
         int8_t compatibility, bool shouldBeSeamless) __INTRODUCED_IN(31);
 
-#endif // __ANDROID_API__ >= 31
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 82d2e66..ffe4412 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -255,7 +255,7 @@
     NATIVE_WINDOW_ALLOCATE_BUFFERS                = 45,    /* private */
     NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER          = 46,    /* private */
     NATIVE_WINDOW_SET_QUERY_INTERCEPTOR           = 47,    /* private */
-    NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC        = 48,    /* private */
+    NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO         = 48,    /* private */
     // clang-format on
 };
 
@@ -1023,10 +1023,11 @@
                            (int)compatibility, (int)shouldBeSeamless);
 }
 
-static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window,
-                                                         int64_t frameTimelineVsyncId) {
-    return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC,
-                           frameTimelineVsyncId);
+static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
+                                                         int64_t frameTimelineVsyncId,
+                                                         int32_t inputEventId) {
+    return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO,
+                           frameTimelineVsyncId, inputEventId);
 }
 
 // ------------------------------------------------------------------------------------------------
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 7bddee6..4714469 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -64,13 +64,15 @@
     }
 }
 
-void SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
+status_t SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
         const sp<hardware::ISensorPrivacyListener>& listener)
 {
     sp<hardware::ISensorPrivacyManager> service = getService();
     if (service != nullptr) {
-        service->addIndividualSensorPrivacyListener(userId, sensor, listener);
+        return service->addIndividualSensorPrivacyListener(userId, sensor, listener)
+                .transactionError();
     }
+    return UNEXPECTED_NULL;
 }
 
 void SensorPrivacyManager::removeSensorPrivacyListener(
@@ -106,6 +108,19 @@
     return false;
 }
 
+status_t SensorPrivacyManager::isIndividualSensorPrivacyEnabled(int userId, int sensor,
+        bool &returnVal)
+{
+    sp<hardware::ISensorPrivacyManager> service = getService();
+    if (service != nullptr) {
+        binder::Status res = service->isIndividualSensorPrivacyEnabled(userId, sensor, &returnVal);
+        return res.transactionError();
+    }
+    // if the SensorPrivacyManager is not available then assume sensor privacy is disabled
+    returnVal = false;
+    return UNKNOWN_ERROR;
+}
+
 status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
 {
     sp<hardware::ISensorPrivacyManager> service = getService();
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index bd7c726..12778e1 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -36,11 +36,12 @@
     SensorPrivacyManager();
 
     void addSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
-    void addIndividualSensorPrivacyListener(int userId, int sensor,
+    status_t addIndividualSensorPrivacyListener(int userId, int sensor,
             const sp<hardware::ISensorPrivacyListener>& listener);
     void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
     bool isSensorPrivacyEnabled();
     bool isIndividualSensorPrivacyEnabled(int userId, int sensor);
+    status_t isIndividualSensorPrivacyEnabled(int userId, int sensor, bool &result);
 
     status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
     status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index ea9b483..69aea84 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -108,6 +108,10 @@
     virtual bool isVibrating(int32_t deviceId) = 0;
 
     virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+    /* Get battery level of a particular input device. */
+    virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0;
+    /* Get battery status of a particular input device. */
+    virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0;
 
     /* Return true if the device can send input events to the specified display. */
     virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index abda4ef..7f979f2 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -30,6 +30,7 @@
         "mapper/accumulator/CursorScrollAccumulator.cpp",
         "mapper/accumulator/SingleTouchMotionAccumulator.cpp",
         "mapper/accumulator/TouchButtonAccumulator.cpp",
+        "mapper/BatteryInputMapper.cpp",
         "mapper/CursorInputMapper.cpp",
         "mapper/ExternalStylusInputMapper.cpp",
         "mapper/InputMapper.cpp",
@@ -60,7 +61,11 @@
         "libui",
         "libutils",
     ],
+    static_libs: [
+        "libc++fs",
+    ],
     header_libs: [
+        "libbatteryservice_headers",
         "libinputreader_headers",
     ],
 }
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index b97ff90..8f8c051 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -29,11 +29,14 @@
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
 #include <sys/limits.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <unistd.h>
 
 #define LOG_TAG "EventHub"
 
 // #define LOG_NDEBUG 0
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <cutils/properties.h>
 #include <input/KeyCharacterMap.h>
@@ -64,6 +67,23 @@
 static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
 static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
 
+// must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c
+static const std::unordered_map<std::string, int32_t> BATTERY_STATUS =
+        {{"Unknown", BATTERY_STATUS_UNKNOWN},
+         {"Charging", BATTERY_STATUS_CHARGING},
+         {"Discharging", BATTERY_STATUS_DISCHARGING},
+         {"Not charging", BATTERY_STATUS_NOT_CHARGING},
+         {"Full", BATTERY_STATUS_FULL}};
+
+// Mapping taken from
+// https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-supply.c#L484
+static const std::unordered_map<std::string, int32_t> BATTERY_LEVEL = {{"Critical", 5},
+                                                                       {"Low", 10},
+                                                                       {"Normal", 55},
+                                                                       {"High", 70},
+                                                                       {"Full", 100},
+                                                                       {"Unknown", 50}};
+
 static inline const char* toString(bool value) {
     return value ? "true" : "false";
 }
@@ -127,6 +147,73 @@
     return inputEventTime;
 }
 
+/**
+ * Returns the sysfs root path of the input device
+ *
+ */
+static std::filesystem::path getSysfsRootPath(const char* devicePath) {
+    std::error_code errorCode;
+
+    // Stat the device path to get the major and minor number of the character file
+    struct stat statbuf;
+    if (stat(devicePath, &statbuf) == -1) {
+        ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
+        return std::filesystem::path();
+    }
+
+    unsigned int major_num = major(statbuf.st_rdev);
+    unsigned int minor_num = minor(statbuf.st_rdev);
+
+    // Realpath "/sys/dev/char/{major}:{minor}" to get the sysfs path to the input event
+    auto sysfsPath = std::filesystem::path("/sys/dev/char/");
+    sysfsPath /= std::to_string(major_num) + ":" + std::to_string(minor_num);
+    sysfsPath = std::filesystem::canonical(sysfsPath, errorCode);
+
+    // Make sure nothing went wrong in call to canonical()
+    if (errorCode) {
+        ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
+              errorCode.message().c_str());
+        return std::filesystem::path();
+    }
+
+    // Continue to go up a directory until we reach a directory named "input"
+    while (sysfsPath != "/" && sysfsPath.filename() != "input") {
+        sysfsPath = sysfsPath.parent_path();
+    }
+
+    // Then go up one more and you will be at the sysfs root of the device
+    sysfsPath = sysfsPath.parent_path();
+
+    // Make sure we didn't reach root path and that directory actually exists
+    if (sysfsPath == "/" || !std::filesystem::exists(sysfsPath, errorCode)) {
+        if (errorCode) {
+            ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
+                  errorCode.message().c_str());
+        }
+
+        // Not found
+        return std::filesystem::path();
+    }
+
+    return sysfsPath;
+}
+
+/**
+ * Returns the power supply node in sys fs
+ *
+ */
+static std::filesystem::path findPowerSupplyNode(const std::filesystem::path& sysfsRootPath) {
+    for (auto path = sysfsRootPath; path != "/"; path = path.parent_path()) {
+        std::error_code errorCode;
+        auto iter = std::filesystem::directory_iterator(path / "power_supply", errorCode);
+        if (!errorCode && iter != std::filesystem::directory_iterator()) {
+            return iter->path();
+        }
+    }
+    // Not found
+    return std::filesystem::path();
+}
+
 // --- Global Functions ---
 
 Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
@@ -976,6 +1063,56 @@
     return nullptr;
 }
 
+std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const {
+    std::scoped_lock _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    std::string buffer;
+
+    if (!device || (device->sysfsBatteryPath.empty())) {
+        return std::nullopt;
+    }
+
+    // Some devices report battery capacity as an integer through the "capacity" file
+    if (base::ReadFileToString(device->sysfsBatteryPath / "capacity", &buffer)) {
+        return std::stoi(buffer);
+    }
+
+    // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX
+    // These values are taken from kernel source code include/linux/power_supply.h
+    if (base::ReadFileToString(device->sysfsBatteryPath / "capacity_level", &buffer)) {
+        const auto it = BATTERY_LEVEL.find(buffer);
+        if (it != BATTERY_LEVEL.end()) {
+            return it->second;
+        }
+    }
+    return std::nullopt;
+}
+
+std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const {
+    std::scoped_lock _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    std::string buffer;
+
+    if (!device || (device->sysfsBatteryPath.empty())) {
+        return std::nullopt;
+    }
+
+    if (!base::ReadFileToString(device->sysfsBatteryPath / "status", &buffer)) {
+        ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
+        return std::nullopt;
+    }
+
+    // Remove trailing new line
+    buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end());
+    const auto it = BATTERY_STATUS.find(buffer);
+
+    if (it != BATTERY_STATUS.end()) {
+        return it->second;
+    }
+
+    return std::nullopt;
+}
+
 size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
     ALOG_ASSERT(bufferSize >= 1);
 
@@ -1584,6 +1721,18 @@
         return -1;
     }
 
+    // Grab the device's sysfs path
+    device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+
+    if (!device->sysfsRootPath.empty()) {
+        device->sysfsBatteryPath = findPowerSupplyNode(device->sysfsRootPath);
+
+        // Check if a battery exists
+        if (!device->sysfsBatteryPath.empty()) {
+            device->classes |= InputDeviceClass::BATTERY;
+        }
+    }
+
     // Determine whether the device has a mic.
     if (device->deviceHasMicLocked()) {
         device->classes |= InputDeviceClass::MIC;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 3e6910d..8fc6f4a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -21,6 +21,7 @@
 #include <input/Flags.h>
 #include <algorithm>
 
+#include "BatteryInputMapper.h"
 #include "CursorInputMapper.h"
 #include "ExternalStylusInputMapper.h"
 #include "InputReaderContext.h"
@@ -160,6 +161,11 @@
         mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
     }
 
+    // Battery-like devices.
+    if (classes.test(InputDeviceClass::BATTERY)) {
+        mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+    }
+
     // Keyboard-like devices.
     uint32_t keyboardSource = 0;
     int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
@@ -490,6 +496,15 @@
     for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
 }
 
+std::optional<int32_t> InputDevice::getBatteryCapacity() {
+    return first_in_mappers<int32_t>(
+            [](InputMapper& mapper) { return mapper.getBatteryCapacity(); });
+}
+
+std::optional<int32_t> InputDevice::getBatteryStatus() {
+    return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); });
+}
+
 int32_t InputDevice::getMetaState() {
     int32_t result = 0;
     for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 7c448e4..de5d0e6 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -673,6 +673,26 @@
     }
 }
 
+std::optional<int32_t> InputReader::getBatteryCapacity(int32_t deviceId) {
+    std::scoped_lock _l(mLock);
+
+    InputDevice* device = findInputDeviceLocked(deviceId);
+    if (device) {
+        return device->getBatteryCapacity();
+    }
+    return std::nullopt;
+}
+
+std::optional<int32_t> InputReader::getBatteryStatus(int32_t deviceId) {
+    std::scoped_lock _l(mLock);
+
+    InputDevice* device = findInputDeviceLocked(deviceId);
+    if (device) {
+        return device->getBatteryStatus();
+    }
+    return std::nullopt;
+}
+
 bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
     std::scoped_lock _l(mLock);
 
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 2cea017..30967df 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -23,6 +23,9 @@
 #include <vector>
 
 #include <input/Flags.h>
+#include <filesystem>
+
+#include <batteryservice/BatteryService.h>
 #include <input/Input.h>
 #include <input/InputDevice.h>
 #include <input/KeyCharacterMap.h>
@@ -121,6 +124,9 @@
     /* The input device has a sensor like accelerometer, gyro, etc */
     SENSOR = 0x00002000,
 
+    /* The input device has a battery */
+    BATTERY = 0x00004000,
+
     /* The input device is virtual (not a real device, not part of UI configuration). */
     VIRTUAL = 0x40000000,
 
@@ -242,6 +248,12 @@
     virtual void cancelVibrate(int32_t deviceId) = 0;
     virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
 
+    /* Query battery level. */
+    virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const = 0;
+
+    /* Query battery status. */
+    virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) const = 0;
+
     /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
     virtual void requestReopenDevices() = 0;
 
@@ -404,6 +416,10 @@
 
     void monitor() override final;
 
+    std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const override final;
+
+    std::optional<int32_t> getBatteryStatus(int32_t deviceId) const override final;
+
     bool isDeviceEnabled(int32_t deviceId) override final;
 
     status_t enableDevice(int32_t deviceId) override final;
@@ -442,6 +458,10 @@
         bool ffEffectPlaying;
         int16_t ffEffectId; // initially -1
 
+        // The paths are invalid when .empty() returns true
+        std::filesystem::path sysfsRootPath;
+        std::filesystem::path sysfsBatteryPath;
+
         int32_t controllerNumber;
 
         Device(int fd, int32_t id, const std::string& path,
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 5af76b7..e4186c8 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -92,6 +92,9 @@
     void disableSensor(InputDeviceSensorType sensorType);
     void flushSensor(InputDeviceSensorType sensorType);
 
+    std::optional<int32_t> getBatteryCapacity();
+    std::optional<int32_t> getBatteryStatus();
+
     int32_t getMetaState();
     void updateMetaState(int32_t keyCode);
 
@@ -287,6 +290,12 @@
 
     inline std::vector<int32_t> getVibratorIds() { return mEventHub->getVibratorIds(mId); }
 
+    inline std::optional<int32_t> getBatteryCapacity() {
+        return mEventHub->getBatteryCapacity(mId);
+    }
+
+    inline std::optional<int32_t> getBatteryStatus() { return mEventHub->getBatteryStatus(mId); }
+
     inline bool hasAbsoluteAxis(int32_t code) const {
         RawAbsoluteAxisInfo info;
         mEventHub->getAbsoluteAxisInfo(mId, code, &info);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 7be932a..e2558bc 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -95,6 +95,10 @@
 
     void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override;
 
+    std::optional<int32_t> getBatteryCapacity(int32_t deviceId) override;
+
+    std::optional<int32_t> getBatteryStatus(int32_t deviceId) override;
+
 protected:
     // These members are protected so they can be instrumented by test cases.
     virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
new file mode 100644
index 0000000..afdc5ab
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../Macros.h"
+
+#include "BatteryInputMapper.h"
+
+namespace android {
+
+BatteryInputMapper::BatteryInputMapper(InputDeviceContext& deviceContext)
+      : InputMapper(deviceContext) {}
+
+uint32_t BatteryInputMapper::getSources() {
+    return 0;
+}
+
+void BatteryInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    info->setHasBattery(true);
+}
+
+void BatteryInputMapper::process(const RawEvent* rawEvent) {}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryCapacity() {
+    return getDeviceContext().getBatteryCapacity();
+}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryStatus() {
+    return getDeviceContext().getBatteryStatus();
+}
+
+void BatteryInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Battery Input Mapper:\n";
+    dump += getBatteryCapacity().has_value()
+            ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity().value())
+            : StringPrintf(INDENT3 "Capacity: Unknown");
+
+    std::string status;
+    switch (getBatteryStatus().value_or(BATTERY_STATUS_UNKNOWN)) {
+        case BATTERY_STATUS_CHARGING:
+            status = "Charging";
+            break;
+        case BATTERY_STATUS_DISCHARGING:
+            status = "Discharging";
+            break;
+        case BATTERY_STATUS_NOT_CHARGING:
+            status = "Not charging";
+            break;
+        case BATTERY_STATUS_FULL:
+            status = "Full";
+            break;
+        default:
+            status = "Unknown";
+    }
+    dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.h b/services/inputflinger/reader/mapper/BatteryInputMapper.h
new file mode 100644
index 0000000..4fe373e
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+#define _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+
+#include "InputMapper.h"
+
+namespace android {
+
+class BatteryInputMapper : public InputMapper {
+public:
+    explicit BatteryInputMapper(InputDeviceContext& deviceContext);
+    virtual ~BatteryInputMapper(){};
+
+    uint32_t getSources() override;
+    void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+    void process(const RawEvent* rawEvent) override;
+
+    std::optional<int32_t> getBatteryCapacity() override;
+    std::optional<int32_t> getBatteryStatus() override;
+
+    void dump(std::string& dump) override;
+};
+
+} // namespace android
+
+#endif // _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 6ca6ec9..44af998 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -72,6 +72,9 @@
     virtual void disableSensor(InputDeviceSensorType sensorType);
     virtual void flushSensor(InputDeviceSensorType sensorType);
 
+    virtual std::optional<int32_t> getBatteryCapacity() { return std::nullopt; }
+    virtual std::optional<int32_t> getBatteryStatus() { return std::nullopt; }
+
     virtual int32_t getMetaState();
     virtual void updateMetaState(int32_t keyCode);
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 36da8dd..0e88312 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <BatteryInputMapper.h>
 #include <CursorInputMapper.h>
 #include <InputDevice.h>
 #include <InputMapper.h>
@@ -67,6 +68,8 @@
 static constexpr int32_t FIRST_TRACKING_ID = 0;
 static constexpr int32_t SECOND_TRACKING_ID = 1;
 static constexpr int32_t THIRD_TRACKING_ID = 2;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
 
 // Error tolerance for floating point assertions.
 static const float EPSILON = 0.001f;
@@ -863,6 +866,10 @@
 
     std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
 
+    std::optional<int32_t> getBatteryCapacity(int32_t) const override { return BATTERY_CAPACITY; }
+
+    std::optional<int32_t> getBatteryStatus(int32_t) const override { return BATTERY_STATUS; }
+
     virtual bool isExternal(int32_t) const {
         return false;
     }
@@ -1924,6 +1931,52 @@
     ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
 }
 
+class FakeBatteryInputMapper : public FakeInputMapper {
+public:
+    FakeBatteryInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+          : FakeInputMapper(deviceContext, sources) {}
+
+    std::optional<int32_t> getBatteryCapacity() override {
+        return getDeviceContext().getBatteryCapacity();
+    }
+
+    std::optional<int32_t> getBatteryStatus() override {
+        return getDeviceContext().getBatteryStatus();
+    }
+};
+
+TEST_F(InputReaderTest, BatteryGetCapacity) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+    constexpr int32_t eventHubId = 1;
+    const char* DEVICE_LOCATION = "BLUETOOTH";
+    std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+    FakeBatteryInputMapper& mapper =
+            device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+    mReader->pushNextDevice(device);
+
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+    ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+    ASSERT_EQ(mReader->getBatteryCapacity(deviceId), BATTERY_CAPACITY);
+}
+
+TEST_F(InputReaderTest, BatteryGetStatus) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+    constexpr int32_t eventHubId = 1;
+    const char* DEVICE_LOCATION = "BLUETOOTH";
+    std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+    FakeBatteryInputMapper& mapper =
+            device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+    mReader->pushNextDevice(device);
+
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+    ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+    ASSERT_EQ(mReader->getBatteryStatus(deviceId), BATTERY_STATUS);
+}
+
 // --- InputReaderIntegrationTest ---
 
 // These tests create and interact with the InputReader only through its interface.
@@ -2799,6 +2852,32 @@
     mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
 }
 
+// --- BatteryInputMapperTest ---
+class BatteryInputMapperTest : public InputMapperTest {
+protected:
+    void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); }
+};
+
+TEST_F(BatteryInputMapperTest, GetSources) {
+    BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryCapacity) {
+    BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+    ASSERT_TRUE(mapper.getBatteryCapacity());
+    ASSERT_EQ(*mapper.getBatteryCapacity(), BATTERY_CAPACITY);
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryStatus) {
+    BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+    ASSERT_TRUE(mapper.getBatteryStatus());
+    ASSERT_EQ(*mapper.getBatteryStatus(), BATTERY_STATUS);
+}
+
 // --- KeyboardInputMapperTest ---
 
 class KeyboardInputMapperTest : public InputMapperTest {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 39ae2fd..ec81ff7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -377,7 +377,7 @@
                displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
-        const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
+        const nsecs_t actualPresentTime = display->getRefreshTimestamp();
         mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
         mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                                actualPresentTime,
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 32e6b10..5219787 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -384,8 +384,8 @@
     return NO_ERROR;
 }
 
-void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) {
-    mFrameTimelineVsyncId = frameTimelineVsyncId;
+void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) {
+    mFrameTimelineInfo = frameTimelineInfo;
 }
 
 // -----------------------------------------------------------------------
@@ -445,9 +445,8 @@
         }
 
         auto surfaceFrame =
-                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
-                                                                     mOwnerPid, mOwnerUid, mName,
-                                                                     mName);
+                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid,
+                                                                     mOwnerUid, mName, mName);
         surfaceFrame->setActualQueueTime(systemTime());
 
         mQueueItems.push_back({item, surfaceFrame});
@@ -485,9 +484,8 @@
         }
 
         auto surfaceFrame =
-                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
-                                                                     mOwnerPid, mOwnerUid, mName,
-                                                                     mName);
+                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid,
+                                                                     mOwnerUid, mName, mName);
         surfaceFrame->setActualQueueTime(systemTime());
         mQueueItems[mQueueItems.size() - 1].item = item;
         mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 0e8fdbe..41ff012 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -101,7 +101,7 @@
 
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
-    void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override;
+    void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override;
 
     sp<Layer> createClone() override;
 
@@ -145,10 +145,10 @@
 
     sp<ContentsChangedListener> mContentsChangedListener;
 
-    // The last vsync id received on this layer. This will be used when we get
+    // The last vsync info received on this layer. This will be used when we get
     // a buffer to correlate the buffer with the vsync id. Can only be accessed
     // with the SF state lock held.
-    std::optional<int64_t> mFrameTimelineVsyncId;
+    FrameTimelineInfo mFrameTimelineInfo;
 
     // Keeps track of the time SF latched the last buffer from this layer.
     // Used in buffer stuffing analysis in FrameTimeline.
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0cc15c2..3dc62e3 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -216,8 +216,7 @@
     // Returns true if the most recent Transaction applied to CurrentState will be presented.
     return (getSidebandStreamChanged() || getAutoRefresh() ||
             (mCurrentState.modified &&
-             (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) &&
-        !mLayerDetached;
+             (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
 }
 
 /* TODO: vhau uncomment once deferred transaction migration complete in
@@ -461,11 +460,6 @@
     return willPresent;
 }
 
-void BufferStateLayer::forceSendCallbacks() {
-    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
-            mCurrentState.callbackHandles, std::vector<JankData>());
-}
-
 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
     mCurrentState.transparentRegionHint = transparent;
     mCurrentState.modified = true;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index f638caa..b93d567 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -80,7 +80,6 @@
     bool setApi(int32_t api) override;
     bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
     bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
-    void forceSendCallbacks() override;
     bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
                        nsecs_t requestedPresentTime) override;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index 6559ed8..4502eee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <ui/Size.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
@@ -71,7 +72,7 @@
 
     virtual void dumpAsString(String8& result) const = 0;
 
-    virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
+    virtual void resizeBuffers(const ui::Size&) = 0;
 
     virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
index 31b5f95..168e433 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
@@ -18,6 +18,7 @@
 
 #include <compositionengine/DisplaySurface.h>
 #include <gmock/gmock.h>
+#include <ui/Size.h>
 #include <utils/String8.h>
 
 namespace android::compositionengine::mock {
@@ -32,7 +33,7 @@
     MOCK_METHOD0(advanceFrame, status_t());
     MOCK_METHOD0(onFrameCommitted, void());
     MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
-    MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+    MOCK_METHOD1(resizeBuffers, void(const ui::Size&));
     MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b47f7fd..3bef77d 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -96,8 +96,7 @@
 }
 
 void RenderSurface::setDisplaySize(const ui::Size& size) {
-    mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
-                                   static_cast<uint32_t>(size.height));
+    mDisplaySurface->resizeBuffers(size);
     mSize = size;
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 4d36f0c..ab00385 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -85,18 +85,17 @@
     MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
     MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
     MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
-    MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(PhysicalDisplayId));
     MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getModes, DisplayModes(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getActiveMode, DisplayModePtr(PhysicalDisplayId));
+    MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+    MOCK_CONST_METHOD1(getActiveMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
     MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
     MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
     MOCK_CONST_METHOD0(isUsingVrComposer, bool());
     MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId));
     MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(PhysicalDisplayId));
+    MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
     MOCK_METHOD4(setActiveModeWithConstraints,
-                 status_t(PhysicalDisplayId, DisplayModeId,
+                 status_t(PhysicalDisplayId, hal::HWConfigId,
                           const hal::VsyncPeriodChangeConstraints&,
                           hal::VsyncPeriodChangeTimeline*));
     MOCK_METHOD2(setAutoLowLatencyMode, status_t(PhysicalDisplayId, bool));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index cd39733..5ef5d7b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -119,9 +119,10 @@
  */
 
 TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
-    EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1);
+    const ui::Size size(640, 480);
+    EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
 
-    mSurface.setDisplaySize(ui::Size(640, 480));
+    mSurface.setDisplaySize(size);
 }
 
 /*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index fe9db5a..a785968 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -51,17 +51,22 @@
 ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0;
 
 DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
-        const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken,
+        const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken,
         std::shared_ptr<compositionengine::Display> compositionDisplay)
-      : flinger(flinger), displayToken(displayToken), compositionDisplay(compositionDisplay) {}
+      : flinger(flinger),
+        hwComposer(hwComposer),
+        displayToken(displayToken),
+        compositionDisplay(compositionDisplay) {}
 
 DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
       : mFlinger(args.flinger),
+        mHwComposer(args.hwComposer),
         mDisplayToken(args.displayToken),
         mSequenceId(args.sequenceId),
         mConnectionType(args.connectionType),
         mCompositionDisplay{args.compositionDisplay},
         mPhysicalOrientation(args.physicalOrientation),
+        mSupportedModes(std::move(args.supportedModes)),
         mIsPrimary(args.isPrimary) {
     mCompositionDisplay->editState().isSecure = args.isSecure;
     mCompositionDisplay->createRenderSurface(
@@ -139,12 +144,64 @@
     return mPowerMode != hal::PowerMode::OFF;
 }
 
-void DisplayDevice::setActiveMode(DisplayModeId mode) {
-    mActiveMode = mode;
+void DisplayDevice::setActiveMode(DisplayModeId id) {
+    LOG_FATAL_IF(id.value() >= mSupportedModes.size(),
+                 "Cannot set active mode which is not supported.");
+    mActiveModeId = id;
 }
 
-DisplayModeId DisplayDevice::getActiveMode() const {
-    return mActiveMode;
+status_t DisplayDevice::initiateModeChange(DisplayModeId modeId,
+                                           const hal::VsyncPeriodChangeConstraints& constraints,
+                                           hal::VsyncPeriodChangeTimeline* outTimeline) const {
+    const auto mode = getMode(modeId);
+    if (!mode) {
+        ALOGE("Trying to initiate a mode change to invalid mode %s on display %s",
+              std::to_string(modeId.value()).c_str(), to_string(getId()).c_str());
+        return BAD_VALUE;
+    }
+    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), mode->getHwcId(), constraints,
+                                                    outTimeline);
+}
+
+const DisplayModePtr& DisplayDevice::getActiveMode() const {
+    return mSupportedModes[mActiveModeId.value()];
+}
+
+const DisplayModes& DisplayDevice::getSupportedModes() const {
+    return mSupportedModes;
+}
+
+DisplayModePtr DisplayDevice::getMode(DisplayModeId modeId) const {
+    const auto id = modeId.value();
+    if (id < mSupportedModes.size()) {
+        return mSupportedModes[id];
+    }
+    return nullptr;
+}
+
+nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+    const auto physicalId = getPhysicalId();
+    if (!mHwComposer.isConnected(physicalId)) {
+        return 0;
+    }
+
+    nsecs_t vsyncPeriod;
+    const auto status = mHwComposer.getDisplayVsyncPeriod(physicalId, &vsyncPeriod);
+    if (status == NO_ERROR) {
+        return vsyncPeriod;
+    }
+
+    return getActiveMode()->getFps().getPeriodNsecs();
+}
+
+nsecs_t DisplayDevice::getRefreshTimestamp() const {
+    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
+    return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
+}
+
+void DisplayDevice::onVsync(nsecs_t timestamp) {
+    mLastHwVsync = timestamp;
 }
 
 ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
@@ -206,17 +263,24 @@
 
 void DisplayDevice::dump(std::string& result) const {
     StringAppendF(&result, "+ %s\n", getDebugName().c_str());
-
-    result.append("   ");
-    StringAppendF(&result, "powerMode=%s (%d), ", to_string(mPowerMode).c_str(),
+    StringAppendF(&result, "   powerMode=%s (%d)\n", to_string(mPowerMode).c_str(),
                   static_cast<int32_t>(mPowerMode));
-    StringAppendF(&result, "activeConfig=%zu, ", mActiveMode.value());
-    StringAppendF(&result, "deviceProductInfo=");
+    StringAppendF(&result, "   activeMode=%s\n", to_string(*getActiveMode()).c_str());
+
+    result.append("   supportedModes=\n");
+
+    for (const auto& mode : mSupportedModes) {
+        result.append("     ");
+        result.append(to_string(*mode));
+        result.append("\n");
+    }
+    StringAppendF(&result, "   deviceProductInfo=");
     if (mDeviceProductInfo) {
         mDeviceProductInfo->dump(result);
     } else {
         result.append("{}");
     }
+    result.append("\n");
     getCompositionDisplay()->dump(result);
 }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d29f97d..b4db933 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -34,6 +34,7 @@
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
+#include <utils/Errors.h>
 #include <utils/Mutex.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
@@ -157,10 +158,27 @@
     ui::Dataspace getCompositionDataSpace() const;
 
     /* ------------------------------------------------------------------------
-     * Display active config management.
+     * Display mode management.
      */
-    DisplayModeId getActiveMode() const;
-    void setActiveMode(DisplayModeId mode);
+    const DisplayModePtr& getActiveMode() const;
+    void setActiveMode(DisplayModeId);
+    status_t initiateModeChange(DisplayModeId modeId,
+                                const hal::VsyncPeriodChangeConstraints& constraints,
+                                hal::VsyncPeriodChangeTimeline* outTimeline) const;
+
+    // Return the immutable list of supported display modes. The HWC may report different modes
+    // after a hotplug reconnect event, in which case the DisplayDevice object will be recreated.
+    // Hotplug reconnects are common for external displays.
+    const DisplayModes& getSupportedModes() const;
+
+    // Returns nullptr if the given mode ID is not supported. A previously
+    // supported mode may be no longer supported for some devices like TVs and
+    // set-top boxes after a hotplug reconnect.
+    DisplayModePtr getMode(DisplayModeId) const;
+
+    void onVsync(nsecs_t timestamp);
+    nsecs_t getVsyncPeriodFromHWC() const;
+    nsecs_t getRefreshTimestamp() const;
 
     // release HWC resources (if any) for removable displays
     void disconnect();
@@ -174,6 +192,7 @@
 
 private:
     const sp<SurfaceFlinger> mFlinger;
+    HWComposer& mHwComposer;
     const wp<IBinder> mDisplayToken;
     const int32_t mSequenceId;
     const std::optional<DisplayConnectionType> mConnectionType;
@@ -189,7 +208,10 @@
 
     hardware::graphics::composer::hal::PowerMode mPowerMode =
             hardware::graphics::composer::hal::PowerMode::OFF;
-    DisplayModeId mActiveMode;
+    DisplayModeId mActiveModeId;
+    const DisplayModes mSupportedModes;
+
+    std::atomic<nsecs_t> mLastHwVsync = 0;
 
     // TODO(b/74619554): Remove special cases for primary display.
     const bool mIsPrimary;
@@ -203,6 +225,9 @@
         DisplayConnectionType type;
         hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
         std::optional<DeviceProductInfo> deviceProductInfo;
+        DisplayModes supportedModes;
+        DisplayModePtr activeMode;
+
         bool operator==(const Physical& other) const {
             return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
         }
@@ -229,9 +254,11 @@
 struct DisplayDeviceCreationArgs {
     // We use a constructor to ensure some of the values are set, without
     // assuming a default value.
-    DisplayDeviceCreationArgs(const sp<SurfaceFlinger>&, const wp<IBinder>& displayToken,
+    DisplayDeviceCreationArgs(const sp<SurfaceFlinger>&, HWComposer& hwComposer,
+                              const wp<IBinder>& displayToken,
                               std::shared_ptr<compositionengine::Display>);
     const sp<SurfaceFlinger> flinger;
+    HWComposer& hwComposer;
     const wp<IBinder> displayToken;
     const std::shared_ptr<compositionengine::Display> compositionDisplay;
 
@@ -248,6 +275,7 @@
     hardware::graphics::composer::hal::PowerMode initialPowerMode{
             hardware::graphics::composer::hal::PowerMode::ON};
     bool isPrimary{false};
+    DisplayModes supportedModes;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 7ae54f1..31d1245 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -17,9 +17,12 @@
 #pragma once
 
 #include "DisplayHardware/Hal.h"
+#include "Fps.h"
 #include "Scheduler/StrongTyping.h"
 
+#include <android-base/stringprintf.h>
 #include <android/configuration.h>
+#include <ui/Size.h>
 #include <utils/Timers.h>
 
 #include <cstddef>
@@ -61,7 +64,7 @@
         }
 
         Builder& setVsyncPeriod(int32_t vsyncPeriod) {
-            mDisplayMode->mVsyncPeriod = vsyncPeriod;
+            mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod);
             return *this;
         }
 
@@ -111,7 +114,9 @@
 
     int32_t getWidth() const { return mWidth; }
     int32_t getHeight() const { return mHeight; }
-    nsecs_t getVsyncPeriod() const { return mVsyncPeriod; }
+    ui::Size getSize() const { return {mWidth, mHeight}; }
+    Fps getFps() const { return mFps; }
+    nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
     float getDpiX() const { return mDpiX; }
     float getDpiY() const { return mDpiY; }
     int32_t getConfigGroup() const { return mConfigGroup; }
@@ -124,10 +129,18 @@
 
     int32_t mWidth = -1;
     int32_t mHeight = -1;
-    nsecs_t mVsyncPeriod = -1;
+    Fps mFps;
     float mDpiX = -1;
     float mDpiY = -1;
     int32_t mConfigGroup = -1;
 };
 
+inline std::string to_string(const DisplayMode& mode) {
+    return base::StringPrintf("{id=%zu, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
+                              "dpiX=%.2f, dpiY=%.2f, configGroup=%d}",
+                              mode.getId().value(), mode.getHwcId(), mode.getWidth(),
+                              mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
+                              mode.getDpiY(), mode.getConfigGroup());
+}
+
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3e856bb..f7fc162 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -58,11 +58,10 @@
 
 FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                                        const sp<IGraphicBufferConsumer>& consumer,
-                                       uint32_t maxWidth, uint32_t maxHeight)
+                                       const ui::Size& size, const ui::Size& maxSize)
       : ConsumerBase(consumer),
         mDisplayId(displayId),
-        mMaxWidth(maxWidth),
-        mMaxHeight(maxHeight),
+        mMaxSize(maxSize),
         mCurrentBufferSlot(-1),
         mCurrentBuffer(),
         mCurrentFence(Fence::NO_FENCE),
@@ -77,15 +76,14 @@
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                        GRALLOC_USAGE_HW_RENDER |
                                        GRALLOC_USAGE_HW_COMPOSER);
-    const auto& activeMode = mHwc.getActiveMode(displayId);
-    ui::Size limitedSize = limitFramebufferSize(activeMode->getWidth(), activeMode->getHeight());
+    const auto limitedSize = limitFramebufferSize(size);
     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
     mConsumer->setMaxAcquiredBufferCount(
             SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
 }
 
-void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
-    ui::Size limitedSize = limitFramebufferSize(width, height);
+void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
+    const auto limitedSize = limitFramebufferSize(newSize);
     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
 }
 
@@ -181,24 +179,24 @@
     }
 }
 
-ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
-    ui::Size framebufferSize(width, height);
-    bool wasLimited = true;
-    if (width > mMaxWidth && mMaxWidth != 0) {
-        float aspectRatio = float(width) / float(height);
-        framebufferSize.height = mMaxWidth / aspectRatio;
-        framebufferSize.width = mMaxWidth;
+ui::Size FramebufferSurface::limitFramebufferSize(const ui::Size& size) {
+    ui::Size limitedSize = size;
+    bool wasLimited = false;
+    if (size.width > mMaxSize.width && mMaxSize.width != 0) {
+        const float aspectRatio = static_cast<float>(size.width) / size.height;
+        limitedSize.height = mMaxSize.width / aspectRatio;
+        limitedSize.width = mMaxSize.width;
         wasLimited = true;
     }
-    if (height > mMaxHeight && mMaxHeight != 0) {
-        float aspectRatio = float(width) / float(height);
-        framebufferSize.height = mMaxHeight;
-        framebufferSize.width = mMaxHeight * aspectRatio;
+    if (size.height > mMaxSize.height && mMaxSize.height != 0) {
+        const float aspectRatio = static_cast<float>(size.width) / size.height;
+        limitedSize.height = mMaxSize.height;
+        limitedSize.width = mMaxSize.height * aspectRatio;
         wasLimited = true;
     }
     ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
-             framebufferSize.width, framebufferSize.height, width, height);
-    return framebufferSize;
+             limitedSize.width, limitedSize.height, size.width, size.height);
+    return limitedSize;
 }
 
 void FramebufferSurface::dumpAsString(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 759943a..5d1e131 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,8 +41,8 @@
 class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
 public:
     FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
-                       const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
-                       uint32_t maxHeight);
+                       const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+                       const ui::Size& maxSize);
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
@@ -50,7 +50,7 @@
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
 
-    virtual void resizeBuffers(uint32_t width, uint32_t height);
+    virtual void resizeBuffers(const ui::Size&) override;
 
     virtual const sp<Fence>& getClientTargetAcquireFence() const override;
 
@@ -62,7 +62,7 @@
     virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // Limits the width and height by the maximum width specified in the constructor.
-    ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+    ui::Size limitFramebufferSize(const ui::Size&);
 
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
@@ -74,11 +74,7 @@
 
     // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
     // the device.
-    const uint32_t mMaxWidth;
-
-    // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
-    // the device.
-    const uint32_t mMaxHeight;
+    const ui::Size mMaxSize;
 
     // mCurrentBufferIndex is the slot index of the current buffer or
     // INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6350144..b9a8e4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -223,8 +223,6 @@
                  __FUNCTION__, to_string(*displayId).c_str());
 
     {
-        std::lock_guard lock(displayData.lastHwVsyncLock);
-
         // There have been reports of HWCs that signal several vsync events
         // with the same timestamp when turning the display off and on. This
         // is a bug in the HWC implementation, but filter the extra events
@@ -295,11 +293,10 @@
                                                   hal::DisplayType::PHYSICAL);
     newDisplay->setConnected(true);
     displayData.hwcDisplay = std::move(newDisplay);
-    loadModes(displayData, hwcDisplayId);
 }
 
 int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
-                                 hal::Attribute attribute) {
+                                 hal::Attribute attribute) const {
     int32_t value = 0;
     auto error = static_cast<hal::Error>(
             mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
@@ -308,30 +305,6 @@
     return value;
 }
 
-void HWComposer::loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId) {
-    ALOGV("[HWC display %" PRIu64 "] %s", hwcDisplayId, __FUNCTION__);
-
-    std::vector<hal::HWConfigId> configIds;
-    auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
-    RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId));
-
-    displayData.modes.clear();
-    for (auto configId : configIds) {
-        auto mode = DisplayMode::Builder(configId)
-                            .setId(DisplayModeId(displayData.modes.size()))
-                            .setWidth(getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH))
-                            .setHeight(getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT))
-                            .setVsyncPeriod(getAttribute(hwcDisplayId, configId,
-                                                         hal::Attribute::VSYNC_PERIOD))
-                            .setDpiX(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X))
-                            .setDpiY(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y))
-                            .setConfigGroup(getAttribute(hwcDisplayId, configId,
-                                                         hal::Attribute::CONFIG_GROUP))
-                            .build();
-        displayData.modes.push_back(std::move(mode));
-    }
-}
-
 HWC2::Layer* HWComposer::createLayer(HalDisplayId displayId) {
     RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
 
@@ -348,55 +321,50 @@
     RETURN_IF_HWC_ERROR(error, displayId);
 }
 
-nsecs_t HWComposer::getRefreshTimestamp(PhysicalDisplayId displayId) const {
-    RETURN_IF_INVALID_DISPLAY(displayId, 0);
-    const auto& displayData = mDisplayData.at(displayId);
-    // this returns the last refresh timestamp.
-    // if the last one is not available, we estimate it based on
-    // the refresh period and whatever closest timestamp we have.
-    std::lock_guard lock(displayData.lastHwVsyncLock);
-    nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
-    return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
-
 bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, false);
     return mDisplayData.at(displayId).hwcDisplay->isConnected();
 }
 
-DisplayModes HWComposer::getModes(PhysicalDisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, {});
 
-    // We cache the modes when the DisplayData is created on hotplug. If the modes need to
-    // change HWC will send a hotplug event which will recreate displayData.
-    return mDisplayData.at(displayId).modes;
+    const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+    std::vector<hal::HWConfigId> configIds;
+    auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+    RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+    std::vector<HWCDisplayMode> modes;
+    modes.reserve(configIds.size());
+    for (auto configId : configIds) {
+        modes.push_back(HWCDisplayMode{
+                .hwcId = configId,
+                .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+                .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+                .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+                .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+                .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+                .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+        });
+    }
+
+    return modes;
 }
 
-DisplayModePtr HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
-    RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+    RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
 
     const auto hwcId = *fromPhysicalDisplayId(displayId);
     ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
     hal::HWConfigId configId;
     auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
 
-    const auto& modes = mDisplayData.at(displayId).modes;
     if (error == hal::Error::BAD_CONFIG) {
         LOG_DISPLAY_ERROR(displayId, "No active mode");
-        return nullptr;
+        return std::nullopt;
     }
 
-    RETURN_IF_HWC_ERROR(error, displayId, nullptr);
-
-    const auto it = std::find_if(modes.begin(), modes.end(),
-                                 [configId](auto mode) { return mode->getHwcId() == configId; });
-    if (it == modes.end()) {
-        LOG_DISPLAY_ERROR(displayId, "Unknown mode");
-        return nullptr;
-    }
-
-    return *it;
+    return configId;
 }
 
 // Composer 2.4
@@ -421,27 +389,20 @@
     return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
 }
 
-nsecs_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                           nsecs_t* outVsyncPeriod) const {
     RETURN_IF_INVALID_DISPLAY(displayId, 0);
 
-    if (isVsyncPeriodSwitchSupported(displayId)) {
-        const auto hwcId = *fromPhysicalDisplayId(displayId);
-        Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
-        auto error =
-                static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
-        RETURN_IF_HWC_ERROR(error, displayId, 0);
-        return static_cast<nsecs_t>(vsyncPeriodNanos);
+    if (!isVsyncPeriodSwitchSupported(displayId)) {
+        return INVALID_OPERATION;
     }
-
-    // Get the default vsync period
-    auto mode = getActiveMode(displayId);
-
-    if (!mode) {
-        // HWC has updated the display modes and hasn't notified us yet.
-        RETURN_IF_HWC_ERROR(hal::Error::BAD_CONFIG, displayId, 0);
-    }
-
-    return mode->getVsyncPeriod();
+    const auto hwcId = *fromPhysicalDisplayId(displayId);
+    Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+    auto error =
+            static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+    RETURN_IF_HWC_ERROR(error, displayId, 0);
+    *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+    return NO_ERROR;
 }
 
 std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
@@ -674,20 +635,14 @@
 }
 
 status_t HWComposer::setActiveModeWithConstraints(
-        PhysicalDisplayId displayId, DisplayModeId modeId,
+        PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
         const hal::VsyncPeriodChangeConstraints& constraints,
         hal::VsyncPeriodChangeTimeline* outTimeline) {
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
 
-    auto& displayData = mDisplayData[displayId];
-    if (modeId.value() >= displayData.modes.size()) {
-        LOG_DISPLAY_ERROR(displayId, ("Invalid mode " + std::to_string(modeId.value())).c_str());
-        return BAD_INDEX;
-    }
-
-    const auto hwcConfigId = displayData.modes[modeId.value()]->getHwcId();
-    auto error = displayData.hwcDisplay->setActiveConfigWithConstraints(hwcConfigId, constraints,
-                                                                        outTimeline);
+    auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
+                                                                                    constraints,
+                                                                                    outTimeline);
     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
     return NO_ERROR;
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 59c3699..f9c8e2e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -83,6 +83,16 @@
         ClientTargetProperty clientTargetProperty;
     };
 
+    struct HWCDisplayMode {
+        hal::HWConfigId hwcId;
+        int32_t width = -1;
+        int32_t height = -1;
+        nsecs_t vsyncPeriod = -1;
+        int32_t dpiX = -1;
+        int32_t dpiY = -1;
+        int32_t configGroup = -1;
+    };
+
     virtual ~HWComposer();
 
     virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -182,12 +192,11 @@
     virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
     virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
 
-    virtual nsecs_t getRefreshTimestamp(PhysicalDisplayId) const = 0;
     virtual bool isConnected(PhysicalDisplayId) const = 0;
 
-    virtual DisplayModes getModes(PhysicalDisplayId) const = 0;
+    virtual std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const = 0;
 
-    virtual DisplayModePtr getActiveMode(PhysicalDisplayId) const = 0;
+    virtual std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const = 0;
 
     virtual std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const = 0;
 
@@ -197,8 +206,9 @@
     // Composer 2.4
     virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
     virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
-    virtual nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId) const = 0;
-    virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, DisplayModeId,
+    virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                           nsecs_t* outVsyncPeriod) const = 0;
+    virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
                                                   const hal::VsyncPeriodChangeConstraints&,
                                                   hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
     virtual status_t setAutoLowLatencyMode(PhysicalDisplayId, bool on) = 0;
@@ -314,12 +324,11 @@
     bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
     void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
 
-    nsecs_t getRefreshTimestamp(PhysicalDisplayId) const override;
     bool isConnected(PhysicalDisplayId) const override;
 
-    DisplayModes getModes(PhysicalDisplayId) const override;
+    std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const override;
 
-    DisplayModePtr getActiveMode(PhysicalDisplayId) const override;
+    std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const override;
 
     std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const override;
 
@@ -328,8 +337,9 @@
     // Composer 2.4
     DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
     bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
-    nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId displayId) const override;
-    status_t setActiveModeWithConstraints(PhysicalDisplayId, DisplayModeId,
+    status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                   nsecs_t* outVsyncPeriod) const override;
+    status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
                                           const hal::VsyncPeriodChangeConstraints&,
                                           hal::VsyncPeriodChangeTimeline* outTimeline) override;
     status_t setAutoLowLatencyMode(PhysicalDisplayId, bool) override;
@@ -365,7 +375,6 @@
         std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
         buffer_handle_t outbufHandle = nullptr;
         sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
-        DisplayModes modes;
 
         bool validateWasSkipped;
         hal::Error presentError;
@@ -375,8 +384,7 @@
         std::mutex vsyncEnabledLock;
         hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
 
-        mutable std::mutex lastHwVsyncLock;
-        nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
+        nsecs_t lastHwVsync = 0;
     };
 
     std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
@@ -384,8 +392,7 @@
     bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
 
     int32_t getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
-                         hal::Attribute attribute);
-    void loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId);
+                         hal::Attribute attribute) const;
 
     void loadCapabilities();
     void loadLayerMetadataSupport();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2ac67cb..e26ab11 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -291,11 +291,11 @@
 void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
 }
 
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
-    mQueueBufferOutput.width = w;
-    mQueueBufferOutput.height = h;
-    mSinkBufferWidth = w;
-    mSinkBufferHeight = h;
+void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
+    mQueueBufferOutput.width = newSize.width;
+    mQueueBufferOutput.height = newSize.height;
+    mSinkBufferWidth = newSize.width;
+    mSinkBufferHeight = newSize.height;
 }
 
 const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fba0e3b..bbb6306 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,7 +90,7 @@
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
-    virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+    virtual void resizeBuffers(const ui::Size&) override;
     virtual const sp<Fence>& getClientTargetAcquireFence() const override;
 
 private:
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 17d1f3b..3743716 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -275,13 +275,15 @@
     return ++mTraceCookie;
 }
 
-SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
-                           std::string debugName, PredictionState predictionState,
+SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
+                           uid_t ownerUid, std::string layerName, std::string debugName,
+                           PredictionState predictionState,
                            frametimeline::TimelineItem&& predictions,
                            std::shared_ptr<TimeStats> timeStats,
                            JankClassificationThresholds thresholds,
                            TraceCookieCounter* traceCookieCounter)
-      : mToken(token),
+      : mToken(frameTimelineInfo.vsyncId),
+        mInputEventId(frameTimelineInfo.inputEventId),
         mOwnerPid(ownerPid),
         mOwnerUid(ownerUid),
         mLayerName(std::move(layerName)),
@@ -295,27 +297,27 @@
         mTraceCookieCounter(*traceCookieCounter) {}
 
 void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mActuals.startTime = actualStartTime;
 }
 
 void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mActualQueueTime = actualQueueTime;
 }
 void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
 }
 
 void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mPresentState = presentState;
     mLastLatchTime = lastLatchTime;
 }
 
 std::optional<int32_t> SurfaceFrame::getJankType() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     if (mActuals.presentTime == 0) {
         return std::nullopt;
     }
@@ -323,32 +325,32 @@
 }
 
 nsecs_t SurfaceFrame::getBaseTime() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     return getMinTime(mPredictionState, mPredictions, mActuals);
 }
 
 TimelineItem SurfaceFrame::getActuals() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     return mActuals;
 }
 
 SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     return mPresentState;
 }
 
 FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     return mFramePresentMetadata;
 }
 
 FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     return mFrameReadyMetadata;
 }
 
 void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     StringAppendF(&result, "%s", indent.c_str());
     StringAppendF(&result, "Layer - %s", mDebugName.c_str());
     if (mJankType != JankType::None) {
@@ -387,7 +389,7 @@
 
 void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
                              nsecs_t vsyncPeriod) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     if (mPresentState != PresentState::Presented) {
         // No need to update dropped buffers
         return;
@@ -479,6 +481,9 @@
     mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
 }
 
+/**
+ * TODO(b/178637512): add inputEventId to the perfetto trace.
+ */
 void SurfaceFrame::trace(int64_t displayFrameToken) {
     using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
 
@@ -486,12 +491,12 @@
     bool missingToken = false;
     // Expected timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+        std::scoped_lock lock(mMutex);
+        if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
             ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
             missingToken = true;
             return;
-        } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+        } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
             ALOGD("Cannot trace SurfaceFrame  - %s with invalid displayFrameToken",
                   mLayerName.c_str());
             missingToken = true;
@@ -521,7 +526,7 @@
 
     // Expected timeline end
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mMutex);
+        std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
         packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
         packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
@@ -535,7 +540,7 @@
     int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
     // Actual timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mMutex);
+        std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
         packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
         // Actual start time is not yet available, so use expected start instead
@@ -566,7 +571,7 @@
     });
     // Actual timeline end
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mMutex);
+        std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
         packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
         packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
@@ -582,7 +587,7 @@
 
 int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
     ATRACE_CALL();
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     const int64_t assignedToken = mCurrentToken++;
     mPredictions[assignedToken] = {systemTime(), predictions};
     flushTokens(systemTime());
@@ -590,7 +595,7 @@
 }
 
 std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     auto predictionsIterator = mPredictions.find(token);
     if (predictionsIterator != mPredictions.end()) {
         return predictionsIterator->second.predictions;
@@ -634,26 +639,28 @@
 }
 
 std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
-        std::optional<int64_t> token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
-        std::string debugName) {
+        const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+        std::string layerName, std::string debugName) {
     ATRACE_CALL();
-    if (!token) {
-        return std::make_shared<SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid,
-                                              ownerUid, std::move(layerName), std::move(debugName),
+    if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
+        return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+                                              std::move(layerName), std::move(debugName),
                                               PredictionState::None, TimelineItem(), mTimeStats,
                                               mJankClassificationThresholds, &mTraceCookieCounter);
     }
-    std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
+    std::optional<TimelineItem> predictions =
+            mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
     if (predictions) {
-        return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
-                                              std::move(debugName), PredictionState::Valid,
-                                              std::move(*predictions), mTimeStats,
-                                              mJankClassificationThresholds, &mTraceCookieCounter);
+        return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+                                              std::move(layerName), std::move(debugName),
+                                              PredictionState::Valid, std::move(*predictions),
+                                              mTimeStats, mJankClassificationThresholds,
+                                              &mTraceCookieCounter);
     }
-    return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
-                                          std::move(debugName), PredictionState::Expired,
-                                          TimelineItem(), mTimeStats, mJankClassificationThresholds,
-                                          &mTraceCookieCounter);
+    return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+                                          std::move(layerName), std::move(debugName),
+                                          PredictionState::Expired, TimelineItem(), mTimeStats,
+                                          mJankClassificationThresholds, &mTraceCookieCounter);
 }
 
 FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
@@ -669,13 +676,13 @@
 
 void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
     ATRACE_CALL();
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
 }
 
 void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) {
     ATRACE_CALL();
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod,
                                      mTokenManager.getPredictionsForToken(token), wakeUpTime);
 }
@@ -683,7 +690,7 @@
 void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
                                  const std::shared_ptr<FenceTime>& presentFence) {
     ATRACE_CALL();
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
     mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
     flushPendingPresentFences();
@@ -826,7 +833,7 @@
     // Expected timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         auto packet = ctx.NewTracePacket();
-        if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+        if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
             ALOGD("Cannot trace DisplayFrame with invalid token");
             missingToken = true;
             return;
@@ -999,7 +1006,7 @@
 }
 
 void FrameTimeline::dumpAll(std::string& result) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
     nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
     for (size_t i = 0; i < mDisplayFrames.size(); i++) {
@@ -1009,7 +1016,7 @@
 }
 
 void FrameTimeline::dumpJank(std::string& result) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
     nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
     for (size_t i = 0; i < mDisplayFrames.size(); i++) {
         mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
@@ -1031,7 +1038,7 @@
 }
 
 void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
-    std::lock_guard<std::mutex> lock(mMutex);
+    std::scoped_lock lock(mMutex);
 
     // The size can either increase or decrease, clear everything, to be consistent
     mDisplayFrames.clear();
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index ed38cc6..54e8efb 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -154,10 +154,10 @@
 
     // Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through
     // TokenManager), Thresholds and TimeStats pointer.
-    SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
-                 std::string debugName, PredictionState predictionState, TimelineItem&& predictions,
-                 std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds,
-                 TraceCookieCounter* traceCookieCounter);
+    SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+                 std::string layerName, std::string debugName, PredictionState predictionState,
+                 TimelineItem&& predictions, std::shared_ptr<TimeStats> timeStats,
+                 JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter);
     ~SurfaceFrame() = default;
 
     // Returns std::nullopt if the frame hasn't been classified yet.
@@ -166,6 +166,7 @@
 
     // Functions called by SF
     int64_t getToken() const { return mToken; };
+    int32_t getInputEventId() const { return mInputEventId; };
     TimelineItem getPredictions() const { return mPredictions; };
     // Actual timestamps of the app are set individually at different functions.
     // Start time (if the app provides) and Queue time are accessible after queueing the frame,
@@ -198,6 +199,7 @@
 
 private:
     const int64_t mToken;
+    const int32_t mInputEventId;
     const pid_t mOwnerPid;
     const uid_t mOwnerUid;
     const std::string mLayerName;
@@ -243,10 +245,9 @@
 
     // Create a new surface frame, set the predictions based on a token and return it to the caller.
     // Debug name is the human-readable debugging string for dumpsys.
-    virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
-                                                                     pid_t ownerPid, uid_t ownerUid,
-                                                                     std::string layerName,
-                                                                     std::string debugName) = 0;
+    virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+            const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+            std::string layerName, std::string debugName) = 0;
 
     // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
     // composited into one display frame.
@@ -279,7 +280,7 @@
 
 class TokenManager : public android::frametimeline::TokenManager {
 public:
-    TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {}
+    TokenManager() : mCurrentToken(FrameTimelineInfo::INVALID_VSYNC_ID + 1) {}
     ~TokenManager() = default;
 
     int64_t generateTokenForPredictions(TimelineItem&& predictions) override;
@@ -353,7 +354,7 @@
     private:
         void dump(std::string& result, nsecs_t baseTime) const;
 
-        int64_t mToken = ISurfaceComposer::INVALID_VSYNC_ID;
+        int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID;
 
         /* Usage of TimelineItem w.r.t SurfaceFlinger
          * startTime    Time when SurfaceFlinger wakes up to handle transactions and buffer updates
@@ -393,10 +394,9 @@
     ~FrameTimeline() = default;
 
     frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
-    std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
-                                                             pid_t ownerPid, uid_t ownerUid,
-                                                             std::string layerName,
-                                                             std::string debugName) override;
+    std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+            const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+            std::string layerName, std::string debugName) override;
     void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override;
     void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override;
     void setSfPresent(nsecs_t sfPresentTime,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 66ce3f1..08a5f0f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -129,7 +129,7 @@
     mCurrentState.shadowRadius = 0.f;
     mCurrentState.treeHasFrameRateVote = false;
     mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
-    mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+    mCurrentState.frameTimelineInfo = {};
     mCurrentState.postTime = -1;
 
     if (args.flags & ISurfaceComposerClient::eNoColorFill) {
@@ -907,14 +907,10 @@
     }
 
     if (stateUpdateAvailable) {
-        const auto vsyncId =
-                stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID
-                ? std::nullopt
-                : std::make_optional(stateToCommit->frameTimelineVsyncId);
-
         mSurfaceFrame =
-                mFlinger->mFrameTimeline->createSurfaceFrameForToken(vsyncId, mOwnerPid, mOwnerUid,
-                                                                     mName, mTransactionName);
+                mFlinger->mFrameTimeline
+                        ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid,
+                                                     mOwnerUid, mName, mTransactionName);
         mSurfaceFrame->setActualQueueTime(stateToCommit->postTime);
         // For transactions we set the acquire fence time to the post time as we
         // don't have a buffer. For BufferStateLayer it is overridden in
@@ -1004,19 +1000,6 @@
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
-    if (mLayerDetached) {
-        // Ensure BLAST buffer callbacks are processed.
-        // detachChildren and mLayerDetached were implemented to avoid geometry updates
-        // to layers in the cases of animation. For BufferQueue layers buffers are still
-        // consumed as normal. This is useful as otherwise the client could get hung
-        // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue
-        // even though it is a little consistent. detachChildren is shortly slated for removal
-        // by the hierarchy mirroring work so we don't need to worry about it too much.
-        forceSendCallbacks();
-        mCurrentState.callbackHandles = {};
-        return flags;
-    }
-
     if (mChildrenChanged) {
         flags |= eVisibleRegion;
         mChildrenChanged = false;
@@ -1312,7 +1295,7 @@
     return true;
 }
 
-bool Layer::setFlags(uint8_t flags, uint8_t mask) {
+bool Layer::setFlags(uint32_t flags, uint32_t mask) {
     const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
     if (mCurrentState.flags == newFlags) return false;
     mCurrentState.sequence++;
@@ -1491,8 +1474,8 @@
     return true;
 }
 
-void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) {
-    mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId;
+void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) {
+    mCurrentState.frameTimelineInfo = info;
     mCurrentState.postTime = postTime;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1523,12 +1506,6 @@
 
 void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
     ATRACE_CALL();
-    if (mLayerDetached) {
-        // If the layer is detached, then we don't defer this transaction since we will not
-        // commit the pending state while the layer is detached. Adding sync points may cause
-        // the barrier layer to wait for the states to be committed before dequeuing a buffer.
-        return;
-    }
 
     mCurrentState.barrierLayer_legacy = barrierLayer;
     mCurrentState.barrierFrameNumber = frameNumber;
@@ -1814,10 +1791,6 @@
 }
 
 void Layer::reparentChildren(const sp<Layer>& newParent) {
-    if (attachChildren()) {
-        setTransactionFlags(eTransactionNeeded);
-    }
-
     for (const sp<Layer>& child : mCurrentChildren) {
         newParent->addChild(child);
     }
@@ -1853,17 +1826,6 @@
 }
 
 bool Layer::reparent(const sp<IBinder>& newParentHandle) {
-    bool callSetTransactionFlags = false;
-
-    // While layers are detached, we allow most operations
-    // and simply halt performing the actual transaction. However
-    // for reparent != null we would enter the mRemovedFromCurrentState
-    // state, regardless of whether doTransaction was called, and
-    // so we need to prevent the update here.
-    if (mLayerDetached && newParentHandle == nullptr) {
-        return false;
-    }
-
     sp<Layer> newParent;
     if (newParentHandle != nullptr) {
         auto handle = static_cast<Handle*>(newParentHandle.get());
@@ -1890,52 +1852,13 @@
         } else {
             onRemovedFromCurrentState();
         }
-
-        if (mLayerDetached) {
-            mLayerDetached = false;
-            callSetTransactionFlags = true;
-        }
     } else {
         onRemovedFromCurrentState();
     }
 
-    if (attachChildren() || callSetTransactionFlags) {
-        setTransactionFlags(eTransactionNeeded);
-    }
     return true;
 }
 
-bool Layer::detachChildren() {
-    for (const sp<Layer>& child : mCurrentChildren) {
-        sp<Client> parentClient = mClientRef.promote();
-        sp<Client> client(child->mClientRef.promote());
-        if (client != nullptr && parentClient != client) {
-            child->mLayerDetached = true;
-            child->detachChildren();
-            child->removeRemoteSyncPoints();
-        }
-    }
-
-    return true;
-}
-
-bool Layer::attachChildren() {
-    bool changed = false;
-    for (const sp<Layer>& child : mCurrentChildren) {
-        sp<Client> parentClient = mClientRef.promote();
-        sp<Client> client(child->mClientRef.promote());
-        if (client != nullptr && parentClient != client) {
-            if (child->mLayerDetached) {
-                child->mLayerDetached = false;
-                child->attachChildren();
-                changed = true;
-            }
-        }
-    }
-
-    return changed;
-}
-
 bool Layer::setColorTransform(const mat4& matrix) {
     static const mat4 identityMatrix = mat4();
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 359340e..4b40c8e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -207,7 +207,7 @@
         // to achieve mirroring.
         uint32_t layerStack;
 
-        uint8_t flags;
+        uint32_t flags;
         uint8_t reserved[2];
         int32_t sequence; // changes when visible regions can change
         bool modified;
@@ -304,8 +304,8 @@
         // a fixed transform hint is not set.
         ui::Transform::RotationFlags fixedTransformHint;
 
-        // The vsync id that was used to start the transaction
-        int64_t frameTimelineVsyncId;
+        // The vsync info that was used to start the transaction
+        FrameTimelineInfo frameTimelineInfo;
 
         // When the transaction was posted
         nsecs_t postTime;
@@ -425,7 +425,7 @@
     virtual bool setBackgroundBlurRadius(int backgroundBlurRadius);
     virtual bool setBlurRegions(const std::vector<BlurRegion>& effectRegions);
     virtual bool setTransparentRegionHint(const Region& transparent);
-    virtual bool setFlags(uint8_t flags, uint8_t mask);
+    virtual bool setFlags(uint32_t flags, uint32_t mask);
     virtual bool setLayerStack(uint32_t layerStack);
     virtual uint32_t getLayerStack() const;
     virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
@@ -434,7 +434,6 @@
     virtual bool setMetadata(const LayerMetadata& data);
     virtual void setChildrenDrawingParent(const sp<Layer>&);
     virtual bool reparent(const sp<IBinder>& newParentHandle);
-    virtual bool detachChildren();
     virtual bool setColorTransform(const mat4& matrix);
     virtual mat4 getColorTransform() const;
     virtual bool hasColorTransform() const;
@@ -461,7 +460,6 @@
             const std::vector<sp<CallbackHandle>>& /*handles*/) {
         return false;
     };
-    virtual void forceSendCallbacks() {}
     virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
                                nsecs_t /*requestedPresentTime*/) {
         return false;
@@ -666,8 +664,6 @@
 
     bool reparentChildren(const sp<IBinder>& newParentHandle);
     void reparentChildren(const sp<Layer>& newParent);
-    bool attachChildren();
-    bool isLayerDetached() const { return mLayerDetached; }
     bool setShadowRadius(float shadowRadius);
 
     // Before color management is introduced, contents on Android have to be
@@ -869,8 +865,9 @@
 
     bool setFrameRate(FrameRate);
 
-    virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {}
-    void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime);
+    virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {}
+    void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo,
+                                            nsecs_t postTime);
 
     // Creates a new handle each time, so we only expect
     // this to be called once.
@@ -906,6 +903,9 @@
 
     bool mPendingHWCDestroy{false};
 
+    bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
+    bool hasPendingBuffer() { return mCurrentState.buffer != mDrawingState.buffer; };
+
 protected:
     class SyncPoint {
     public:
@@ -1100,8 +1100,6 @@
     wp<Layer> mDrawingParent;
 
     // Can only be accessed with the SF state lock held.
-    bool mLayerDetached{false};
-    // Can only be accessed with the SF state lock held.
     bool mChildrenChanged{false};
 
     // Window types from WindowManager.LayoutParams
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 19b3d6e..9186538 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -451,7 +451,7 @@
 
     const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
     mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
-                                 true /* regionSampling */, captureListener);
+                                 true /* regionSampling */, false /* grayscale */, captureListener);
     ScreenCaptureResults captureResults = captureListener->waitForResults();
 
     std::vector<Descriptor> activeDescriptors;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c12a7b1..f90c130 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -303,6 +303,10 @@
     std::lock_guard<std::mutex> lock(mMutex);
 
     const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
+    if (request != VSyncRequest::None && connection->resyncCallback) {
+        connection->resyncCallback();
+    }
+
     if (connection->vsyncRequest != request) {
         connection->vsyncRequest = request;
         mCondition.notify_all();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c1fabf8..e9b5875 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -68,6 +68,7 @@
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayConfig.h>
+#include <ui/DisplayId.h>
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/DisplayState.h>
@@ -155,7 +156,6 @@
 using ui::ColorMode;
 using ui::Dataspace;
 using ui::DisplayPrimaries;
-using ui::Hdr;
 using ui::RenderIntent;
 
 namespace hal = android::hardware::graphics::composer::hal;
@@ -276,7 +276,6 @@
 const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
 const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
 const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sUseBackgroundBlur("android.permission.USE_BACKGROUND_BLUR");
 const String16 sDump("android.permission.DUMP");
 const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
 
@@ -334,10 +333,6 @@
             PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
 }
 
-bool originalCallerCanUseBlurs(int originPid, int originUid) {
-    return PermissionCache::checkPermission(sUseBackgroundBlur, originPid, originUid);
-}
-
 SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
 
 SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
@@ -900,16 +895,14 @@
 
     Mutex::Autolock lock(mStateLock);
 
-    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
-    if (!displayId) {
+    const auto display = getDisplayDeviceLocked(displayToken);
+    if (!display) {
         return NAME_NOT_FOUND;
     }
 
-    const bool isInternal = (displayId == getInternalDisplayIdLocked());
-
     configs->clear();
 
-    for (const auto& mode : getHwComposer().getModes(*displayId)) {
+    for (const auto& mode : display->getSupportedModes()) {
         DisplayConfig config;
 
         auto width = mode->getWidth();
@@ -918,7 +911,7 @@
         auto xDpi = mode->getDpiX();
         auto yDpi = mode->getDpiY();
 
-        if (isInternal &&
+        if (display->isPrimary() &&
             (internalDisplayOrientation == ui::ROTATION_90 ||
              internalDisplayOrientation == ui::ROTATION_270)) {
             std::swap(width, height);
@@ -981,7 +974,7 @@
         Mutex::Autolock lock(mStateLock);
 
         if (const auto display = getDisplayDeviceLocked(displayToken)) {
-            activeConfig = display->getActiveMode().value();
+            activeConfig = display->getActiveMode()->getId().value();
             isPrimary = display->isPrimary();
         } else {
             ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
@@ -1011,9 +1004,9 @@
         mDesiredActiveConfig = info;
         mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
     } else {
-        // Check is we are already at the desired config
+        // Check if we are already at the desired config
         const auto display = getDefaultDisplayDeviceLocked();
-        if (!display || display->getActiveMode() == refreshRate.getConfigId()) {
+        if (!display || display->getActiveMode()->getId() == refreshRate.getConfigId()) {
             return;
         }
 
@@ -1030,7 +1023,7 @@
         // VsyncController model is locked.
         modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
 
-        updatePhaseConfiguration(refreshRate);
+        updatePhaseConfiguration(refreshRate.getFps());
         mScheduler->setConfigChangePending(true);
     }
 
@@ -1039,7 +1032,7 @@
     }
 }
 
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int modeId) {
     ATRACE_CALL();
 
     if (!displayToken) {
@@ -1052,22 +1045,29 @@
             ALOGE("Attempt to set allowed display configs for invalid display token %p",
                   displayToken.get());
             return NAME_NOT_FOUND;
-        } else if (display->isVirtual()) {
+        }
+
+        if (display->isVirtual()) {
             ALOGW("Attempt to set allowed display configs for virtual display");
             return INVALID_OPERATION;
-        } else {
-            const DisplayModeId config(mode);
-            const auto fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps();
-            // Keep the old switching type.
-            const auto allowGroupSwitching =
-                    mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching;
-            const scheduler::RefreshRateConfigs::Policy policy{config,
-                                                               allowGroupSwitching,
-                                                               {fps, fps}};
-            constexpr bool kOverridePolicy = false;
-
-            return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
         }
+
+        const auto mode = display->getMode(DisplayModeId{modeId});
+        if (!mode) {
+            ALOGW("Attempt to switch to an unsupported mode %d.", modeId);
+            return BAD_VALUE;
+        }
+
+        const auto fps = mode->getFps();
+        // Keep the old switching type.
+        const auto allowGroupSwitching =
+                mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching;
+        const scheduler::RefreshRateConfigs::Policy policy{mode->getId(),
+                                                           allowGroupSwitching,
+                                                           {fps, fps}};
+        constexpr bool kOverridePolicy = false;
+
+        return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
     });
 
     return future.get();
@@ -1081,48 +1081,58 @@
         return;
     }
 
-    auto oldRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveMode());
+    const auto upcomingConfig = display->getMode(mUpcomingActiveConfig.configId);
+    if (!upcomingConfig) {
+        ALOGW("Upcoming active config is no longer supported. ConfigId = %zu",
+              mUpcomingActiveConfig.configId.value());
+        // TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may
+        // have been already updated with the upcoming active config.
+        return;
+    }
+    const Fps oldRefreshRate = display->getActiveMode()->getFps();
 
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
     mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId);
     display->setActiveMode(mUpcomingActiveConfig.configId);
 
-    auto refreshRate =
-            mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
-    mRefreshRateStats->setRefreshRate(refreshRate.getFps());
+    const Fps refreshRate = upcomingConfig->getFps();
 
-    if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) {
+    mRefreshRateStats->setRefreshRate(refreshRate);
+
+    if (!refreshRate.equalsWithMargin(oldRefreshRate)) {
         mTimeStats->incrementRefreshRateSwitches();
     }
     updatePhaseConfiguration(refreshRate);
-    ATRACE_INT("ActiveConfigFPS", refreshRate.getFps().getValue());
+    ATRACE_INT("ActiveConfigFPS", refreshRate.getValue());
 
     if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
-        const nsecs_t vsyncPeriod =
-                mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId)
-                        .getVsyncPeriod();
+        const nsecs_t vsyncPeriod = refreshRate.getPeriodNsecs();
         const auto physicalId = display->getPhysicalId();
         mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId,
                                                   mUpcomingActiveConfig.configId, vsyncPeriod);
     }
 }
 
-void SurfaceFlinger::desiredActiveConfigChangeDone() {
+void SurfaceFlinger::clearDesiredActiveConfigState() {
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
     mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
     mDesiredActiveConfigChanged = false;
-
-    const auto& refreshRate =
-            mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId);
-
-    mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod());
-    updatePhaseConfiguration(refreshRate);
     mScheduler->setConfigChangePending(false);
 }
 
+void SurfaceFlinger::desiredActiveConfigChangeDone() {
+    const auto modeId = getDesiredActiveConfig()->configId;
+
+    clearDesiredActiveConfigState();
+
+    const auto refreshRate = getDefaultDisplayDeviceLocked()->getMode(modeId)->getFps();
+    mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs());
+    updatePhaseConfiguration(refreshRate);
+}
+
 void SurfaceFlinger::performSetActiveConfig() {
     ATRACE_CALL();
-    ALOGV("performSetActiveConfig");
+    ALOGV("%s", __FUNCTION__);
     // Store the local variable to release the lock.
     const auto desiredActiveConfig = getDesiredActiveConfig();
     if (!desiredActiveConfig) {
@@ -1130,12 +1140,19 @@
         return;
     }
 
-    auto refreshRate =
-            mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId);
-    ALOGV("performSetActiveConfig changing active config to %zu(%s)",
-          refreshRate.getConfigId().value(), refreshRate.getName().c_str());
     const auto display = getDefaultDisplayDeviceLocked();
-    if (!display || display->getActiveMode() == desiredActiveConfig->configId) {
+    const auto desiredConfig = display->getMode(desiredActiveConfig->configId);
+    if (!desiredConfig) {
+        ALOGW("Desired display config is no longer supported. Config ID = %zu",
+              desiredActiveConfig->configId.value());
+        clearDesiredActiveConfigState();
+        return;
+    }
+    const auto refreshRate = desiredConfig->getFps();
+    ALOGV("performSetActiveConfig changing active config to %zu(%s)",
+          desiredConfig->getId().value(), to_string(refreshRate).c_str());
+
+    if (!display || display->getActiveMode()->getId() == desiredActiveConfig->configId) {
         // display is not valid or we are already in the requested mode
         // on both cases there is nothing left to do
         desiredActiveConfigChangeDone();
@@ -1143,7 +1160,7 @@
     }
 
     // Desired active config was set, it is different than the config currently in use, however
-    // allowed configs might have change by the time we process the refresh.
+    // allowed configs might have changed by the time we process the refresh.
     // Make sure the desired config is still allowed
     if (!isDisplayConfigAllowed(desiredActiveConfig->configId)) {
         desiredActiveConfigChangeDone();
@@ -1151,9 +1168,8 @@
     }
 
     mUpcomingActiveConfig = *desiredActiveConfig;
-    const auto displayId = display->getPhysicalId();
 
-    ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps().getValue());
+    ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getValue());
 
     // TODO(b/142753666) use constrains
     hal::VsyncPeriodChangeConstraints constraints;
@@ -1161,13 +1177,12 @@
     constraints.seamlessRequired = false;
 
     hal::VsyncPeriodChangeTimeline outTimeline;
-    auto status =
-            getHwComposer().setActiveModeWithConstraints(displayId, mUpcomingActiveConfig.configId,
-                                                         constraints, &outTimeline);
+    const auto status =
+            display->initiateModeChange(mUpcomingActiveConfig.configId, constraints, &outTimeline);
     if (status != NO_ERROR) {
-        // setActiveModeWithConstraints may fail if a hotplug event is just about
+        // initiateModeChange may fail if a hotplug event is just about
         // to be sent. We just log the error in this case.
-        ALOGW("setActiveModeWithConstraints failed: %d", status);
+        ALOGW("initiateModeChange failed: %d", status);
         return;
     }
 
@@ -1567,12 +1582,11 @@
 }
 
 nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
-    const auto displayId = getInternalDisplayIdLocked();
-    if (!displayId || !getHwComposer().isConnected(*displayId)) {
-        return 0;
+    if (const auto display = getDefaultDisplayDeviceLocked()) {
+        return display->getVsyncPeriodFromHWC();
     }
 
-    return getHwComposer().getDisplayVsyncPeriod(*displayId);
+    return 0;
 }
 
 void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1586,6 +1600,12 @@
         return;
     }
 
+    if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
+        auto token = getPhysicalDisplayTokenLocked(*displayId);
+        auto display = getDisplayDeviceLocked(token);
+        display->onVsync(timestamp);
+    }
+
     if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
         return;
     }
@@ -1751,8 +1771,15 @@
     // calculate the expected present time once and use the cached
     // value throughout this frame to make sure all layers are
     // seeing this same value.
-    const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load();
-    mExpectedPresentTime = expectedVSyncTime;
+    if (expectedVSyncTime >= frameStart) {
+        mExpectedPresentTime = expectedVSyncTime;
+    } else {
+        const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameStart);
+        mExpectedPresentTime = calculateExpectedPresentTime(stats);
+    }
+
+    const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
+    mScheduledPresentTime = expectedVSyncTime;
 
     // When Backpressure propagation is enabled we want to give a small grace period
     // for the present fence to fire instead of just giving up on this frame to handle cases
@@ -1778,7 +1805,7 @@
     const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
                                              framePending ||
                                                      (previousPresentTime >= 0 &&
-                                                      (lastExpectedPresentTime <
+                                                      (lastScheduledPresentTime <
                                                        previousPresentTime - frameMissedSlop))};
     const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
                                                 mHadDeviceComposition && frameMissed};
@@ -1917,19 +1944,16 @@
 
 bool SurfaceFlinger::handleMessageTransaction() {
     ATRACE_CALL();
+
+    if (getTransactionFlags(eTransactionFlushNeeded)) {
+        flushTransactionQueues();
+    }
     uint32_t transactionFlags = peekTransactionFlags();
-
-    bool flushedATransaction = flushTransactionQueues();
-
     bool runHandleTransaction =
-            (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
-            flushedATransaction ||
-            mForceTraversal;
+            ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
 
     if (runHandleTransaction) {
         handleTransaction(eTransactionMask);
-    } else {
-        getTransactionFlags(eTransactionFlushNeeded);
     }
 
     if (transactionFlushNeeded()) {
@@ -2197,8 +2221,7 @@
         } else if (isDisplayConnected) {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
-            const nsecs_t presentTime =
-                    getHwComposer().getRefreshTimestamp(display->getPhysicalId());
+            const nsecs_t presentTime = display->getRefreshTimestamp();
             mAnimFrameTracker.setActualPresentTime(presentTime);
         }
         mAnimFrameTracker.advanceFrame();
@@ -2335,6 +2358,24 @@
     // here the transaction has been committed
 }
 
+DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
+    const auto hwcModes = getHwComposer().getModes(displayId);
+    DisplayModes modes;
+    size_t nextModeId = 0;
+    for (const auto& hwcMode : hwcModes) {
+        modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
+                                .setId(DisplayModeId{nextModeId++})
+                                .setWidth(hwcMode.width)
+                                .setHeight(hwcMode.height)
+                                .setVsyncPeriod(hwcMode.vsyncPeriod)
+                                .setDpiX(hwcMode.dpiX)
+                                .setDpiY(hwcMode.dpiY)
+                                .setConfigGroup(hwcMode.configGroup)
+                                .build());
+    }
+    return modes;
+}
+
 void SurfaceFlinger::processDisplayHotplugEventsLocked() {
     for (const auto& event : mPendingHotplugEvents) {
         std::optional<DisplayIdentificationInfo> info =
@@ -2348,18 +2389,26 @@
         const auto it = mPhysicalDisplayTokens.find(displayId);
 
         if (event.connection == hal::Connection::CONNECTED) {
+            auto supportedModes = loadSupportedDisplayModes(displayId);
+            const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
+            LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active config");
+
+            const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
+                                                  [activeModeHwcId](const DisplayModePtr& mode) {
+                                                      return mode->getHwcId() == *activeModeHwcId;
+                                                  });
+            // TODO(b/175678215) Handle the case when activeMode is not in supportedModes
+
             if (it == mPhysicalDisplayTokens.end()) {
                 ALOGV("Creating display %s", to_string(displayId).c_str());
 
-                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
-                    initScheduler(displayId);
-                }
-
                 DisplayDeviceState state;
                 state.physical = {.id = displayId,
                                   .type = getHwComposer().getDisplayConnectionType(displayId),
                                   .hwcDisplayId = event.hwcDisplayId,
-                                  .deviceProductInfo = std::move(info->deviceProductInfo)};
+                                  .deviceProductInfo = std::move(info->deviceProductInfo),
+                                  .supportedModes = std::move(supportedModes),
+                                  .activeMode = activeMode};
                 state.isSecure = true; // All physical displays are currently considered secure.
                 state.displayName = std::move(info->name);
 
@@ -2367,6 +2416,10 @@
                 mCurrentState.displays.add(token, state);
                 mPhysicalDisplayTokens.emplace(displayId, std::move(token));
 
+                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
+                    initScheduler(state);
+                }
+
                 mInterceptor->saveDisplayCreation(state);
             } else {
                 ALOGV("Recreating display %s", to_string(displayId).c_str());
@@ -2374,6 +2427,8 @@
                 const auto token = it->second;
                 auto& state = mCurrentState.displays.editValueFor(token);
                 state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId
+                state.physical->supportedModes = std::move(supportedModes);
+                state.physical->activeMode = activeMode;
                 if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
                     state.physical->deviceProductInfo = std::move(info->deviceProductInfo);
                 }
@@ -2409,8 +2464,9 @@
         const DisplayDeviceState& state,
         const sp<compositionengine::DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer) {
-    DisplayDeviceCreationArgs creationArgs(this, displayToken, compositionDisplay);
+    DisplayDeviceCreationArgs creationArgs(this, getHwComposer(), displayToken, compositionDisplay);
     creationArgs.sequenceId = state.sequenceId;
+    creationArgs.hwComposer = getHwComposer();
     creationArgs.isSecure = state.isSecure;
     creationArgs.displaySurface = displaySurface;
     creationArgs.hasWideColorGamut = false;
@@ -2418,6 +2474,7 @@
 
     if (const auto& physical = state.physical) {
         creationArgs.connectionType = physical->type;
+        creationArgs.supportedModes = physical->supportedModes;
     }
 
     if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
@@ -2476,9 +2533,7 @@
                                                     RenderIntent::COLORIMETRIC,
                                                     Dataspace::UNKNOWN});
     if (!state.isVirtual()) {
-        const auto physicalId = display->getPhysicalId();
-        auto activeConfigId = getHwComposer().getActiveMode(physicalId)->getId();
-        display->setActiveMode(activeConfigId);
+        display->setActiveMode(state.physical->activeMode->getId());
         display->setDeviceProductInfo(state.physical->deviceProductInfo);
     }
 
@@ -2492,19 +2547,15 @@
 
 void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                          const DisplayDeviceState& state) {
-    int width = 0;
-    int height = 0;
+    ui::Size resolution(0, 0);
     ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
     if (state.physical) {
-        const auto& activeConfig =
-                getCompositionEngine().getHwComposer().getActiveMode(state.physical->id);
-        width = activeConfig->getWidth();
-        height = activeConfig->getHeight();
+        resolution = state.physical->activeMode->getSize();
         pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
     } else if (state.surface != nullptr) {
-        int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+        int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
         ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
-        status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+        status = state.surface->query(NATIVE_WINDOW_HEIGHT, &resolution.height);
         ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
         int intPixelFormat;
         status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
@@ -2521,7 +2572,7 @@
     if (const auto& physical = state.physical) {
         builder.setPhysical({physical->id, physical->type});
     }
-    builder.setPixels(ui::Size(width, height));
+    builder.setPixels(resolution);
     builder.setPixelFormat(pixelFormat);
     builder.setIsSecure(state.isSecure);
     builder.setLayerStackId(state.layerStack);
@@ -2556,7 +2607,8 @@
         const auto physicalId = PhysicalDisplayId::tryCast(displayId);
         LOG_FATAL_IF(!physicalId);
         displaySurface = new FramebufferSurface(getHwComposer(), *physicalId, bqConsumer,
-                                                maxGraphicsWidth, maxGraphicsHeight);
+                                                state.physical->activeMode->getSize(),
+                                                ui::Size(maxGraphicsWidth, maxGraphicsHeight));
         producer = bqProducer;
     }
 
@@ -2623,13 +2675,11 @@
 
             // TODO(b/175678251) Call a listener instead.
             if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
-                const auto displayId = currentState.physical->id;
-                const auto configs = getHwComposer().getModes(displayId);
-                const auto currentConfig = getHwComposer().getActiveMode(displayId)->getId();
-                // TODO(b/175678215) Handle the case when currentConfig is not in configs
-                mRefreshRateConfigs->updateDisplayConfigs(configs, currentConfig);
+                mRefreshRateConfigs
+                        ->updateDisplayConfigs(currentState.physical->supportedModes,
+                                               currentState.physical->activeMode->getId());
                 mVsyncConfiguration->reset();
-                updatePhaseConfiguration(mRefreshRateConfigs->getCurrentRefreshRate());
+                updatePhaseConfiguration(mRefreshRateConfigs->getCurrentRefreshRate().getFps());
                 if (mRefreshRateOverlay) {
                     mRefreshRateOverlay->reset();
                 }
@@ -2834,7 +2884,6 @@
         });
     }
 
-    commitInputWindowCommands();
     commitTransaction();
 }
 
@@ -2875,11 +2924,6 @@
                                                                      : nullptr);
 }
 
-void SurfaceFlinger::commitInputWindowCommands() {
-    mInputWindowCommands.merge(mPendingInputWindowCommands);
-    mPendingInputWindowCommands.clear();
-}
-
 void SurfaceFlinger::updateCursorAsync() {
     compositionengine::CompositionRefreshArgs refreshArgs;
     for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -2910,31 +2954,29 @@
     mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
 }
 
-void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) {
+void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
     if (mScheduler) {
         // In practice it's not allowed to hotplug in/out the primary display once it's been
         // connected during startup, but some tests do it, so just warn and return.
         ALOGW("Can't re-init scheduler");
         return;
     }
-
-    auto currentConfig = getHwComposer().getActiveMode(primaryDisplayId)->getId();
-    const auto modes = getHwComposer().getModes(primaryDisplayId);
+    const auto displayId = displayState.physical->id;
     mRefreshRateConfigs = std::make_unique<
-            scheduler::RefreshRateConfigs>(modes, currentConfig,
+            scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
+                                           displayState.physical->activeMode->getId(),
                                            android::sysprop::enable_frame_rate_override(true));
-    const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig);
-    mRefreshRateStats =
-            std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(),
-                                                          hal::PowerMode::OFF);
+    const auto currRefreshRate = displayState.physical->activeMode->getFps();
+    mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
+                                                                      hal::PowerMode::OFF);
 
-    mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate.getFps());
+    mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
     mVsyncModulator.emplace(mVsyncConfiguration->getCurrentConfigs());
 
     // start the EventThread
     mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
     const auto configs = mVsyncConfiguration->getCurrentConfigs();
-    const nsecs_t vsyncPeriod = currRefreshRate.getVsyncPeriod();
+    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
     mAppConnectionHandle =
             mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                          /*workDuration=*/configs.late.appWorkDuration,
@@ -2961,7 +3003,8 @@
     // This is a bit hacky, but this avoids a back-pointer into the main SF
     // classes from EventThread, and there should be no run-time binder cost
     // anyway since there are no connected apps at this point.
-    mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, primaryDisplayId, currentConfig,
+    mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId,
+                                              displayState.physical->activeMode->getId(),
                                               vsyncPeriod);
     static auto ignorePresentFences =
             base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
@@ -2970,10 +3013,10 @@
             getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
 }
 
-void SurfaceFlinger::updatePhaseConfiguration(const RefreshRate& refreshRate) {
-    mVsyncConfiguration->setRefreshRateFps(refreshRate.getFps());
+void SurfaceFlinger::updatePhaseConfiguration(const Fps& refreshRate) {
+    mVsyncConfiguration->setRefreshRateFps(refreshRate);
     setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()),
-                   refreshRate.getVsyncPeriod());
+                   refreshRate.getPeriodNsecs());
 }
 
 void SurfaceFlinger::setVsyncConfig(const VsyncModulator::VsyncConfig& config,
@@ -3243,64 +3286,86 @@
     mForceTraversal = true;
 }
 
-bool SurfaceFlinger::flushTransactionQueues() {
+void SurfaceFlinger::flushTransactionQueues() {
     // 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()) {
+        Mutex::Autolock _l(mQueueLock);
+        // Collect transactions from pending transaction queue.
+        auto it = mPendingTransactionQueues.begin();
+        while (it != mPendingTransactionQueues.end()) {
             auto& [applyToken, transactionQueue] = *it;
 
             while (!transactionQueue.empty()) {
                 const auto& transaction = transactionQueue.front();
-                if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+                if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+                                                   transaction.desiredPresentTime,
                                                    transaction.states)) {
                     setTransactionFlags(eTransactionFlushNeeded);
                     break;
                 }
                 transactions.push_back(transaction);
-                applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
-                                      transaction.displays, transaction.flags,
-                                      mPendingInputWindowCommands, transaction.desiredPresentTime,
-                                      transaction.isAutoTimestamp, transaction.buffer,
-                                      transaction.postTime, transaction.privileged,
-                                      transaction.hasListenerCallbacks,
-                                      transaction.listenerCallbacks, transaction.originPid,
-                                      transaction.originUid, transaction.id, /*isMainThread*/ true);
                 transactionQueue.pop();
-                flushedATransaction = true;
             }
 
             if (transactionQueue.empty()) {
-                it = mTransactionQueues.erase(it);
-                mTransactionCV.broadcast();
+                it = mPendingTransactionQueues.erase(it);
+                mTransactionQueueCV.broadcast();
             } else {
                 it = std::next(it, 1);
             }
         }
+
+        // Collect transactions from current transaction queue or queue to pending transactions.
+        // Case 1: push to pending when transactionIsReadyToBeApplied is false.
+        // Case 2: push to pending when there exist a pending queue.
+        // Case 3: others are ready to apply.
+        while (!mTransactionQueue.empty()) {
+            const auto& transaction = mTransactionQueue.front();
+            bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+                    mPendingTransactionQueues.end();
+            // Call transactionIsReadyToBeApplied first in case we need to
+            // incrementPendingBufferCount if the transaction contains a buffer.
+            if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+                                               transaction.desiredPresentTime, transaction.states,
+                                               true) ||
+                pendingTransactions) {
+                mPendingTransactionQueues[transaction.applyToken].push(transaction);
+            } else {
+                transactions.push_back(transaction);
+            }
+            mTransactionQueue.pop();
+        }
     }
-    return flushedATransaction;
+
+    // Now apply all transactions.
+    Mutex::Autolock _l(mStateLock);
+    for (const auto& transaction : transactions) {
+        applyTransactionState(transaction.frameTimelineInfo, transaction.states,
+                              transaction.displays, transaction.flags,
+                              transaction.inputWindowCommands, transaction.desiredPresentTime,
+                              transaction.isAutoTimestamp, transaction.buffer, transaction.postTime,
+                              transaction.privileged, transaction.hasListenerCallbacks,
+                              transaction.listenerCallbacks, transaction.originPid,
+                              transaction.originUid, transaction.id);
+    }
 }
 
 bool SurfaceFlinger::transactionFlushNeeded() {
-    return !mTransactionQueues.empty();
+    Mutex::Autolock _l(mQueueLock);
+    return !mPendingTransactionQueues.empty();
 }
 
-
-bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
                                                    const Vector<ComposerState>& states,
                                                    bool updateTransactionCounters) {
-
     const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
     bool ready = true;
     // Do not present if the desiredPresentTime has not passed unless it is more than one second
     // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
-    if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime &&
+    if (!isAutoTimestamp && desiredPresentTime >= expectedPresentTime &&
         desiredPresentTime < expectedPresentTime + s2ns(1)) {
         ready = false;
     }
@@ -3311,8 +3376,10 @@
             continue;
         }
         if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
-          ready = false;
+            ready = false;
         }
+
+        Mutex::Autolock _l(mStateLock);
         sp<Layer> layer = nullptr;
         if (s.surface) {
             layer = fromHandleLocked(s.surface).promote();
@@ -3320,115 +3387,158 @@
             ALOGW("Transaction with buffer, but no Layer?");
             continue;
         }
-        if (layer && !mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) {
+        if (!layer) {
+            continue;
+        }
+
+        if (!mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) {
             ATRACE_NAME("!isVsyncValidForUid");
             ready = false;
         }
         if (updateTransactionCounters) {
-              // See BufferStateLayer::mPendingBufferTransactions
-              if (layer) layer->incrementPendingBufferCount();
+            // See BufferStateLayer::mPendingBufferTransactions
+            layer->incrementPendingBufferCount();
+        }
 
+        // If backpressure is enabled and we already have a buffer to commit, keep the transaction
+        // in the queue.
+        bool hasBuffer = s.what & layer_state_t::eBufferChanged ||
+                s.what & layer_state_t::eCachedBufferChanged;
+        if (hasBuffer && layer->backpressureEnabled() && layer->hasPendingBuffer() &&
+            isAutoTimestamp) {
+            ready = false;
         }
     }
     return ready;
 }
 
 status_t SurfaceFlinger::setTransactionState(
-        int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
+        const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
         const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
         bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
         const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
     ATRACE_CALL();
 
-    const int64_t postTime = systemTime();
+    {
+        Mutex::Autolock _l(mQueueLock);
 
-    bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
+        const int64_t postTime = systemTime();
+        bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
 
-    Mutex::Autolock _l(mStateLock);
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int originPid = ipc->getCallingPid();
+        const int originUid = ipc->getCallingUid();
 
-    // If its TransactionQueue already has a pending TransactionState or if it is pending
-    auto itr = mTransactionQueues.find(applyToken);
-    // if this is an animation frame, wait until prior animation frame has
-    // been applied by SF
-    if (flags & eAnimation) {
-        while (itr != mTransactionQueues.end()) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                ALOGW_IF(err == TIMED_OUT,
-                         "setTransactionState timed out "
-                         "waiting for animation frame to apply");
-                break;
+        // If its TransactionQueue already has a pending TransactionState or if it is pending
+        auto itr = mPendingTransactionQueues.find(applyToken);
+        // if this is an animation frame, wait until prior animation frame has
+        // been applied by SF
+        if (flags & eAnimation) {
+            while (itr != mPendingTransactionQueues.end()) {
+                status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
+                if (CC_UNLIKELY(err != NO_ERROR)) {
+                    ALOGW_IF(err == TIMED_OUT,
+                             "setTransactionState timed out "
+                             "waiting for animation frame to apply");
+                    break;
+                }
+                itr = mPendingTransactionQueues.find(applyToken);
             }
-            itr = mTransactionQueues.find(applyToken);
         }
+
+        const bool pendingTransactions = itr != mPendingTransactionQueues.end();
+        // Expected present time is computed and cached on invalidate, so it may be stale.
+        if (!pendingTransactions) {
+            const auto now = systemTime();
+            const bool nextVsyncPending = now < mExpectedPresentTime.load();
+            const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
+            mExpectedPresentTime = calculateExpectedPresentTime(stats);
+            // The transaction might arrive just before the next vsync but after
+            // invalidate was called. In that case we need to get the next vsync
+            // afterwards.
+            if (nextVsyncPending) {
+                mExpectedPresentTime += stats.vsyncPeriod;
+            }
+        }
+
+        mTransactionQueue.emplace(frameTimelineInfo, states, displays, flags, applyToken,
+                                  inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+                                  uncacheBuffer, postTime, privileged, hasListenerCallbacks,
+                                  listenerCallbacks, originPid, originUid, transactionId);
+
+        if (pendingTransactions ||
+            (!isAutoTimestamp && desiredPresentTime > mExpectedPresentTime.load())) {
+            setTransactionFlags(eTransactionFlushNeeded);
+            return NO_ERROR;
+        }
+
+        // TODO(b/159125966): Remove eEarlyWakeup completely as no client should use this flag
+        if (flags & eEarlyWakeup) {
+            ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+        }
+
+        if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
+            ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
+            flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+        }
+
+        const auto schedule = [](uint32_t flags) {
+            if (flags & eEarlyWakeup) return TransactionSchedule::Early;
+            if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
+            if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
+            return TransactionSchedule::Late;
+        }(flags);
+        setTransactionFlags(eTransactionFlushNeeded, schedule);
     }
 
-    const bool pendingTransactions = itr != mTransactionQueues.end();
-    // Expected present time is computed and cached on invalidate, so it may be stale.
-    if (!pendingTransactions) {
-        const auto now = systemTime();
-        const bool nextVsyncPending = now < mExpectedPresentTime.load();
-        const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
-        mExpectedPresentTime = calculateExpectedPresentTime(stats);
-        // The transaction might arrive just before the next vsync but after
-        // invalidate was called. In that case we need to get the next vsync
-        // afterwards.
-        if (nextVsyncPending) {
-            mExpectedPresentTime += stats.vsyncPeriod;
-        }
-    }
-
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int originPid = ipc->getCallingPid();
-    const int originUid = ipc->getCallingUid();
-
-    // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
-    // if the transaction contains a buffer.
-    if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) ||
-        pendingTransactions) {
-        mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
-                                               desiredPresentTime, isAutoTimestamp, uncacheBuffer,
-                                               postTime, privileged, hasListenerCallbacks,
-                                               listenerCallbacks, originPid, originUid,
-                                               transactionId);
-        setTransactionFlags(eTransactionFlushNeeded);
+    // if this is a synchronous transaction, wait for it to take effect
+    // before returning.
+    const bool synchronous = flags & eSynchronous;
+    const bool syncInput = inputWindowCommands.syncInputWindows;
+    if (!synchronous && !syncInput) {
         return NO_ERROR;
     }
 
-    applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands,
-                          desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
-                          hasListenerCallbacks, listenerCallbacks, originPid, originUid,
-                          transactionId, /*isMainThread*/ false);
+    Mutex::Autolock _l(mStateLock);
+    if (synchronous) {
+        mTransactionPending = true;
+    }
+    if (syncInput) {
+        mPendingSyncInputWindows = true;
+    }
+
+    // applyTransactionState can be called by either the main SF thread or by
+    // another process through setTransactionState.  While a given process may wish
+    // to wait on synchronous transactions, the main SF thread should never
+    // be blocked.  Therefore, we only wait if isMainThread is false.
+    while (mTransactionPending || mPendingSyncInputWindows) {
+        status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+        if (CC_UNLIKELY(err != NO_ERROR)) {
+            // just in case something goes wrong in SF, return to the
+            // called after a few seconds.
+            ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+            mTransactionPending = false;
+            mPendingSyncInputWindows = false;
+            break;
+        }
+    }
+
     return NO_ERROR;
 }
 
-void SurfaceFlinger::applyTransactionState(
-        int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
-        const Vector<DisplayState>& displays, uint32_t flags,
-        const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
-        bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
-        bool privileged, bool hasListenerCallbacks,
-        const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
-        uint64_t transactionId, bool isMainThread) {
+void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+                                           const Vector<ComposerState>& states,
+                                           const Vector<DisplayState>& displays, uint32_t flags,
+                                           const InputWindowCommands& inputWindowCommands,
+                                           const int64_t desiredPresentTime, bool isAutoTimestamp,
+                                           const client_cache_t& uncacheBuffer,
+                                           const int64_t postTime, bool privileged,
+                                           bool hasListenerCallbacks,
+                                           const std::vector<ListenerCallbacks>& listenerCallbacks,
+                                           int originPid, int originUid, uint64_t transactionId) {
     uint32_t transactionFlags = 0;
 
-    if (flags & eAnimation) {
-        // For window updates that are part of an animation we must wait for
-        // previous animation "frames" to be handled.
-        while (!isMainThread && mAnimTransactionPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // caller after a few seconds.
-                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
-                        "waiting for previous animation frame");
-                mAnimTransactionPending = false;
-                break;
-            }
-        }
-    }
-
     for (const DisplayState& display : displays) {
         transactionFlags |= setDisplayStateLocked(display);
     }
@@ -3445,9 +3555,8 @@
     uint32_t clientStateFlags = 0;
     for (const ComposerState& state : states) {
         clientStateFlags |=
-                setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime,
-                                     isAutoTimestamp, postTime, privileged,
-                                     listenerCallbacksWithSurfaces, originPid, originUid);
+                setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp,
+                                     postTime, privileged, listenerCallbacksWithSurfaces);
         if ((flags & eAnimation) && state.state.surface) {
             if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) {
                 mScheduler->recordLayerHistory(layer.get(),
@@ -3487,80 +3596,25 @@
         transactionFlags = eTransactionNeeded;
     }
 
-    // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
-    // so we don't have to wake up again next frame to preform an uneeded traversal.
-    if (isMainThread && (transactionFlags & eTraversalNeeded)) {
-        transactionFlags = transactionFlags & (~eTraversalNeeded);
-        mForceTraversal = true;
-    }
-
-    const auto schedule = [](uint32_t flags) {
-        if (flags & eEarlyWakeup) return TransactionSchedule::Early;
-        if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
-        if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
-        return TransactionSchedule::Late;
-    }(flags);
-
     if (transactionFlags) {
         if (mInterceptor->isEnabled()) {
             mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
                                           originPid, originUid, transactionId);
         }
 
-        // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
-        if (flags & eEarlyWakeup) {
-            ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+        // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
+        // so we don't have to wake up again next frame to preform an unnecessary traversal.
+        if (transactionFlags & eTraversalNeeded) {
+            transactionFlags = transactionFlags & (~eTraversalNeeded);
+            mForceTraversal = true;
         }
-
-        if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
-            ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
-            flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+        if (transactionFlags) {
+            setTransactionFlags(transactionFlags);
         }
 
-        // this triggers the transaction
-        setTransactionFlags(transactionFlags, schedule);
-
         if (flags & eAnimation) {
             mAnimTransactionPending = true;
         }
-
-        // if this is a synchronous transaction, wait for it to take effect
-        // before returning.
-        const bool synchronous = flags & eSynchronous;
-        const bool syncInput = inputWindowCommands.syncInputWindows;
-        if (!synchronous && !syncInput) {
-            return;
-        }
-
-        if (synchronous) {
-            mTransactionPending = true;
-        }
-        if (syncInput) {
-            mPendingSyncInputWindows = true;
-        }
-
-
-        // applyTransactionState can be called by either the main SF thread or by
-        // another process through setTransactionState.  While a given process may wish
-        // to wait on synchronous transactions, the main SF thread should never
-        // be blocked.  Therefore, we only wait if isMainThread is false.
-        while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // called after a few seconds.
-                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
-                mTransactionPending = false;
-                mPendingSyncInputWindows = false;
-                break;
-            }
-        }
-    } else {
-        // Update VsyncModulator state machine even if transaction is not needed.
-        if (schedule == TransactionSchedule::EarlyStart ||
-            schedule == TransactionSchedule::EarlyEnd) {
-            modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
-        }
     }
 }
 
@@ -3625,10 +3679,9 @@
 }
 
 uint32_t SurfaceFlinger::setClientStateLocked(
-        int64_t frameTimelineVsyncId, const ComposerState& composerState,
+        const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState,
         int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
-        std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
-        int originPid, int originUid) {
+        std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) {
     const layer_state_t& s = composerState.state;
 
     for (auto& listener : s.listeners) {
@@ -3694,9 +3747,11 @@
     if (what & layer_state_t::eRelativeLayerChanged) {
         // NOTE: index needs to be calculated before we update the state
         const auto& p = layer->getParent();
+        const auto& relativeHandle = s.relativeLayerSurfaceControl ?
+                s.relativeLayerSurfaceControl->getHandle() : nullptr;
         if (p == nullptr) {
             ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            if (layer->setRelativeLayer(s.relativeLayerSurfaceControl->getHandle(), s.z) &&
+            if (layer->setRelativeLayer(relativeHandle, s.z) &&
                 idx >= 0) {
                 mCurrentState.layersSortedByZ.removeAt(idx);
                 mCurrentState.layersSortedByZ.add(layer);
@@ -3705,7 +3760,7 @@
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
         } else {
-            if (p->setChildRelativeLayer(layer, s.relativeLayerSurfaceControl->getHandle(), s.z)) {
+            if (p->setChildRelativeLayer(layer, relativeHandle, s.z)) {
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
@@ -3772,14 +3827,10 @@
         if (layer->setCornerRadius(s.cornerRadius))
             flags |= eTraversalNeeded;
     }
-
-    if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur &&
-        originalCallerCanUseBlurs(originPid, originUid)) {
+    if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) {
         if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
     }
-
-    if (what & layer_state_t::eBlurRegionsChanged &&
-        originalCallerCanUseBlurs(originPid, originUid)) {
+    if (what & layer_state_t::eBlurRegionsChanged) {
         if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded;
     }
     if (what & layer_state_t::eLayerStackChanged) {
@@ -3813,9 +3864,6 @@
             flags |= eTransactionNeeded|eTraversalNeeded;
         }
     }
-    if (what & layer_state_t::eDetachChildren) {
-        layer->detachChildren();
-    }
     if (what & layer_state_t::eTransformChanged) {
         if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
     }
@@ -3883,10 +3931,10 @@
             flags |= eTraversalNeeded;
         }
     }
-    if (what & layer_state_t::eFrameTimelineVsyncChanged) {
-        layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime);
-    } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
-        layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime);
+    if (what & layer_state_t::eFrameTimelineInfoChanged) {
+        layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime);
+    } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+        layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime);
     }
     if (what & layer_state_t::eFixedTransformHintChanged) {
         if (layer->setFixedTransformHint(s.fixedTransformHint)) {
@@ -3957,7 +4005,7 @@
 }
 
 uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
-    bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
+    bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
     return hasChanges ? eTraversalNeeded : 0;
 }
 
@@ -4222,9 +4270,11 @@
     d.width = 0;
     d.height = 0;
     displays.add(d);
-    setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr,
-                        mPendingInputWindowCommands, systemTime(), true, {}, false, {},
-                        0 /* Undefined transactionId */);
+
+    // It should be on the main thread, apply it directly.
+    applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
+                          systemTime(), true, {}, systemTime(), true, false, {}, getpid(), getuid(),
+                          0 /* Undefined transactionId */);
 
     setPowerModeInternal(display, hal::PowerMode::ON);
     const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -4801,15 +4851,12 @@
                   "  gpu_to_cpu_unsupported    : %d\n",
                   mTransactionFlags.load(), !mGpuToCpuSupported);
 
-    if (const auto displayId = getInternalDisplayIdLocked();
-        displayId && getHwComposer().isConnected(*displayId)) {
-        const auto activeConfig = getHwComposer().getActiveMode(*displayId);
+    if (const auto display = getDefaultDisplayDeviceLocked()) {
         std::string fps, xDpi, yDpi;
-        if (activeConfig) {
-            const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId);
-            fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str());
-            xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX());
-            yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY());
+        if (const auto activeMode = display->getActiveMode()) {
+            fps = to_string(activeMode->getFps());
+            xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
+            yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
         } else {
             fps = "unknown";
             xDpi = "unknown";
@@ -4867,23 +4914,24 @@
     result.append("\n");
 }
 
-void SurfaceFlinger::updateColorMatrixLocked() {
-    mat4 colorMatrix;
-    if (mGlobalSaturationFactor != 1.0f) {
-        // Rec.709 luma coefficients
-        float3 luminance{0.213f, 0.715f, 0.072f};
-        luminance *= 1.0f - mGlobalSaturationFactor;
-        mat4 saturationMatrix = mat4(
-            vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
-            vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
-            vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
-            vec4{0.0f, 0.0f, 0.0f, 1.0f}
-        );
-        colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
-    } else {
-        colorMatrix = mClientColorMatrix * mDaltonizer();
+mat4 SurfaceFlinger::calculateColorMatrix(float saturation) {
+    if (saturation == 1) {
+        return mat4();
     }
 
+    float3 luminance{0.213f, 0.715f, 0.072f};
+    luminance *= 1.0f - saturation;
+    mat4 saturationMatrix = mat4(vec4{luminance.r + saturation, luminance.r, luminance.r, 0.0f},
+                                 vec4{luminance.g, luminance.g + saturation, luminance.g, 0.0f},
+                                 vec4{luminance.b, luminance.b, luminance.b + saturation, 0.0f},
+                                 vec4{0.0f, 0.0f, 0.0f, 1.0f});
+    return saturationMatrix;
+}
+
+void SurfaceFlinger::updateColorMatrixLocked() {
+    mat4 colorMatrix =
+            mClientColorMatrix * calculateColorMatrix(mGlobalSaturationFactor) * mDaltonizer();
+
     if (mCurrentState.colorMatrix != colorMatrix) {
         mCurrentState.colorMatrix = colorMatrix;
         mCurrentState.colorMatrixChanged = true;
@@ -4973,7 +5021,7 @@
         case CAPTURE_LAYERS:
         case CAPTURE_DISPLAY:
         case SET_DISPLAY_BRIGHTNESS:
-        case SET_FRAME_TIMELINE_VSYNC:
+        case SET_FRAME_TIMELINE_INFO:
         // This is not sensitive information, so should not require permission control.
         case GET_GPU_CONTEXT_PRIORITY: {
             return OK;
@@ -5326,22 +5374,22 @@
                 return NO_ERROR;
             }
             case 1035: {
-                const int newConfigId = data.readInt32();
+                const int modeId = data.readInt32();
                 mDebugDisplayConfigSetByBackdoor = false;
+
                 const auto displayId = getInternalDisplayId();
                 if (!displayId) {
                     ALOGE("No internal display found.");
                     return NO_ERROR;
                 }
-                const auto numConfigs = getHwComposer().getModes(*displayId).size();
-                if (newConfigId >= 0 && newConfigId < numConfigs) {
-                    const auto displayToken = getInternalDisplayToken();
-                    status_t result = setActiveConfig(displayToken, newConfigId);
-                    if (result != NO_ERROR) {
-                        return result;
-                    }
-                    mDebugDisplayConfigSetByBackdoor = true;
+
+                status_t result = setActiveConfig(getPhysicalDisplayToken(*displayId), modeId);
+                if (result != NO_ERROR) {
+                    return result;
                 }
+
+                mDebugDisplayConfigSetByBackdoor = true;
+
                 return NO_ERROR;
             }
             case 1036: {
@@ -5595,7 +5643,8 @@
     };
 
     return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
-                               args.pixelFormat, args.allowProtected, captureListener);
+                               args.pixelFormat, args.allowProtected, args.grayscale,
+                               captureListener);
 }
 
 status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,
@@ -5631,7 +5680,7 @@
 
     return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
                                ui::PixelFormat::RGBA_8888, false /* allowProtected */,
-                               captureListener);
+                               false /* grayscale */, captureListener);
 }
 
 status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -5677,12 +5726,12 @@
             crop.bottom = parentSourceBounds.getHeight();
         }
 
-        if (crop.isEmpty() || args.frameScale <= 0.0f) {
+        if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
             // Error out if the layer has no source bounds (i.e. they are boundless) and a source
             // crop was not specified, or an invalid frame scale was provided.
             return BAD_VALUE;
         }
-        reqSize = ui::Size(crop.width() * args.frameScale, crop.height() * args.frameScale);
+        reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);
 
         for (const auto& handle : args.excludeHandles) {
             sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
@@ -5752,13 +5801,14 @@
     };
 
     return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
-                               args.pixelFormat, args.allowProtected, captureListener);
+                               args.pixelFormat, args.allowProtected, args.grayscale,
+                               captureListener);
 }
 
 status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
                                              TraverseLayersFunction traverseLayers,
                                              ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
-                                             const bool allowProtected,
+                                             bool allowProtected, bool grayscale,
                                              const sp<IScreenCaptureListener>& captureListener) {
     ATRACE_CALL();
 
@@ -5789,12 +5839,13 @@
                                              static_cast<android_pixel_format>(reqPixelFormat),
                                              1 /* layerCount */, usage, "screenshot");
     return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
-                               false /* regionSampling */, captureListener);
+                               false /* regionSampling */, grayscale, captureListener);
 }
 
 status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
                                              TraverseLayersFunction traverseLayers,
-                                             sp<GraphicBuffer>& buffer, const bool regionSampling,
+                                             sp<GraphicBuffer>& buffer, bool regionSampling,
+                                             bool grayscale,
                                              const sp<IScreenCaptureListener>& captureListener) {
     ATRACE_CALL();
 
@@ -5810,7 +5861,7 @@
         if (mRefreshPending) {
             ALOGW("Skipping screenshot for now");
             captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
-                                captureListener);
+                                grayscale, captureListener);
             return;
         }
         ScreenCaptureResults captureResults;
@@ -5818,23 +5869,18 @@
         if (!renderArea) {
             ALOGW("Skipping screen capture because of invalid render area.");
             captureResults.result = NO_MEMORY;
-            captureListener->onScreenCaptureComplete(captureResults);
+            captureListener->onScreenCaptureCompleted(captureResults);
             return;
         }
 
         status_t result = NO_ERROR;
-        int syncFd = -1;
         renderArea->render([&] {
-            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem, &syncFd,
-                                            regionSampling, captureResults);
+            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
+                                            regionSampling, grayscale, captureResults);
         });
 
-        if (result == NO_ERROR) {
-            sync_wait(syncFd, -1);
-            close(syncFd);
-        }
         captureResults.result = result;
-        captureListener->onScreenCaptureComplete(captureResults);
+        captureListener->onScreenCaptureCompleted(captureResults);
     }));
 
     return NO_ERROR;
@@ -5843,7 +5889,7 @@
 status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
                                                 TraverseLayersFunction traverseLayers,
                                                 const sp<GraphicBuffer>& buffer, bool forSystem,
-                                                int* outSyncFd, bool regionSampling,
+                                                bool regionSampling, bool grayscale,
                                                 ScreenCaptureResults& captureResults) {
     ATRACE_CALL();
 
@@ -5884,6 +5930,9 @@
     clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
     clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
 
+    const float colorSaturation = grayscale ? 0 : 1;
+    clientCompositionDisplay.colorTransform = calculateColorMatrix(colorSaturation);
+
     const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
 
     compositionengine::LayerFE::LayerSettings fillLayer;
@@ -5952,14 +6001,14 @@
     getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer,
                                  /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
 
-    *outSyncFd = drawFence.release();
-
-    if (*outSyncFd >= 0) {
-        sp<Fence> releaseFence = new Fence(dup(*outSyncFd));
+    if (drawFence >= 0) {
+        sp<Fence> releaseFence = new Fence(dup(drawFence));
         for (auto* layer : renderedLayers) {
             layer->onLayerDisplayed(releaseFence);
         }
     }
+
+    captureResults.fence = new Fence(drawFence.release());
     // Always switch back to unprotected context.
     getRenderEngine().useProtectedContext(false);
 
@@ -6023,7 +6072,7 @@
 
     if (!display->isPrimary()) {
         // TODO(b/144711714): For non-primary displays we should be able to set an active config
-        // as well. For now, just call directly to setActiveModeWithConstraints but ideally
+        // as well. For now, just call directly to initiateModeChange but ideally
         // it should go thru setDesiredActiveConfig, similar to primary display.
         ALOGV("setAllowedDisplayConfigsInternal for non-primary display");
         const auto displayId = display->getPhysicalId();
@@ -6033,8 +6082,8 @@
         constraints.seamlessRequired = false;
 
         hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
-        if (getHwComposer().setActiveModeWithConstraints(displayId, policy->defaultConfig,
-                                                         constraints, &timeline) < 0) {
+        if (display->initiateModeChange(policy->defaultConfig, constraints, &timeline) !=
+            NO_ERROR) {
             return BAD_VALUE;
         }
         if (timeline.refreshRequired) {
@@ -6042,9 +6091,7 @@
         }
 
         display->setActiveMode(policy->defaultConfig);
-        const nsecs_t vsyncPeriod = getHwComposer()
-                                            .getModes(displayId)[policy->defaultConfig.value()]
-                                            ->getVsyncPeriod();
+        const nsecs_t vsyncPeriod = display->getMode(policy->defaultConfig)->getVsyncPeriod();
         mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId,
                                                      policy->defaultConfig, vsyncPeriod);
         return NO_ERROR;
@@ -6070,12 +6117,11 @@
 
     // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
     // be depending in this callback.
-    const nsecs_t vsyncPeriod =
-            mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveMode())
-                    .getVsyncPeriod();
+    const auto activeConfig = display->getActiveMode();
+    const nsecs_t vsyncPeriod = activeConfig->getVsyncPeriod();
     const auto physicalId = display->getPhysicalId();
     mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId,
-                                              display->getActiveMode(), vsyncPeriod);
+                                              activeConfig->getId(), vsyncPeriod);
     toggleKernelIdleTimer();
 
     auto configId = mScheduler->getPreferredConfigId();
@@ -6163,8 +6209,7 @@
     } else if (display->isVirtual()) {
         return INVALID_OPERATION;
     } else {
-        const auto displayId = display->getPhysicalId();
-        const auto activeMode = getHwComposer().getActiveMode(displayId);
+        const auto activeMode = display->getActiveMode();
         *outDefaultConfig = activeMode->getId().value();
         *outAllowGroupSwitching = false;
         auto vsyncPeriod = activeMode->getVsyncPeriod();
@@ -6350,21 +6395,21 @@
     }));
 }
 
-status_t SurfaceFlinger::setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
-                                               int64_t frameTimelineVsyncId) {
+status_t SurfaceFlinger::setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+                                              const FrameTimelineInfo& frameTimelineInfo) {
     Mutex::Autolock lock(mStateLock);
     if (!authenticateSurfaceTextureLocked(surface)) {
-        ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer");
+        ALOGE("Attempt to set frame timeline info on an unrecognized IGraphicBufferProducer");
         return BAD_VALUE;
     }
 
     sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
     if (layer == nullptr) {
-        ALOGE("Attempt to set frame timeline vsync on a layer that no longer exists");
+        ALOGE("Attempt to set frame timeline info on a layer that no longer exists");
         return BAD_VALUE;
     }
 
-    layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId);
+    layer->setFrameTimelineInfoForBuffer(frameTimelineInfo);
     return NO_ERROR;
 }
 
@@ -6384,10 +6429,8 @@
 
             if (const auto display = getDefaultDisplayDeviceLocked()) {
                 mRefreshRateOverlay->setViewport(display->getSize());
+                mRefreshRateOverlay->changeRefreshRate(display->getActiveMode()->getFps());
             }
-
-            mRefreshRateOverlay->changeRefreshRate(
-                    mRefreshRateConfigs->getCurrentRefreshRate().getFps());
         }
     }));
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c90fb4a..66fc4f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -54,6 +54,7 @@
 #include "DisplayHardware/PowerAdvisor.h"
 #include "DisplayIdGenerator.h"
 #include "Effects/Daltonizer.h"
+#include "Fps.h"
 #include "FrameTracker.h"
 #include "LayerVector.h"
 #include "Scheduler/RefreshRateConfigs.h"
@@ -342,10 +343,10 @@
     virtual ~SurfaceFlinger();
 
     virtual uint32_t setClientStateLocked(
-            int64_t frameTimelineVsyncId, const ComposerState& composerState,
+            const FrameTimelineInfo& info, const ComposerState& composerState,
             int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
-            std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
-            int originPid, int originUid) REQUIRES(mStateLock);
+            std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
+            REQUIRES(mStateLock);
     virtual void commitTransactionLocked();
 
     // Used internally by computeLayerBounds() to gets the clip rectangle to use for the
@@ -434,17 +435,21 @@
     };
 
     struct TransactionState {
-        TransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& composerStates,
+        TransactionState(const FrameTimelineInfo& frameTimelineInfo,
+                         const Vector<ComposerState>& composerStates,
                          const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
-                         int64_t desiredPresentTime, bool isAutoTimestamp,
-                         const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
-                         bool hasListenerCallbacks,
+                         const sp<IBinder>& applyToken,
+                         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+                         bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
+                         int64_t postTime, bool privileged, bool hasListenerCallbacks,
                          std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
                          int originUid, uint64_t transactionId)
-              : frameTimelineVsyncId(frameTimelineVsyncId),
+              : frameTimelineInfo(frameTimelineInfo),
                 states(composerStates),
                 displays(displayStates),
                 flags(transactionFlags),
+                applyToken(applyToken),
+                inputWindowCommands(inputWindowCommands),
                 desiredPresentTime(desiredPresentTime),
                 isAutoTimestamp(isAutoTimestamp),
                 buffer(uncacheBuffer),
@@ -456,10 +461,12 @@
                 originUid(originUid),
                 id(transactionId) {}
 
-        int64_t frameTimelineVsyncId;
+        FrameTimelineInfo frameTimelineInfo;
         Vector<ComposerState> states;
         Vector<DisplayState> displays;
         uint32_t flags;
+        sp<IBinder> applyToken;
+        InputWindowCommands inputWindowCommands;
         const int64_t desiredPresentTime;
         const bool isAutoTimestamp;
         client_cache_t buffer;
@@ -521,7 +528,8 @@
     void destroyDisplay(const sp<IBinder>& displayToken) override;
     std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override;
     sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;
-    status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+    status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+                                 const Vector<ComposerState>& state,
                                  const Vector<DisplayState>& displays, uint32_t flags,
                                  const sp<IBinder>& applyToken,
                                  const InputWindowCommands& inputWindowCommands,
@@ -607,8 +615,8 @@
                           int8_t compatibility, bool shouldBeSeamless) override;
     status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override;
 
-    status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
-                                   int64_t frameTimelineVsyncId) override;
+    status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+                                  const FrameTimelineInfo& frameTimelineInfo) override;
 
     status_t addTransactionTraceListener(
             const sp<gui::ITransactionTraceListener>& listener) override;
@@ -667,7 +675,7 @@
     void signalLayerUpdate();
     void signalRefresh();
 
-    // called on the main thread in response to initializeDisplays()
+    // Called on the main thread in response to initializeDisplays()
     void onInitializeDisplays() REQUIRES(mStateLock);
     // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
     void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock);
@@ -678,9 +686,10 @@
     // Calls to setActiveConfig on the main thread if there is a pending config
     // that needs to be applied.
     void performSetActiveConfig() REQUIRES(mStateLock);
+    void clearDesiredActiveConfigState() REQUIRES(mStateLock) EXCLUDES(mActiveConfigLock);
     // Called when active config is no longer is progress
     void desiredActiveConfigChangeDone() REQUIRES(mStateLock);
-    // called on the main thread in response to setPowerMode()
+    // Called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
             REQUIRES(mStateLock);
 
@@ -712,8 +721,8 @@
     void commitInputWindowCommands() REQUIRES(mStateLock);
     void updateCursorAsync();
 
-    void initScheduler(PhysicalDisplayId primaryDisplayId);
-    void updatePhaseConfiguration(const RefreshRate&);
+    void initScheduler(const DisplayDeviceState&) REQUIRES(mStateLock);
+    void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock);
     void setVsyncConfig(const VsyncModulator::VsyncConfig&, nsecs_t vsyncPeriod);
 
     /* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -725,17 +734,17 @@
     /*
      * Transactions
      */
-    void applyTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+    void applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state,
                                const Vector<DisplayState>& displays, uint32_t flags,
                                const InputWindowCommands& inputWindowCommands,
                                const int64_t desiredPresentTime, bool isAutoTimestamp,
                                const client_cache_t& uncacheBuffer, const int64_t postTime,
                                bool privileged, bool hasListenerCallbacks,
                                const std::vector<ListenerCallbacks>& listenerCallbacks,
-                               int originPid, int originUid, uint64_t transactionId,
-                               bool isMainThread = false) REQUIRES(mStateLock);
-    // Returns true if at least one transaction was flushed
-    bool flushTransactionQueues();
+                               int originPid, int originUid, uint64_t transactionId)
+            REQUIRES(mStateLock);
+    // flush pending transaction that was presented after desiredPresentTime.
+    void flushTransactionQueues();
     // Returns true if there is at least one transaction that needs to be flushed
     bool transactionFlushNeeded();
     uint32_t getTransactionFlags(uint32_t flags);
@@ -751,9 +760,9 @@
     uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule);
     void commitTransaction() REQUIRES(mStateLock);
     void commitOffscreenLayers();
-    bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+    bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
                                        const Vector<ComposerState>& states,
-                                       bool updateTransactionCounters = false) REQUIRES(mStateLock);
+                                       bool updateTransactionCounters = false);
     uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
     uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
             REQUIRES(mStateLock);
@@ -808,13 +817,14 @@
     void startBootAnim();
 
     status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
-                                 ui::PixelFormat, const bool allowProtected,
+                                 ui::PixelFormat, bool allowProtected, bool grayscale,
                                  const sp<IScreenCaptureListener>&);
     status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&,
-                                 bool regionSampling, const sp<IScreenCaptureListener>&);
+                                 bool regionSampling, bool grayscale,
+                                 const sp<IScreenCaptureListener>&);
     status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
-                                    const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd,
-                                    bool regionSampling, ScreenCaptureResults&);
+                                    const sp<GraphicBuffer>&, bool forSystem, bool regionSampling,
+                                    bool grayscale, ScreenCaptureResults&);
 
     sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
     sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
@@ -892,6 +902,7 @@
     /*
      * Display management
      */
+    DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const;
     sp<DisplayDevice> setupNewDisplayDeviceInternal(
             const wp<IBinder>& displayToken,
             std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -1017,6 +1028,8 @@
 
     void onFrameRateFlexibilityTokenReleased();
 
+    static mat4 calculateColorMatrix(float saturation);
+
     void updateColorMatrixLocked();
 
     // Verify that transaction is being called by an approved process:
@@ -1170,8 +1183,11 @@
     uint32_t mTexturePoolSize = 0;
     std::vector<uint32_t> mTexturePool;
 
-    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;
-
+    mutable Mutex mQueueLock;
+    Condition mTransactionQueueCV;
+    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
+            mPendingTransactionQueues GUARDED_BY(mQueueLock);
+    std::queue<TransactionState> mTransactionQueue GUARDED_BY(mQueueLock);
     /*
      * Feature prototyping
      */
@@ -1225,6 +1241,7 @@
     std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
 
     std::atomic<nsecs_t> mExpectedPresentTime = 0;
+    nsecs_t mScheduledPresentTime = 0;
     hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
 
     std::mutex mActiveConfigLock;
@@ -1248,7 +1265,6 @@
     const float mEmulatedDisplayDensity;
 
     sp<os::IInputFlinger> mInputFlinger;
-    InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
     // Should only be accessed by the main thread.
     InputWindowCommands mInputWindowCommands;
 
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 3548923..61005c9 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -150,7 +150,6 @@
                    layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
                            layer_state_t::eLayerSecure);
     addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
-    addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
     addRelativeParentLocked(transaction, layerId,
                             getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
                             layer->mCurrentState.z);
@@ -409,13 +408,6 @@
     overrideChange->set_parent_id(parentId);
 }
 
-void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
-                                                 bool detached) {
-    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
-    DetachChildrenChange* overrideChange(change->mutable_detach_children());
-    overrideChange->set_detach_children(detached);
-}
-
 void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
                                                  int32_t parentId, int z) {
     SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -498,9 +490,6 @@
         addReparentChildrenLocked(transaction, layerId,
                                   getLayerIdFromHandle(state.reparentSurfaceControl->getHandle()));
     }
-    if (state.what & layer_state_t::eDetachChildren) {
-        addDetachChildrenLocked(transaction, layerId, true);
-    }
     if (state.what & layer_state_t::eRelativeLayerChanged) {
         addRelativeParentLocked(transaction, layerId,
                                 getLayerIdFromHandle(
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 3df79c6..3e27e83 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -177,7 +177,6 @@
                               uint64_t transactionId);
     void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
     void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
-    void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
     void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
                                  int z);
     void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius);
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 8fac8e9..df40ef6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -315,8 +315,9 @@
 
     static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_LAYER_STATS = 200;
+    static const size_t MAX_NUM_PULLED_LAYERS = MAX_NUM_LAYER_STATS;
     std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>();
-    size_t mMaxPulledLayers = 8;
+    size_t mMaxPulledLayers = MAX_NUM_PULLED_LAYERS;
     size_t mMaxPulledHistogramBuckets = 6;
 };
 
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index e8b24b4..cfaf229 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -21,7 +21,6 @@
         "CommonTypes_test.cpp",
         "Credentials_test.cpp",
         "DereferenceSurfaceControl_test.cpp",
-        "DetachChildren_test.cpp",
         "DisplayConfigs_test.cpp",
         "EffectLayer_test.cpp",
         "InvalidHandles_test.cpp",
diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp
deleted file mode 100644
index abf8b1a..0000000
--- a/services/surfaceflinger/tests/DetachChildren_test.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "LayerTransactionTest.h"
-
-namespace android {
-
-class DetachChildren : public LayerTransactionTest {
-protected:
-    virtual void SetUp() {
-        LayerTransactionTest::SetUp();
-
-        mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
-                                   mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
-
-        ASSERT_TRUE(mMainSurface != nullptr);
-        ASSERT_TRUE(mMainSurface->isValid());
-
-        TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
-
-        asTransaction([&](Transaction& t) {
-            t.setLayer(mMainSurface, INT32_MAX - 1)
-                    .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
-                    .show(mMainSurface);
-        });
-    }
-
-    virtual void TearDown() {
-        LayerTransactionTest::TearDown();
-        mMainSurface = 0;
-    }
-
-    sp<SurfaceControl> mMainSurface;
-    Color mMainSurfaceColor = {195, 63, 63, 255};
-    Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
-    std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(DetachChildren, RelativesAreNotDetached) {
-    Color relativeColor = {10, 10, 10, 255};
-    Rect relBounds = Rect(64, 64, 74, 74);
-
-    sp<SurfaceControl> relative =
-            createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
-    TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
-
-    Transaction{}
-            .setRelativeLayer(relative, mMainSurface, 1)
-            .setPosition(relative, relBounds.left, relBounds.top)
-            .apply();
-
-    {
-        // The relative should be on top of the FG control.
-        mCapture = screenshot();
-        mCapture->expectColor(relBounds, relativeColor);
-    }
-    Transaction{}.detachChildren(mMainSurface).apply();
-
-    {
-        // Nothing should change at this point.
-        mCapture = screenshot();
-        mCapture->expectColor(relBounds, relativeColor);
-    }
-
-    Transaction{}.hide(relative).apply();
-
-    {
-        // Ensure that the relative was actually hidden, rather than
-        // being left in the detached but visible state.
-        mCapture = screenshot();
-        mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
-    }
-}
-
-TEST_F(DetachChildren, DetachChildrenSameClient) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 84, 84);
-    sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
-                                           childBounds.height(), 0, mMainSurface.get());
-    ASSERT_TRUE(child->isValid());
-
-    TransactionUtils::fillSurfaceRGBA8(child, childColor);
-
-    asTransaction([&](Transaction& t) {
-        t.show(child);
-        t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
-                      childBounds.top - mMainSurfaceBounds.top);
-    });
-
-    {
-        mCapture = screenshot();
-        // Expect main color around the child surface
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
-    asTransaction([&](Transaction& t) { t.hide(child); });
-
-    // Since the child has the same client as the parent, it will not get
-    // detached and will be hidden.
-    {
-        mCapture = screenshot();
-        mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
-    }
-}
-
-TEST_F(DetachChildren, DetachChildrenDifferentClient) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 84, 84);
-
-    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
-    sp<SurfaceControl> childNewClient =
-            createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
-                          childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
-    ASSERT_TRUE(childNewClient->isValid());
-
-    TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
-    asTransaction([&](Transaction& t) {
-        t.show(childNewClient);
-        t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
-                      childBounds.top - mMainSurfaceBounds.top);
-    });
-
-    {
-        mCapture = screenshot();
-        // Expect main color around the child surface
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
-    asTransaction([&](Transaction& t) { t.hide(childNewClient); });
-
-    // Nothing should have changed.
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-}
-
-TEST_F(DetachChildren, DetachChildrenThenAttach) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 84, 84);
-
-    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
-    sp<SurfaceControl> childNewClient =
-            createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
-                          childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
-    ASSERT_TRUE(childNewClient->isValid());
-
-    TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
-    Transaction()
-            .show(childNewClient)
-            .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
-                         childBounds.top - mMainSurfaceBounds.top)
-            .apply();
-
-    {
-        mCapture = screenshot();
-        // Expect main color around the child surface
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    Transaction().detachChildren(mMainSurface).apply();
-    Transaction().hide(childNewClient).apply();
-
-    // Nothing should have changed.
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    Color newParentColor = Color::RED;
-    Rect newParentBounds = Rect(20, 20, 52, 52);
-    sp<SurfaceControl> newParentSurface =
-            createLayer(String8("New Parent Surface"), newParentBounds.width(),
-                        newParentBounds.height(), 0);
-    TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
-    Transaction()
-            .setLayer(newParentSurface, INT32_MAX - 1)
-            .show(newParentSurface)
-            .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
-            .reparent(childNewClient, newParentSurface)
-            .apply();
-    {
-        mCapture = screenshot();
-        // Child is now hidden.
-        mCapture->expectColor(newParentBounds, newParentColor);
-    }
-}
-
-TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 84, 84);
-
-    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
-    sp<SurfaceControl> childNewClient =
-            createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
-                          childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
-    ASSERT_TRUE(childNewClient->isValid());
-
-    TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
-    Transaction()
-            .show(childNewClient)
-            .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
-                         childBounds.top - mMainSurfaceBounds.top)
-            .apply();
-
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    Transaction()
-            .deferTransactionUntil_legacy(childNewClient, mMainSurface,
-                                          mMainSurface->getSurface()->getNextFrameNumber())
-            .apply();
-    Transaction().detachChildren(mMainSurface).apply();
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
-                                                      mMainSurfaceBounds.width(),
-                                                      mMainSurfaceBounds.height()));
-
-    // BufferLayer can still dequeue buffers even though there's a detached layer with a
-    // deferred transaction.
-    {
-        SCOPED_TRACE("new buffer");
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, Color::RED);
-        mCapture->expectColor(childBounds, childColor);
-    }
-}
-
-/**
- * Tests that a deferring transaction on an already detached layer will be dropped gracefully and
- * allow the barrier layer to dequeue buffers.
- *
- * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer
- * to commit its pending states.
- */
-TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 84, 84);
-
-    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
-    sp<SurfaceControl> childNewClient =
-            createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
-                          childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
-    ASSERT_TRUE(childNewClient->isValid());
-
-    TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
-    Transaction()
-            .show(childNewClient)
-            .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
-                         childBounds.top - mMainSurfaceBounds.top)
-            .apply();
-
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectColor(childBounds, childColor);
-    }
-
-    Transaction().detachChildren(mMainSurface).apply();
-    Transaction()
-            .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()})
-            .deferTransactionUntil_legacy(childNewClient, mMainSurface,
-                                          mMainSurface->getSurface()->getNextFrameNumber())
-            .apply();
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
-                                                      mMainSurfaceBounds.width(),
-                                                      mMainSurfaceBounds.height()));
-
-    // BufferLayer can still dequeue buffers even though there's a detached layer with a
-    // deferred transaction.
-    {
-        SCOPED_TRACE("new buffer");
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, Color::RED);
-        mCapture->expectColor(childBounds, childColor);
-    }
-}
-
-TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
-    Color childColor = {200, 200, 200, 255};
-    Rect childBounds = Rect(74, 74, 94, 94);
-    Color grandchildColor = Color::RED;
-    Rect grandchildBounds = Rect(80, 80, 90, 90);
-
-    sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
-    sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
-
-    sp<SurfaceControl> childSurface =
-            createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
-                          PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
-    sp<SurfaceControl> grandchildSurface =
-            createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
-                          grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
-
-    TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
-    TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
-
-    Transaction()
-            .show(childSurface)
-            .show(grandchildSurface)
-            .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
-                         childBounds.top - mMainSurfaceBounds.top)
-            .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
-                         grandchildBounds.top - childBounds.top)
-            .apply();
-
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectBorder(grandchildBounds, childColor);
-        mCapture->expectColor(grandchildBounds, grandchildColor);
-    }
-
-    Transaction().detachChildren(childSurface).apply();
-
-    // Remove main surface offscreen
-    Transaction().reparent(mMainSurface, nullptr).apply();
-    {
-        mCapture = screenshot();
-        mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
-    }
-
-    Transaction().reparent(mMainSurface, mBlackBgSurface).apply();
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectBorder(grandchildBounds, childColor);
-        mCapture->expectColor(grandchildBounds, grandchildColor);
-    }
-
-    Transaction().hide(grandchildSurface).apply();
-
-    // grandchild is still detached so it will not hide
-    {
-        mCapture = screenshot();
-        mCapture->expectBorder(childBounds, mMainSurfaceColor);
-        mCapture->expectBorder(grandchildBounds, childColor);
-        mCapture->expectColor(grandchildBounds, grandchildColor);
-    }
-}
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
index ecfed13..f010786 100644
--- a/services/surfaceflinger/tests/LayerState_test.cpp
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -30,12 +30,14 @@
     DisplayCaptureArgs args;
     args.pixelFormat = ui::PixelFormat::RGB_565;
     args.sourceCrop = Rect(0, 0, 500, 200);
-    args.frameScale = 2;
+    args.frameScaleX = 2;
+    args.frameScaleY = 4;
     args.captureSecureLayers = true;
     args.displayToken = new BBinder();
     args.width = 10;
     args.height = 20;
     args.useIdentityTransform = true;
+    args.grayscale = true;
 
     Parcel p;
     args.write(p);
@@ -46,23 +48,27 @@
 
     ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
     ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
-    ASSERT_EQ(args.frameScale, args2.frameScale);
+    ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+    ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
     ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
     ASSERT_EQ(args.displayToken, args2.displayToken);
     ASSERT_EQ(args.width, args2.width);
     ASSERT_EQ(args.height, args2.height);
     ASSERT_EQ(args.useIdentityTransform, args2.useIdentityTransform);
+    ASSERT_EQ(args.grayscale, args2.grayscale);
 }
 
 TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
     LayerCaptureArgs args;
     args.pixelFormat = ui::PixelFormat::RGB_565;
     args.sourceCrop = Rect(0, 0, 500, 200);
-    args.frameScale = 2;
+    args.frameScaleX = 2;
+    args.frameScaleY = 4;
     args.captureSecureLayers = true;
     args.layerHandle = new BBinder();
     args.excludeHandles = {new BBinder(), new BBinder()};
     args.childrenOnly = false;
+    args.grayscale = true;
 
     Parcel p;
     args.write(p);
@@ -73,16 +79,19 @@
 
     ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
     ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
-    ASSERT_EQ(args.frameScale, args2.frameScale);
+    ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+    ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
     ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
     ASSERT_EQ(args.layerHandle, args2.layerHandle);
     ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
     ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
+    ASSERT_EQ(args.grayscale, args2.grayscale);
 }
 
 TEST(LayerStateTest, ParcellingScreenCaptureResults) {
     ScreenCaptureResults results;
     results.buffer = new GraphicBuffer(100, 200, PIXEL_FORMAT_RGBA_8888, 1, 0);
+    results.fence = new Fence(dup(fileno(tmpfile())));
     results.capturedSecureLayers = true;
     results.capturedDataspace = ui::Dataspace::DISPLAY_P3;
     results.result = BAD_VALUE;
@@ -99,10 +108,40 @@
     ASSERT_EQ(results.buffer->getWidth(), results2.buffer->getWidth());
     ASSERT_EQ(results.buffer->getHeight(), results2.buffer->getHeight());
     ASSERT_EQ(results.buffer->getPixelFormat(), results2.buffer->getPixelFormat());
+    ASSERT_EQ(results.fence->isValid(), results2.fence->isValid());
     ASSERT_EQ(results.capturedSecureLayers, results2.capturedSecureLayers);
     ASSERT_EQ(results.capturedDataspace, results2.capturedDataspace);
     ASSERT_EQ(results.result, results2.result);
 }
 
+/**
+ * Parcel a layer_state_t struct, and then unparcel. Ensure that the object that was parceled
+ * matches the object that's unparceled.
+ */
+TEST(LayerStateTest, ParcelUnparcelLayerStateT) {
+    layer_state_t input;
+    input.frameTimelineInfo.vsyncId = 1;
+    input.frameTimelineInfo.inputEventId = 2;
+    Parcel p;
+    input.write(p);
+    layer_state_t output;
+    p.setDataPosition(0);
+    output.read(p);
+    ASSERT_EQ(input.frameTimelineInfo.vsyncId, output.frameTimelineInfo.vsyncId);
+    ASSERT_EQ(input.frameTimelineInfo.inputEventId, output.frameTimelineInfo.inputEventId);
+}
+
+TEST(LayerStateTest, LayerStateMerge_SelectsValidInputEvent) {
+    layer_state_t layer1;
+    layer1.frameTimelineInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+    layer_state_t layer2;
+    layer2.frameTimelineInfo.inputEventId = 1;
+    layer2.what |= layer_state_t::eFrameTimelineInfoChanged;
+
+    layer1.merge(layer2);
+
+    ASSERT_EQ(1, layer1.frameTimelineInfo.inputEventId);
+}
+
 } // namespace test
 } // namespace android
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 214a0cd..51ce1d3 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -487,7 +487,9 @@
     // red area to the right of the blue area
     mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
 
-    captureArgs.frameScale = 0.5f;
+    captureArgs.frameScaleX = 0.5f;
+    captureArgs.frameScaleY = 0.5f;
+
     ScreenCapture::captureLayers(&mCapture, captureArgs);
     // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
     mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
@@ -768,6 +770,41 @@
     mCapture->expectBorder(Rect(128, 128, 160, 160), {63, 63, 195, 255});
 }
 
+TEST_F(ScreenCaptureTest, CaptureWithGrayscale) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+                                                ISurfaceComposerClient::eFXSurfaceBufferState,
+                                                mBGSurfaceControl.get()));
+    ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+    Transaction().show(layer).setLayer(layer, INT32_MAX).apply();
+
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = layer->getHandle();
+
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
+    mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
+
+    captureArgs.grayscale = true;
+
+    const uint8_t tolerance = 1;
+
+    // Values based on SurfaceFlinger::calculateColorMatrix
+    float3 luminance{0.213f, 0.715f, 0.072f};
+
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+    uint8_t expectedColor = luminance.r * 255;
+    mCapture->expectColor(Rect(0, 0, 32, 32),
+                          Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+
+    ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+    expectedColor = luminance.b * 255;
+    mCapture->expectColor(Rect(0, 0, 32, 32),
+                          Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+}
+
 // In the following tests we verify successful skipping of a parent layer,
 // so we use the same verification logic and only change how we mutate
 // the parent layer to verify that various properties are ignored.
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8dc9a12..fa88ca5 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -194,7 +194,6 @@
     bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
     bool reparentUpdateFound(const SurfaceChange& change, bool found);
     bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
-    bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
     bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
     bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found);
     bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
@@ -232,7 +231,6 @@
     void deferredTransactionUpdate(Transaction&);
     void reparentUpdate(Transaction&);
     void relativeParentUpdate(Transaction&);
-    void detachChildrenUpdate(Transaction&);
     void reparentChildrenUpdate(Transaction&);
     void shadowRadiusUpdate(Transaction&);
     void surfaceCreation(Transaction&);
@@ -412,10 +410,6 @@
     t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z);
 }
 
-void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
-    t.detachChildren(mBGSurfaceControl);
-}
-
 void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
     t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl);
 }
@@ -452,7 +446,6 @@
     runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
     runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
     runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
-    runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
     runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
     runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate);
 }
@@ -667,16 +660,6 @@
     return found;
 }
 
-bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
-    bool detachChildren(change.detach_children().detach_children());
-    if (detachChildren && !found) {
-        found = true;
-    } else if (detachChildren && found) {
-        []() { FAIL(); }();
-    }
-    return found;
-}
-
 bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
     bool hasId(change.reparent_children().parent_id() == mFGLayerId);
     if (hasId && !found) {
@@ -761,9 +744,6 @@
                         case SurfaceChange::SurfaceChangeCase::kRelativeParent:
                             foundUpdate = relativeParentUpdateFound(change, foundUpdate);
                             break;
-                        case SurfaceChange::SurfaceChangeCase::kDetachChildren:
-                            foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
-                            break;
                         case SurfaceChange::SurfaceChangeCase::kShadowRadius:
                             foundUpdate = shadowRadiusUpdateFound(change, foundUpdate);
                             break;
@@ -793,7 +773,6 @@
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
-    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
 }
 
 bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -968,11 +947,6 @@
                 SurfaceChange::SurfaceChangeCase::kRelativeParent);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
-                SurfaceChange::SurfaceChangeCase::kDetachChildren);
-}
-
 TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate,
                 SurfaceChange::SurfaceChangeCase::kShadowRadius);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index a361b1e..33823d7 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -57,6 +57,8 @@
                                                       // Sample usage bits from screenrecord
                                                       GRALLOC_USAGE_HW_VIDEO_ENCODER |
                                                               GRALLOC_USAGE_SW_READ_OFTEN);
+                sp<BufferListener> listener = new BufferListener(this);
+                itemConsumer->setFrameAvailableListener(listener);
 
                 vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
                                                                 false /*secure*/);
@@ -68,6 +70,13 @@
                                        Rect(displayState.layerStackSpaceRect), Rect(resolution));
                 t.apply();
                 SurfaceComposerClient::Transaction().apply(true);
+
+                std::unique_lock lock(mMutex);
+                mAvailable = false;
+                // Wait for frame buffer ready.
+                mCondition.wait_for(lock, std::chrono::seconds(2),
+                                    [this]() NO_THREAD_SAFETY_ANALYSIS { return mAvailable; });
+
                 BufferItem item;
                 itemConsumer->acquireBuffer(&item, 0, true);
                 auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
@@ -80,6 +89,23 @@
 protected:
     LayerTransactionTest* mDelegate;
     RenderPath mRenderPath;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+    bool mAvailable = false;
+
+    void onFrameAvailable() {
+        std::unique_lock lock(mMutex);
+        mAvailable = true;
+        mCondition.notify_all();
+    }
+
+    class BufferListener : public ConsumerBase::FrameAvailableListener {
+    public:
+        BufferListener(LayerRenderPathTestHarness* owner) : mOwner(owner) {}
+        LayerRenderPathTestHarness* mOwner;
+
+        void onFrameAvailable(const BufferItem& /*item*/) { mOwner->onFrameAvailable(); }
+    };
 };
 
 class LayerTypeTransactionHarness : public LayerTransactionTest {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index bd49728..efa15f1 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -63,9 +63,7 @@
 
 // Mock test helpers
 using ::testing::_;
-using ::testing::AtLeast;
 using ::testing::DoAll;
-using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::SetArgPointee;
 
@@ -74,9 +72,11 @@
 using Display = V2_1::Display;
 
 ///////////////////////////////////////////////
-
-constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
-constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) {
+    return PhysicalDisplayId::fromPort(hwcId);
+}
+constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY);
 
 struct TestColor {
 public:
@@ -158,7 +158,7 @@
                 self->mReceivedDisplayEvents.push_back(buffer[i]);
             }
         }
-        ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n));
+        ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n));
         return 1;
     }
 
@@ -174,7 +174,7 @@
     void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs,
                                    Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) {
         std::vector<Config> configIds;
-        for (int i = 0; i < testConfigs.size(); i++) {
+        for (size_t i = 0; i < testConfigs.size(); i++) {
             configIds.push_back(testConfigs[i].id);
 
             EXPECT_CALL(*mMockComposer,
@@ -269,10 +269,10 @@
         mMockComposer = nullptr;
     }
 
-    void waitForDisplayTransaction() {
+    void waitForDisplayTransaction(Display display) {
         // Both a refresh and a vsync event are needed to apply pending display
         // transactions.
-        mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY);
+        mFakeComposerClient->refreshDisplay(display);
         mFakeComposerClient->runVSyncAndWait();
 
         // Extra vsync and wait to avoid a 10% flake due to a race.
@@ -291,7 +291,7 @@
                 mReceivedDisplayEvents.pop_front();
 
                 ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
-                         "event hotplug: displayId %s, connected %d\t",
+                         "event hotplug: displayId %s, connected %d",
                          to_string(event.header.displayId).c_str(), event.hotplug.connected);
 
                 if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
@@ -314,7 +314,7 @@
                 mReceivedDisplayEvents.pop_front();
 
                 ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
-                         "event config: displayId %s, configId %d\t",
+                         "event config: displayId %s, configId %d",
                          to_string(event.header.displayId).c_str(), event.config.configId);
 
                 if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
@@ -341,7 +341,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         {
@@ -372,7 +372,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
 
@@ -403,7 +403,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -456,7 +456,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -487,7 +487,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -510,7 +510,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -562,7 +562,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -593,7 +593,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -626,7 +626,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -669,7 +669,7 @@
                     .WillOnce(Return(V2_1::Error::NONE));
         }
 
-        for (int i = 0; i < configs.size(); i++) {
+        for (size_t i = 0; i < configs.size(); i++) {
             const auto& config = configs[i];
             if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
                 EXPECT_EQ(NO_ERROR,
@@ -679,7 +679,7 @@
                                                                configs[i].refreshRate,
                                                                configs[i].refreshRate,
                                                                configs[i].refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -726,7 +726,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -773,7 +773,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -804,7 +804,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -815,7 +815,7 @@
         mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
 
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(PRIMARY_DISPLAY);
 
         EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
         {
@@ -840,7 +840,7 @@
         mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
 
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(PRIMARY_DISPLAY);
 
         EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
 
@@ -856,6 +856,121 @@
         }
     }
 
+    void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) {
+        ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay");
+
+        // Send a hotplug connected event to set up the initial display modes.
+        // The primary display is already connected so this will update it.
+        // If we're running the test of an external display this will create it.
+        setExpectationsForConfigs(hwcDisplayId,
+                                  {{.id = 1,
+                                    .w = 800,
+                                    .h = 1600,
+                                    .vsyncPeriod = 11'111'111,
+                                    .group = 1}},
+                                  /* activeConfig */ 1, 11'111'111);
+
+        mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+                                            V2_1::IComposerCallback::Connection::CONNECTED);
+        waitForDisplayTransaction(hwcDisplayId);
+        EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+        const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId);
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+        EXPECT_FALSE(display == nullptr);
+
+        // Verify that the active mode and the supported moded are updated
+        {
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+
+            Vector<DisplayConfig> configs;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+            EXPECT_EQ(configs.size(), 1);
+        }
+
+        // Send another hotplug connected event
+        setExpectationsForConfigs(hwcDisplayId,
+                                  {
+                                          {.id = 1,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 16'666'666,
+                                           .group = 1},
+                                          {.id = 2,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 11'111'111,
+                                           .group = 1},
+                                          {.id = 3,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 8'333'333,
+                                           .group = 1},
+                                  },
+                                  /* activeConfig */ 1, 16'666'666);
+
+        mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+                                            V2_1::IComposerCallback::Connection::CONNECTED);
+        waitForDisplayTransaction(hwcDisplayId);
+        EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+        // Verify that the active mode and the supported moded are updated
+        {
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+        }
+
+        Vector<DisplayConfig> configs;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+        EXPECT_EQ(configs.size(), 3);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[0].resolution);
+        EXPECT_EQ(1e9f / 16'666'666, configs[0].refreshRate);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[1].resolution);
+        EXPECT_EQ(1e9f / 11'111'111, configs[1].refreshRate);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[2].resolution);
+        EXPECT_EQ(1e9f / 8'333'333, configs[2].refreshRate);
+
+        // Verify that we are able to switch to any of the modes
+        for (int i = configs.size() - 1; i >= 0; i--) {
+            const auto hwcId = i + 1;
+            // Set up HWC expectations for the mode change
+            if (mIs2_4Client) {
+                EXPECT_CALL(*mMockComposer,
+                            setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _))
+                        .WillOnce(Return(V2_4::Error::NONE));
+            } else {
+                EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId))
+                        .WillOnce(Return(V2_1::Error::NONE));
+            }
+
+            EXPECT_EQ(NO_ERROR,
+                      SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate));
+            // We need to refresh twice - once to apply the pending mode change request,
+            // and once to process the change.
+            waitForDisplayTransaction(hwcDisplayId);
+            waitForDisplayTransaction(hwcDisplayId);
+            EXPECT_TRUE(waitForConfigChangedEvent(hwcDisplayId, i))
+                    << "Failure while switching to mode " << i;
+
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(configs[i].refreshRate, config.refreshRate);
+        }
+    }
+
     sp<V2_1::IComposer> mFakeService;
     sp<SurfaceComposerClient> mComposerClient;
 
@@ -911,6 +1026,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>;
 
 TEST_F(DisplayTest_2_2, HotplugOneConfig) {
@@ -933,6 +1056,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>;
 
 TEST_F(DisplayTest_2_3, HotplugOneConfig) {
@@ -955,6 +1086,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>;
 
 TEST_F(DisplayTest_2_4, HotplugOneConfig) {
@@ -977,6 +1116,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 ////////////////////////////////////////////////
 
 template <typename FakeComposerService>
@@ -1639,82 +1786,6 @@
         EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
     }
 
-    void Test_DetachChildrenSameClient() {
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.show(mChild);
-            ts.setPosition(mChild, 10, 10);
-            ts.setPosition(Base::mFGSurfaceControl, 64, 64);
-        }
-
-        auto referenceFrame = Base::mBaseFrame;
-        referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
-        referenceFrame[CHILD_LAYER].mDisplayFrame =
-                hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
-        EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.setPosition(Base::mFGSurfaceControl, 0, 0);
-            ts.detachChildren(Base::mFGSurfaceControl);
-        }
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.setPosition(Base::mFGSurfaceControl, 64, 64);
-            ts.hide(mChild);
-        }
-
-        std::vector<RenderState> refFrame(2);
-        refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER];
-        refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER];
-
-        EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame()));
-    }
-
-    void Test_DetachChildrenDifferentClient() {
-        sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
-        sp<SurfaceControl> childNewClient =
-                newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
-                                                 PIXEL_FORMAT_RGBA_8888, 0,
-                                                 Base::mFGSurfaceControl->getHandle());
-        ASSERT_TRUE(childNewClient != nullptr);
-        ASSERT_TRUE(childNewClient->isValid());
-        fillSurfaceRGBA8(childNewClient, LIGHT_GRAY);
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.hide(mChild);
-            ts.show(childNewClient);
-            ts.setPosition(childNewClient, 10, 10);
-            ts.setPosition(Base::mFGSurfaceControl, 64, 64);
-        }
-
-        auto referenceFrame = Base::mBaseFrame;
-        referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
-        referenceFrame[CHILD_LAYER].mDisplayFrame =
-                hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
-        EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.detachChildren(Base::mFGSurfaceControl);
-            ts.setPosition(Base::mFGSurfaceControl, 0, 0);
-        }
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.setPosition(Base::mFGSurfaceControl, 64, 64);
-            ts.setPosition(childNewClient, 0, 0);
-            ts.hide(childNewClient);
-        }
-
-        // Nothing should have changed. The child control becomes a no-op
-        // zombie on detach. See comments for detachChildren in the
-        // SurfaceControl.h file.
-        EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-    }
-
     // Regression test for b/37673612
     void Test_ChildrenWithParentBufferTransform() {
         {
@@ -1815,14 +1886,6 @@
     Test_ReparentChildren();
 }
 
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) {
-    Test_DetachChildrenSameClient();
-}
-
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) {
-    Test_DetachChildrenDifferentClient();
-}
-
 // Regression test for b/37673612
 TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) {
     Test_ChildrenWithParentBufferTransform();
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 83e3ba4..b696a6d 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -62,15 +62,9 @@
 
 using testing::_;
 using testing::AtLeast;
-using testing::Between;
-using testing::ByMove;
 using testing::DoAll;
-using testing::Field;
-using testing::Invoke;
 using testing::IsNull;
 using testing::Mock;
-using testing::NotNull;
-using testing::Ref;
 using testing::Return;
 using testing::ReturnRef;
 using testing::SetArgPointee;
@@ -86,7 +80,6 @@
 constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
 constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
 
-constexpr int DEFAULT_CONFIG_ID = 0;
 constexpr int DEFAULT_TEXTURE_ID = 6000;
 constexpr int DEFAULT_LAYER_STACK = 7000;
 
@@ -147,7 +140,7 @@
 
         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
         EXPECT_CALL(*vsyncTracker, currentPeriod())
-                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
 
         constexpr ISchedulerCallback* kCallback = nullptr;
@@ -253,14 +246,9 @@
     mCaptureScreenBuffer = new GraphicBuffer(renderArea->getReqWidth(), renderArea->getReqHeight(),
                                              HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot");
 
-    int fd = -1;
     status_t result =
             mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(),
-                                            forSystem, &fd, regionSampling);
-    if (fd >= 0) {
-        close(fd);
-    }
-
+                                            forSystem, regionSampling);
     EXPECT_EQ(NO_ERROR, result);
 
     LayerCase::cleanup(this);
@@ -553,12 +541,6 @@
         setupLatchedBuffer(test, layer);
     }
 
-    static void setupBufferLayerPostFrameCallExpectations(CompositionTest* test) {
-        // BufferLayer::onPostComposition(), when there is no present fence
-        EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY, _))
-                .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
-    }
-
     static void setupHwcSetGeometryCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
             // TODO: Coverage of other values
@@ -637,8 +619,6 @@
                     .Times(1);
             EXPECT_CALL(*test->mComposer, setLayerBuffer(HWC_DISPLAY, HWC_LAYER, _, _, _)).Times(1);
         }
-
-        setupBufferLayerPostFrameCallExpectations(test);
     }
 
     static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
@@ -798,7 +778,6 @@
 
     static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
         setupInsecureREBufferCompositionCommonCallExpectations(test);
-        Base::setupBufferLayerPostFrameCallExpectations(test);
     }
 
     static void setupInsecureREBufferScreenshotCompositionCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 9ec2d16..1664301 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -136,7 +136,7 @@
     DisplayTransactionTest();
 };
 
-constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
+constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'667;
 constexpr int32_t DEFAULT_DPI = 320;
 constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
 
@@ -436,7 +436,7 @@
                         getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
                                             IComposerClient::Attribute::VSYNC_PERIOD, _))
                     .WillRepeatedly(
-                            DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
+                            DoAll(SetArgPointee<3>(DEFAULT_VSYNC_PERIOD), Return(Error::NONE)));
             EXPECT_CALL(*test->mComposer,
                         getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
                                             IComposerClient::Attribute::DPI_X, _))
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index e2584e2..6e9f09b 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra"
 
 #include "gmock/gmock-spec-builders.h"
 #include "mock/MockTimeStats.h"
@@ -177,16 +174,17 @@
 static constexpr const uid_t sUidOne = 0;
 static constexpr pid_t sPidOne = 10;
 static constexpr pid_t sPidTwo = 20;
+static constexpr int32_t sInputEventId = 5;
 
 TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
     int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
-    EXPECT_EQ(getPredictions().size(), 1);
+    EXPECT_EQ(getPredictions().size(), 1u);
     flushTokens(systemTime() + maxTokenRetentionTime);
     int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
     std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
 
     // token1 should have expired
-    EXPECT_EQ(getPredictions().size(), 1);
+    EXPECT_EQ(getPredictions().size(), 1u);
     EXPECT_EQ(predictions.has_value(), false);
 
     predictions = mTokenManager->getPredictionsForToken(token2);
@@ -194,16 +192,16 @@
 }
 
 TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) {
-    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
                                                                     sLayerNameOne, sLayerNameOne);
-    auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidTwo, sUidOne,
+    auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne,
                                                                     sLayerNameOne, sLayerNameOne);
     EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne);
     EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo);
 }
 
 TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {
-    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
                                                                    sLayerNameOne, sLayerNameOne);
     EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None);
 }
@@ -211,21 +209,33 @@
 TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
     int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
     flushTokens(systemTime() + maxTokenRetentionTime);
-    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
-                                                                   sLayerNameOne, sLayerNameOne);
+    auto surfaceFrame =
+            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
 
     EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
 }
 
 TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
     int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
-    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
-                                                                   sLayerNameOne, sLayerNameOne);
+    auto surfaceFrame =
+            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
 
     EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
     EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true);
 }
 
+TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) {
+    int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+    constexpr int32_t inputEventId = 1;
+    auto surfaceFrame =
+            mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
+
+    EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId());
+}
+
 TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
     // Global increment
     EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
@@ -234,8 +244,9 @@
 
     int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
     int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
-    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
-                                                                    sLayerNameOne, sLayerNameOne);
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
 
     // Set up the display frame
     mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -264,11 +275,11 @@
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
     int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     auto surfaceFrame2 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameTwo, sLayerNameTwo);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameTwo, sLayerNameTwo);
     mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
     mFrameTimeline->addSurfaceFrame(surfaceFrame1);
@@ -288,8 +299,8 @@
     // Trigger a flush by finalizing the next DisplayFrame
     auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     auto surfaceFrame3 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
     surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped);
     mFrameTimeline->addSurfaceFrame(surfaceFrame3);
@@ -320,8 +331,9 @@
         int64_t sfToken = mTokenManager->generateTokenForPredictions(
                 {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
         auto surfaceFrame =
-                mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
-                                                           sLayerNameOne, sLayerNameOne);
+                mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId},
+                                                           sPidOne, sUidOne, sLayerNameOne,
+                                                           sLayerNameOne);
         mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
         surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
         mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -341,8 +353,8 @@
     int64_t sfToken = mTokenManager->generateTokenForPredictions(
             {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
     auto surfaceFrame =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
     surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
     mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -356,18 +368,18 @@
 }
 
 TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) {
-    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
-                                                                   "acquireFenceAfterQueue",
-                                                                   "acquireFenceAfterQueue");
+    auto surfaceFrame =
+            mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+                                                       "acquireFenceAfterQueue");
     surfaceFrame->setActualQueueTime(123);
     surfaceFrame->setAcquireFenceTime(456);
     EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
 }
 
 TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) {
-    auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
-                                                                   "acquireFenceAfterQueue",
-                                                                   "acquireFenceAfterQueue");
+    auto surfaceFrame =
+            mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+                                                       "acquireFenceAfterQueue");
     surfaceFrame->setActualQueueTime(456);
     surfaceFrame->setAcquireFenceTime(123);
     EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
@@ -383,8 +395,8 @@
     // Size shouldn't exceed maxDisplayFrames - 64
     for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
         auto surfaceFrame =
-                mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
-                                                           sLayerNameOne, sLayerNameOne);
+                mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+                                                           sLayerNameOne);
         int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
         mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
         surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -395,15 +407,15 @@
 
     // Increase the size to 256
     mFrameTimeline->setMaxDisplayFrames(256);
-    EXPECT_EQ(*maxDisplayFrames, 256);
+    EXPECT_EQ(*maxDisplayFrames, 256u);
     // Global increment
     EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
             .Times(static_cast<int32_t>(*maxDisplayFrames + 10));
 
     for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
         auto surfaceFrame =
-                mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
-                                                           sLayerNameOne, sLayerNameOne);
+                mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+                                                           sLayerNameOne);
         int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
         mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
         surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -414,15 +426,15 @@
 
     // Shrink the size to 128
     mFrameTimeline->setMaxDisplayFrames(128);
-    EXPECT_EQ(*maxDisplayFrames, 128);
+    EXPECT_EQ(*maxDisplayFrames, 128u);
     // Global increment
     EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
             .Times(static_cast<int32_t>(*maxDisplayFrames + 10));
 
     for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
         auto surfaceFrame =
-                mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
-                                                           sLayerNameOne, sLayerNameOne);
+                mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+                                                           sLayerNameOne);
         int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
         mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
         surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -449,8 +461,8 @@
              std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
              std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     mFrameTimeline->setSfWakeUp(sfToken1,
                                 std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                 11);
@@ -478,8 +490,8 @@
              std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
              std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     mFrameTimeline->setSfWakeUp(sfToken1,
                                 std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                 30);
@@ -507,8 +519,8 @@
              std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
              std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(
             std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
     mFrameTimeline->setSfWakeUp(sfToken1,
@@ -542,8 +554,9 @@
 
     int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
     int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
-    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
-                                                                    sLayerNameOne, sLayerNameOne);
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
 
     // Set up the display frame
     mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -558,7 +571,7 @@
     mFrameTimeline->setSfPresent(55, presentFence2);
 
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
-    EXPECT_EQ(packets.size(), 0);
+    EXPECT_EQ(packets.size(), 0u);
 }
 
 TEST_F(FrameTimelineTest, tracing_sanityTest) {
@@ -573,8 +586,9 @@
     tracingSession->StartBlocking();
     int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
     int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
-    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
-                                                                    sLayerNameOne, sLayerNameOne);
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+                                                       sLayerNameOne, sLayerNameOne);
 
     // Set up the display frame
     mFrameTimeline->setSfWakeUp(token2, 20, 11);
@@ -594,7 +608,7 @@
 
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
     // Display Frame 1 has 8 packets - 4 from DisplayFrame and 4 from SurfaceFrame.
-    EXPECT_EQ(packets.size(), 8);
+    EXPECT_EQ(packets.size(), 8u);
 }
 
 TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -622,7 +636,7 @@
     tracingSession->StopBlocking();
 
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
-    EXPECT_EQ(packets.size(), 0);
+    EXPECT_EQ(packets.size(), 0u);
 }
 
 TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -635,7 +649,7 @@
     tracingSession->StartBlocking();
     int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
     int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
-    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+    auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
                                                                     sLayerNameOne, sLayerNameOne);
 
     // Set up the display frame
@@ -657,7 +671,7 @@
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
     // Display Frame 1 has 4 packets (SurfaceFrame shouldn't be traced since it has an invalid
     // token).
-    EXPECT_EQ(packets.size(), 4);
+    EXPECT_EQ(packets.size(), 4u);
 }
 
 void validateTraceEvent(const ProtoExpectedDisplayFrameStart& received,
@@ -791,12 +805,12 @@
     tracingSession->StopBlocking();
 
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
-    EXPECT_EQ(packets.size(), 4);
+    EXPECT_EQ(packets.size(), 4u);
 
     // Packet - 0 : ExpectedDisplayFrameStart
     const auto& packet0 = packets[0];
     ASSERT_TRUE(packet0.has_timestamp());
-    EXPECT_EQ(packet0.timestamp(), 10);
+    EXPECT_EQ(packet0.timestamp(), 10u);
     ASSERT_TRUE(packet0.has_frame_timeline_event());
 
     const auto& event0 = packet0.frame_timeline_event();
@@ -807,7 +821,7 @@
     // Packet - 1 : FrameEnd (ExpectedDisplayFrame)
     const auto& packet1 = packets[1];
     ASSERT_TRUE(packet1.has_timestamp());
-    EXPECT_EQ(packet1.timestamp(), 25);
+    EXPECT_EQ(packet1.timestamp(), 25u);
     ASSERT_TRUE(packet1.has_frame_timeline_event());
 
     const auto& event1 = packet1.frame_timeline_event();
@@ -818,7 +832,7 @@
     // Packet - 2 : ActualDisplayFrameStart
     const auto& packet2 = packets[2];
     ASSERT_TRUE(packet2.has_timestamp());
-    EXPECT_EQ(packet2.timestamp(), 20);
+    EXPECT_EQ(packet2.timestamp(), 20u);
     ASSERT_TRUE(packet2.has_frame_timeline_event());
 
     const auto& event2 = packet2.frame_timeline_event();
@@ -829,7 +843,7 @@
     // Packet - 3 : FrameEnd (ActualDisplayFrame)
     const auto& packet3 = packets[3];
     ASSERT_TRUE(packet3.has_timestamp());
-    EXPECT_EQ(packet3.timestamp(), 26);
+    EXPECT_EQ(packet3.timestamp(), 26u);
     ASSERT_TRUE(packet3.has_frame_timeline_event());
 
     const auto& event3 = packet3.frame_timeline_event();
@@ -853,8 +867,8 @@
     int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
 
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setActualStartTime(0);
     surfaceFrame1->setActualQueueTime(15);
     surfaceFrame1->setAcquireFenceTime(20);
@@ -904,12 +918,12 @@
     tracingSession->StopBlocking();
 
     auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
-    EXPECT_EQ(packets.size(), 8);
+    EXPECT_EQ(packets.size(), 8u);
 
     // Packet - 4 : ExpectedSurfaceFrameStart
     const auto& packet4 = packets[4];
     ASSERT_TRUE(packet4.has_timestamp());
-    EXPECT_EQ(packet4.timestamp(), 10);
+    EXPECT_EQ(packet4.timestamp(), 10u);
     ASSERT_TRUE(packet4.has_frame_timeline_event());
 
     const auto& event4 = packet4.frame_timeline_event();
@@ -920,7 +934,7 @@
     // Packet - 5 : FrameEnd (ExpectedSurfaceFrame)
     const auto& packet5 = packets[5];
     ASSERT_TRUE(packet5.has_timestamp());
-    EXPECT_EQ(packet5.timestamp(), 25);
+    EXPECT_EQ(packet5.timestamp(), 25u);
     ASSERT_TRUE(packet5.has_frame_timeline_event());
 
     const auto& event5 = packet5.frame_timeline_event();
@@ -931,7 +945,7 @@
     // Packet - 6 : ActualSurfaceFrameStart
     const auto& packet6 = packets[6];
     ASSERT_TRUE(packet6.has_timestamp());
-    EXPECT_EQ(packet6.timestamp(), 10);
+    EXPECT_EQ(packet6.timestamp(), 10u);
     ASSERT_TRUE(packet6.has_frame_timeline_event());
 
     const auto& event6 = packet6.frame_timeline_event();
@@ -942,7 +956,7 @@
     // Packet - 7 : FrameEnd (ActualSurfaceFrame)
     const auto& packet7 = packets[7];
     ASSERT_TRUE(packet7.has_timestamp());
-    EXPECT_EQ(packet7.timestamp(), 20);
+    EXPECT_EQ(packet7.timestamp(), 20u);
     ASSERT_TRUE(packet7.has_frame_timeline_event());
 
     const auto& event7 = packet7.frame_timeline_event();
@@ -961,8 +975,8 @@
     int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30});
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
     auto surfaceFrame =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
     surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
     mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -1126,8 +1140,8 @@
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
     int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(16);
     mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1145,8 +1159,8 @@
     // Trigger a flush by finalizing the next DisplayFrame
     auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     auto surfaceFrame2 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame2->setAcquireFenceTime(36);
     mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
     surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1199,8 +1213,8 @@
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
     int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(16);
     mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1218,8 +1232,8 @@
     // Trigger a flush by finalizing the next DisplayFrame
     auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     auto surfaceFrame2 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame2->setAcquireFenceTime(36);
     mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
     surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1270,8 +1284,8 @@
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50});
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(40);
     mFrameTimeline->setSfWakeUp(sfToken1, 42, 11);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1316,8 +1330,8 @@
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30});
     int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(26);
     mFrameTimeline->setSfWakeUp(sfToken1, 32, 11);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1335,8 +1349,8 @@
     // Trigger a flush by finalizing the next DisplayFrame
     auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     auto surfaceFrame2 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame2->setAcquireFenceTime(40);
     mFrameTimeline->setSfWakeUp(sfToken2, 43, 11);
     surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1390,8 +1404,8 @@
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 56, 60});
     int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120});
     auto surfaceFrame1 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame1->setAcquireFenceTime(50);
     mFrameTimeline->setSfWakeUp(sfToken1, 52, 30);
     surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1409,8 +1423,8 @@
     // Trigger a flush by finalizing the next DisplayFrame
     auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     auto surfaceFrame2 =
-            mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
-                                                       sLayerNameOne, sLayerNameOne);
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerNameOne, sLayerNameOne);
     surfaceFrame2->setAcquireFenceTime(84);
     mFrameTimeline->setSfWakeUp(sfToken2, 112, 30);
     surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54);
@@ -1456,6 +1470,3 @@
               JankType::AppDeadlineMissed | JankType::BufferStuffing);
 }
 } // namespace android::frametimeline
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 71986fe..6b82170 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -35,6 +35,7 @@
 
 #include "DisplayHardware/DisplayMode.h"
 #include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/Hal.h"
 #include "mock/DisplayHardware/MockComposer.h"
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -174,88 +175,5 @@
     EXPECT_EQ(hal::Error::UNSUPPORTED, result);
 }
 
-class HWComposerConfigsTest : public testing::Test {
-public:
-    Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
-    MockHWC2ComposerCallback mCallback;
-
-    void setActiveConfig(Config config) {
-        EXPECT_CALL(*mHal, getActiveConfig(_, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(config), Return(V2_1::Error::NONE)));
-    }
-
-    void setDisplayConfigs(std::vector<Config> configs) {
-        EXPECT_CALL(*mHal, getDisplayConfigs(_, _))
-                .WillOnce(DoAll(SetArgPointee<1>(configs), Return(V2_1::Error::NONE)));
-        EXPECT_CALL(*mHal, getDisplayAttribute(_, _, _, _))
-                .WillRepeatedly(DoAll(SetArgPointee<3>(1), Return(V2_1::Error::NONE)));
-    }
-
-    void testSetActiveModeWithConstraintsCommon(bool isVsyncPeriodSwitchSupported);
-};
-
-void HWComposerConfigsTest::testSetActiveModeWithConstraintsCommon(
-        bool isVsyncPeriodSwitchSupported) {
-    EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
-    EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
-    EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_)).WillOnce(Return(V2_4::Error::UNSUPPORTED));
-    EXPECT_CALL(*mHal, registerCallback(_));
-    EXPECT_CALL(*mHal, setVsyncEnabled(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
-    EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
-            .WillRepeatedly(Return(V2_1::Error::UNSUPPORTED));
-    EXPECT_CALL(*mHal, setClientTargetSlotCount(_)).WillRepeatedly(Return(V2_1::Error::NONE));
-
-    EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported())
-            .WillRepeatedly(Return(isVsyncPeriodSwitchSupported));
-
-    if (isVsyncPeriodSwitchSupported) {
-        EXPECT_CALL(*mHal, setActiveConfigWithConstraints(_, _, _, _))
-                .WillRepeatedly(Return(V2_4::Error::NONE));
-    } else {
-        EXPECT_CALL(*mHal, setActiveConfig(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
-    }
-
-    impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
-    hwc.setConfiguration(&mCallback, 123);
-
-    setDisplayConfigs({15});
-    setActiveConfig(15);
-
-    const auto physicalId = PhysicalDisplayId::fromPort(0);
-    const hal::HWDisplayId hwcId = 0;
-    hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
-    hal::VsyncPeriodChangeConstraints constraints;
-    constraints.desiredTimeNanos = systemTime();
-    constraints.seamlessRequired = false;
-
-    hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
-    constexpr DisplayModeId kConfigIndex(0);
-    const auto status =
-            hwc.setActiveModeWithConstraints(physicalId, kConfigIndex, constraints, &timeline);
-    EXPECT_EQ(NO_ERROR, status);
-
-    const std::vector<Config> kConfigs{7, 8, 9, 10, 11};
-    // Change the set of supported modes.
-    setDisplayConfigs(kConfigs);
-    setActiveConfig(11);
-    hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
-    hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
-    for (size_t configIndex = 0; configIndex < kConfigs.size(); configIndex++) {
-        const auto status = hwc.setActiveModeWithConstraints(physicalId, DisplayModeId(configIndex),
-                                                             constraints, &timeline);
-        EXPECT_EQ(NO_ERROR, status) << "Error when switching to config " << configIndex;
-    }
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingSupported) {
-    testSetActiveModeWithConstraintsCommon(/*supported=*/true);
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingNotSupported) {
-    testSetActiveModeWithConstraintsCommon(/*supported=*/false);
-}
-
 } // namespace
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index c5deb7c..abecd4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -144,7 +144,7 @@
 
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     EXPECT_CALL(*vsyncTracker, currentPeriod())
-            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
                             std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e060df2..a6d07d0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -185,7 +185,7 @@
 
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     EXPECT_CALL(*vsyncTracker, currentPeriod())
-            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
                             std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
index 8552e15..b713334 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -669,7 +669,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -714,7 +714,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -764,7 +764,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(kNewWidth, kNewHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
index 7a9403b..ef8b149 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
@@ -86,16 +86,16 @@
     // The display refresh period should be set in the orientedDisplaySpaceRect tracker.
     FrameStats stats;
     mFlinger.getAnimFrameTracker().getStats(&stats);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, stats.refreshPeriodNano);
+    EXPECT_EQ(DEFAULT_VSYNC_PERIOD, stats.refreshPeriodNano);
 
     // The display transaction needed flag should be set.
     EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
 
     // The compositor timing should be set to default values
     const auto& compositorTiming = mFlinger.getCompositorTiming();
-    EXPECT_EQ(-DEFAULT_REFRESH_RATE, compositorTiming.deadline);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.interval);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.presentLatency);
+    EXPECT_EQ(-DEFAULT_VSYNC_PERIOD, compositorTiming.deadline);
+    EXPECT_EQ(DEFAULT_VSYNC_PERIOD, compositorTiming.interval);
+    EXPECT_EQ(DEFAULT_VSYNC_PERIOD, compositorTiming.presentLatency);
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index 2117628..6502420 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -105,7 +105,7 @@
 
 struct DispSyncIsSupportedVariant {
     static void setupResetModelCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mVsyncController, startPeriodTransition(DEFAULT_REFRESH_RATE)).Times(1);
+        EXPECT_CALL(*test->mVsyncController, startPeriodTransition(DEFAULT_VSYNC_PERIOD)).Times(1);
         EXPECT_CALL(*test->mVSyncTracker, resetModel()).Times(1);
     }
 };
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index ca7c755..2b5cb77 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -17,6 +17,8 @@
 #undef LOG_TAG
 #define LOG_TAG "LibSurfaceFlingerUnittests"
 
+#include "DisplayHardware/DisplayMode.h"
+
 #include "DisplayTransactionTestHelpers.h"
 
 namespace android {
@@ -232,13 +234,26 @@
     // Invocation
 
     DisplayDeviceState state;
-    if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
+    if constexpr (constexpr auto connectionType = Case::Display::CONNECTION_TYPE::value) {
         const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
         ASSERT_TRUE(displayId);
         const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
         ASSERT_TRUE(hwcDisplayId);
         mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId);
-        state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId};
+        DisplayModePtr activeMode = DisplayMode::Builder(Case::Display::HWC_ACTIVE_CONFIG_ID)
+                                            .setWidth(Case::Display::WIDTH)
+                                            .setHeight(Case::Display::HEIGHT)
+                                            .setVsyncPeriod(DEFAULT_VSYNC_PERIOD)
+                                            .setDpiX(DEFAULT_DPI)
+                                            .setDpiY(DEFAULT_DPI)
+                                            .setConfigGroup(0)
+                                            .build();
+        DisplayModes modes{activeMode};
+        state.physical = {.id = *displayId,
+                          .type = *connectionType,
+                          .hwcDisplayId = *hwcDisplayId,
+                          .supportedModes = modes,
+                          .activeMode = activeMode};
     }
 
     state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -262,12 +277,14 @@
     EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support());
     EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport());
     EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport());
-    // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are
-    // remapped, and the test only ever sets up one config. If there were an error
-    // looking up the remapped index, device->getActiveMode() would be -1 instead.
-    EXPECT_EQ(0, device->getActiveMode().value());
     EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS,
               device->getSupportedPerFrameMetadata());
+
+    if constexpr (Case::Display::CONNECTION_TYPE::value) {
+        EXPECT_EQ(1, device->getSupportedModes().size());
+        EXPECT_NE(nullptr, device->getActiveMode());
+        EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode()->getHwcId());
+    }
 }
 
 TEST_F(SetupNewDisplayDeviceInternalTest, createSimplePrimaryDisplay) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9a9eeab..3787c43 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -41,6 +41,7 @@
 #include "SurfaceFlingerDefaultFactory.h"
 #include "SurfaceInterceptor.h"
 #include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockComposer.h"
 #include "mock/MockDisplayIdGenerator.h"
 #include "mock/MockFrameTimeline.h"
 #include "mock/MockFrameTracer.h"
@@ -349,11 +350,12 @@
 
     auto renderScreenImplLocked(const RenderArea& renderArea,
                                 SurfaceFlinger::TraverseLayersFunction traverseLayers,
-                                const sp<GraphicBuffer>& buffer, bool forSystem, int* outSyncFd,
+                                const sp<GraphicBuffer>& buffer, bool forSystem,
                                 bool regionSampling) {
         ScreenCaptureResults captureResults;
         return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem,
-                                                outSyncFd, regionSampling, captureResults);
+                                                regionSampling, false /* grayscale */,
+                                                captureResults);
     }
 
     auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
@@ -366,18 +368,17 @@
         return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
     }
 
-    auto& getTransactionQueue() { return mFlinger->mTransactionQueues; }
+    auto& getTransactionQueue() { return mFlinger->mTransactionQueue; }
+    auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
 
-    auto setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
-                             const Vector<DisplayState>& displays, uint32_t flags,
-                             const sp<IBinder>& applyToken,
-                             const InputWindowCommands& inputWindowCommands,
-                             int64_t desiredPresentTime, bool isAutoTimestamp,
-                             const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
-                             std::vector<ListenerCallbacks>& listenerCallbacks,
-                             uint64_t transactionId) {
-        return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags,
-                                             applyToken, inputWindowCommands, desiredPresentTime,
+    auto setTransactionState(
+            const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
+            const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+            const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+            bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+            std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+        return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
+                                             inputWindowCommands, desiredPresentTime,
                                              isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
                                              listenerCallbacks, transactionId);
     }
@@ -478,7 +479,7 @@
         static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
         static constexpr int32_t DEFAULT_WIDTH = 1920;
         static constexpr int32_t DEFAULT_HEIGHT = 1280;
-        static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+        static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'666;
         static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
         static constexpr int32_t DEFAULT_DPI = 320;
         static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
@@ -503,8 +504,8 @@
             return *this;
         }
 
-        auto& setRefreshRate(int32_t refreshRate) {
-            mRefreshRate = refreshRate;
+        auto& setVsyncPeriod(int32_t vsyncPeriod) {
+            mVsyncPeriod = vsyncPeriod;
             return *this;
         }
 
@@ -533,7 +534,12 @@
             return *this;
         }
 
-        void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
+        void inject(TestableSurfaceFlinger* flinger, Hwc2::mock::Composer* composer) {
+            using ::testing::_;
+            using ::testing::DoAll;
+            using ::testing::Return;
+            using ::testing::SetArgPointee;
+
             static const std::unordered_set<hal::Capability> defaultCapabilities;
             if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
 
@@ -548,15 +554,39 @@
             display->setPowerMode(mPowerMode);
             flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
 
-            auto config = DisplayMode::Builder(mActiveConfig)
-                                  .setWidth(mWidth)
-                                  .setHeight(mHeight)
-                                  .setVsyncPeriod(mRefreshRate)
-                                  .setDpiX(mDpiX)
-                                  .setDpiY(mDpiY)
-                                  .setConfigGroup(mConfigGroup)
-                                  .build();
-            flinger->mutableHwcDisplayData()[mDisplayId].modes.push_back(config);
+            EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
+                                  Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
+                                            _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+                                            hal::Attribute::VSYNC_PERIOD, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiX), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_Y, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiY), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+                                            hal::Attribute::CONFIG_GROUP, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
 
             if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
                 const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
@@ -582,10 +612,10 @@
         hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
         int32_t mWidth = DEFAULT_WIDTH;
         int32_t mHeight = DEFAULT_HEIGHT;
-        int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
+        int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
         int32_t mDpiX = DEFAULT_DPI;
-        int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
         int32_t mDpiY = DEFAULT_DPI;
+        int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
         hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
         hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
         const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
@@ -598,10 +628,26 @@
                                   std::optional<DisplayConnectionType> connectionType,
                                   std::optional<hal::HWDisplayId> hwcDisplayId, bool isPrimary)
               : mFlinger(flinger),
-                mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay),
+                mCreationArgs(flinger.mFlinger.get(), flinger.mFlinger->getHwComposer(),
+                              mDisplayToken, compositionDisplay),
                 mHwcDisplayId(hwcDisplayId) {
             mCreationArgs.connectionType = connectionType;
             mCreationArgs.isPrimary = isPrimary;
+
+            mActiveModeId = DisplayModeId(0);
+            DisplayModePtr activeMode =
+                    DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+                            .setId(mActiveModeId)
+                            .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+                            .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+                            .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+                            .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+                            .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+                            .setConfigGroup(0)
+                            .build();
+
+            DisplayModes modes{activeMode};
+            mCreationArgs.supportedModes = modes;
         }
 
         sp<IBinder> token() const { return mDisplayToken; }
@@ -624,6 +670,16 @@
 
         auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
 
+        auto& setActiveMode(DisplayModeId mode) {
+            mActiveModeId = mode;
+            return *this;
+        }
+
+        auto& setSupportedModes(DisplayModes mode) {
+            mCreationArgs.supportedModes = mode;
+            return *this;
+        }
+
         auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
             mCreationArgs.nativeWindow = nativeWindow;
             return *this;
@@ -676,6 +732,9 @@
             state.isSecure = mCreationArgs.isSecure;
 
             sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
+            if (!device->isVirtual()) {
+                device->setActiveMode(mActiveModeId);
+            }
             mFlinger.mutableDisplays().emplace(mDisplayToken, device);
             mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
             mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -692,6 +751,7 @@
         sp<BBinder> mDisplayToken = new BBinder();
         DisplayDeviceCreationArgs mCreationArgs;
         const std::optional<hal::HWDisplayId> mHwcDisplayId;
+        DisplayModeId mActiveModeId;
     };
 
 private:
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 06275c6..eb2c1ba 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
 
 #undef LOG_TAG
 #define LOG_TAG "CompositionTest"
@@ -76,7 +72,7 @@
 
         EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
         EXPECT_CALL(*mVSyncTracker, currentPeriod())
-                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
 
         mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
                                 std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -100,50 +96,50 @@
         InputWindowCommands inputWindowCommands;
         int64_t desiredPresentTime = 0;
         bool isAutoTimestamp = true;
-        int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+        FrameTimelineInfo frameTimelineInfo;
         client_cache_t uncacheBuffer;
-        int64_t id = -1;
+        uint64_t id = static_cast<uint64_t>(-1);
+        static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
     };
 
     void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) {
-        EXPECT_EQ(0, info.states.size());
-        EXPECT_EQ(0, state.states.size());
+        EXPECT_EQ(0u, info.states.size());
+        EXPECT_EQ(0u, state.states.size());
 
-        EXPECT_EQ(0, info.displays.size());
-        EXPECT_EQ(0, state.displays.size());
+        EXPECT_EQ(0u, info.displays.size());
+        EXPECT_EQ(0u, state.displays.size());
         EXPECT_EQ(info.flags, state.flags);
         EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
     }
 
     void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows,
                      int64_t desiredPresentTime, bool isAutoTimestamp,
-                     int64_t frameTimelineVsyncId) {
+                     const FrameTimelineInfo& frameTimelineInfo) {
         mTransactionNumber++;
         transaction.flags |= flags; // ISurfaceComposer::eSynchronous;
         transaction.inputWindowCommands.syncInputWindows = syncInputWindows;
         transaction.desiredPresentTime = desiredPresentTime;
         transaction.isAutoTimestamp = isAutoTimestamp;
-        transaction.frameTimelineVsyncId = frameTimelineVsyncId;
+        transaction.frameTimelineInfo = frameTimelineInfo;
     }
 
     void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
-        ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+        ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
         // called in SurfaceFlinger::signalTransaction
         EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
         EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime()));
         TransactionInfo transaction;
         setupSingle(transaction, flags, syncInputWindows,
                     /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
-                    ISurfaceComposer::INVALID_VSYNC_ID);
+                    FrameTimelineInfo{});
         nsecs_t applicationTime = systemTime();
-        mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+        mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
                                      transaction.desiredPresentTime, transaction.isAutoTimestamp,
                                      transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
                                      transaction.id);
 
-        // This transaction should not have been placed on the transaction queue.
         // If transaction is synchronous or syncs input windows, SF
         // applyTransactionState should time out (5s) wating for SF to commit
         // the transaction or to receive a signal that syncInputWindows has
@@ -154,12 +150,13 @@
         } else {
             EXPECT_LE(returnedTime, applicationTime + s2ns(5));
         }
+        // Each transaction should have been placed on the transaction queue
         auto transactionQueue = mFlinger.getTransactionQueue();
-        EXPECT_EQ(0, transactionQueue.size());
+        EXPECT_EQ(1u, transactionQueue.size());
     }
 
     void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
-        ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+        ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
         // called in SurfaceFlinger::signalTransaction
         EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
 
@@ -170,10 +167,9 @@
                 .WillOnce(Return(time + nsecs_t(5 * 1e8)));
         TransactionInfo transaction;
         setupSingle(transaction, flags, syncInputWindows,
-                    /*desiredPresentTime*/ time + s2ns(1), false,
-                    ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
         nsecs_t applicationSentTime = systemTime();
-        mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+        mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
                                      transaction.desiredPresentTime, transaction.isAutoTimestamp,
@@ -184,11 +180,11 @@
         EXPECT_LE(returnedTime, applicationSentTime + s2ns(5));
         // This transaction should have been placed on the transaction queue
         auto transactionQueue = mFlinger.getTransactionQueue();
-        EXPECT_EQ(1, transactionQueue.size());
+        EXPECT_EQ(1u, transactionQueue.size());
     }
 
     void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) {
-        ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+        ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
         // called in SurfaceFlinger::signalTransaction
         nsecs_t time = systemTime();
         EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -197,18 +193,17 @@
         // transaction that should go on the pending thread
         TransactionInfo transactionA;
         setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
-                    /*desiredPresentTime*/ time + s2ns(1), false,
-                    ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
 
         // transaction that would not have gone on the pending thread if not
         // blocked
         TransactionInfo transactionB;
         setupSingle(transactionB, flags, syncInputWindows,
                     /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
-                    ISurfaceComposer::INVALID_VSYNC_ID);
+                    FrameTimelineInfo{});
 
         nsecs_t applicationSentTime = systemTime();
-        mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+        mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
                                      transactionA.displays, transactionA.flags,
                                      transactionA.applyToken, transactionA.inputWindowCommands,
                                      transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
@@ -219,9 +214,11 @@
         // (5s is the timeout period that applyTransactionState waits for SF to
         // commit the transaction)
         EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+        // transaction that would goes to pending transaciton queue.
+        mFlinger.flushTransactionQueues();
 
         applicationSentTime = systemTime();
-        mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states,
+        mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
                                      transactionB.displays, transactionB.flags,
                                      transactionB.applyToken, transactionB.inputWindowCommands,
                                      transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
@@ -238,12 +235,15 @@
             EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
         }
 
+        // transaction that would goes to pending transaciton queue.
+        mFlinger.flushTransactionQueues();
+
         // check that there is one binder on the pending queue.
-        auto transactionQueue = mFlinger.getTransactionQueue();
-        EXPECT_EQ(1, transactionQueue.size());
+        auto transactionQueue = mFlinger.getPendingTransactionQueue();
+        EXPECT_EQ(1u, transactionQueue.size());
 
         auto& [applyToken, transactionStates] = *(transactionQueue.begin());
-        EXPECT_EQ(2, transactionStates.size());
+        EXPECT_EQ(2u, transactionStates.size());
 
         auto& transactionStateA = transactionStates.front();
         transactionStates.pop();
@@ -258,7 +258,7 @@
 };
 
 TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
-    ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+    ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
     // called in SurfaceFlinger::signalTransaction
     EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
 
@@ -268,20 +268,17 @@
             .WillOnce(Return(s2ns(2)));
     TransactionInfo transactionA; // transaction to go on pending queue
     setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
-                /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID);
-    mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+                /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{});
+    mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
                                  transactionA.displays, transactionA.flags, transactionA.applyToken,
                                  transactionA.inputWindowCommands, transactionA.desiredPresentTime,
                                  transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
                                  mHasListenerCallbacks, mCallbacks, transactionA.id);
 
     auto& transactionQueue = mFlinger.getTransactionQueue();
-    ASSERT_EQ(1, transactionQueue.size());
+    ASSERT_EQ(1u, transactionQueue.size());
 
-    auto& [applyToken, transactionStates] = *(transactionQueue.begin());
-    ASSERT_EQ(1, transactionStates.size());
-
-    auto& transactionState = transactionStates.front();
+    auto& transactionState = transactionQueue.front();
     checkEqual(transactionA, transactionState);
 
     // because flushing uses the cached expected present time, we send an empty
@@ -289,8 +286,8 @@
     // different process) to re-query and reset the cached expected present time
     TransactionInfo empty;
     empty.applyToken = sp<IBinder>();
-    mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays,
-                                 empty.flags, empty.applyToken, empty.inputWindowCommands,
+    mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
+                                 empty.applyToken, empty.inputWindowCommands,
                                  empty.desiredPresentTime, empty.isAutoTimestamp,
                                  empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
 
@@ -298,7 +295,7 @@
     // passed
     mFlinger.flushTransactionQueues();
 
-    EXPECT_EQ(0, transactionQueue.size());
+    EXPECT_EQ(0u, transactionQueue.size());
 }
 
 TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) {
@@ -343,6 +340,3 @@
     EXPECT_EQ(nullptr, ret.promote().get());
 }
 } // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index a13f93b..2fefa45 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -84,11 +84,13 @@
     }
 
     void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+        ASSERT_NE(nullptr, mOutBuffer);
         ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
         TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
     }
 
     void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+        ASSERT_NE(nullptr, mOutBuffer);
         ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
         const bool leftBorder = rect.left > 0;
         const bool topBorder = rect.top > 0;
@@ -146,6 +148,7 @@
     }
 
     void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+        ASSERT_NE(nullptr, mOutBuffer);
         ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
         const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
         if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
@@ -163,10 +166,14 @@
     void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
 
     explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
-        mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+        if (mOutBuffer) {
+            mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+        }
     }
 
-    ~ScreenCapture() { mOutBuffer->unlock(); }
+    ~ScreenCapture() {
+        if (mOutBuffer) mOutBuffer->unlock();
+    }
 
 private:
     sp<GraphicBuffer> mOutBuffer;