Merge "Fix the logic of adding skipped frame." into main
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index ba0a38a..a8d12a1 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -39,6 +39,7 @@
     std::string calling_package;
     int32_t user_id = -1;
     bool keep_bugreport_on_retrieval = false;
+    bool skip_user_consent = false;
 };
 
 static binder::Status exception(uint32_t code, const std::string& msg,
@@ -62,7 +63,8 @@
 
 [[noreturn]] static void* dumpstate_thread_retrieve(void* data) {
     std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
-    ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package, ds_info->keep_bugreport_on_retrieval);
+    ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package,
+    ds_info->keep_bugreport_on_retrieval, ds_info->skip_user_consent);
     MYLOGD("Finished retrieving a bugreport. Exiting.\n");
     exit(0);
 }
@@ -116,7 +118,8 @@
                                                 int bugreport_mode,
                                                 int bugreport_flags,
                                                 const sp<IDumpstateListener>& listener,
-                                                bool is_screenshot_requested) {
+                                                bool is_screenshot_requested,
+                                                bool skip_user_consent) {
     MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
 
     // Ensure there is only one bugreport in progress at a time.
@@ -151,7 +154,7 @@
 
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
     options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_flags,
-                        bugreport_fd, screenshot_fd, is_screenshot_requested);
+                        bugreport_fd, screenshot_fd, is_screenshot_requested, skip_user_consent);
 
     if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
         MYLOGE("Invalid filedescriptor");
@@ -207,6 +210,7 @@
     android::base::unique_fd bugreport_fd,
     const std::string& bugreport_file,
     const bool keep_bugreport_on_retrieval,
+    const bool skip_user_consent,
     const sp<IDumpstateListener>& listener) {
 
     ds_ = &(Dumpstate::GetInstance());
@@ -216,6 +220,7 @@
     ds_info->calling_package = calling_package;
     ds_info->user_id = user_id;
     ds_info->keep_bugreport_on_retrieval = keep_bugreport_on_retrieval;
+    ds_info->skip_user_consent = skip_user_consent;
     ds_->listener_ = listener;
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
     // Use a /dev/null FD when initializing options since none is provided.
@@ -223,7 +228,7 @@
         TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
 
     options->Initialize(Dumpstate::BugreportMode::BUGREPORT_DEFAULT,
-                        0, bugreport_fd, devnull_fd, false);
+                        0, bugreport_fd, devnull_fd, false, skip_user_consent);
 
     if (bugreport_fd.get() == -1) {
         MYLOGE("Invalid filedescriptor");
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 7b76c36..c99f70e 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -44,7 +44,7 @@
                                   android::base::unique_fd bugreport_fd,
                                   android::base::unique_fd screenshot_fd, int bugreport_mode,
                                   int bugreport_flags, const sp<IDumpstateListener>& listener,
-                                  bool is_screenshot_requested) override;
+                                  bool is_screenshot_requested, bool skip_user_consent) override;
 
     binder::Status retrieveBugreport(int32_t calling_uid,
                                      const std::string& calling_package,
@@ -52,6 +52,7 @@
                                      android::base::unique_fd bugreport_fd,
                                      const std::string& bugreport_file,
                                      const bool keep_bugreport_on_retrieval,
+                                     const bool skip_user_consent,
                                      const sp<IDumpstateListener>& listener)
                                      override;
 
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 97c470e..3b8fde9 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -96,7 +96,8 @@
     void startBugreport(int callingUid, @utf8InCpp String callingPackage,
                         FileDescriptor bugreportFd, FileDescriptor screenshotFd,
                         int bugreportMode, int bugreportFlags,
-                        IDumpstateListener listener, boolean isScreenshotRequested);
+                        IDumpstateListener listener, boolean isScreenshotRequested,
+                        boolean skipUserConsent);
 
     /**
      * Cancels the bugreport currently in progress.
@@ -130,5 +131,6 @@
                            FileDescriptor bugreportFd,
                            @utf8InCpp String bugreportFile,
                            boolean keepBugreportOnRetrieval,
+                           boolean skipUserConsent,
                            IDumpstateListener listener);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6b9a0a0..d5125f0 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2902,9 +2902,11 @@
                                         int bugreport_flags,
                                         const android::base::unique_fd& bugreport_fd_in,
                                         const android::base::unique_fd& screenshot_fd_in,
-                                        bool is_screenshot_requested) {
+                                        bool is_screenshot_requested,
+                                        bool skip_user_consent) {
     this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
     this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
+    this->skip_user_consent = skip_user_consent;
     // Duplicate the fds because the passed in fds don't outlive the binder transaction.
     bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
     screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
@@ -2992,46 +2994,52 @@
 }
 
 Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
-                                         const bool keep_bugreport_on_retrieval) {
+                                         const bool keep_bugreport_on_retrieval,
+                                         const bool skip_user_consent) {
     Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
-                                                    keep_bugreport_on_retrieval);
+                                                    keep_bugreport_on_retrieval,
+                                                    skip_user_consent);
     HandleRunStatus(status);
     return status;
 }
 
 Dumpstate::RunStatus  Dumpstate::RetrieveInternal(int32_t calling_uid,
                                                   const std::string& calling_package,
-                                                  const bool keep_bugreport_on_retrieval) {
-  consent_callback_ = new ConsentCallback();
-  const String16 incidentcompanion("incidentcompanion");
-  sp<android::IBinder> ics(
-      defaultServiceManager()->checkService(incidentcompanion));
-  android::String16 package(calling_package.c_str());
-  if (ics != nullptr) {
-    MYLOGD("Checking user consent via incidentcompanion service\n");
-    android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
-        calling_uid, package, String16(), String16(),
-        0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
-  } else {
-    MYLOGD(
-        "Unable to check user consent; incidentcompanion service unavailable\n");
-    return RunStatus::USER_CONSENT_TIMED_OUT;
-  }
-  UserConsentResult consent_result = consent_callback_->getResult();
-  int timeout_ms = 30 * 1000;
-  while (consent_result == UserConsentResult::UNAVAILABLE &&
-      consent_callback_->getElapsedTimeMs() < timeout_ms) {
-    sleep(1);
-    consent_result = consent_callback_->getResult();
-  }
-  if (consent_result == UserConsentResult::DENIED) {
-    return RunStatus::USER_CONSENT_DENIED;
-  }
-  if (consent_result == UserConsentResult::UNAVAILABLE) {
-    MYLOGD("Canceling user consent request via incidentcompanion service\n");
-    android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
-        consent_callback_.get());
-    return RunStatus::USER_CONSENT_TIMED_OUT;
+                                                  const bool keep_bugreport_on_retrieval,
+                                                  const bool skip_user_consent) {
+  if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
+      consent_callback_ = new ConsentCallback();
+      const String16 incidentcompanion("incidentcompanion");
+      sp<android::IBinder> ics(
+          defaultServiceManager()->checkService(incidentcompanion));
+      android::String16 package(calling_package.c_str());
+      if (ics != nullptr) {
+        MYLOGD("Checking user consent via incidentcompanion service\n");
+
+        android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
+            calling_uid, package, String16(), String16(),
+            0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
+      } else {
+        MYLOGD(
+            "Unable to check user consent; incidentcompanion service unavailable\n");
+        return RunStatus::USER_CONSENT_TIMED_OUT;
+      }
+      UserConsentResult consent_result = consent_callback_->getResult();
+      int timeout_ms = 30 * 1000;
+      while (consent_result == UserConsentResult::UNAVAILABLE &&
+          consent_callback_->getElapsedTimeMs() < timeout_ms) {
+        sleep(1);
+        consent_result = consent_callback_->getResult();
+      }
+      if (consent_result == UserConsentResult::DENIED) {
+        return RunStatus::USER_CONSENT_DENIED;
+      }
+      if (consent_result == UserConsentResult::UNAVAILABLE) {
+        MYLOGD("Canceling user consent request via incidentcompanion service\n");
+        android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
+            consent_callback_.get());
+        return RunStatus::USER_CONSENT_TIMED_OUT;
+      }
   }
 
   bool copy_succeeded =
@@ -3510,7 +3518,9 @@
 
 void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
     if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
-        !CalledByApi() || options_->is_consent_deferred) {
+        !CalledByApi() || options_->is_consent_deferred ||
+        (android::app::admin::flags::onboarding_consentless_bugreports() &&
+        options_->skip_user_consent)) {
         // No need to get consent for shell triggered dumpstates, or not
         // through bugreporting API (i.e. no fd to copy back), or when consent
         // is deferred.
@@ -3596,7 +3606,8 @@
     // If the caller has asked to copy the bugreport over to their directory, we need explicit
     // user consent (unless the caller is Shell).
     UserConsentResult consent_result;
-    if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
+    if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
+    && android::app::admin::flags::onboarding_consentless_bugreports())) {
         consent_result = UserConsentResult::APPROVED;
     } else {
         consent_result = consent_callback_->getResult();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 46d949e..fcb8cf3 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -364,7 +364,7 @@
      * Initialize() dumpstate before calling this method.
      */
     RunStatus Retrieve(int32_t calling_uid, const std::string& calling_package,
-                        const bool keep_bugreport_on_retrieval);
+                        const bool keep_bugreport_on_retrieval, const bool skip_user_consent);
 
 
 
@@ -412,6 +412,7 @@
         bool do_screenshot = false;
         bool is_screenshot_copied = false;
         bool is_consent_deferred = false;
+        bool skip_user_consent = false;
         bool is_remote_mode = false;
         bool show_header_only = false;
         bool telephony_only = false;
@@ -448,7 +449,8 @@
         void Initialize(BugreportMode bugreport_mode, int bugreport_flags,
                         const android::base::unique_fd& bugreport_fd,
                         const android::base::unique_fd& screenshot_fd,
-                        bool is_screenshot_requested);
+                        bool is_screenshot_requested,
+                        bool skip_user_consent);
 
         /* Returns true if the options set so far are consistent. */
         bool ValidateOptions() const;
@@ -564,7 +566,8 @@
   private:
     RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package);
     RunStatus RetrieveInternal(int32_t calling_uid, const std::string& calling_package,
-                                const bool keep_bugreport_on_retrieval);
+                                const bool keep_bugreport_on_retrieval,
+                                const bool skip_user_consent);
 
     RunStatus DumpstateDefaultAfterCritical();
     RunStatus dumpstate();
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index ccf64fe..a29923a 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -507,7 +507,7 @@
         ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
                                   std::move(screenshot_fd),
                                   Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener,
-                                  true);
+                                  true, false);
     // startBugreport is an async call. Verify binder call succeeded first, then wait till listener
     // gets expected callbacks.
     EXPECT_TRUE(status.isOk());
@@ -545,7 +545,7 @@
     android::binder::Status status =
         ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
                                   std::move(screenshot_fd), 2000,  // invalid bugreport mode
-                                  flags, listener, false);
+                                  flags, listener, false, false);
     EXPECT_EQ(listener->getErrorCode(), IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
 
     // The service should have died, freeing itself up for a new invocation.
@@ -579,7 +579,7 @@
         ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
                                   std::move(screenshot_fd),
                                   Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener1,
-                                  true);
+                                  true, false);
     EXPECT_TRUE(status.isOk());
 
     // try to make another call to startBugreport. This should fail.
@@ -587,7 +587,7 @@
     status = ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd2),
                                         std::move(screenshot_fd2),
                                        Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags,
-                                       listener2, true);
+                                       listener2, true, false);
     EXPECT_FALSE(status.isOk());
     WaitTillExecutionComplete(listener2.get());
     EXPECT_EQ(listener2->getErrorCode(),
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2afabed..18c2f94 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -239,7 +239,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeFullBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false);
     EXPECT_TRUE(options_.do_screenshot);
 
     // Other options retain default values
@@ -253,7 +253,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true, false);
     EXPECT_TRUE(options_.do_progress_updates);
     EXPECT_TRUE(options_.do_screenshot);
 
@@ -267,7 +267,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false, false);
     EXPECT_TRUE(options_.is_remote_mode);
     EXPECT_FALSE(options_.do_vibrate);
     EXPECT_FALSE(options_.do_screenshot);
@@ -281,7 +281,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeWearBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true, false);
     EXPECT_TRUE(options_.do_screenshot);
     EXPECT_TRUE(options_.do_progress_updates);
 
@@ -296,7 +296,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false, false);
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_TRUE(options_.telephony_only);
     EXPECT_TRUE(options_.do_progress_updates);
@@ -311,7 +311,7 @@
 }
 
 TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
-    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false);
+    options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false, false);
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_TRUE(options_.wifi_only);
 
@@ -491,12 +491,12 @@
     int flags = Dumpstate::BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA |
                 Dumpstate::BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
     options_.Initialize(
-      Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true);
+      Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true, false);
     EXPECT_TRUE(options_.is_consent_deferred);
     EXPECT_TRUE(options_.use_predumped_ui_data);
 
     options_.Initialize(
-      Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
+      Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false);
     EXPECT_FALSE(options_.is_consent_deferred);
     EXPECT_FALSE(options_.use_predumped_ui_data);
 }
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 54457fc..7a855e1 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "BpBinder"
+#define ATRACE_TAG ATRACE_TAG_AIDL
 //#define LOG_NDEBUG 0
 
 #include <binder/BpBinder.h>
@@ -26,6 +27,12 @@
 
 #include <stdio.h>
 
+#ifndef __TRUSTY__
+#include <cutils/trace.h>
+#else
+#define ATRACE_INT(...)
+#endif
+
 #include "BuildFlags.h"
 #include "file.h"
 
@@ -209,6 +216,7 @@
         sTrackingMap[trackedUid]++;
     }
     uint32_t numProxies = sBinderProxyCount.fetch_add(1, std::memory_order_relaxed);
+    ATRACE_INT("binder_proxies", numProxies);
     uint32_t numLastWarned = sBinderProxyCountWarned.load(std::memory_order_relaxed);
     uint32_t numNextWarn = numLastWarned + kBinderProxyCountWarnInterval;
     if (numProxies >= numNextWarn) {
@@ -632,8 +640,8 @@
             }
         }
     }
-    --sBinderProxyCount;
-
+    [[maybe_unused]] uint32_t numProxies = --sBinderProxyCount;
+    ATRACE_INT("binder_proxies", numProxies);
     if (ipc) {
         ipc->expungeHandle(binderHandle(), this);
         ipc->decWeakHandle(binderHandle());
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7aaaebb..0a85cf8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1280,18 +1280,22 @@
 }
 // ---------------------------------------------------------------------------
 
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool isSecure,
-                                                 const std::string& uniqueId,
-                                                 float requestedRefreshRate) {
+sp<IBinder> SurfaceComposerClient::createVirtualDisplay(const std::string& displayName,
+                                                        bool isSecure, const std::string& uniqueId,
+                                                        float requestedRefreshRate) {
     sp<IBinder> display = nullptr;
-    binder::Status status = ComposerServiceAIDL::getComposerService()
-                                    ->createDisplay(std::string(displayName.c_str()), isSecure,
-                                                    uniqueId, requestedRefreshRate, &display);
+    binder::Status status =
+            ComposerServiceAIDL::getComposerService()->createVirtualDisplay(displayName, isSecure,
+                                                                            uniqueId,
+                                                                            requestedRefreshRate,
+                                                                            &display);
     return status.isOk() ? display : nullptr;
 }
 
-void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
-    ComposerServiceAIDL::getComposerService()->destroyDisplay(display);
+status_t SurfaceComposerClient::destroyVirtualDisplay(const sp<IBinder>& displayToken) {
+    return ComposerServiceAIDL::getComposerService()
+            ->destroyVirtualDisplay(displayToken)
+            .transactionError();
 }
 
 std::vector<PhysicalDisplayId> SurfaceComposerClient::getPhysicalDisplayIds() {
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index c6e7197..11ccc9c 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -105,14 +105,14 @@
      *
      * requires ACCESS_SURFACE_FLINGER permission.
      */
-    @nullable IBinder createDisplay(@utf8InCpp String displayName, boolean isSecure,
+    @nullable IBinder createVirtualDisplay(@utf8InCpp String displayName, boolean isSecure,
             @utf8InCpp String uniqueId, float requestedRefreshRate);
 
     /**
      * Destroy a virtual display.
      * requires ACCESS_SURFACE_FLINGER permission.
      */
-    void destroyDisplay(IBinder display);
+    void destroyVirtualDisplay(IBinder displayToken);
 
     /**
      * Get stable IDs for connected physical displays.
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 738c73a..eb4a802 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -130,8 +130,8 @@
         CREATE_CONNECTION,               // Deprecated. Autogenerated by .aidl now.
         GET_STATIC_DISPLAY_INFO,         // Deprecated. Autogenerated by .aidl now.
         CREATE_DISPLAY_EVENT_CONNECTION, // Deprecated. Autogenerated by .aidl now.
-        CREATE_DISPLAY,                  // Deprecated. Autogenerated by .aidl now.
-        DESTROY_DISPLAY,                 // Deprecated. Autogenerated by .aidl now.
+        CREATE_VIRTUAL_DISPLAY,          // Deprecated. Autogenerated by .aidl now.
+        DESTROY_VIRTUAL_DISPLAY,         // Deprecated. Autogenerated by .aidl now.
         GET_PHYSICAL_DISPLAY_TOKEN,      // Deprecated. Autogenerated by .aidl now.
         SET_TRANSACTION_STATE,
         AUTHENTICATE_SURFACE,           // Deprecated. Autogenerated by .aidl now.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index ebdf232..ca7acf9 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -279,9 +279,6 @@
             layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged |
             layer_state_t::eLayerStackChanged;
 
-    // Changes requiring a composition pass.
-    static constexpr uint64_t REQUIRES_COMPOSITION = layer_state_t::CONTENT_DIRTY;
-
     // Changes that affect the visible region on a display.
     static constexpr uint64_t VISIBLE_REGION_CHANGES = layer_state_t::GEOMETRY_CHANGES |
             layer_state_t::HIERARCHY_CHANGES | layer_state_t::eAlphaChanged;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 987efe0..e2307ed 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -376,11 +376,11 @@
     sp<SurfaceControl> mirrorDisplay(DisplayId displayId);
 
     static const std::string kEmpty;
-    static sp<IBinder> createDisplay(const String8& displayName, bool isSecure,
-                                     const std::string& uniqueId = kEmpty,
-                                     float requestedRefreshRate = 0);
+    static sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure,
+                                            const std::string& uniqueId = kEmpty,
+                                            float requestedRefreshRate = 0);
 
-    static void destroyDisplay(const sp<IBinder>& display);
+    static status_t destroyVirtualDisplay(const sp<IBinder>& displayToken);
 
     static std::vector<PhysicalDisplayId> getPhysicalDisplayIds();
 
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 45e3390..7d0b512 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -1184,9 +1184,8 @@
     MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); }
 
     void TearDown() override {
-        for (auto& token : mVirtualDisplays) {
-            SurfaceComposerClient::destroyDisplay(token);
-        }
+        std::for_each(mVirtualDisplays.begin(), mVirtualDisplays.end(),
+                      SurfaceComposerClient::destroyVirtualDisplay);
         InputSurfacesTest::TearDown();
     }
 
@@ -1201,7 +1200,7 @@
 
         std::string name = "VirtualDisplay";
         name += std::to_string(mVirtualDisplays.size());
-        sp<IBinder> token = SurfaceComposerClient::createDisplay(String8(name.c_str()), isSecure);
+        sp<IBinder> token = SurfaceComposerClient::createVirtualDisplay(name, isSecure);
         SurfaceComposerClient::Transaction t;
         t.setDisplaySurface(token, producer);
         t.setDisplayFlags(token, receivesInput ? 0x01 /* DisplayDevice::eReceivesInput */ : 0);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index eee4fb9..6c6a849 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -673,13 +673,14 @@
         return binder::Status::ok();
     }
 
-    binder::Status createDisplay(const std::string& /*displayName*/, bool /*isSecure*/,
-                                 const std::string& /*uniqueId*/, float /*requestedRefreshRate*/,
-                                 sp<IBinder>* /*outDisplay*/) override {
+    binder::Status createVirtualDisplay(const std::string& /*displayName*/, bool /*isSecure*/,
+                                        const std::string& /*uniqueId*/,
+                                        float /*requestedRefreshRate*/,
+                                        sp<IBinder>* /*outDisplay*/) override {
         return binder::Status::ok();
     }
 
-    binder::Status destroyDisplay(const sp<IBinder>& /*display*/) override {
+    binder::Status destroyVirtualDisplay(const sp<IBinder>& /*displayToken*/) override {
         return binder::Status::ok();
     }
 
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 6cf5a7e..889ee09 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -106,15 +106,15 @@
 
     // The associations between input ports and display ports.
     // Used to determine which DisplayViewport should be tied to which InputDevice.
-    std::unordered_map<std::string, uint8_t> portAssociations;
+    std::unordered_map<std::string, uint8_t> inputPortToDisplayPortAssociations;
 
     // The associations between input device ports and display unique ids.
     // Used to determine which DisplayViewport should be tied to which InputDevice.
-    std::unordered_map<std::string, std::string> uniqueIdAssociationsByPort;
+    std::unordered_map<std::string, std::string> inputPortToDisplayUniqueIdAssociations;
 
     // The associations between input device descriptor and display unique ids.
     // Used to determine which DisplayViewport should be tied to which InputDevice.
-    std::unordered_map<std::string, std::string> uniqueIdAssociationsByDescriptor;
+    std::unordered_map<std::string, std::string> inputDeviceDescriptorToDisplayUniqueIdAssociations;
 
     // The associations between input device ports device types.
     // This is used to determine which device type and source should be tied to which InputDevice.
@@ -310,9 +310,6 @@
     /* Called by the heartbeat to ensures that the reader has not deadlocked. */
     virtual void monitor() = 0;
 
-    /* Returns true if the input device is enabled. */
-    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
-
     /* Makes the reader start processing events from the kernel. */
     virtual status_t start() = 0;
 
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 956484c..b807b27 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -281,14 +281,14 @@
             const std::string& inputDeviceDescriptor = mIdentifier.descriptor;
             if (!inputDeviceDescriptor.empty()) {
                 const std::unordered_map<std::string, uint8_t>& ports =
-                        readerConfig.portAssociations;
+                        readerConfig.inputPortToDisplayPortAssociations;
                 const auto& displayPort = ports.find(inputDeviceDescriptor);
                 if (displayPort != ports.end()) {
                     mAssociatedDisplayPort = std::make_optional(displayPort->second);
                 } else {
                     const std::unordered_map<std::string, std::string>&
                             displayUniqueIdsByDescriptor =
-                                    readerConfig.uniqueIdAssociationsByDescriptor;
+                                    readerConfig.inputDeviceDescriptorToDisplayUniqueIdAssociations;
                     const auto& displayUniqueIdByDescriptor =
                             displayUniqueIdsByDescriptor.find(inputDeviceDescriptor);
                     if (displayUniqueIdByDescriptor != displayUniqueIdsByDescriptor.end()) {
@@ -301,13 +301,13 @@
             const std::string& inputPort = mIdentifier.location;
             if (!inputPort.empty()) {
                 const std::unordered_map<std::string, uint8_t>& ports =
-                        readerConfig.portAssociations;
+                        readerConfig.inputPortToDisplayPortAssociations;
                 const auto& displayPort = ports.find(inputPort);
                 if (displayPort != ports.end()) {
                     mAssociatedDisplayPort = std::make_optional(displayPort->second);
                 } else {
                     const std::unordered_map<std::string, std::string>& displayUniqueIdsByPort =
-                            readerConfig.uniqueIdAssociationsByPort;
+                            readerConfig.inputPortToDisplayUniqueIdAssociations;
                     const auto& displayUniqueIdByPort = displayUniqueIdsByPort.find(inputPort);
                     if (displayUniqueIdByPort != displayUniqueIdsByPort.end()) {
                         mAssociatedDisplayUniqueIdByPort = displayUniqueIdByPort->second;
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 69555f8..b9523ef 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -874,17 +874,6 @@
     return std::nullopt;
 }
 
-bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
-    std::scoped_lock _l(mLock);
-
-    InputDevice* device = findInputDeviceLocked(deviceId);
-    if (device) {
-        return device->isEnabled();
-    }
-    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
-    return false;
-}
-
 bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) {
     std::scoped_lock _l(mLock);
 
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 92a778a..7e701c5 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -61,8 +61,6 @@
 
     std::vector<InputDeviceInfo> getInputDevices() const override;
 
-    bool isInputDeviceEnabled(int32_t deviceId) override;
-
     int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) override;
     int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) override;
     int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) override;
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 088c7df..d2cb0ac 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -129,7 +129,7 @@
 
 void FakeInputReaderPolicy::addInputPortAssociation(const std::string& inputPort,
                                                     uint8_t displayPort) {
-    mConfig.portAssociations.insert({inputPort, displayPort});
+    mConfig.inputPortToDisplayPortAssociations.insert({inputPort, displayPort});
 }
 
 void FakeInputReaderPolicy::addDeviceTypeAssociation(const std::string& inputPort,
@@ -139,7 +139,7 @@
 
 void FakeInputReaderPolicy::addInputUniqueIdAssociation(const std::string& inputUniqueId,
                                                         const std::string& displayUniqueId) {
-    mConfig.uniqueIdAssociationsByPort.insert({inputUniqueId, displayUniqueId});
+    mConfig.inputPortToDisplayUniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
 }
 
 void FakeInputReaderPolicy::addKeyboardLayoutAssociation(const std::string& inputUniqueId,
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8ad235f..8de28c6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -7814,6 +7814,7 @@
  * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
  */
 TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
+    SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index a19726a..7d26a43 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -55,8 +55,6 @@
 
     void monitor() { reader->monitor(); }
 
-    bool isInputDeviceEnabled(int32_t deviceId) { return reader->isInputDeviceEnabled(deviceId); }
-
     status_t start() { return reader->start(); }
 
     status_t stop() { return reader->stop(); }
@@ -206,7 +204,6 @@
                 },
                 [&]() -> void { reader->monitor(); },
                 [&]() -> void { reader->getInputDevices(); },
-                [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); },
                 [&]() -> void {
                     reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(),
                                              fdp->ConsumeIntegral<uint32_t>(),
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index f62562c..9c4d1ac 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -429,14 +429,18 @@
 }
 
 void SensorDevice::onDynamicSensorsDisconnected(
-        const std::vector<int32_t>& dynamicSensorHandlesRemoved) {
-    if (sensorservice_flags::sensor_device_on_dynamic_sensor_disconnected()) {
-        for (auto handle : dynamicSensorHandlesRemoved) {
-            auto it = mConnectedDynamicSensors.find(handle);
-            if (it != mConnectedDynamicSensors.end()) {
-                mConnectedDynamicSensors.erase(it);
-            }
-        }
+        const std::vector<int32_t>& /*dynamicSensorHandlesRemoved*/) {
+    // This function is currently a no-op has removing data in mConnectedDynamicSensors here will
+    // cause a race condition between when this callback is invoked and when the dynamic sensor meta
+    // event is processed by polling. The clean up should only happen after processing the meta
+    // event. See the call stack of cleanupDisconnectedDynamicSensor.
+}
+
+void SensorDevice::cleanupDisconnectedDynamicSensor(int handle) {
+    std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
+    auto it = mConnectedDynamicSensors.find(handle);
+    if (it != mConnectedDynamicSensors.end()) {
+        mConnectedDynamicSensors.erase(it);
     }
 }
 
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 52f7cf2..b7b04b5 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -63,6 +63,14 @@
     std::vector<int32_t> getDynamicSensorHandles();
 
     void handleDynamicSensorConnection(int handle, bool connected);
+    /**
+     * Removes handle from connected dynamic sensor list. Note that this method must be called after
+     * SensorService has done using sensor data.
+     *
+     * @param handle of the disconnected dynamic sensor.
+     */
+    void cleanupDisconnectedDynamicSensor(int handle);
+
     status_t initCheck() const;
     int getHalDeviceVersion() const;
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 69e4309..70ca702 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1273,6 +1273,7 @@
                 } else {
                     int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
                     disconnectDynamicSensor(handle, activeConnections);
+                    device.cleanupDisconnectedDynamicSensor(handle);
                 }
             }
         }
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/senserservice_flags.aconfig
index f20b213..5b499a8 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/senserservice_flags.aconfig
@@ -21,3 +21,10 @@
   description: "This flag controls we allow to pass in nullptr as scratch in SensorEventConnection::sendEvents()"
   bug: "339306599"
 }
+
+flag {
+  name: "sensor_service_clear_dynamic_sensor_data_at_the_end"
+  namespace: "sensors"
+  description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition."
+  bug: "329020894"
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index c8e1fbb..2596a25 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -543,12 +543,14 @@
 }
 
 void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
-                                      Fps displayFrameRenderRate, nsecs_t& deadlineDelta) {
+                                      Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
     if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
         // Cannot do any classification for invalid present time.
         mJankType = JankType::Unknown;
         mJankSeverityType = JankSeverityType::Unknown;
-        deadlineDelta = -1;
+        if (outDeadlineDelta) {
+            *outDeadlineDelta = -1;
+        }
         return;
     }
 
@@ -559,7 +561,9 @@
         mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
                                                              : JankType::AppDeadlineMissed;
         mJankSeverityType = JankSeverityType::Unknown;
-        deadlineDelta = -1;
+        if (outDeadlineDelta) {
+            *outDeadlineDelta = -1;
+        }
         return;
     }
 
@@ -568,11 +572,14 @@
         return;
     }
 
-    deadlineDelta = mActuals.endTime - mPredictions.endTime;
     const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
     const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
             ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
             : 0;
+    const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
+    if (outDeadlineDelta) {
+        *outDeadlineDelta = deadlineDelta;
+    }
 
     if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
         mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
@@ -671,7 +678,7 @@
     mActuals.presentTime = presentTime;
     nsecs_t deadlineDelta = 0;
 
-    classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, deadlineDelta);
+    classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
 
     if (mPredictionState != PredictionState::None) {
         // Only update janky frames if the app used vsync predictions
@@ -686,8 +693,7 @@
 
     mDisplayFrameRenderRate = displayFrameRenderRate;
     mActuals.presentTime = mPredictions.presentTime;
-    nsecs_t deadlineDelta = 0;
-    classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, deadlineDelta);
+    classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
 }
 
 void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 21bc95a..94cfcb4 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -237,7 +237,7 @@
     void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
     void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
     void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
-                            Fps displayFrameRenderRate, nsecs_t& deadlineDelta) REQUIRES(mMutex);
+                            Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) REQUIRES(mMutex);
 
     const int64_t mToken;
     const int32_t mInputEventId;
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 52f8bea..4b0618e 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -41,8 +41,7 @@
         return;
     }
 
-    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy |
-            RequestedLayerState::Changes::RequiresComposition;
+    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
     for (auto& newLayer : newLayers) {
         RequestedLayerState& layer = *newLayer.get();
         auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
@@ -105,8 +104,7 @@
         if (!layer.canBeDestroyed()) {
             continue;
         }
-        layer.changes |= RequestedLayerState::Changes::Destroyed |
-                RequestedLayerState::Changes::RequiresComposition;
+        layer.changes |= RequestedLayerState::Changes::Destroyed;
         layersToBeDestroyed.emplace_back(layerId);
     }
 
@@ -114,8 +112,7 @@
         return;
     }
 
-    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy |
-            RequestedLayerState::Changes::RequiresComposition;
+    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
     for (size_t i = 0; i < layersToBeDestroyed.size(); i++) {
         uint32_t layerId = layersToBeDestroyed[i];
         auto it = mIdToLayer.find(layerId);
@@ -145,8 +142,7 @@
             if (linkedLayer->parentId == layer.id) {
                 linkedLayer->parentId = UNASSIGNED_LAYER_ID;
                 if (linkedLayer->canBeDestroyed()) {
-                    linkedLayer->changes |= RequestedLayerState::Changes::Destroyed |
-                            RequestedLayerState::Changes::RequiresComposition;
+                    linkedLayer->changes |= RequestedLayerState::Changes::Destroyed;
                     layersToBeDestroyed.emplace_back(linkedLayer->id);
                 }
             }
@@ -253,8 +249,7 @@
                             layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged;
                     bgColorLayer->changes |= RequestedLayerState::Changes::Content;
                     mChangedLayers.push_back(bgColorLayer);
-                    mGlobalChanges |= RequestedLayerState::Changes::Content |
-                            RequestedLayerState::Changes::RequiresComposition;
+                    mGlobalChanges |= RequestedLayerState::Changes::Content;
                 }
             }
 
@@ -412,8 +407,7 @@
     layer.relativeParentId = unlinkLayer(layer.relativeParentId, layer.id);
     layer.changes |=
             RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::RelativeParent;
-    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy |
-            RequestedLayerState::Changes::RequiresComposition;
+    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
 }
 
 // Some layers mirror the entire display stack. Since we don't have a single root layer per display
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index f5e5b02..5631fac 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -58,8 +58,7 @@
         parentId(args.parentId),
         layerIdToMirror(args.layerIdToMirror) {
     layerId = static_cast<int32_t>(args.sequence);
-    changes |= RequestedLayerState::Changes::Created |
-            RequestedLayerState::Changes::RequiresComposition;
+    changes |= RequestedLayerState::Changes::Created;
     metadata.merge(args.metadata);
     changes |= RequestedLayerState::Changes::Metadata;
     handleAlive = true;
@@ -249,8 +248,7 @@
 
     if (hadSomethingToDraw != hasSomethingToDraw()) {
         changes |= RequestedLayerState::Changes::Visibility |
-                RequestedLayerState::Changes::VisibleRegion |
-                RequestedLayerState::Changes::RequiresComposition;
+                RequestedLayerState::Changes::VisibleRegion;
     }
     if (clientChanges & layer_state_t::HIERARCHY_CHANGES)
         changes |= RequestedLayerState::Changes::Hierarchy;
@@ -260,8 +258,6 @@
         changes |= RequestedLayerState::Changes::Geometry;
     if (clientChanges & layer_state_t::AFFECTS_CHILDREN)
         changes |= RequestedLayerState::Changes::AffectsChildren;
-    if (clientChanges & layer_state_t::REQUIRES_COMPOSITION)
-        changes |= RequestedLayerState::Changes::RequiresComposition;
     if (clientChanges & layer_state_t::INPUT_CHANGES)
         changes |= RequestedLayerState::Changes::Input;
     if (clientChanges & layer_state_t::VISIBLE_REGION_CHANGES)
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 4829d4c..48b9640 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -26,6 +26,7 @@
 #include "TransactionState.h"
 
 namespace android::surfaceflinger::frontend {
+using namespace ftl::flag_operators;
 
 // Stores client requested states for a layer.
 // This struct does not store any other states or states pertaining to
@@ -57,8 +58,14 @@
         BufferSize = 1u << 18,
         GameMode = 1u << 19,
         BufferUsageFlags = 1u << 20,
-        RequiresComposition = 1u << 21,
     };
+
+    static constexpr ftl::Flags<Changes> kMustComposite = Changes::Created | Changes::Destroyed |
+            Changes::Hierarchy | Changes::Geometry | Changes::Content | Changes::Input |
+            Changes::Z | Changes::Mirror | Changes::Parent | Changes::RelativeParent |
+            Changes::Metadata | Changes::Visibility | Changes::VisibleRegion | Changes::Buffer |
+            Changes::SidebandStream | Changes::Animation | Changes::BufferSize | Changes::GameMode |
+            Changes::BufferUsageFlags;
     static Rect reduce(const Rect& win, const Region& exclude);
     RequestedLayerState(const LayerCreationArgs&);
     void merge(const ResolvedComposerState&);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index f72e7a0..60681a2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -1153,8 +1153,10 @@
         return pacesetterFps;
     }();
 
+    // Choose a mode for powered-on follower displays.
     for (const auto& [id, display] : mDisplays) {
         if (id == *mPacesetterDisplayId) continue;
+        if (display.powerMode != hal::PowerMode::ON) continue;
 
         auto rankedFrameRates =
                 display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 28d8018..b2ca572 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -56,6 +56,7 @@
 #include <configstore/Utils.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
+#include <fmt/format.h>
 #include <ftl/algorithm.h>
 #include <ftl/concat.h>
 #include <ftl/fake_guard.h>
@@ -573,8 +574,9 @@
     mScheduler->run();
 }
 
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool isSecure,
-                                          const std::string& uniqueId, float requestedRefreshRate) {
+sp<IBinder> SurfaceFlinger::createVirtualDisplay(const std::string& displayName, bool isSecure,
+                                                 const std::string& uniqueId,
+                                                 float requestedRefreshRate) {
     // SurfaceComposerAIDL checks for some permissions, but adding an additional check here.
     // This is to ensure that only root, system, and graphics can request to create a secure
     // display. Secure displays can show secure content so we add an additional restriction on it.
@@ -614,22 +616,23 @@
     return token;
 }
 
-void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) {
+status_t SurfaceFlinger::destroyVirtualDisplay(const sp<IBinder>& displayToken) {
     Mutex::Autolock lock(mStateLock);
 
     const ssize_t index = mCurrentState.displays.indexOfKey(displayToken);
     if (index < 0) {
         ALOGE("%s: Invalid display token %p", __func__, displayToken.get());
-        return;
+        return NAME_NOT_FOUND;
     }
 
     const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
     if (state.physical) {
         ALOGE("%s: Invalid operation on physical display", __func__);
-        return;
+        return INVALID_OPERATION;
     }
     mCurrentState.displays.removeItemsAt(index);
     setTransactionFlags(eDisplayTransactionNeeded);
+    return NO_ERROR;
 }
 
 void SurfaceFlinger::enableHalVirtualDisplays(bool enable) {
@@ -1426,11 +1429,6 @@
             continue;
         }
 
-        if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
-            dropModeRequest(display);
-            continue;
-        }
-
         const auto desiredModeId = desiredModeOpt->mode.modePtr->getId();
         const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId);
 
@@ -2447,8 +2445,8 @@
     }
     outTransactionsAreEmpty = mLayerLifecycleManager.getGlobalChanges().get() == 0;
     if (FlagManager::getInstance().vrr_bugfix_24q4()) {
-        mustComposite |= mLayerLifecycleManager.getGlobalChanges().test(
-                frontend::RequestedLayerState::Changes::RequiresComposition);
+        mustComposite |= mLayerLifecycleManager.getGlobalChanges().any(
+                frontend::RequestedLayerState::kMustComposite);
     } else {
         mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
     }
@@ -4240,12 +4238,6 @@
 
         if (!display) continue;
 
-        if (ftl::FakeGuard guard(kMainThreadContext);
-            !shouldApplyRefreshRateSelectorPolicy(*display)) {
-            ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
-            continue;
-        }
-
         if (display->refreshRateSelector().isModeAllowed(request.mode)) {
             setDesiredMode(std::move(request));
         } else {
@@ -6549,18 +6541,19 @@
     StringAppendF(&result, "DisplayColorSetting: %s\n",
                   decodeDisplayColorSetting(mDisplayColorSetting).c_str());
 
-    // TODO: print out if wide-color mode is active or not
+    // TODO: print out if wide-color mode is active or not.
 
     for (const auto& [id, display] : mPhysicalDisplays) {
         StringAppendF(&result, "Display %s color modes:\n", to_string(id).c_str());
         for (const auto mode : display.snapshot().colorModes()) {
-            StringAppendF(&result, "    %s (%d)\n", decodeColorMode(mode).c_str(), mode);
+            StringAppendF(&result, "    %s (%d)\n", decodeColorMode(mode).c_str(),
+                          fmt::underlying(mode));
         }
 
         if (const auto display = getDisplayDeviceLocked(id)) {
             ui::ColorMode currentMode = display->getCompositionDisplay()->getState().colorMode;
             StringAppendF(&result, "    Current color mode: %s (%d)\n",
-                          decodeColorMode(currentMode).c_str(), currentMode);
+                          decodeColorMode(currentMode).c_str(), fmt::underlying(currentMode));
         }
     }
     result.append("\n");
@@ -7017,8 +7010,8 @@
         // Used by apps to hook Choreographer to SurfaceFlinger.
         case CREATE_DISPLAY_EVENT_CONNECTION:
         case CREATE_CONNECTION:
-        case CREATE_DISPLAY:
-        case DESTROY_DISPLAY:
+        case CREATE_VIRTUAL_DISPLAY:
+        case DESTROY_VIRTUAL_DISPLAY:
         case GET_PRIMARY_PHYSICAL_DISPLAY_ID:
         case GET_PHYSICAL_DISPLAY_IDS:
         case GET_PHYSICAL_DISPLAY_TOKEN:
@@ -8575,35 +8568,11 @@
             break;
     }
 
-    if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
-        ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
-        return NO_ERROR;
-    }
-
     return applyRefreshRateSelectorPolicy(displayId, selector);
 }
 
-bool SurfaceFlinger::shouldApplyRefreshRateSelectorPolicy(const DisplayDevice& display) const {
-    if (display.isPoweredOn() || mPhysicalDisplays.size() == 1) return true;
-
-    LOG_ALWAYS_FATAL_IF(display.isVirtual());
-    const auto displayId = display.getPhysicalId();
-
-    // The display is powered off, and this is a multi-display device. If the display is the
-    // inactive internal display of a dual-display foldable, then the policy will be applied
-    // when it becomes active upon powering on.
-    //
-    // TODO(b/255635711): Remove this function (i.e. returning `false` as a special case) once
-    // concurrent mode setting across multiple (potentially powered off) displays is supported.
-    //
-    return displayId == mActiveDisplayId ||
-            !mPhysicalDisplays.get(displayId)
-                     .transform(&PhysicalDisplay::isInternal)
-                     .value_or(false);
-}
-
 status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(
-        PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector, bool force) {
+        PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector) {
     const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy();
     ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
 
@@ -8634,7 +8603,7 @@
         return INVALID_OPERATION;
     }
 
-    setDesiredMode({std::move(preferredMode), .emitEvent = true, .force = force});
+    setDesiredMode({std::move(preferredMode), .emitEvent = true});
 
     // Update the frameRateOverride list as the display render rate might have changed
     if (mScheduler->updateFrameRateOverrides(scheduler::GlobalSignals{}, preferredFps)) {
@@ -8992,13 +8961,8 @@
                                                   const DisplayDevice& activeDisplay) {
     ATRACE_CALL();
 
-    // For the first display activated during boot, there is no need to force setDesiredMode,
-    // because DM is about to send its policy via setDesiredDisplayModeSpecs.
-    bool forceApplyPolicy = false;
-
     if (inactiveDisplayPtr) {
         inactiveDisplayPtr->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(false);
-        forceApplyPolicy = true;
     }
 
     mActiveDisplayId = activeDisplay.getPhysicalId();
@@ -9015,12 +8979,11 @@
     mActiveDisplayTransformHint = activeDisplay.getTransformHint();
     sActiveDisplayRotationFlags = ui::Transform::toRotationFlags(activeDisplay.getOrientation());
 
-    // The policy of the new active/pacesetter display may have changed while it was inactive. In
-    // that case, its preferred mode has not been propagated to HWC (via setDesiredMode). In either
-    // case, the Scheduler's cachedModeChangedParams must be initialized to the newly active mode,
-    // and the kernel idle timer of the newly active display must be toggled.
-    applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector(),
-                                   forceApplyPolicy);
+    // Whether or not the policy of the new active/pacesetter display changed while it was inactive
+    // (in which case its preferred mode has already been propagated to HWC via setDesiredMode), the
+    // Scheduler's cachedModeChangedParams must be initialized to the newly active mode, and the
+    // kernel idle timer of the newly active display must be toggled.
+    applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector());
 }
 
 status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener,
@@ -9573,26 +9536,25 @@
     }
 }
 
-binder::Status SurfaceComposerAIDL::createDisplay(const std::string& displayName, bool isSecure,
-                                                  const std::string& uniqueId,
-                                                  float requestedRefreshRate,
-                                                  sp<IBinder>* outDisplay) {
+binder::Status SurfaceComposerAIDL::createVirtualDisplay(const std::string& displayName,
+                                                         bool isSecure, const std::string& uniqueId,
+                                                         float requestedRefreshRate,
+                                                         sp<IBinder>* outDisplay) {
     status_t status = checkAccessPermission();
     if (status != OK) {
         return binderStatusFromStatusT(status);
     }
-    String8 displayName8 = String8::format("%s", displayName.c_str());
-    *outDisplay = mFlinger->createDisplay(displayName8, isSecure, uniqueId, requestedRefreshRate);
+    *outDisplay =
+            mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId, requestedRefreshRate);
     return binder::Status::ok();
 }
 
-binder::Status SurfaceComposerAIDL::destroyDisplay(const sp<IBinder>& display) {
+binder::Status SurfaceComposerAIDL::destroyVirtualDisplay(const sp<IBinder>& displayToken) {
     status_t status = checkAccessPermission();
     if (status != OK) {
         return binderStatusFromStatusT(status);
     }
-    mFlinger->destroyDisplay(display);
-    return binder::Status::ok();
+    return binder::Status::fromStatusT(mFlinger->destroyVirtualDisplay(displayToken));
 }
 
 binder::Status SurfaceComposerAIDL::getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a198768..d56072a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -547,9 +547,10 @@
     status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
 
     // ISurfaceComposer implementation:
-    sp<IBinder> createDisplay(const String8& displayName, bool isSecure,
-                              const std::string& uniqueId, float requestedRefreshRate = 0.0f);
-    void destroyDisplay(const sp<IBinder>& displayToken);
+    sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure,
+                                     const std::string& uniqueId,
+                                     float requestedRefreshRate = 0.0f);
+    status_t destroyVirtualDisplay(const sp<IBinder>& displayToken);
     std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) {
         Mutex::Autolock lock(mStateLock);
         return getPhysicalDisplayIdsLocked();
@@ -756,13 +757,9 @@
             const sp<DisplayDevice>&, const scheduler::RefreshRateSelector::PolicyVariant&)
             EXCLUDES(mStateLock) REQUIRES(kMainThreadContext);
 
-    bool shouldApplyRefreshRateSelectorPolicy(const DisplayDevice&) const
-            REQUIRES(mStateLock, kMainThreadContext);
-
     // TODO(b/241285191): Look up RefreshRateSelector on Scheduler to remove redundant parameter.
     status_t applyRefreshRateSelectorPolicy(PhysicalDisplayId,
-                                            const scheduler::RefreshRateSelector&,
-                                            bool force = false)
+                                            const scheduler::RefreshRateSelector&)
             REQUIRES(mStateLock, kMainThreadContext);
 
     void commitTransactionsLegacy() EXCLUDES(mStateLock) REQUIRES(kMainThreadContext);
@@ -1570,10 +1567,10 @@
             const sp<IBinder>& layerHandle,
             sp<gui::IDisplayEventConnection>* outConnection) override;
     binder::Status createConnection(sp<gui::ISurfaceComposerClient>* outClient) override;
-    binder::Status createDisplay(const std::string& displayName, bool isSecure,
-                                 const std::string& uniqueId, float requestedRefreshRate,
-                                 sp<IBinder>* outDisplay) override;
-    binder::Status destroyDisplay(const sp<IBinder>& display) override;
+    binder::Status createVirtualDisplay(const std::string& displayName, bool isSecure,
+                                        const std::string& uniqueId, float requestedRefreshRate,
+                                        sp<IBinder>* outDisplay) override;
+    binder::Status destroyVirtualDisplay(const sp<IBinder>& displayToken) override;
     binder::Status getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) override;
     binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override;
     binder::Status setPowerMode(const sp<IBinder>& display, int mode) override;
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index c1ef48e..ebe11fb 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -39,8 +39,8 @@
 using ui::ColorMode;
 
 namespace {
-const String8 DISPLAY_NAME("Credentials Display Test");
-const String8 SURFACE_NAME("Test Surface Name");
+const std::string kDisplayName("Credentials Display Test");
+const String8 kSurfaceName("Test Surface Name");
 } // namespace
 
 /**
@@ -99,7 +99,7 @@
         ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
 
         // Background surface
-        mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(),
+        mBGSurfaceControl = mComposerClient->createSurface(kSurfaceName, mode.resolution.getWidth(),
                                                            mode.resolution.getHeight(),
                                                            PIXEL_FORMAT_RGBA_8888, 0);
         ASSERT_TRUE(mBGSurfaceControl != nullptr);
@@ -232,7 +232,7 @@
 TEST_F(CredentialsTest, CreateDisplayTest) {
     // Only graphics and system processes can create a secure display.
     std::function<bool()> condition = [=]() {
-        sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+        sp<IBinder> testDisplay = SurfaceComposerClient::createVirtualDisplay(kDisplayName, true);
         return testDisplay.get() != nullptr;
     };
 
@@ -267,7 +267,7 @@
     }
 
     condition = [=]() {
-        sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
+        sp<IBinder> testDisplay = SurfaceComposerClient::createVirtualDisplay(kDisplayName, false);
         return testDisplay.get() != nullptr;
     };
     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
index 7fce7e9..56cf13d 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -53,14 +53,15 @@
     }
 
     virtual void TearDown() {
-        SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::destroyVirtualDisplay(mVirtualDisplay));
         LayerTransactionTest::TearDown();
         mColorLayer = 0;
     }
 
     void createDisplay(const ui::Size& layerStackSize, ui::LayerStack layerStack) {
+        static const std::string kDisplayName("VirtualDisplay");
         mVirtualDisplay =
-                SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
+                SurfaceComposerClient::createVirtualDisplay(kDisplayName, false /*isSecure*/);
         asTransaction([&](Transaction& t) {
             t.setDisplaySurface(mVirtualDisplay, mProducer);
             t.setDisplayLayerStack(mVirtualDisplay, layerStack);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 87e6d3e..af3cb9a 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -66,8 +66,9 @@
                 sp<BufferListener> listener = sp<BufferListener>::make(this);
                 itemConsumer->setFrameAvailableListener(listener);
 
-                vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
-                                                                false /*secure*/);
+                static const std::string kDisplayName("VirtualDisplay");
+                vDisplay = SurfaceComposerClient::createVirtualDisplay(kDisplayName,
+                                                                       false /*isSecure*/);
 
                 constexpr ui::LayerStack layerStack{
                         848472}; // ASCII for TTH (TransactionTestHarnesses)
@@ -107,7 +108,7 @@
                     t.setLayerStack(mirrorSc, ui::INVALID_LAYER_STACK);
                     t.apply(true);
                 }
-                SurfaceComposerClient::destroyDisplay(vDisplay);
+                SurfaceComposerClient::destroyVirtualDisplay(vDisplay);
                 return sc;
         }
     }
diff --git a/services/surfaceflinger/tests/VirtualDisplay_test.cpp b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
index f31f582..cd66dd2 100644
--- a/services/surfaceflinger/tests/VirtualDisplay_test.cpp
+++ b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
@@ -41,14 +41,15 @@
 };
 
 TEST_F(VirtualDisplayTest, VirtualDisplayDestroyedSurfaceReuse) {
+    static const std::string kDisplayName("VirtualDisplay");
     sp<IBinder> virtualDisplay =
-            SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
+            SurfaceComposerClient::createVirtualDisplay(kDisplayName, false /*isSecure*/);
 
     SurfaceComposerClient::Transaction t;
     t.setDisplaySurface(virtualDisplay, mProducer);
     t.apply(true);
 
-    SurfaceComposerClient::destroyDisplay(virtualDisplay);
+    EXPECT_EQ(NO_ERROR, SurfaceComposerClient::destroyVirtualDisplay(virtualDisplay));
     virtualDisplay.clear();
     // Sync here to ensure the display was completely destroyed in SF
     t.apply(true);
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index 158db75..cfc8e99 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -462,8 +462,7 @@
                                                                GRALLOC_USAGE_PROTECTED /*usage*/));
     EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
               ftl::Flags<RequestedLayerState::Changes>(
-                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content)
                       .get());
     mLifecycleManager.commitChanges();
 
@@ -497,8 +496,7 @@
               ftl::Flags<RequestedLayerState::Changes>(
                       RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content |
                       RequestedLayerState::Changes::VisibleRegion |
-                      RequestedLayerState::Changes::Visibility |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::Visibility)
                       .get());
     mLifecycleManager.commitChanges();
 }
@@ -522,8 +520,7 @@
                       RequestedLayerState::Changes::AffectsChildren |
                       RequestedLayerState::Changes::Content |
                       RequestedLayerState::Changes::Geometry |
-                      RequestedLayerState::Changes::VisibleRegion |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::VisibleRegion)
                       .get());
     mLifecycleManager.commitChanges();
 }
@@ -541,8 +538,7 @@
               ftl::Flags<RequestedLayerState::Changes>(
                       RequestedLayerState::Changes::Content |
                       RequestedLayerState::Changes::AffectsChildren |
-                      RequestedLayerState::Changes::VisibleRegion |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::VisibleRegion)
                       .string());
     EXPECT_EQ(mLifecycleManager.getChangedLayers()[0]->color.a, static_cast<half>(startingAlpha));
     mLifecycleManager.commitChanges();
@@ -555,8 +551,7 @@
               ftl::Flags<RequestedLayerState::Changes>(
                       RequestedLayerState::Changes::Content |
                       RequestedLayerState::Changes::AffectsChildren |
-                      RequestedLayerState::Changes::VisibleRegion |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::VisibleRegion)
                       .string());
     EXPECT_EQ(mLifecycleManager.getChangedLayers()[0]->color.a, static_cast<half>(endingAlpha));
     mLifecycleManager.commitChanges();
@@ -586,8 +581,7 @@
                                                             GRALLOC_USAGE_SW_READ_NEVER /*usage*/));
     EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
               ftl::Flags<RequestedLayerState::Changes>(
-                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content |
-                      RequestedLayerState::Changes::RequiresComposition)
+                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content)
                       .get());
     mLifecycleManager.commitChanges();
 
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index ce4d798..23b6851 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -255,8 +255,7 @@
     setColor(11, {1._hf, 0._hf, 0._hf});
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
     EXPECT_EQ(getSnapshot(11)->changes,
-              RequestedLayerState::Changes::Content |
-                      RequestedLayerState::Changes::RequiresComposition);
+              RequestedLayerState::Changes::Content);
     EXPECT_EQ(getSnapshot(11)->clientChanges, layer_state_t::eColorChanged);
     EXPECT_EQ(getSnapshot(1)->changes.get(), 0u);
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
@@ -267,8 +266,7 @@
     setColor(1, {1._hf, 0._hf, 0._hf});
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
     EXPECT_EQ(getSnapshot(1)->changes,
-              RequestedLayerState::Changes::Content |
-                      RequestedLayerState::Changes::RequiresComposition);
+              RequestedLayerState::Changes::Content);
     EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eColorChanged);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 7479a4f..4fb0690 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -350,6 +350,9 @@
                                 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
                                                                       kDisplay2Mode60->getId()));
 
+    mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
+    mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
+
     using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
     TestableScheduler::DisplayModeChoiceMap expectedChoices;
 
@@ -412,6 +415,7 @@
                 ->registerDisplay(kDisplayId3,
                                   std::make_shared<RefreshRateSelector>(kDisplay3Modes,
                                                                         kDisplay3Mode60->getId()));
+        mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
 
         const GlobalSignals globalSignals = {.touch = true};
         mScheduler->replaceTouchTimer(10);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
index 5852b1c..ff7612e 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
@@ -53,7 +53,8 @@
     mFlinger.commitAndComposite();
     EXPECT_COLOR_MATRIX_CHANGED(false, false);
 
-    mFlinger.createDisplay(String8("Test Display"), false);
+    static const std::string kDisplayName("Test Display");
+    mFlinger.createVirtualDisplay(kDisplayName, false /*isSecure=*/);
 
     mFlinger.commit();
     EXPECT_COLOR_MATRIX_CHANGED(false, true);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index bf5ae21..e5f2a91 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -27,7 +27,7 @@
 
 class CreateDisplayTest : public DisplayTransactionTest {
 public:
-    void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId,
+    void createDisplayWithRequestedRefreshRate(const std::string& name, uint64_t displayId,
                                                float pacesetterDisplayRefreshRate,
                                                float requestedRefreshRate,
                                                float expectedAdjustedRefreshRate) {
@@ -37,7 +37,7 @@
         // --------------------------------------------------------------------
         // Invocation
 
-        sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate);
+        sp<IBinder> displayToken = mFlinger.createVirtualDisplay(name, false, requestedRefreshRate);
 
         // --------------------------------------------------------------------
         // Postconditions
@@ -73,7 +73,7 @@
 };
 
 TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
-    const String8 name("virtual.test");
+    static const std::string name("virtual.test");
 
     // --------------------------------------------------------------------
     // Call Expectations
@@ -81,7 +81,7 @@
     // --------------------------------------------------------------------
     // Invocation
 
-    sp<IBinder> displayToken = mFlinger.createDisplay(name, false);
+    sp<IBinder> displayToken = mFlinger.createVirtualDisplay(name, false);
 
     // --------------------------------------------------------------------
     // Postconditions
@@ -101,7 +101,7 @@
 }
 
 TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) {
-    const String8 name("virtual.test");
+    static const std::string kDisplayName("virtual.test");
 
     // --------------------------------------------------------------------
     // Call Expectations
@@ -112,7 +112,7 @@
     // Set the calling identity to graphics so captureDisplay with secure is allowed.
     IPCThreadState::self()->restoreCallingIdentity(static_cast<int64_t>(AID_GRAPHICS) << 32 |
                                                    AID_GRAPHICS);
-    sp<IBinder> displayToken = mFlinger.createDisplay(name, true);
+    sp<IBinder> displayToken = mFlinger.createVirtualDisplay(kDisplayName, true);
     IPCThreadState::self()->restoreCallingIdentity(oldId);
 
     // --------------------------------------------------------------------
@@ -123,7 +123,7 @@
     const auto& display = getCurrentDisplayState(displayToken);
     EXPECT_TRUE(display.isVirtual());
     EXPECT_TRUE(display.isSecure);
-    EXPECT_EQ(name.c_str(), display.displayName);
+    EXPECT_EQ(kDisplayName.c_str(), display.displayName);
 
     // --------------------------------------------------------------------
     // Cleanup conditions
@@ -133,8 +133,8 @@
 }
 
 TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForUniqueId) {
-    const String8 name("virtual.test");
-    const std::string uniqueId = "virtual:package:id";
+    static const std::string kDisplayName("virtual.test");
+    static const std::string kUniqueId = "virtual:package:id";
 
     // --------------------------------------------------------------------
     // Call Expectations
@@ -142,7 +142,7 @@
     // --------------------------------------------------------------------
     // Invocation
 
-    sp<IBinder> displayToken = mFlinger.createDisplay(name, false, uniqueId);
+    sp<IBinder> displayToken = mFlinger.createVirtualDisplay(kDisplayName, false, kUniqueId);
 
     // --------------------------------------------------------------------
     // Postconditions
@@ -153,7 +153,7 @@
     EXPECT_TRUE(display.isVirtual());
     EXPECT_FALSE(display.isSecure);
     EXPECT_EQ(display.uniqueId, "virtual:package:id");
-    EXPECT_EQ(name.c_str(), display.displayName);
+    EXPECT_EQ(kDisplayName.c_str(), display.displayName);
 
     // --------------------------------------------------------------------
     // Cleanup conditions
@@ -164,78 +164,78 @@
 
 // Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 60.f;
-    const float kRequestedRefreshRate = 0.f;
-    const float kExpectedAdjustedRefreshRate = 0.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 60.f;
+    constexpr float kRequestedRefreshRate = 0.f;
+    constexpr float kExpectedAdjustedRefreshRate = 0.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting negative refresh rate, will be ignored, same as requesting 0
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 60.f;
-    const float kRequestedRefreshRate = -60.f;
-    const float kExpectedAdjustedRefreshRate = 0.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 60.f;
+    constexpr float kRequestedRefreshRate = -60.f;
+    constexpr float kExpectedAdjustedRefreshRate = 0.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting a higher refresh rate than the pacesetter
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 60.f;
-    const float kRequestedRefreshRate = 90.f;
-    const float kExpectedAdjustedRefreshRate = 60.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 60.f;
+    constexpr float kRequestedRefreshRate = 90.f;
+    constexpr float kExpectedAdjustedRefreshRate = 60.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting the same refresh rate as the pacesetter
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 60.f;
-    const float kRequestedRefreshRate = 60.f;
-    const float kExpectedAdjustedRefreshRate = 60.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 60.f;
+    constexpr float kRequestedRefreshRate = 60.f;
+    constexpr float kExpectedAdjustedRefreshRate = 60.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting a divisor (30) of the pacesetter (60) should be honored
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 60.f;
-    const float kRequestedRefreshRate = 30.f;
-    const float kExpectedAdjustedRefreshRate = 30.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 60.f;
+    constexpr float kRequestedRefreshRate = 30.f;
+    constexpr float kExpectedAdjustedRefreshRate = 30.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60)
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 120.f;
-    const float kRequestedRefreshRate = 45.f;
-    const float kExpectedAdjustedRefreshRate = 60.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 120.f;
+    constexpr float kRequestedRefreshRate = 45.f;
+    constexpr float kExpectedAdjustedRefreshRate = 60.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
 // Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120)
 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) {
-    const String8 displayName("virtual.test");
-    const uint64_t displayId = 123ull;
-    const float kPacesetterDisplayRefreshRate = 120.f;
-    const float kRequestedRefreshRate = 75.f;
-    const float kExpectedAdjustedRefreshRate = 120.f;
-    createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+    static const std::string kDisplayName("virtual.test");
+    constexpr uint64_t kDisplayId = 123ull;
+    constexpr float kPacesetterDisplayRefreshRate = 120.f;
+    constexpr float kRequestedRefreshRate = 75.f;
+    constexpr float kExpectedAdjustedRefreshRate = 120.f;
+    createDisplayWithRequestedRefreshRate(kDisplayName, kDisplayId, kPacesetterDisplayRefreshRate,
                                           kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
index 93a3811..f8ad8e1 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
@@ -43,18 +43,18 @@
     // --------------------------------------------------------------------
     // Invocation
 
-    mFlinger.destroyDisplay(existing.token());
+    EXPECT_EQ(NO_ERROR, mFlinger.destroyVirtualDisplay(existing.token()));
 
     // --------------------------------------------------------------------
     // Postconditions
 
-    // The display should have been removed from the current state
+    // The display should have been removed from the current state.
     EXPECT_FALSE(hasCurrentDisplayState(existing.token()));
 
-    // Ths display should still exist in the drawing state
+    // Ths display should still exist in the drawing state.
     EXPECT_TRUE(hasDrawingDisplayState(existing.token()));
 
-    // The display transaction needed flasg should be set
+    // The display transaction needed flags should be set.
     EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
 }
 
@@ -67,7 +67,7 @@
     // --------------------------------------------------------------------
     // Invocation
 
-    mFlinger.destroyDisplay(displayToken);
+    EXPECT_EQ(NAME_NOT_FOUND, mFlinger.destroyVirtualDisplay(displayToken));
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 15a6db6..078b4fe 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -327,7 +327,9 @@
         return false;
     }
 
-    if (!flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) {
+    // VsyncModulator should react to mode switches on the pacesetter display.
+    if (arg->getPhysicalId() == flinger->scheduler()->pacesetterDisplayId() &&
+        !flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) {
         *result_listener << "VsyncModulator did not shift to early phase";
         return false;
     }
@@ -368,8 +370,8 @@
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
 
-    // Only the inner display is powered on.
-    mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
+    mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
 
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -385,41 +387,45 @@
                                                                                0.f, 120.f)));
 
     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
+    EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
 
     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
-
-    mFlinger.commit();
-
-    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
-    mFlinger.commit();
-
-    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
-    innerDisplay->setPowerMode(hal::PowerMode::OFF);
-    outerDisplay->setPowerMode(hal::PowerMode::ON);
-
-    // Only the outer display is powered on.
-    mFlinger.onActiveDisplayChanged(innerDisplay.get(), *outerDisplay);
-
-    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
-
     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
 
     mFlinger.commit();
 
-    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
 
     mFlinger.commit();
 
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+    mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
+
+    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+    EXPECT_EQ(NO_ERROR,
+              mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
+                                                  mock::createDisplayModeSpecs(kModeId60, false,
+                                                                               0.f, 120.f)));
+
+    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
+    EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60);
+
+    mFlinger.commit();
+
+    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
+    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+    mFlinger.commit();
+
+    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
+    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
 }
 
 TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) {
@@ -437,10 +443,8 @@
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
 
-    outerDisplay->setPowerMode(hal::PowerMode::ON);
-
-    // Both displays are powered on.
-    mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+    mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
 
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -485,7 +489,7 @@
     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
 
     // Power off the display before the mode has been set.
-    mDisplay->setPowerMode(hal::PowerMode::OFF);
+    mFlinger.setPowerModeInternal(mDisplay, hal::PowerMode::OFF);
 
     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
@@ -517,10 +521,8 @@
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
 
-    outerDisplay->setPowerMode(hal::PowerMode::ON);
-
-    // Both displays are powered on.
-    mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+    mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
 
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -539,40 +541,42 @@
     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
 
     // Power off the outer display before the mode has been set.
-    outerDisplay->setPowerMode(hal::PowerMode::OFF);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
 
     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
-
-    mFlinger.commit();
-
-    // Powering off the inactive display should abort the mode set.
-    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
-    mFlinger.commit();
-
-    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
-    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
-    innerDisplay->setPowerMode(hal::PowerMode::OFF);
-    outerDisplay->setPowerMode(hal::PowerMode::ON);
-
-    // Only the outer display is powered on.
-    mFlinger.onActiveDisplayChanged(innerDisplay.get(), *outerDisplay);
-
     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
 
     mFlinger.commit();
 
-    // The mode set should resume once the display becomes active.
-    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+    // Powering off the inactive display should not abort the mode set.
+    EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
 
     mFlinger.commit();
 
     EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
     EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+    mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
+    mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
+
+    EXPECT_EQ(NO_ERROR,
+              mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
+                                                  mock::createDisplayModeSpecs(kModeId120, false,
+                                                                               0.f, 120.f)));
+
+    EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId120);
+
+    mFlinger.commit();
+
+    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+    EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
+
+    mFlinger.commit();
+
+    EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+    EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
index 4e9fba7..f424133 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
@@ -42,8 +42,8 @@
 }
 
 TEST_F(SurfaceFlingerGetDisplayStatsTest, invalidToken) {
-    const String8 displayName("fakeDisplay");
-    sp<IBinder> displayToken = mFlinger.createDisplay(displayName, false);
+    static const std::string kDisplayName("fakeDisplay");
+    sp<IBinder> displayToken = mFlinger.createVirtualDisplay(kDisplayName, false /*isSecure*/);
     DisplayStatInfo info;
     status_t status = mFlinger.getDisplayStats(displayToken, &info);
     EXPECT_EQ(status, NAME_NOT_FOUND);
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 1e02c67..198a5de 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -111,6 +111,11 @@
         Scheduler::unregisterDisplay(displayId);
     }
 
+    void setDisplayPowerMode(PhysicalDisplayId displayId, hal::PowerMode powerMode) {
+        ftl::FakeGuard guard(kMainThreadContext);
+        Scheduler::setDisplayPowerMode(displayId, powerMode);
+    }
+
     std::optional<PhysicalDisplayId> pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS {
         return mPacesetterDisplayId;
     }
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b251e2c..265f804 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -420,19 +420,21 @@
         commit(kComposite);
     }
 
-    auto createDisplay(const String8& displayName, bool isSecure,
-                       float requestedRefreshRate = 0.0f) {
-        const std::string testId = "virtual:libsurfaceflinger_unittest:TestableSurfaceFlinger";
-        return mFlinger->createDisplay(displayName, isSecure, testId, requestedRefreshRate);
+    auto createVirtualDisplay(const std::string& displayName, bool isSecure,
+                              float requestedRefreshRate = 0.0f) {
+        static const std::string kTestId =
+                "virtual:libsurfaceflinger_unittest:TestableSurfaceFlinger";
+        return mFlinger->createVirtualDisplay(displayName, isSecure, kTestId, requestedRefreshRate);
     }
 
-    auto createDisplay(const String8& displayName, bool isSecure, const std::string& uniqueId,
-                       float requestedRefreshRate = 0.0f) {
-        return mFlinger->createDisplay(displayName, isSecure, uniqueId, requestedRefreshRate);
+    auto createVirtualDisplay(const std::string& displayName, bool isSecure,
+                              const std::string& uniqueId, float requestedRefreshRate = 0.0f) {
+        return mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId,
+                                              requestedRefreshRate);
     }
 
-    auto destroyDisplay(const sp<IBinder>& displayToken) {
-        return mFlinger->destroyDisplay(displayToken);
+    auto destroyVirtualDisplay(const sp<IBinder>& displayToken) {
+        return mFlinger->destroyVirtualDisplay(displayToken);
     }
 
     auto getDisplay(const sp<IBinder>& displayToken) {