Merge "Create more expressive shader cache config." into main
diff --git a/cmds/cmd/fuzzer/cmd_fuzzer.cpp b/cmds/cmd/fuzzer/cmd_fuzzer.cpp
index ab514a1..72b295b 100644
--- a/cmds/cmd/fuzzer/cmd_fuzzer.cpp
+++ b/cmds/cmd/fuzzer/cmd_fuzzer.cpp
@@ -58,6 +58,12 @@
         while (mFDP->remaining_bytes() > 0) {
             size_t sizestr = mFDP->ConsumeIntegralInRange<size_t>(1, mFDP->remaining_bytes());
             string argument = mFDP->ConsumeBytesAsString(sizestr);
+            /**
+             * Filtering out strings based on "-w" argument. Since it leads to timeout.
+             */
+            if(strcmp(argument.c_str(), "-w") == 0) {
+                continue;
+            }
             arguments.emplace_back(argument);
         }
     }
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/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
deleted file mode 100644
index 44235cc..0000000
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ /dev/null
@@ -1,707 +0,0 @@
-/* Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SurfaceReplayer"
-
-#include "Replayer.h"
-
-#include <android/native_window.h>
-
-#include <android-base/file.h>
-
-#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/LayerState.h>
-#include <gui/Surface.h>
-#include <private/gui/ComposerService.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
-#include <chrono>
-#include <cmath>
-#include <condition_variable>
-#include <cstdlib>
-#include <fstream>
-#include <functional>
-#include <iostream>
-#include <mutex>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <vector>
-
-using namespace android;
-
-std::atomic_bool Replayer::sReplayingManually(false);
-
-Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads, bool wait,
-        nsecs_t stopHere)
-      : mTrace(),
-        mLoaded(false),
-        mIncrementIndex(0),
-        mCurrentTime(0),
-        mNumThreads(numThreads),
-        mWaitForTimeStamps(wait),
-        mStopTimeStamp(stopHere) {
-    srand(RAND_COLOR_SEED);
-
-    std::string input;
-    if (!android::base::ReadFileToString(filename, &input, true)) {
-        std::cerr << "Trace did not load. Does " << filename << " exist?" << std::endl;
-        abort();
-    }
-
-    mLoaded = mTrace.ParseFromString(input);
-    if (!mLoaded) {
-        std::cerr << "Trace did not load." << std::endl;
-        abort();
-    }
-
-    mCurrentTime = mTrace.increment(0).time_stamp();
-
-    sReplayingManually.store(replayManually);
-
-    if (stopHere < 0) {
-        mHasStopped = true;
-    }
-}
-
-Replayer::Replayer(const Trace& t, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)
-      : mTrace(t),
-        mLoaded(true),
-        mIncrementIndex(0),
-        mCurrentTime(0),
-        mNumThreads(numThreads),
-        mWaitForTimeStamps(wait),
-        mStopTimeStamp(stopHere) {
-    srand(RAND_COLOR_SEED);
-    mCurrentTime = mTrace.increment(0).time_stamp();
-
-    sReplayingManually.store(replayManually);
-
-    if (stopHere < 0) {
-        mHasStopped = true;
-    }
-}
-
-status_t Replayer::replay() {
-    signal(SIGINT, Replayer::stopAutoReplayHandler); //for manual control
-
-    ALOGV("There are %d increments.", mTrace.increment_size());
-
-    status_t status = loadSurfaceComposerClient();
-
-    if (status != NO_ERROR) {
-        ALOGE("Couldn't create SurfaceComposerClient (%d)", status);
-        return status;
-    }
-
-    SurfaceComposerClient::enableVSyncInjections(true);
-
-    initReplay();
-
-    ALOGV("Starting actual Replay!");
-    while (!mPendingIncrements.empty()) {
-        mCurrentIncrement = mTrace.increment(mIncrementIndex);
-
-        if (mHasStopped == false && mCurrentIncrement.time_stamp() >= mStopTimeStamp) {
-            mHasStopped = true;
-            sReplayingManually.store(true);
-        }
-
-        waitForConsoleCommmand();
-
-        if (mWaitForTimeStamps) {
-            waitUntilTimestamp(mCurrentIncrement.time_stamp());
-        }
-
-        auto event = mPendingIncrements.front();
-        mPendingIncrements.pop();
-
-        event->complete();
-
-        if (event->getIncrementType() == Increment::kVsyncEvent) {
-            mWaitingForNextVSync = false;
-        }
-
-        if (mIncrementIndex + mNumThreads < mTrace.increment_size()) {
-            status = dispatchEvent(mIncrementIndex + mNumThreads);
-
-            if (status != NO_ERROR) {
-                SurfaceComposerClient::enableVSyncInjections(false);
-                return status;
-            }
-        }
-
-        mIncrementIndex++;
-        mCurrentTime = mCurrentIncrement.time_stamp();
-    }
-
-    SurfaceComposerClient::enableVSyncInjections(false);
-
-    return status;
-}
-
-status_t Replayer::initReplay() {
-    for (int i = 0; i < mNumThreads && i < mTrace.increment_size(); i++) {
-        status_t status = dispatchEvent(i);
-
-        if (status != NO_ERROR) {
-            ALOGE("Unable to dispatch event (%d)", status);
-            return status;
-        }
-    }
-
-    return NO_ERROR;
-}
-
-void Replayer::stopAutoReplayHandler(int /*signal*/) {
-    if (sReplayingManually) {
-        SurfaceComposerClient::enableVSyncInjections(false);
-        exit(0);
-    }
-
-    sReplayingManually.store(true);
-}
-
-std::vector<std::string> split(const std::string& s, const char delim) {
-    std::vector<std::string> elems;
-    std::stringstream ss(s);
-    std::string item;
-    while (getline(ss, item, delim)) {
-        elems.push_back(item);
-    }
-    return elems;
-}
-
-bool isNumber(const std::string& s) {
-    return !s.empty() &&
-           std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
-}
-
-void Replayer::waitForConsoleCommmand() {
-    if (!sReplayingManually || mWaitingForNextVSync) {
-        return;
-    }
-
-    while (true) {
-        std::string input = "";
-        std::cout << "> ";
-        getline(std::cin, input);
-
-        if (input.empty()) {
-            input = mLastInput;
-        } else {
-            mLastInput = input;
-        }
-
-        if (mLastInput.empty()) {
-            continue;
-        }
-
-        std::vector<std::string> inputs = split(input, ' ');
-
-        if (inputs[0] == "n") {  // next vsync
-            mWaitingForNextVSync = true;
-            break;
-
-        } else if (inputs[0] == "ni") {  // next increment
-            break;
-
-        } else if (inputs[0] == "c") {  // continue
-            if (inputs.size() > 1 && isNumber(inputs[1])) {
-                long milliseconds = stoi(inputs[1]);
-                std::thread([&] {
-                    std::cout << "Started!" << std::endl;
-                    std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
-                    sReplayingManually.store(true);
-                    std::cout << "Should have stopped!" << std::endl;
-                }).detach();
-            }
-            sReplayingManually.store(false);
-            mWaitingForNextVSync = false;
-            break;
-
-        } else if (inputs[0] == "s") {  // stop at this timestamp
-            if (inputs.size() < 1) {
-                std::cout << "No time stamp given" << std::endl;
-                continue;
-            }
-            sReplayingManually.store(false);
-            mStopTimeStamp = stol(inputs[1]);
-            mHasStopped = false;
-            break;
-        } else if (inputs[0] == "l") {  // list
-            std::cout << "Time stamp: " << mCurrentIncrement.time_stamp() << "\n";
-            continue;
-        } else if (inputs[0] == "q") {  // quit
-            SurfaceComposerClient::enableVSyncInjections(false);
-            exit(0);
-
-        } else if (inputs[0] == "h") {  // help
-                                        // add help menu
-            std::cout << "Manual Replay options:\n";
-            std::cout << " n  - Go to next VSync\n";
-            std::cout << " ni - Go to next increment\n";
-            std::cout << " c  - Continue\n";
-            std::cout << " c [milliseconds] - Continue until specified number of milliseconds\n";
-            std::cout << " s [timestamp]    - Continue and stop at specified timestamp\n";
-            std::cout << " l  - List out timestamp of current increment\n";
-            std::cout << " h  - Display help menu\n";
-            std::cout << std::endl;
-            continue;
-        }
-
-        std::cout << "Invalid Command" << std::endl;
-    }
-}
-
-status_t Replayer::dispatchEvent(int index) {
-    auto increment = mTrace.increment(index);
-    std::shared_ptr<Event> event = std::make_shared<Event>(increment.increment_case());
-    mPendingIncrements.push(event);
-
-    status_t status = NO_ERROR;
-    switch (increment.increment_case()) {
-        case increment.kTransaction: {
-            std::thread(&Replayer::doTransaction, this, increment.transaction(), event).detach();
-        } break;
-        case increment.kSurfaceCreation: {
-            std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
-                    .detach();
-        } break;
-        case increment.kBufferUpdate: {
-            std::lock_guard<std::mutex> lock1(mLayerLock);
-            std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
-
-            Dimensions dimensions(increment.buffer_update().w(), increment.buffer_update().h());
-            BufferEvent bufferEvent(event, dimensions);
-
-            auto layerId = increment.buffer_update().id();
-            if (mBufferQueueSchedulers.count(layerId) == 0) {
-                mBufferQueueSchedulers[layerId] = std::make_shared<BufferQueueScheduler>(
-                        mLayers[layerId], mColors[layerId], layerId);
-                mBufferQueueSchedulers[layerId]->addEvent(bufferEvent);
-
-                std::thread(&BufferQueueScheduler::startScheduling,
-                        mBufferQueueSchedulers[increment.buffer_update().id()].get())
-                        .detach();
-            } else {
-                auto bqs = mBufferQueueSchedulers[increment.buffer_update().id()];
-                bqs->addEvent(bufferEvent);
-            }
-        } break;
-        case increment.kVsyncEvent: {
-            std::thread(&Replayer::injectVSyncEvent, this, increment.vsync_event(), event).detach();
-        } break;
-        case increment.kDisplayCreation: {
-            std::thread(&Replayer::createDisplay, this, increment.display_creation(), event)
-                    .detach();
-        } break;
-        case increment.kDisplayDeletion: {
-            std::thread(&Replayer::deleteDisplay, this, increment.display_deletion(), event)
-                    .detach();
-        } break;
-        case increment.kPowerModeUpdate: {
-            std::thread(&Replayer::updatePowerMode, this, increment.power_mode_update(), event)
-                    .detach();
-        } break;
-        default:
-            ALOGE("Unknown Increment Type: %d", increment.increment_case());
-            status = BAD_VALUE;
-            break;
-    }
-
-    return status;
-}
-
-status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
-    ALOGV("Started Transaction");
-
-    SurfaceComposerClient::Transaction liveTransaction;
-
-    status_t status = NO_ERROR;
-
-    status = doSurfaceTransaction(liveTransaction, t.surface_change());
-    doDisplayTransaction(liveTransaction, t.display_change());
-
-    if (t.animation()) {
-        liveTransaction.setAnimationTransaction();
-    }
-
-    event->readyToExecute();
-
-    liveTransaction.apply(t.synchronous());
-
-    ALOGV("Ended Transaction");
-
-    return status;
-}
-
-status_t Replayer::doSurfaceTransaction(
-        SurfaceComposerClient::Transaction& transaction,
-        const SurfaceChanges& surfaceChanges) {
-    status_t status = NO_ERROR;
-
-    for (const SurfaceChange& change : surfaceChanges) {
-        std::unique_lock<std::mutex> lock(mLayerLock);
-        if (mLayers[change.id()] == nullptr) {
-            mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
-        }
-
-        switch (change.SurfaceChange_case()) {
-            case SurfaceChange::SurfaceChangeCase::kPosition:
-                setPosition(transaction, change.id(), change.position());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kSize:
-                setSize(transaction, change.id(), change.size());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kAlpha:
-                setAlpha(transaction, change.id(), change.alpha());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kLayer:
-                setLayer(transaction, change.id(), change.layer());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kCrop:
-                setCrop(transaction, change.id(), change.crop());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kCornerRadius:
-                setCornerRadius(transaction, change.id(), change.corner_radius());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kMatrix:
-                setMatrix(transaction, change.id(), change.matrix());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
-                setTransparentRegionHint(transaction, change.id(),
-                        change.transparent_region_hint());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kLayerStack:
-                setLayerStack(transaction, change.id(), change.layer_stack());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
-                setHiddenFlag(transaction, change.id(), change.hidden_flag());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
-                setOpaqueFlag(transaction, change.id(), change.opaque_flag());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kSecureFlag:
-                setSecureFlag(transaction, change.id(), change.secure_flag());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kReparent:
-                setReparentChange(transaction, change.id(), change.reparent());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kRelativeParent:
-                setRelativeParentChange(transaction, change.id(), change.relative_parent());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kShadowRadius:
-                setShadowRadiusChange(transaction, change.id(), change.shadow_radius());
-                break;
-            case SurfaceChange::SurfaceChangeCase::kBlurRegions:
-                setBlurRegionsChange(transaction, change.id(), change.blur_regions());
-                break;
-            default:
-                status = 1;
-                break;
-        }
-
-        if (status != NO_ERROR) {
-            ALOGE("Unknown Transaction Code");
-            return status;
-        }
-    }
-    return status;
-}
-
-void Replayer::doDisplayTransaction(SurfaceComposerClient::Transaction& t,
-        const DisplayChanges& displayChanges) {
-    for (const DisplayChange& change : displayChanges) {
-        ALOGV("Doing display transaction");
-        std::unique_lock<std::mutex> lock(mDisplayLock);
-        if (mDisplays[change.id()] == nullptr) {
-            mDisplayCond.wait(lock, [&] { return (mDisplays[change.id()] != nullptr); });
-        }
-
-        switch (change.DisplayChange_case()) {
-            case DisplayChange::DisplayChangeCase::kSurface:
-                setDisplaySurface(t, change.id(), change.surface());
-                break;
-            case DisplayChange::DisplayChangeCase::kLayerStack:
-                setDisplayLayerStack(t, change.id(), change.layer_stack());
-                break;
-            case DisplayChange::DisplayChangeCase::kSize:
-                setDisplaySize(t, change.id(), change.size());
-                break;
-            case DisplayChange::DisplayChangeCase::kProjection:
-                setDisplayProjection(t, change.id(), change.projection());
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-void Replayer::setPosition(SurfaceComposerClient::Transaction& t,
-        layer_id id, const PositionChange& pc) {
-    ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
-    t.setPosition(mLayers[id], pc.x(), pc.y());
-}
-
-void Replayer::setSize(SurfaceComposerClient::Transaction& t,
-        layer_id id, const SizeChange& sc) {
-    ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
-}
-
-void Replayer::setLayer(SurfaceComposerClient::Transaction& t,
-        layer_id id, const LayerChange& lc) {
-    ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
-    t.setLayer(mLayers[id], lc.layer());
-}
-
-void Replayer::setAlpha(SurfaceComposerClient::Transaction& t,
-        layer_id id, const AlphaChange& ac) {
-    ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
-    t.setAlpha(mLayers[id], ac.alpha());
-}
-
-void Replayer::setCrop(SurfaceComposerClient::Transaction& t,
-        layer_id id, const CropChange& cc) {
-    ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
-            cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
-            cc.rectangle().bottom());
-
-    Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
-            cc.rectangle().bottom());
-    t.setCrop(mLayers[id], r);
-}
-
-void Replayer::setCornerRadius(SurfaceComposerClient::Transaction& t,
-        layer_id id, const CornerRadiusChange& cc) {
-    ALOGV("Layer %d: Setting Corner Radius -- cornerRadius=%d", id, cc.corner_radius());
-
-    t.setCornerRadius(mLayers[id], cc.corner_radius());
-}
-
-void Replayer::setBackgroundBlurRadius(SurfaceComposerClient::Transaction& t,
-        layer_id id, const BackgroundBlurRadiusChange& cc) {
-    ALOGV("Layer %d: Setting Background Blur Radius -- backgroundBlurRadius=%d", id,
-        cc.background_blur_radius());
-
-    t.setBackgroundBlurRadius(mLayers[id], cc.background_blur_radius());
-}
-
-void Replayer::setMatrix(SurfaceComposerClient::Transaction& t,
-        layer_id id, const MatrixChange& mc) {
-    ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
-            mc.dtdx(), mc.dsdy(), mc.dtdy());
-    t.setMatrix(mLayers[id], mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
-}
-
-void Replayer::setTransparentRegionHint(SurfaceComposerClient::Transaction& t,
-        layer_id id, const TransparentRegionHintChange& trhc) {
-    ALOGV("Setting Transparent Region Hint");
-    Region re = Region();
-
-    for (const auto& r : trhc.region()) {
-        Rect rect = Rect(r.left(), r.top(), r.right(), r.bottom());
-        re.merge(rect);
-    }
-
-    t.setTransparentRegionHint(mLayers[id], re);
-}
-
-void Replayer::setLayerStack(SurfaceComposerClient::Transaction& t,
-        layer_id id, const LayerStackChange& lsc) {
-    ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
-    t.setLayerStack(mLayers[id], ui::LayerStack::fromValue(lsc.layer_stack()));
-}
-
-void Replayer::setHiddenFlag(SurfaceComposerClient::Transaction& t,
-        layer_id id, const HiddenFlagChange& hfc) {
-    ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
-    layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
-
-    t.setFlags(mLayers[id], flag, layer_state_t::eLayerHidden);
-}
-
-void Replayer::setOpaqueFlag(SurfaceComposerClient::Transaction& t,
-        layer_id id, const OpaqueFlagChange& ofc) {
-    ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
-    layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
-
-    t.setFlags(mLayers[id], flag, layer_state_t::eLayerOpaque);
-}
-
-void Replayer::setSecureFlag(SurfaceComposerClient::Transaction& t,
-        layer_id id, const SecureFlagChange& sfc) {
-    ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
-    layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
-
-    t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure);
-}
-
-void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t,
-        display_id id, const DispSurfaceChange& /*dsc*/) {
-    sp<IGraphicBufferProducer> outProducer;
-    sp<IGraphicBufferConsumer> outConsumer;
-    BufferQueue::createBufferQueue(&outProducer, &outConsumer);
-
-    t.setDisplaySurface(mDisplays[id], outProducer);
-}
-
-void Replayer::setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
-        display_id id, const LayerStackChange& lsc) {
-    t.setDisplayLayerStack(mDisplays[id], ui::LayerStack::fromValue(lsc.layer_stack()));
-}
-
-void Replayer::setDisplaySize(SurfaceComposerClient::Transaction& t,
-        display_id id, const SizeChange& sc) {
-    t.setDisplaySize(mDisplays[id], sc.w(), sc.h());
-}
-
-void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t,
-        display_id id, const ProjectionChange& pc) {
-    Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
-            pc.viewport().bottom());
-    Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
-
-    t.setDisplayProjection(mDisplays[id], ui::toRotation(pc.orientation()), viewport, frame);
-}
-
-status_t Replayer::createSurfaceControl(
-        const SurfaceCreation& create, const std::shared_ptr<Event>& event) {
-    event->readyToExecute();
-
-    ALOGV("Creating Surface Control: ID: %d", create.id());
-    sp<SurfaceControl> surfaceControl = mComposerClient->createSurface(
-            String8(create.name().c_str()), create.w(), create.h(), PIXEL_FORMAT_RGBA_8888, 0);
-
-    if (surfaceControl == nullptr) {
-        ALOGE("CreateSurfaceControl: unable to create surface control");
-        return BAD_VALUE;
-    }
-
-    std::lock_guard<std::mutex> lock1(mLayerLock);
-    auto& layer = mLayers[create.id()];
-    layer = surfaceControl;
-
-    mColors[create.id()] = HSV(rand() % 360, 1, 1);
-
-    mLayerCond.notify_all();
-
-    std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
-    if (mBufferQueueSchedulers.count(create.id()) != 0) {
-        mBufferQueueSchedulers[create.id()]->setSurfaceControl(
-                mLayers[create.id()], mColors[create.id()]);
-    }
-
-    return NO_ERROR;
-}
-
-status_t Replayer::injectVSyncEvent(
-        const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) {
-    ALOGV("Injecting VSync Event");
-
-    event->readyToExecute();
-
-    SurfaceComposerClient::injectVSync(vSyncEvent.when());
-
-    return NO_ERROR;
-}
-
-void Replayer::createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event) {
-    ALOGV("Creating display");
-    event->readyToExecute();
-
-    std::lock_guard<std::mutex> lock(mDisplayLock);
-    sp<IBinder> display = SurfaceComposerClient::createDisplay(
-            String8(create.name().c_str()), create.is_secure());
-    mDisplays[create.id()] = display;
-
-    mDisplayCond.notify_all();
-
-    ALOGV("Done creating display");
-}
-
-void Replayer::deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event) {
-    ALOGV("Delete display");
-    event->readyToExecute();
-
-    std::lock_guard<std::mutex> lock(mDisplayLock);
-    SurfaceComposerClient::destroyDisplay(mDisplays[delete_.id()]);
-    mDisplays.erase(delete_.id());
-}
-
-void Replayer::updatePowerMode(const PowerModeUpdate& pmu, const std::shared_ptr<Event>& event) {
-    ALOGV("Updating power mode");
-    event->readyToExecute();
-    SurfaceComposerClient::setDisplayPowerMode(mDisplays[pmu.id()], pmu.mode());
-}
-
-void Replayer::waitUntilTimestamp(int64_t timestamp) {
-    ALOGV("Waiting for %lld nanoseconds...", static_cast<int64_t>(timestamp - mCurrentTime));
-    std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));
-}
-
-status_t Replayer::loadSurfaceComposerClient() {
-    mComposerClient = new SurfaceComposerClient;
-    return mComposerClient->initCheck();
-}
-
-void Replayer::setReparentChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const ReparentChange& c) {
-    sp<SurfaceControl> newSurfaceControl = nullptr;
-    if (mLayers.count(c.parent_id()) != 0 && mLayers[c.parent_id()] != nullptr) {
-        newSurfaceControl = mLayers[c.parent_id()];
-    }
-    t.reparent(mLayers[id], newSurfaceControl);
-}
-
-void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const RelativeParentChange& c) {
-    if (mLayers.count(c.relative_parent_id()) == 0 || mLayers[c.relative_parent_id()] == nullptr) {
-        ALOGE("Layer %d not found in set relative parent transaction", c.relative_parent_id());
-        return;
-    }
-    t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
-}
-
-void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const ShadowRadiusChange& c) {
-    t.setShadowRadius(mLayers[id], c.radius());
-}
-
-void Replayer::setBlurRegionsChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const BlurRegionsChange& c) {
-    std::vector<BlurRegion> regions;
-    for(size_t i=0; i < c.blur_regions_size(); i++) {
-        auto protoRegion = c.blur_regions(i);
-        regions.push_back(BlurRegion{
-            .blurRadius = protoRegion.blur_radius(),
-            .alpha = protoRegion.alpha(),
-            .cornerRadiusTL = protoRegion.corner_radius_tl(),
-            .cornerRadiusTR = protoRegion.corner_radius_tr(),
-            .cornerRadiusBL = protoRegion.corner_radius_bl(),
-            .cornerRadiusBR = protoRegion.corner_radius_br(),
-            .left = protoRegion.left(),
-            .top = protoRegion.top(),
-            .right = protoRegion.right(),
-            .bottom = protoRegion.bottom()
-        });
-    }
-    t.setBlurRegions(mLayers[id], regions);
-}
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 01f523b..bec3283 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -17,8 +17,20 @@
 /**
  * @addtogroup Choreographer
  *
- * Choreographer coordinates the timing of frame rendering. This is the C version of the
- * android.view.Choreographer object in Java.
+ * Choreographer coordinates the timing of frame rendering. This is the C
+ * version of the android.view.Choreographer object in Java. If you do not use
+ * Choreographer to pace your render loop, you may render too quickly for the
+ * display, increasing latency between frame submission and presentation.
+ *
+ * Input events are guaranteed to be processed before the frame callback is
+ * called, and will not be run concurrently. Input and sensor events should not
+ * be handled in the Choregrapher callback.
+ *
+ * The frame callback is also the appropriate place to run any per-frame state
+ * update logic. For example, in a game, the frame callback should be
+ * responsible for updating things like physics, AI, game state, and rendering
+ * the frame. Input and sensors should be handled separately via callbacks
+ * registered with AInputQueue and ASensorManager.
  *
  * As of API level 33, apps can follow proper frame pacing and even choose a future frame to render.
  * The API is used as follows:
@@ -38,6 +50,11 @@
  * 4. SurfaceFlinger attempts to follow the chosen frame timeline, by not applying transactions or
  * latching buffers before the desired presentation time.
  *
+ * On older devices, AChoreographer_postFrameCallback64 or
+ * AChoreographer_postFrameCallback can be used to lesser effect. They cannot be
+ * used to precisely plan your render timeline, but will rate limit to avoid
+ * overloading the display pipeline and increasing frame latency.
+ *
  * @{
  */
 
@@ -129,14 +146,46 @@
 AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
 
 /**
- * Deprecated: Use AChoreographer_postFrameCallback64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallback64, which uses a 64-bit frame time for all
+ * platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallback64, which does not have the
+ * bug described above.
  */
 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
                                       AChoreographer_frameCallback callback, void* data)
         __INTRODUCED_IN(24) __DEPRECATED_IN(29, "Use AChoreographer_postFrameCallback64 instead");
 
 /**
- * Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallbackDelayed64, which uses a 64-bit frame time for
+ * all platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallbackDelayed64, which does not
+ * have the bug described above.
  */
 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
                                              AChoreographer_frameCallback callback, void* data,
@@ -144,8 +193,13 @@
         __DEPRECATED_IN(29, "Use AChoreographer_postFrameCallbackDelayed64 instead");
 
 /**
- * Post a callback to be run on the next frame.  The data pointer provided will
- * be passed to the callback function when it's called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run on the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback64.
  *
  * Available since API level 29.
  */
@@ -154,9 +208,13 @@
         __INTRODUCED_IN(29);
 
 /**
- * Post a callback to be run on the frame following the specified delay.  The
- * data pointer provided will be passed to the callback function when it's
- * called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed64.
  *
  * Available since API level 29.
  */
@@ -165,8 +223,13 @@
                                                uint32_t delayMillis) __INTRODUCED_IN(29);
 
 /**
- * Posts a callback to be run on the next frame. The data pointer provided will
- * be passed to the callback function when it's called.
+ * Posts a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postVsyncCallback.
  *
  * Available since API level 33.
  */
diff --git a/include/android/looper.h b/include/android/looper.h
index 6a02916..d80a366 100644
--- a/include/android/looper.h
+++ b/include/android/looper.h
@@ -182,23 +182,27 @@
  * If the timeout is zero, returns immediately without blocking.
  * If the timeout is negative, waits indefinitely until an event appears.
  *
- * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+ * Returns ALOOPER_POLL_WAKE if the poll was awoken using ALooper_wake() before
  * the timeout expired and no callbacks were invoked and no other file
- * descriptors were ready.
+ * descriptors were ready. **All return values may also imply
+ * ALOOPER_POLL_WAKE.**
  *
- * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+ * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. The poll
+ * may also have been explicitly woken by ALooper_wake.
  *
- * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
- * timeout expired.
+ * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given timeout
+ * expired. The poll may also have been explicitly woken by ALooper_wake.
  *
- * Returns ALOOPER_POLL_ERROR if an error occurred.
+ * Returns ALOOPER_POLL_ERROR if the calling thread has no associated Looper or
+ * for unrecoverable internal errors. The poll may also have been explicitly
+ * woken by ALooper_wake.
  *
- * Returns a value >= 0 containing an identifier (the same identifier
- * `ident` passed to ALooper_addFd()) if its file descriptor has data
- * and it has no callback function (requiring the caller here to
- * handle it).  In this (and only this) case outFd, outEvents and
- * outData will contain the poll events and data associated with the
- * fd, otherwise they will be set to NULL.
+ * Returns a value >= 0 containing an identifier (the same identifier `ident`
+ * passed to ALooper_addFd()) if its file descriptor has data and it has no
+ * callback function (requiring the caller here to handle it).  In this (and
+ * only this) case outFd, outEvents and outData will contain the poll events and
+ * data associated with the fd, otherwise they will be set to NULL. The poll may
+ * also have been explicitly woken by ALooper_wake.
  *
  * This method does not return until it has finished invoking the appropriate callbacks
  * for all file descriptors that were signalled.
@@ -210,11 +214,21 @@
  * data has been consumed or a file descriptor is available with no callback.
  * This function will never return ALOOPER_POLL_CALLBACK.
  *
- * Removed in API 34 as ALooper_pollAll can swallow ALooper_wake calls.
- * Use ALooper_pollOnce instead.
+ * This API cannot be used safely, but a safe alternative exists (see below). As
+ * such, new builds will not be able to call this API and must migrate to the
+ * safe API. Binary compatibility is preserved to support already-compiled apps.
+ *
+ * \bug ALooper_pollAll will not wake in response to ALooper_wake calls if it
+ * also handles another event at the same time.
+ *
+ * \deprecated Calls to ALooper_pollAll should be replaced with
+ * ALooper_pollOnce. If you call ALooper_pollOnce in a loop, you *must* treat
+ * all return values as if they also indicate ALOOPER_POLL_WAKE.
  */
 int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
-    __REMOVED_IN(1, "ALooper_pollAll may ignore wakes. Use ALooper_pollOnce instead. See https://github.com/android/ndk/discussions/2020 for more information");
+        __REMOVED_IN(1,
+                     "ALooper_pollAll may ignore wakes. Use ALooper_pollOnce instead. See "
+                     "The API documentation for more information");
 
 /**
  * Wakes the poll asynchronously.
diff --git a/include/ftl/concat.h b/include/ftl/concat.h
index e0774d3..7680bed 100644
--- a/include/ftl/concat.h
+++ b/include/ftl/concat.h
@@ -57,7 +57,7 @@
 template <std::size_t N>
 struct Concat<N> {
   static constexpr std::size_t max_size() { return N; }
-  constexpr std::size_t size() const { return end_ - buffer_; }
+  constexpr std::size_t size() const { return static_cast<std::size_t>(end_ - buffer_); }
 
   constexpr const char* c_str() const { return buffer_; }
 
@@ -68,6 +68,8 @@
 
  protected:
   constexpr Concat() : end_(buffer_) {}
+  constexpr Concat(const Concat&) = delete;
+
   constexpr void append() { *end_ = '\0'; }
 
   char buffer_[N + 1];
diff --git a/include/ftl/details/hash.h b/include/ftl/details/hash.h
new file mode 100644
index 0000000..230ae51
--- /dev/null
+++ b/include/ftl/details/hash.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cinttypes>
+#include <cstring>
+
+namespace android::ftl::details {
+
+// Based on CityHash64 v1.0.1 (http://code.google.com/p/cityhash/), but slightly
+// modernized and trimmed for cases with bounded lengths.
+
+template <typename T = std::uint64_t>
+inline T read_unaligned(const void* ptr) {
+  T v;
+  std::memcpy(&v, ptr, sizeof(T));
+  return v;
+}
+
+template <bool NonZeroShift = false>
+constexpr std::uint64_t rotate(std::uint64_t v, std::uint8_t shift) {
+  if constexpr (!NonZeroShift) {
+    if (shift == 0) return v;
+  }
+  return (v >> shift) | (v << (64 - shift));
+}
+
+constexpr std::uint64_t shift_mix(std::uint64_t v) {
+  return v ^ (v >> 47);
+}
+
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+constexpr std::uint64_t hash_length_16(std::uint64_t u, std::uint64_t v) {
+  constexpr std::uint64_t kPrime = 0x9ddfea08eb382d69ull;
+  auto a = (u ^ v) * kPrime;
+  a ^= (a >> 47);
+  auto b = (v ^ a) * kPrime;
+  b ^= (b >> 47);
+  b *= kPrime;
+  return b;
+}
+
+constexpr std::uint64_t kPrime0 = 0xc3a5c85c97cb3127ull;
+constexpr std::uint64_t kPrime1 = 0xb492b66fbe98f273ull;
+constexpr std::uint64_t kPrime2 = 0x9ae16a3b2f90404full;
+constexpr std::uint64_t kPrime3 = 0xc949d7c7509e6557ull;
+
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+inline std::uint64_t hash_length_0_to_16(const char* str, std::uint64_t length) {
+  if (length > 8) {
+    const auto a = read_unaligned(str);
+    const auto b = read_unaligned(str + length - 8);
+    return hash_length_16(a, rotate<true>(b + length, static_cast<std::uint8_t>(length))) ^ b;
+  }
+  if (length >= 4) {
+    const auto a = read_unaligned<std::uint32_t>(str);
+    const auto b = read_unaligned<std::uint32_t>(str + length - 4);
+    return hash_length_16(length + (a << 3), b);
+  }
+  if (length > 0) {
+    const auto a = static_cast<unsigned char>(str[0]);
+    const auto b = static_cast<unsigned char>(str[length >> 1]);
+    const auto c = static_cast<unsigned char>(str[length - 1]);
+    const auto y = static_cast<std::uint32_t>(a) + (static_cast<std::uint32_t>(b) << 8);
+    const auto z = static_cast<std::uint32_t>(length) + (static_cast<std::uint32_t>(c) << 2);
+    return shift_mix(y * kPrime2 ^ z * kPrime3) * kPrime2;
+  }
+  return kPrime2;
+}
+
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+inline std::uint64_t hash_length_17_to_32(const char* str, std::uint64_t length) {
+  const auto a = read_unaligned(str) * kPrime1;
+  const auto b = read_unaligned(str + 8);
+  const auto c = read_unaligned(str + length - 8) * kPrime2;
+  const auto d = read_unaligned(str + length - 16) * kPrime0;
+  return hash_length_16(rotate(a - b, 43) + rotate(c, 30) + d,
+                        a + rotate(b ^ kPrime3, 20) - c + length);
+}
+
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+inline std::uint64_t hash_length_33_to_64(const char* str, std::uint64_t length) {
+  auto z = read_unaligned(str + 24);
+  auto a = read_unaligned(str) + (length + read_unaligned(str + length - 16)) * kPrime0;
+  auto b = rotate(a + z, 52);
+  auto c = rotate(a, 37);
+
+  a += read_unaligned(str + 8);
+  c += rotate(a, 7);
+  a += read_unaligned(str + 16);
+
+  const auto vf = a + z;
+  const auto vs = b + rotate(a, 31) + c;
+
+  a = read_unaligned(str + 16) + read_unaligned(str + length - 32);
+  z += read_unaligned(str + length - 8);
+  b = rotate(a + z, 52);
+  c = rotate(a, 37);
+  a += read_unaligned(str + length - 24);
+  c += rotate(a, 7);
+  a += read_unaligned(str + length - 16);
+
+  const auto wf = a + z;
+  const auto ws = b + rotate(a, 31) + c;
+  const auto r = shift_mix((vf + ws) * kPrime2 + (wf + vs) * kPrime0);
+  return shift_mix(r * kPrime0 + vs) * kPrime2;
+}
+
+}  // namespace android::ftl::details
diff --git a/include/ftl/expected.h b/include/ftl/expected.h
index 12b6102..57448dc 100644
--- a/include/ftl/expected.h
+++ b/include/ftl/expected.h
@@ -18,9 +18,57 @@
 
 #include <android-base/expected.h>
 #include <ftl/optional.h>
+#include <ftl/unit.h>
 
 #include <utility>
 
+// Given an expression `expr` that evaluates to an ftl::Expected<T, E> result (R for short), FTL_TRY
+// unwraps T out of R, or bails out of the enclosing function F if R has an error E. The return type
+// of F must be R, since FTL_TRY propagates R in the error case. As a special case, ftl::Unit may be
+// used as the error E to allow FTL_TRY expressions when F returns `void`.
+//
+// The non-standard syntax requires `-Wno-gnu-statement-expression-from-macro-expansion` to compile.
+// The UnitToVoid conversion allows the macro to be used for early exit from a function that returns
+// `void`.
+//
+// Example usage:
+//
+//   using StringExp = ftl::Expected<std::string, std::errc>;
+//
+//   StringExp repeat(StringExp exp) {
+//     const std::string str = FTL_TRY(exp);
+//     return StringExp(str + str);
+//   }
+//
+//   assert(StringExp("haha"s) == repeat(StringExp("ha"s)));
+//   assert(repeat(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
+//     return e == std::errc::bad_message;
+//   }));
+//
+//
+// FTL_TRY may be used in void-returning functions by using ftl::Unit as the error type:
+//
+//   void uppercase(char& c, ftl::Optional<char> opt) {
+//     c = std::toupper(FTL_TRY(std::move(opt).ok_or(ftl::Unit())));
+//   }
+//
+//   char c = '?';
+//   uppercase(c, std::nullopt);
+//   assert(c == '?');
+//
+//   uppercase(c, 'a');
+//   assert(c == 'A');
+//
+#define FTL_TRY(expr)                                                     \
+  ({                                                                      \
+    auto exp_ = (expr);                                                   \
+    if (!exp_.has_value()) {                                              \
+      using E = decltype(exp_)::error_type;                               \
+      return android::ftl::details::UnitToVoid<E>::from(std::move(exp_)); \
+    }                                                                     \
+    exp_.value();                                                         \
+  })
+
 namespace android::ftl {
 
 // Superset of base::expected<T, E> with monadic operations.
diff --git a/include/ftl/hash.h b/include/ftl/hash.h
new file mode 100644
index 0000000..29a6f71
--- /dev/null
+++ b/include/ftl/hash.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cinttypes>
+#include <optional>
+#include <string_view>
+
+#include <ftl/details/hash.h>
+
+namespace android::ftl {
+
+// Non-cryptographic hash function (namely CityHash64) for strings with at most 64 characters.
+// Unlike std::hash, which returns std::size_t and is only required to produce the same result
+// for the same input within a single execution of a program, this hash is stable.
+inline std::optional<std::uint64_t> stable_hash(std::string_view view) {
+  const auto length = view.length();
+  if (length <= 16) {
+    return details::hash_length_0_to_16(view.data(), length);
+  }
+  if (length <= 32) {
+    return details::hash_length_17_to_32(view.data(), length);
+  }
+  if (length <= 64) {
+    return details::hash_length_33_to_64(view.data(), length);
+  }
+  return {};
+}
+
+}  // namespace android::ftl
diff --git a/include/ftl/optional.h b/include/ftl/optional.h
index 94d8e3d..e245d88 100644
--- a/include/ftl/optional.h
+++ b/include/ftl/optional.h
@@ -20,13 +20,14 @@
 #include <optional>
 #include <utility>
 
+#include <android-base/expected.h>
 #include <ftl/details/optional.h>
 
 namespace android::ftl {
 
 // Superset of std::optional<T> with monadic operations, as proposed in https://wg21.link/P0798R8.
 //
-// TODO: Remove in C++23.
+// TODO: Remove standard APIs in C++23.
 //
 template <typename T>
 struct Optional final : std::optional<T> {
@@ -109,6 +110,13 @@
     return std::forward<F>(f)();
   }
 
+  // Maps this Optional<T> to expected<T, E> where nullopt becomes E.
+  template <typename E>
+  constexpr auto ok_or(E&& e) && -> base::expected<T, E> {
+    if (has_value()) return std::move(value());
+    return base::unexpected(std::forward<E>(e));
+  }
+
   // Delete new for this class. Its base doesn't have a virtual destructor, and
   // if it got deleted via base class pointer, it would cause undefined
   // behavior. There's not a good reason to allocate this object on the heap
diff --git a/include/ftl/unit.h b/include/ftl/unit.h
index e38230b..62549a3 100644
--- a/include/ftl/unit.h
+++ b/include/ftl/unit.h
@@ -58,4 +58,22 @@
   return {std::forward<F>(f)};
 }
 
+namespace details {
+
+// Identity function for all T except Unit, which maps to void.
+template <typename T>
+struct UnitToVoid {
+  template <typename U>
+  static auto from(U&& value) {
+    return value;
+  }
+};
+
+template <>
+struct UnitToVoid<Unit> {
+  template <typename U>
+  static void from(U&&) {}
+};
+
+}  // namespace details
 }  // namespace android::ftl
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index b0eceef..56294dd 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -19,7 +19,6 @@
 #include <android-base/stringprintf.h>
 #include <ftl/enum.h>
 #include <ftl/string.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 #include <ui/Rotation.h>
 
@@ -47,7 +46,7 @@
  * See com.android.server.display.DisplayViewport.
  */
 struct DisplayViewport {
-    int32_t displayId; // -1 if invalid
+    ui::LogicalDisplayId displayId;
     ui::Rotation orientation;
     int32_t logicalLeft;
     int32_t logicalTop;
@@ -67,7 +66,7 @@
     ViewportType type;
 
     DisplayViewport()
-          : displayId(ADISPLAY_ID_NONE),
+          : displayId(ui::LogicalDisplayId::INVALID),
             orientation(ui::ROTATION_0),
             logicalLeft(0),
             logicalTop(0),
@@ -99,12 +98,10 @@
         return !(*this == other);
     }
 
-    inline bool isValid() const {
-        return displayId >= 0;
-    }
+    inline bool isValid() const { return displayId.isValid(); }
 
     void setNonDisplayViewport(int32_t width, int32_t height) {
-        displayId = ADISPLAY_ID_NONE;
+        displayId = ui::LogicalDisplayId::INVALID;
         orientation = ui::ROTATION_0;
         logicalLeft = 0;
         logicalTop = 0;
@@ -123,12 +120,13 @@
     }
 
     std::string toString() const {
-        return StringPrintf("Viewport %s: displayId=%d, uniqueId=%s, port=%s, orientation=%d, "
+        return StringPrintf("Viewport %s: displayId=%s, uniqueId=%s, port=%s, orientation=%d, "
                             "logicalFrame=[%d, %d, %d, %d], "
                             "physicalFrame=[%d, %d, %d, %d], "
                             "deviceSize=[%d, %d], "
                             "isActive=[%d]",
-                            ftl::enum_string(type).c_str(), displayId, uniqueId.c_str(),
+                            ftl::enum_string(type).c_str(), displayId.toString().c_str(),
+                            uniqueId.c_str(),
                             physicalPort ? ftl::to_string(*physicalPort).c_str() : "<none>",
                             static_cast<int>(orientation), logicalLeft, logicalTop, logicalRight,
                             logicalBottom, physicalLeft, physicalTop, physicalRight, physicalBottom,
diff --git a/include/input/Input.h b/include/input/Input.h
index 3f81fb0..3ca9c19 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -29,6 +29,7 @@
 #include <android/os/PointerIconType.h>
 #include <math.h>
 #include <stdint.h>
+#include <ui/LogicalDisplayId.h>
 #include <ui/Transform.h>
 #include <utils/BitSet.h>
 #include <utils/Timers.h>
@@ -40,13 +41,11 @@
  * Additional private constants not defined in ndk/ui/input.h.
  */
 enum {
-#ifdef __linux__
+
     /* This event was generated or modified by accessibility service. */
     AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
             android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT,
-#else
-    AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800,
-#endif
+
     /* Signifies that the key is being predispatched */
     AKEY_EVENT_FLAG_PREDISPATCH = 0x20000000,
 
@@ -89,15 +88,11 @@
     AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE =
             android::os::IInputConstants::MOTION_EVENT_FLAG_NO_FOCUS_CHANGE,
 
-#if defined(__linux__)
     /**
      * This event was generated or modified by accessibility service.
      */
     AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
             android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT,
-#else
-    AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800,
-#endif
 
     AMOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS =
             android::os::IInputConstants::MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS,
@@ -203,9 +198,7 @@
 
 namespace android {
 
-#ifdef __linux__
 class Parcel;
-#endif
 
 /*
  * Apply the given transform to the point without applying any translation/offset.
@@ -311,12 +304,8 @@
 
     POLICY_FLAG_RAW_MASK = 0x0000ffff,
 
-#ifdef __linux__
     POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY =
             android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
-#else
-    POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000,
-#endif
 
     /* These flags are set by the input dispatcher. */
 
@@ -485,10 +474,8 @@
 
     vec2 getXYValue() const { return vec2(getX(), getY()); }
 
-#ifdef __linux__
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
-#endif
 
     bool operator==(const PointerCoords& other) const;
     inline bool operator!=(const PointerCoords& other) const {
@@ -547,9 +534,9 @@
 
     inline void setSource(uint32_t source) { mSource = source; }
 
-    inline int32_t getDisplayId() const { return mDisplayId; }
+    inline ui::LogicalDisplayId getDisplayId() const { return mDisplayId; }
 
-    inline void setDisplayId(int32_t displayId) { mDisplayId = displayId; }
+    inline void setDisplayId(ui::LogicalDisplayId displayId) { mDisplayId = displayId; }
 
     inline std::array<uint8_t, 32> getHmac() const { return mHmac; }
 
@@ -558,7 +545,7 @@
     bool operator==(const InputEvent&) const = default;
 
 protected:
-    void initialize(int32_t id, DeviceId deviceId, uint32_t source, int32_t displayId,
+    void initialize(int32_t id, DeviceId deviceId, uint32_t source, ui::LogicalDisplayId displayId,
                     std::array<uint8_t, 32> hmac);
 
     void initialize(const InputEvent& from);
@@ -566,7 +553,7 @@
     int32_t mId;
     DeviceId mDeviceId;
     uint32_t mSource;
-    int32_t mDisplayId;
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::INVALID};
     std::array<uint8_t, 32> mHmac;
 };
 
@@ -602,7 +589,7 @@
     static const char* getLabel(int32_t keyCode);
     static std::optional<int> getKeyCodeFromLabel(const char* label);
 
-    void initialize(int32_t id, DeviceId deviceId, uint32_t source, int32_t displayId,
+    void initialize(int32_t id, DeviceId deviceId, uint32_t source, ui::LogicalDisplayId displayId,
                     std::array<uint8_t, 32> hmac, int32_t action, int32_t flags, int32_t keyCode,
                     int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime,
                     nsecs_t eventTime);
@@ -864,7 +851,7 @@
 
     ssize_t findPointerIndex(int32_t pointerId) const;
 
-    void initialize(int32_t id, DeviceId deviceId, uint32_t source, int32_t displayId,
+    void initialize(int32_t id, DeviceId deviceId, uint32_t source, ui::LogicalDisplayId displayId,
                     std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
                     int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState,
                     MotionClassification classification, const ui::Transform& transform,
@@ -911,10 +898,8 @@
     // Matrix is in row-major form and compatible with SkMatrix.
     void applyTransform(const std::array<float, 9>& matrix);
 
-#ifdef __linux__
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
-#endif
 
     static bool isTouchEvent(uint32_t source, int32_t action);
     inline bool isTouchEvent() const {
@@ -1073,7 +1058,7 @@
     DeviceId deviceId;
     nsecs_t eventTimeNanos;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
 };
 
 /**
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index e93fe8c..7d8c19e 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -280,7 +280,7 @@
 
     void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
                     const InputDeviceIdentifier& identifier, const std::string& alias,
-                    bool isExternal, bool hasMic, int32_t associatedDisplayId,
+                    bool isExternal, bool hasMic, ui::LogicalDisplayId associatedDisplayId,
                     InputDeviceViewBehavior viewBehavior = {{}}, bool enabled = true);
 
     inline int32_t getId() const { return mId; }
@@ -348,7 +348,7 @@
     }
     inline std::optional<InputDeviceUsiVersion> getUsiVersion() const { return mUsiVersion; }
 
-    inline int32_t getAssociatedDisplayId() const { return mAssociatedDisplayId; }
+    inline ui::LogicalDisplayId getAssociatedDisplayId() const { return mAssociatedDisplayId; }
 
     inline void setEnabled(bool enabled) { mEnabled = enabled; }
     inline bool isEnabled() const { return mEnabled; }
@@ -366,7 +366,7 @@
     int32_t mKeyboardType;
     std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
     std::optional<InputDeviceUsiVersion> mUsiVersion;
-    int32_t mAssociatedDisplayId;
+    ui::LogicalDisplayId mAssociatedDisplayId{ui::LogicalDisplayId::INVALID};
     bool mEnabled;
 
     bool mHasVibrator;
diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h
index c0c5e24..25d35e9 100644
--- a/include/input/InputEventBuilders.h
+++ b/include/input/InputEventBuilders.h
@@ -18,7 +18,6 @@
 
 #include <android/input.h>
 #include <attestation/HmacKeyManager.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 #include <utils/Timers.h> // for nsecs_t, systemTime
 
@@ -83,7 +82,7 @@
         return *this;
     }
 
-    MotionEventBuilder& displayId(int32_t displayId) {
+    MotionEventBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
     }
@@ -159,7 +158,7 @@
     int32_t mSource;
     nsecs_t mDownTime;
     nsecs_t mEventTime;
-    int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
     int32_t mActionButton{0};
     int32_t mButtonState{0};
     int32_t mFlags{0};
@@ -209,7 +208,7 @@
         return *this;
     }
 
-    KeyEventBuilder& displayId(int32_t displayId) {
+    KeyEventBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
     }
@@ -248,7 +247,7 @@
     uint32_t mSource;
     nsecs_t mDownTime;
     nsecs_t mEventTime;
-    int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
     uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
     int32_t mFlags{0};
     int32_t mKeyCode{AKEYCODE_UNKNOWN};
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 5f9c8f5..6548810 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -353,9 +353,10 @@
      * Other errors probably indicate that the channel is broken.
      */
     status_t publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source,
-                             int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action,
-                             int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-                             int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime);
+                             ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac,
+                             int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+                             int32_t metaState, int32_t repeatCount, nsecs_t downTime,
+                             nsecs_t eventTime);
 
     /* Publishes a motion event to the input channel.
      *
@@ -366,9 +367,9 @@
      * Other errors probably indicate that the channel is broken.
      */
     status_t publishMotionEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source,
-                                int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action,
-                                int32_t actionButton, int32_t flags, int32_t edgeFlags,
-                                int32_t metaState, int32_t buttonState,
+                                ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac,
+                                int32_t action, int32_t actionButton, int32_t flags,
+                                int32_t edgeFlags, int32_t metaState, int32_t buttonState,
                                 MotionClassification classification, const ui::Transform& transform,
                                 float xPrecision, float yPrecision, float xCursorPosition,
                                 float yCursorPosition, const ui::Transform& rawTransform,
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index dfcf766..92d5ec4 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -19,9 +19,7 @@
 #include <stdint.h>
 #include <list>
 
-#ifdef __linux__
 #include <binder/IBinder.h>
-#endif
 
 #include <android-base/result.h>
 #include <input/Input.h>
@@ -144,13 +142,11 @@
     std::pair<int32_t /*keyCode*/, int32_t /*metaState*/> applyKeyBehavior(int32_t keyCode,
                                                                            int32_t metaState) const;
 
-#ifdef __linux__
     /* Reads a key map from a parcel. */
     static std::unique_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel);
 
     /* Writes a key map to a parcel. */
     void writeToParcel(Parcel* parcel) const;
-#endif
 
     bool operator==(const KeyCharacterMap& other) const = default;
 
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/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 39573ec..fbcf823 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -20,6 +20,7 @@
 
 #include <inttypes.h>
 #include <unistd.h>
+#include <condition_variable>
 
 #include <android-base/properties.h>
 #include <android/os/BnServiceCallback.h>
@@ -642,7 +643,7 @@
 
 protected:
     // Override realGetService for ServiceManagerShim::waitForService.
-    Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
+    Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) override {
         *_aidl_return = getDeviceService({"-g", name}, mOptions);
         return Status::ok();
     }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 611169d..3f70e8c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2768,7 +2768,7 @@
         }
         if (type == BINDER_TYPE_FD) {
             // FDs from the kernel are always owned
-            FdTag(flat->handle, 0, this);
+            FdTag(flat->handle, nullptr, this);
         }
         minOffset = offset + sizeof(flat_binder_object);
     }
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index de2a69f..924537e 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -230,8 +230,8 @@
         }
 
         size_t memoryMappedSize = chunkPayloadSize + mmapPayloadStartOffset;
-        void* mappedMemory =
-                mmap(NULL, memoryMappedSize, PROT_READ, MAP_SHARED, fd.get(), mmapPageAlignedStart);
+        void* mappedMemory = mmap(nullptr, memoryMappedSize, PROT_READ, MAP_SHARED, fd.get(),
+                                  mmapPageAlignedStart);
         auto mmap_guard = make_scope_guard(
                 [mappedMemory, memoryMappedSize] { munmap(mappedMemory, memoryMappedSize); });
 
@@ -382,7 +382,7 @@
         return UNKNOWN_ERROR;
     }
 
-    if (NO_ERROR != writeChunk(fd, END_CHUNK, 0, NULL)) {
+    if (NO_ERROR != writeChunk(fd, END_CHUNK, 0, nullptr)) {
         ALOGE("Failed to write end chunk to fd %d", fd.get());
         return UNKNOWN_ERROR;
     }
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 665dfea..4fb8fa0 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -70,7 +70,7 @@
 }
 
 void Stability::tryMarkCompilationUnit(IBinder* binder) {
-    (void)setRepr(binder, getLocalLevel(), REPR_NONE);
+    std::ignore = setRepr(binder, getLocalLevel(), REPR_NONE);
 }
 
 // after deprecation of the VNDK, these should be aliases. At some point
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5e18b91..eb73037 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -1009,7 +1009,7 @@
             typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
     status_t writeData(const CT& c) {
         using T = first_template_type_t<CT>;  // The T in CT == C<T, ...>
-        if (c.size() >  std::numeric_limits<int32_t>::max()) return BAD_VALUE;
+        if (c.size() > static_cast<size_t>(std::numeric_limits<int32_t>::max())) return BAD_VALUE;
         const auto size = static_cast<int32_t>(c.size());
         writeData(size);
         if constexpr (is_pointer_equivalent_array_v<T>) {
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 18769b1..8c62924 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -377,7 +377,7 @@
 
 namespace internal {
 
-static void closeWithError(int fd) {
+inline void closeWithError(int fd) {
     if (fd == -1) return;
     int ret = close(fd);
     if (ret != 0) {
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index b1ab7b0..2929bce 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -718,9 +718,17 @@
  *     When registering the interface, add:
  *         std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
  *         std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
- *         ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
+ *         SpAIBinder binder = foo->asBinder(); // target binder to extend
+ *         ... = AIBinder_setExtension(binder.get(), bar->asBinder().get());
+ *         ... = AServiceManager_addService(binder.get(), instanceName);
  *         // handle error
  *
+ *         Do not use foo->asBinder().get() as the target binder argument to
+ *         AIBinder_setExtensions because asBinder it creates a new binder
+ *         object that will be destroyed after the function is called. The same
+ *         binder object must be used for AIBinder_setExtension and
+ *         AServiceManager_addService to register the service with an extension.
+ *
  *     Then, clients of IFoo can get this extension:
  *         SpAIBinder binder = ...;
  *         std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index ef556d7..725744c 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -59,6 +59,7 @@
     ],
     host_supported: true,
     vendor_available: true,
+    product_available: true,
     target: {
         darwin: {
             enabled: false,
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs
index 1dc0b24..71bb95b 100644
--- a/libs/binder/rust/binder_tokio/lib.rs
+++ b/libs/binder/rust/binder_tokio/lib.rs
@@ -34,6 +34,7 @@
 
 /// Retrieve an existing service for a particular interface, sleeping for a few
 /// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
 pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
     name: &str,
 ) -> Result<Strong<T>, StatusCode> {
@@ -56,6 +57,32 @@
     }
 }
 
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+///
+/// NOTE: "immediately" above does not mean the future will complete the first time it is polled.
+pub async fn check_interface<T: FromIBinder + ?Sized + 'static>(
+    name: &str,
+) -> Result<Strong<T>, StatusCode> {
+    if binder::is_handling_transaction() {
+        // See comment in the BinderAsyncPool impl.
+        return binder::check_interface::<T>(name);
+    }
+
+    let name = name.to_string();
+    let res = tokio::task::spawn_blocking(move || binder::check_interface::<T>(&name)).await;
+
+    // The `is_panic` branch is not actually reachable in Android as we compile
+    // with `panic = abort`.
+    match res {
+        Ok(Ok(service)) => Ok(service),
+        Ok(Err(err)) => Err(err),
+        Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+        Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
+        Err(_) => Err(StatusCode::UNKNOWN_ERROR),
+    }
+}
+
 /// Retrieve an existing service for a particular interface, or start it if it
 /// is configured as a dynamic service and isn't yet started.
 pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 0f9c58c..e70f4f0 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -114,9 +114,9 @@
 pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
 #[cfg(not(trusty))]
 pub use service::{
-    add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service,
-    is_declared, is_handling_transaction, register_lazy_service, wait_for_interface,
-    wait_for_service, LazyServiceGuard,
+    add_service, check_interface, check_service, force_lazy_services_persist,
+    get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction,
+    register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard,
 };
 #[cfg(not(trusty))]
 pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/service.rs b/libs/binder/rust/src/service.rs
index 3ca3b54..29dd8e1 100644
--- a/libs/binder/rust/src/service.rs
+++ b/libs/binder/rust/src/service.rs
@@ -144,6 +144,7 @@
 
 /// Retrieve an existing service, blocking for a few seconds if it doesn't yet
 /// exist.
+#[deprecated = "this polls 5s, use wait_for_service or check_service"]
 pub fn get_service(name: &str) -> Option<SpIBinder> {
     let name = CString::new(name).ok()?;
     // Safety: `AServiceManager_getService` returns either a null pointer or a
@@ -152,6 +153,15 @@
     unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) }
 }
 
+/// Retrieve an existing service. Returns `None` immediately if the service is not available.
+pub fn check_service(name: &str) -> Option<SpIBinder> {
+    let name = CString::new(name).ok()?;
+    // Safety: `AServiceManager_checkService` returns either a null pointer or
+    // a valid pointer to an owned `AIBinder`. Either of these values is safe to
+    // pass to `SpIBinder::from_raw`.
+    unsafe { SpIBinder::from_raw(sys::AServiceManager_checkService(name.as_ptr())) }
+}
+
 /// Retrieve an existing service, or start it if it is configured as a dynamic
 /// service and isn't yet started.
 pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
@@ -164,10 +174,17 @@
 
 /// Retrieve an existing service for a particular interface, blocking for a few
 /// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
 pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
     interface_cast(get_service(name))
 }
 
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+pub fn check_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+    interface_cast(check_service(name))
+}
+
 /// Retrieve an existing service for a particular interface, or start it if it
 /// is configured as a dynamic service and isn't yet started.
 pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index c87fa89..15ae56f 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -421,7 +421,7 @@
     }
 
     #[test]
-    fn check_services() {
+    fn check_get_service() {
         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
         assert!(sm.is_binder_alive());
         assert!(sm.ping_binder().is_ok());
@@ -445,7 +445,7 @@
     }
 
     #[tokio::test]
-    async fn check_services_async() {
+    async fn check_get_service_async() {
         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
         assert!(sm.is_binder_alive());
         assert!(sm.ping_binder().is_ok());
@@ -474,6 +474,62 @@
     }
 
     #[test]
+    fn check_check_service() {
+        let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+        assert!(sm.is_binder_alive());
+        assert!(sm.ping_binder().is_ok());
+
+        assert!(binder::check_service("this_service_does_not_exist").is_none());
+        assert_eq!(
+            binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+        assert_eq!(
+            binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+
+        // The service manager service isn't an ITest, so this must fail.
+        assert_eq!(
+            binder::check_interface::<dyn ITest>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+        assert_eq!(
+            binder::check_interface::<dyn IATest<Tokio>>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+    }
+
+    #[tokio::test]
+    async fn check_check_service_async() {
+        let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+        assert!(sm.is_binder_alive());
+        assert!(sm.ping_binder().is_ok());
+
+        assert!(binder::check_service("this_service_does_not_exist").is_none());
+        assert_eq!(
+            binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+        assert_eq!(
+            binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
+                .await
+                .err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+
+        // The service manager service isn't an ITest, so this must fail.
+        assert_eq!(
+            binder_tokio::check_interface::<dyn ITest>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+        assert_eq!(
+            binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+    }
+
+    #[test]
     fn check_wait_for_service() {
         let mut sm =
             binder::wait_for_service("manager").expect("Did not get manager binder service");
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 6800a8d..bd24a20 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -28,6 +28,11 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wformat",
+        "-Wpessimizing-move",
+        "-Wsign-compare",
+        "-Wunused-result",
+        "-Wzero-as-null-pointer-constant",
     ],
 }
 
diff --git a/libs/binder/tests/RpcTlsUtilsTest.cpp b/libs/binder/tests/RpcTlsUtilsTest.cpp
index 530606c..48e3345 100644
--- a/libs/binder/tests/RpcTlsUtilsTest.cpp
+++ b/libs/binder/tests/RpcTlsUtilsTest.cpp
@@ -52,9 +52,9 @@
             << "\nactual: " << toDebugString(deserializedPkey.get());
 }
 
-INSTANTIATE_TEST_CASE_P(RpcTlsUtilsTest, RpcTlsUtilsKeyTest,
-                        testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
-                        RpcTlsUtilsKeyTest::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(RpcTlsUtilsTest, RpcTlsUtilsKeyTest,
+                         testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
+                         RpcTlsUtilsKeyTest::PrintParamInfo);
 
 class RpcTlsUtilsCertTest : public testing::TestWithParam<RpcCertificateFormat> {
 public:
@@ -75,9 +75,9 @@
     EXPECT_EQ(0, X509_cmp(cert.get(), deserializedCert.get()));
 }
 
-INSTANTIATE_TEST_CASE_P(RpcTlsUtilsTest, RpcTlsUtilsCertTest,
-                        testing::Values(RpcCertificateFormat::PEM, RpcCertificateFormat::DER),
-                        RpcTlsUtilsCertTest::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(RpcTlsUtilsTest, RpcTlsUtilsCertTest,
+                         testing::Values(RpcCertificateFormat::PEM, RpcCertificateFormat::DER),
+                         RpcTlsUtilsCertTest::PrintParamInfo);
 
 class RpcTlsUtilsKeyAndCertTest
       : public testing::TestWithParam<std::tuple<RpcKeyFormat, RpcCertificateFormat>> {
@@ -105,10 +105,10 @@
     EXPECT_EQ(0, X509_cmp(cert.get(), deserializedCert.get()));
 }
 
-INSTANTIATE_TEST_CASE_P(RpcTlsUtilsTest, RpcTlsUtilsKeyAndCertTest,
-                        testing::Combine(testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
-                                         testing::Values(RpcCertificateFormat::PEM,
-                                                         RpcCertificateFormat::DER)),
-                        RpcTlsUtilsKeyAndCertTest::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(RpcTlsUtilsTest, RpcTlsUtilsKeyAndCertTest,
+                         testing::Combine(testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
+                                          testing::Values(RpcCertificateFormat::PEM,
+                                                          RpcCertificateFormat::DER)),
+                         RpcTlsUtilsKeyAndCertTest::PrintParamInfo);
 
 } // namespace android
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index 7e0b594..c0c0aae 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -114,12 +114,12 @@
     {
         const auto on_malloc = OnMalloc([&](size_t bytes) {
             mallocs++;
-            EXPECT_EQ(bytes, 40);
+            EXPECT_EQ(bytes, 40u);
         });
 
         imaginary_use = new int[10];
     }
-    EXPECT_EQ(mallocs, 1);
+    EXPECT_EQ(mallocs, 1u);
 }
 
 
@@ -196,9 +196,9 @@
         // Happens to be SM package length. We could switch to forking
         // and registering our own service if it became an issue.
 #if defined(__LP64__)
-        EXPECT_EQ(bytes, 78);
+        EXPECT_EQ(bytes, 78u);
 #else
-        EXPECT_EQ(bytes, 70);
+        EXPECT_EQ(bytes, 70u);
 #endif
     });
 
@@ -206,7 +206,7 @@
     a_binder->getInterfaceDescriptor();
     a_binder->getInterfaceDescriptor();
 
-    EXPECT_EQ(mallocs, 1);
+    EXPECT_EQ(mallocs, 1u);
 }
 
 TEST(BinderAllocation, SmallTransaction) {
@@ -217,11 +217,11 @@
     const auto on_malloc = OnMalloc([&](size_t bytes) {
         mallocs++;
         // Parcel should allocate a small amount by default
-        EXPECT_EQ(bytes, 128);
+        EXPECT_EQ(bytes, 128u);
     });
     manager->checkService(empty_descriptor);
 
-    EXPECT_EQ(mallocs, 1);
+    EXPECT_EQ(mallocs, 1u);
 }
 
 TEST(RpcBinderAllocation, SetupRpcServer) {
@@ -250,8 +250,8 @@
         });
         ASSERT_EQ(OK, remoteBinder->pingBinder());
     }
-    EXPECT_EQ(mallocs, 1);
-    EXPECT_EQ(totalBytes, 40);
+    EXPECT_EQ(mallocs, 1u);
+    EXPECT_EQ(totalBytes, 40u);
 }
 
 int main(int argc, char** argv) {
diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp
index e43ee5f..3230a3f 100644
--- a/libs/binder/tests/binderClearBufTest.cpp
+++ b/libs/binder/tests/binderClearBufTest.cpp
@@ -88,7 +88,7 @@
     // the buffer must have at least some length for the string, but we will
     // just check it has some length, to avoid assuming anything about the
     // format
-    EXPECT_GT(replyBuffer.size(), 0);
+    EXPECT_GT(replyBuffer.size(), 0u);
 
     for (size_t i = 0; i < replyBuffer.size(); i++) {
         EXPECT_EQ(replyBuffer[i], '0') << "reply buffer at " << i;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 1f61f18..9788d9d 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -528,8 +528,8 @@
     EXPECT_EQ(NO_ERROR, IPCThreadState::self()->getProcessFreezeInfo(pid, &sync_received,
                 &async_received));
 
-    EXPECT_EQ(sync_received, 1);
-    EXPECT_EQ(async_received, 0);
+    EXPECT_EQ(sync_received, 1u);
+    EXPECT_EQ(async_received, 0u);
 
     EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, false, 0));
     EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
@@ -1238,13 +1238,13 @@
     data.setDataCapacity(1024);
     // Write a bogus object at offset 0 to get an entry in the offset table
     data.writeFileDescriptor(0);
-    EXPECT_EQ(data.objectsCount(), 1);
+    EXPECT_EQ(data.objectsCount(), 1u);
     uint8_t *parcelData = const_cast<uint8_t*>(data.data());
     // And now, overwrite it with the buffer object
     memcpy(parcelData, &obj, sizeof(obj));
     data.setDataSize(sizeof(obj));
 
-    EXPECT_EQ(data.objectsCount(), 1);
+    EXPECT_EQ(data.objectsCount(), 1u);
 
     // Either the kernel should reject this transaction (if it's correct), but
     // if it's not, the server implementation should return an error if it
@@ -1269,7 +1269,7 @@
     data.setDataCapacity(1024);
     // Write a bogus object at offset 0 to get an entry in the offset table
     data.writeFileDescriptor(0);
-    EXPECT_EQ(data.objectsCount(), 1);
+    EXPECT_EQ(data.objectsCount(), 1u);
     uint8_t *parcelData = const_cast<uint8_t *>(data.data());
     // And now, overwrite it with the weak binder
     memcpy(parcelData, &obj, sizeof(obj));
@@ -1279,7 +1279,7 @@
     // test with an object that libbinder will actually try to release
     EXPECT_EQ(OK, data.writeStrongBinder(sp<BBinder>::make()));
 
-    EXPECT_EQ(data.objectsCount(), 2);
+    EXPECT_EQ(data.objectsCount(), 2u);
 
     // send it many times, since previous error was memory corruption, make it
     // more likely that the server crashes
@@ -1648,8 +1648,8 @@
     EXPECT_THAT(binder->setRpcClientDebug(std::move(socket), nullptr),
                 Debuggable(StatusEq(UNEXPECTED_NULL)));
 }
-INSTANTIATE_TEST_CASE_P(BinderLibTest, BinderLibRpcTestP, testing::Bool(),
-                        BinderLibRpcTestP::ParamToString);
+INSTANTIATE_TEST_SUITE_P(BinderLibTest, BinderLibRpcTestP, testing::Bool(),
+                         BinderLibRpcTestP::ParamToString);
 
 class BinderLibTestService : public BBinder {
 public:
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 4f10d74..865f0ec 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -216,7 +216,7 @@
     // by how many binder calls work together (and by factors like the scheduler,
     // thermal throttling, core choice, etc..).
     std::string str = std::string(getpagesize() * 2, 'a');
-    CHECK_EQ(str.size(), getpagesize() * 2);
+    CHECK_EQ(static_cast<ssize_t>(str.size()), getpagesize() * 2);
 
     while (state.KeepRunning()) {
         std::string out;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 2769a88..c044d39 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -64,12 +64,12 @@
 
 static std::string WaitStatusToString(int wstatus) {
     if (WIFEXITED(wstatus)) {
-        return std::format("exit status {}", WEXITSTATUS(wstatus));
+        return "exit status " + std::to_string(WEXITSTATUS(wstatus));
     }
     if (WIFSIGNALED(wstatus)) {
-        return std::format("term signal {}", WTERMSIG(wstatus));
+        return "term signal " + std::to_string(WTERMSIG(wstatus));
     }
-    return std::format("unexpected state {}", wstatus);
+    return "unexpected state " + std::to_string(wstatus);
 }
 
 static void debugBacktrace(pid_t pid) {
@@ -177,7 +177,7 @@
 
             EXPECT_NE(nullptr, session);
             EXPECT_NE(nullptr, session->state());
-            EXPECT_EQ(0, session->state()->countBinders()) << (session->state()->dump(), "dump:");
+            EXPECT_EQ(0u, session->state()->countBinders()) << (session->state()->dump(), "dump:");
 
             wp<RpcSession> weakSession = session;
             session = nullptr;
@@ -235,7 +235,7 @@
     if (binder::os::sendMessageOnSocket(transportFd, &iov, 1, &fds) < 0) {
         PLOGF("Failed sendMessageOnSocket");
     }
-    return std::move(sockClient);
+    return sockClient;
 }
 #endif // BINDER_RPC_TO_TRUSTY_TEST
 
@@ -263,9 +263,8 @@
     bool noKernel = GetParam().noKernel;
 
     std::string path = GetExecutableDirectory();
-    auto servicePath =
-            std::format("{}/binder_rpc_test_service{}{}", path,
-                        singleThreaded ? "_single_threaded" : "", noKernel ? "_no_kernel" : "");
+    auto servicePath = path + "/binder_rpc_test_service" +
+            (singleThreaded ? "_single_threaded" : "") + (noKernel ? "_no_kernel" : "");
 
     unique_fd bootstrapClientFd, socketFd;
 
@@ -623,7 +622,7 @@
     for (size_t i = 0; i + 1 < kNumQueued; i++) {
         int n;
         proc.rootIface->blockingRecvInt(&n);
-        EXPECT_EQ(n, i);
+        EXPECT_EQ(n, static_cast<ssize_t>(i));
     }
 
     saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
@@ -1148,8 +1147,8 @@
     return ret;
 }
 
-INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderRpcParams()),
-                        BinderRpc::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderRpcParams()),
+                         BinderRpc::PrintParamInfo);
 #else // BINDER_RPC_TO_TRUSTY_TEST
 bool testSupportVsockLoopback() {
     // We don't need to enable TLS to know if vsock is supported.
@@ -1308,8 +1307,8 @@
     return ret;
 }
 
-INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc, ::testing::ValuesIn(getBinderRpcParams()),
-                        BinderRpc::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(PerSocket, BinderRpc, ::testing::ValuesIn(getBinderRpcParams()),
+                         BinderRpc::PrintParamInfo);
 
 class BinderRpcServerRootObject
       : public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
@@ -1337,9 +1336,9 @@
     EXPECT_EQ((isStrong2 ? binderRaw2 : nullptr), server->getRootObject());
 }
 
-INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerRootObject,
-                        ::testing::Combine(::testing::Bool(), ::testing::Bool(),
-                                           ::testing::ValuesIn(RpcSecurityValues())));
+INSTANTIATE_TEST_SUITE_P(BinderRpc, BinderRpcServerRootObject,
+                         ::testing::Combine(::testing::Bool(), ::testing::Bool(),
+                                            ::testing::ValuesIn(RpcSecurityValues())));
 
 class OneOffSignal {
 public:
@@ -1384,7 +1383,7 @@
     auto binder = sm->checkService(String16("batteryproperties"));
     ASSERT_NE(nullptr, binder);
     auto descriptor = binder->getInterfaceDescriptor();
-    ASSERT_GE(descriptor.size(), 0);
+    ASSERT_GE(descriptor.size(), 0u);
     ASSERT_EQ(OK, binder->pingBinder());
 
     auto rpcServer = RpcServer::make();
@@ -1468,10 +1467,10 @@
             << "After server->shutdown() returns true, join() did not stop after 2s";
 }
 
-INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerOnly,
-                        ::testing::Combine(::testing::ValuesIn(RpcSecurityValues()),
-                                           ::testing::ValuesIn(testVersions())),
-                        BinderRpcServerOnly::PrintTestParam);
+INSTANTIATE_TEST_SUITE_P(BinderRpc, BinderRpcServerOnly,
+                         ::testing::Combine(::testing::ValuesIn(RpcSecurityValues()),
+                                            ::testing::ValuesIn(testVersions())),
+                         BinderRpcServerOnly::PrintTestParam);
 
 class RpcTransportTestUtils {
 public:
@@ -2018,9 +2017,9 @@
     server->shutdown();
 }
 
-INSTANTIATE_TEST_CASE_P(BinderRpc, RpcTransportTest,
-                        ::testing::ValuesIn(RpcTransportTest::getRpcTranportTestParams()),
-                        RpcTransportTest::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(BinderRpc, RpcTransportTest,
+                         ::testing::ValuesIn(RpcTransportTest::getRpcTranportTestParams()),
+                         RpcTransportTest::PrintParamInfo);
 
 class RpcTransportTlsKeyTest
       : public testing::TestWithParam<
@@ -2075,7 +2074,7 @@
     client.run();
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
         BinderRpc, RpcTransportTlsKeyTest,
         testing::Combine(testing::ValuesIn(testSocketTypes(false /* hasPreconnected*/)),
                          testing::Values(RpcCertificateFormat::PEM, RpcCertificateFormat::DER),
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 8832f1a..acc0373 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -60,7 +60,6 @@
 #include "../FdUtils.h"
 #include "../RpcState.h" // for debugging
 #include "FileUtils.h"
-#include "format.h"
 #include "utils/Errors.h"
 
 namespace android {
@@ -99,7 +98,7 @@
 }
 
 static inline std::string trustyIpcPort(uint32_t serverVersion) {
-    return std::format("com.android.trusty.binderRpcTestService.V{}", serverVersion);
+    return "com.android.trusty.binderRpcTestService.V" + std::to_string(serverVersion);
 }
 
 enum class SocketType {
@@ -210,7 +209,7 @@
             return RpcTransportCtxFactoryTls::make(std::move(verifier), std::move(auth));
         }
         default:
-            LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
+            LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", static_cast<int>(rpcSecurity));
     }
 }
 
@@ -256,7 +255,7 @@
         mValue.reset();
         lock.unlock();
         mCvEmpty.notify_all();
-        return std::move(v);
+        return v;
     }
 
 private:
diff --git a/libs/binder/tests/binderRpcTestTrusty.cpp b/libs/binder/tests/binderRpcTestTrusty.cpp
index 18751cc..31c0eba 100644
--- a/libs/binder/tests/binderRpcTestTrusty.cpp
+++ b/libs/binder/tests/binderRpcTestTrusty.cpp
@@ -45,7 +45,7 @@
         case RpcSecurity::RAW:
             return RpcTransportCtxFactoryTipcTrusty::make();
         default:
-            LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
+            LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", static_cast<int>(rpcSecurity));
     }
 }
 
@@ -110,8 +110,8 @@
     return ret;
 }
 
-INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderRpcParams()),
-                        BinderRpc::PrintParamInfo);
+INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderRpcParams()),
+                         BinderRpc::PrintParamInfo);
 
 } // namespace android
 
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 41cb552..0aa678d 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -723,7 +723,7 @@
     ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
 }
 
-TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
+TEST_F(SafeInterfaceTest, TestIncrementParcelableVector) {
     const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
     std::vector<TestParcelable> aPlusOne;
     status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
diff --git a/libs/binder/tests/format.h b/libs/binder/tests/format.h
deleted file mode 100644
index c588de7..0000000
--- a/libs/binder/tests/format.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO(b/302723053): remove this header and replace with <format> once b/175635923 is done
-// ETA for this blocker is 2023-10-27~2023-11-10.
-// Also, remember to remove fmtlib's format.cc from trusty makefiles.
-
-#if __has_include(<format>) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
-#include <format>
-#else
-#include <fmt/format.h>
-
-namespace std {
-using fmt::format;
-}
-#endif
\ No newline at end of file
diff --git a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
index 73a15be..82f528e 100644
--- a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
+++ b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//!
-
 use crate::{
     buffers::BufferPool, subscriptions::SharedBufferSubscription, BufferPublisher,
     BufferSubscriber, Frame, StreamConfig,
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 6ccc6ca..81f6a58 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,9 @@
 static constexpr uint64_t NSEC_PER_SEC = 1000000000;
 static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
 
+// Declare busy loop variable globally to prevent removal during optimization
+static long sum __attribute__((used)) = 0;
+
 using std::vector;
 
 class TimeInStateTest : public testing::Test {
@@ -576,7 +579,7 @@
 
 // Keeps CPU busy with some number crunching
 void useCpu() {
-    long sum = 0;
+    sum = 0;
     for (int i = 0; i < 100000; i++) {
         sum *= i;
     }
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index 32b2b68..368f5e0 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -24,6 +24,7 @@
         "flags_test.cpp",
         "function_test.cpp",
         "future_test.cpp",
+        "hash_test.cpp",
         "match_test.cpp",
         "mixins_test.cpp",
         "non_null_test.cpp",
@@ -40,5 +41,6 @@
         "-Wextra",
         "-Wpedantic",
         "-Wthread-safety",
+        "-Wno-gnu-statement-expression-from-macro-expansion",
     ],
 }
diff --git a/libs/ftl/expected_test.cpp b/libs/ftl/expected_test.cpp
index 8cb07e4..9b7f017 100644
--- a/libs/ftl/expected_test.cpp
+++ b/libs/ftl/expected_test.cpp
@@ -15,8 +15,11 @@
  */
 
 #include <ftl/expected.h>
+#include <ftl/optional.h>
+#include <ftl/unit.h>
 #include <gtest/gtest.h>
 
+#include <cctype>
 #include <string>
 #include <system_error>
 
@@ -74,4 +77,42 @@
   }
 }
 
+namespace {
+
+IntExp increment(IntExp exp) {
+  const int i = FTL_TRY(exp);
+  return IntExp(i + 1);
+}
+
+StringExp repeat(StringExp exp) {
+  const std::string str = FTL_TRY(exp);
+  return StringExp(str + str);
+}
+
+void uppercase(char& c, ftl::Optional<char> opt) {
+  c = std::toupper(FTL_TRY(std::move(opt).ok_or(ftl::Unit())));
+}
+
+}  // namespace
+
+// Keep in sync with example usage in header file.
+TEST(Expected, Try) {
+  EXPECT_EQ(IntExp(100), increment(IntExp(99)));
+  EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::value_too_large)).has_error([](std::errc e) {
+    return e == std::errc::value_too_large;
+  }));
+
+  EXPECT_EQ(StringExp("haha"s), repeat(StringExp("ha"s)));
+  EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
+    return e == std::errc::bad_message;
+  }));
+
+  char c = '?';
+  uppercase(c, std::nullopt);
+  EXPECT_EQ(c, '?');
+
+  uppercase(c, 'a');
+  EXPECT_EQ(c, 'A');
+}
+
 }  // namespace android::test
diff --git a/libs/ftl/hash_test.cpp b/libs/ftl/hash_test.cpp
new file mode 100644
index 0000000..9c7b8c2
--- /dev/null
+++ b/libs/ftl/hash_test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ftl/hash.h>
+#include <gtest/gtest.h>
+
+#include <numeric>
+#include <string>
+
+namespace android::test {
+
+TEST(Hash, StableHash) {
+  EXPECT_EQ(11160318154034397263ull, (ftl::stable_hash({})));
+
+  std::string string(64, '?');
+  std::iota(string.begin(), string.end(), 'A');
+
+  // Maximum length is 64 characters.
+  EXPECT_FALSE(ftl::stable_hash(string + '\n'));
+
+  EXPECT_EQ(6278090252846864564ull, ftl::stable_hash(std::string_view(string).substr(0, 8)));
+  EXPECT_EQ(1883356980931444616ull, ftl::stable_hash(std::string_view(string).substr(0, 16)));
+  EXPECT_EQ(8073093283835059304ull, ftl::stable_hash(std::string_view(string).substr(0, 32)));
+  EXPECT_EQ(18197365392429149980ull, ftl::stable_hash(string));
+}
+
+}  // namespace android::test
diff --git a/libs/ftl/optional_test.cpp b/libs/ftl/optional_test.cpp
index 91bf7bc..e7f1f14 100644
--- a/libs/ftl/optional_test.cpp
+++ b/libs/ftl/optional_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <ftl/expected.h>
 #include <ftl/optional.h>
 #include <ftl/static_vector.h>
 #include <ftl/string.h>
@@ -23,6 +24,7 @@
 #include <cstdlib>
 #include <functional>
 #include <numeric>
+#include <system_error>
 #include <utility>
 
 using namespace std::placeholders;
@@ -204,6 +206,19 @@
                      .or_else([] { return Optional(-1); }));
 }
 
+TEST(Optional, OkOr) {
+  using CharExp = ftl::Expected<char, std::errc>;
+  using StringExp = ftl::Expected<std::string, std::errc>;
+
+  EXPECT_EQ(CharExp('z'), Optional('z').ok_or(std::errc::broken_pipe));
+  EXPECT_EQ(CharExp(ftl::Unexpected(std::errc::broken_pipe)),
+            Optional<char>().ok_or(std::errc::broken_pipe));
+
+  EXPECT_EQ(StringExp("abc"s), Optional("abc"s).ok_or(std::errc::protocol_error));
+  EXPECT_EQ(StringExp(ftl::Unexpected(std::errc::protocol_error)),
+            Optional<std::string>().ok_or(std::errc::protocol_error));
+}
+
 // Comparison.
 namespace {
 
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index 7b74214..33cebe3 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -96,6 +96,7 @@
     if ((status = parcel->writeUint64(vulkanDeviceFeaturesEnabled)) != OK) return status;
     if ((status = parcel->writeInt32Vector(vulkanInstanceExtensions)) != OK) return status;
     if ((status = parcel->writeInt32Vector(vulkanDeviceExtensions)) != OK) return status;
+    if ((status = parcel->writeUtf8VectorAsUtf16Vector(vulkanEngineNames)) != OK) return status;
 
     return OK;
 }
@@ -118,6 +119,7 @@
     if ((status = parcel->readUint64(&vulkanDeviceFeaturesEnabled)) != OK) return status;
     if ((status = parcel->readInt32Vector(&vulkanInstanceExtensions)) != OK) return status;
     if ((status = parcel->readInt32Vector(&vulkanDeviceExtensions)) != OK) return status;
+    if ((status = parcel->readUtf8VectorFromUtf16Vector(&vulkanEngineNames)) != OK) return status;
 
     return OK;
 }
@@ -161,6 +163,11 @@
         StringAppendF(&result, " 0x%x", extension);
     }
     result.append("\n");
+    result.append("vulkanEngineNames:");
+    for (const std::string& engineName : vulkanEngineNames) {
+        StringAppendF(&result, " %s,", engineName.c_str());
+    }
+    result.append("\n");
     return result;
 }
 
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 50c05f4..52383ac 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -445,6 +445,21 @@
                         extensionHashes, numStats);
 }
 
+void GraphicsEnv::addVulkanEngineName(const char* engineName) {
+    ATRACE_CALL();
+    if (engineName == nullptr) {
+        return;
+    }
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    if (!readyToSendGpuStatsLocked()) return;
+
+    const sp<IGpuService> gpuService = getGpuService();
+    if (gpuService) {
+        gpuService->addVulkanEngineName(mGpuStats.appPackageName, mGpuStats.driverVersionCode,
+                                        engineName);
+    }
+}
+
 bool GraphicsEnv::readyToSendGpuStatsLocked() {
     // Only send stats for processes having at least one activity launched and that process doesn't
     // skip the GraphicsEnvironment setup.
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 5dc195c..42e7c37 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -77,6 +77,19 @@
                            IBinder::FLAG_ONEWAY);
     }
 
+    void addVulkanEngineName(const std::string& appPackageName, const uint64_t driverVersionCode,
+                             const char* engineName) override {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
+
+        data.writeUtf8AsUtf16(appPackageName);
+        data.writeUint64(driverVersionCode);
+        data.writeCString(engineName);
+
+        remote()->transact(BnGpuService::ADD_VULKAN_ENGINE_NAME, data, &reply,
+                           IBinder::FLAG_ONEWAY);
+    }
+
     void setUpdatableDriverPath(const std::string& driverPath) override {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
@@ -197,6 +210,21 @@
 
             return OK;
         }
+        case ADD_VULKAN_ENGINE_NAME: {
+            CHECK_INTERFACE(IGpuService, data, reply);
+
+            std::string appPackageName;
+            if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
+
+            uint64_t driverVersionCode;
+            if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
+
+            const char* engineName;
+            if ((engineName = data.readCString()) == nullptr) return BAD_VALUE;
+
+            addVulkanEngineName(appPackageName, driverVersionCode, engineName);
+            return OK;
+        }
         case SET_UPDATABLE_DRIVER_PATH: {
             CHECK_INTERFACE(IGpuService, data, reply);
 
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 9ebaf16..23f583b 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -60,6 +60,10 @@
 public:
     // This limits the worst case number of extensions to be tracked.
     static const uint32_t MAX_NUM_EXTENSIONS = 100;
+    // Max number of vulkan engine names for a single GpuStatsAppInfo
+    static const uint32_t MAX_VULKAN_ENGINE_NAMES = 16;
+    // Max length of a vulkan engine name string
+    static const size_t MAX_VULKAN_ENGINE_NAME_LENGTH = 50;
 
     GpuStatsAppInfo() = default;
     GpuStatsAppInfo(const GpuStatsAppInfo&) = default;
@@ -84,6 +88,7 @@
     uint64_t vulkanDeviceFeaturesEnabled = 0;
     std::vector<int32_t> vulkanInstanceExtensions = {};
     std::vector<int32_t> vulkanDeviceExtensions = {};
+    std::vector<std::string> vulkanEngineNames = {};
 
     std::chrono::time_point<std::chrono::system_clock> lastAccessTime;
 };
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 6cce3f6..b0ab0b9 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -89,6 +89,8 @@
     // Set which device extensions are enabled for the app.
     void setVulkanDeviceExtensions(uint32_t enabledExtensionCount,
                                    const char* const* ppEnabledExtensionNames);
+    // Add the engine name passed in VkApplicationInfo during CreateInstance
+    void addVulkanEngineName(const char* engineName);
 
     /*
      * Api for Vk/GL layer injection.  Presently, drivers enable certain
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 45f05d6..a0d6e37 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -46,6 +46,8 @@
                                      const uint64_t driverVersionCode,
                                      const GpuStatsInfo::Stats stats, const uint64_t* values,
                                      const uint32_t valueCount) = 0;
+    virtual void addVulkanEngineName(const std::string& appPackageName,
+                                     const uint64_t driverVersionCode, const char* engineName) = 0;
 
     // setter and getter for updatable driver path.
     virtual void setUpdatableDriverPath(const std::string& driverPath) = 0;
@@ -64,6 +66,7 @@
         GET_UPDATABLE_DRIVER_PATH,
         TOGGLE_ANGLE_AS_SYSTEM_DRIVER,
         SET_TARGET_STATS_ARRAY,
+        ADD_VULKAN_ENGINE_NAME,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/DisplayInfo.cpp b/libs/gui/DisplayInfo.cpp
index bd640df..47cec07 100644
--- a/libs/gui/DisplayInfo.cpp
+++ b/libs/gui/DisplayInfo.cpp
@@ -37,8 +37,9 @@
         return BAD_VALUE;
     }
 
+    int32_t displayIdInt;
     float dsdx, dtdx, tx, dtdy, dsdy, ty;
-    SAFE_PARCEL(parcel->readInt32, &displayId);
+    SAFE_PARCEL(parcel->readInt32, &displayIdInt);
     SAFE_PARCEL(parcel->readInt32, &logicalWidth);
     SAFE_PARCEL(parcel->readInt32, &logicalHeight);
     SAFE_PARCEL(parcel->readFloat, &dsdx);
@@ -48,6 +49,7 @@
     SAFE_PARCEL(parcel->readFloat, &dsdy);
     SAFE_PARCEL(parcel->readFloat, &ty);
 
+    displayId = ui::LogicalDisplayId{displayIdInt};
     transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
 
     return OK;
@@ -59,7 +61,7 @@
         return BAD_VALUE;
     }
 
-    SAFE_PARCEL(parcel->writeInt32, displayId);
+    SAFE_PARCEL(parcel->writeInt32, displayId.val());
     SAFE_PARCEL(parcel->writeInt32, logicalWidth);
     SAFE_PARCEL(parcel->writeInt32, logicalHeight);
     SAFE_PARCEL(parcel->writeFloat, transform.dsdx());
@@ -76,7 +78,7 @@
     using android::base::StringAppendF;
 
     out += prefix;
-    StringAppendF(&out, "DisplayViewport[id=%" PRId32 "]\n", displayId);
+    StringAppendF(&out, "DisplayViewport[id=%s]\n", displayId.toString().c_str());
     out += prefix;
     StringAppendF(&out, INDENT "Width=%" PRId32 ", Height=%" PRId32 "\n", logicalWidth,
                   logicalHeight);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3743025..0a85cf8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -89,6 +89,8 @@
 void emptyCallback(nsecs_t, const sp<Fence>&, const std::vector<SurfaceControlStats>&) {}
 } // namespace
 
+const std::string SurfaceComposerClient::kEmpty{};
+
 ComposerService::ComposerService()
 : Singleton<ComposerService>() {
     Mutex::Autolock _l(mLock);
@@ -1278,19 +1280,22 @@
 }
 // ---------------------------------------------------------------------------
 
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure,
-                                                 float requestedRefereshRate) {
+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()),
-                                                                     secure, requestedRefereshRate,
-                                                                     &display);
+            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/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index ad0d99d..82d2554 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -146,7 +146,7 @@
         parcel->writeInt32(ownerUid.val()) ?:
         parcel->writeUtf8AsUtf16(packageName) ?:
         parcel->writeInt32(inputConfig.get()) ?:
-        parcel->writeInt32(displayId) ?:
+        parcel->writeInt32(displayId.val()) ?:
         applicationInfo.writeToParcel(parcel) ?:
         parcel->write(touchableRegion) ?:
         parcel->writeBool(replaceTouchableRegionWithCrop) ?:
@@ -175,7 +175,8 @@
     }
 
     float dsdx, dtdx, tx, dtdy, dsdy, ty;
-    int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt;
+    int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt,
+            displayIdInt;
     sp<IBinder> touchableRegionCropHandleSp;
 
     // clang-format off
@@ -198,7 +199,7 @@
         parcel->readInt32(&ownerUidInt) ?:
         parcel->readUtf8FromUtf16(&packageName) ?:
         parcel->readInt32(&inputConfigInt) ?:
-        parcel->readInt32(&displayId) ?:
+        parcel->readInt32(&displayIdInt) ?:
         applicationInfo.readFromParcel(parcel) ?:
         parcel->read(touchableRegion) ?:
         parcel->readBool(&replaceTouchableRegionWithCrop) ?:
@@ -221,6 +222,7 @@
     ownerPid = Pid{ownerPidInt};
     ownerUid = Uid{static_cast<uid_t>(ownerUidInt)};
     touchableRegionCropHandle = touchableRegionCropHandleSp;
+    displayId = ui::LogicalDisplayId{displayIdInt};
 
     return OK;
 }
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index a2549e7..11ccc9c 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -72,7 +72,7 @@
     void bootFinished();
 
     /**
-     * Create a display event connection
+     * Create a display event connection.
      *
      * layerHandle
      *     Optional binder handle representing a Layer in SF to associate the new
@@ -89,12 +89,14 @@
     @nullable ISurfaceComposerClient createConnection();
 
     /**
-     * Create a virtual display
+     * Create a virtual display.
      *
      * displayName
-     *     The name of the virtual display
-     * secure
-     *     Whether this virtual display is secure
+     *     The name of the virtual display.
+     * isSecure
+     *     Whether this virtual display is secure.
+     * uniqueId
+     *     The unique ID for the display.
      * requestedRefreshRate
      *     The refresh rate, frames per second, to request on the virtual display.
      *     This is just a request, the actual rate may be adjusted to align well
@@ -103,14 +105,14 @@
      *
      * requires ACCESS_SURFACE_FLINGER permission.
      */
-    @nullable IBinder createDisplay(@utf8InCpp String displayName, boolean secure,
-            float requestedRefreshRate);
+    @nullable IBinder createVirtualDisplay(@utf8InCpp String displayName, boolean isSecure,
+            @utf8InCpp String uniqueId, float requestedRefreshRate);
 
     /**
-     * Destroy a virtual display
+     * 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/DisplayInfo.h b/libs/gui/include/gui/DisplayInfo.h
index 42b62c7..7094658 100644
--- a/libs/gui/include/gui/DisplayInfo.h
+++ b/libs/gui/include/gui/DisplayInfo.h
@@ -18,7 +18,7 @@
 
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
-#include <gui/constants.h>
+#include <ui/LogicalDisplayId.h>
 #include <ui/Transform.h>
 
 namespace android::gui {
@@ -29,7 +29,7 @@
  * This should only be used by InputFlinger to support raw coordinates in logical display space.
  */
 struct DisplayInfo : public Parcelable {
-    int32_t displayId = ADISPLAY_ID_NONE;
+    ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
 
     // Logical display dimensions.
     int32_t logicalWidth = 0;
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/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 49b0a7d..e2307ed 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -18,6 +18,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+
 #include <set>
 #include <thread>
 #include <unordered_map>
@@ -374,17 +375,15 @@
 
     sp<SurfaceControl> mirrorDisplay(DisplayId displayId);
 
-    //! Create a virtual display
-    static sp<IBinder> createDisplay(const String8& displayName, bool secure,
-                                     float requestedRefereshRate = 0);
+    static const std::string kEmpty;
+    static sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure,
+                                            const std::string& uniqueId = kEmpty,
+                                            float requestedRefreshRate = 0);
 
-    //! Destroy a virtual display
-    static void destroyDisplay(const sp<IBinder>& display);
+    static status_t destroyVirtualDisplay(const sp<IBinder>& displayToken);
 
-    //! Get stable IDs for connected physical displays
     static std::vector<PhysicalDisplayId> getPhysicalDisplayIds();
 
-    //! Get token for a physical display given its stable ID
     static sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId);
 
     // Returns StalledTransactionInfo if a transaction from the provided pid has not been applied
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index e4f1890..eb3be55 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -23,7 +23,7 @@
 #include <ftl/flags.h>
 #include <ftl/mixins.h>
 #include <gui/PidUid.h>
-#include <gui/constants.h>
+#include <ui/LogicalDisplayId.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 #include <ui/Size.h>
@@ -178,8 +178,8 @@
                 static_cast<uint32_t>(os::InputConfig::CLONE),
         GLOBAL_STYLUS_BLOCKS_TOUCH =
                 static_cast<uint32_t>(os::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH),
-        SENSITIVE_FOR_TRACING =
-                static_cast<uint32_t>(os::InputConfig::SENSITIVE_FOR_TRACING),
+        SENSITIVE_FOR_PRIVACY =
+                static_cast<uint32_t>(os::InputConfig::SENSITIVE_FOR_PRIVACY),
         // clang-format on
     };
 
@@ -234,7 +234,7 @@
     Uid ownerUid = Uid::INVALID;
     std::string packageName;
     ftl::Flags<InputConfig> inputConfig;
-    int32_t displayId = ADISPLAY_ID_NONE;
+    ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
     InputApplicationInfo applicationInfo;
     bool replaceTouchableRegionWithCrop = false;
     wp<IBinder> touchableRegionCropHandle;
diff --git a/libs/gui/include/gui/constants.h b/libs/gui/include/gui/constants.h
deleted file mode 100644
index 8eab378..0000000
--- a/libs/gui/include/gui/constants.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-namespace android {
-
-/**
- * Invalid value for display size. Used when display size isn't available.
- */
-constexpr int32_t INVALID_DISPLAY_SIZE = 0;
-
-enum {
-    /* Used when an event is not associated with any display.
-     * Typically used for non-pointer events. */
-    ADISPLAY_ID_NONE = -1,
-
-    /* The default display id. */
-    ADISPLAY_ID_DEFAULT = 0,
-};
-
-} // namespace android
\ No newline at end of file
diff --git a/libs/gui/tests/DisplayInfo_test.cpp b/libs/gui/tests/DisplayInfo_test.cpp
index df3329c..4df76b1 100644
--- a/libs/gui/tests/DisplayInfo_test.cpp
+++ b/libs/gui/tests/DisplayInfo_test.cpp
@@ -28,7 +28,7 @@
 
 TEST(DisplayInfo, Parcelling) {
     DisplayInfo info;
-    info.displayId = 42;
+    info.displayId = ui::LogicalDisplayId{42};
     info.logicalWidth = 99;
     info.logicalHeight = 78;
     info.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1});
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index f441eaa..7d0b512 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -60,7 +60,13 @@
 using android::gui::TouchOcclusionMode;
 using android::gui::WindowInfo;
 
-namespace android::test {
+namespace android {
+namespace {
+ui::LogicalDisplayId toDisplayId(ui::LayerStack layerStack) {
+    return ui::LogicalDisplayId{static_cast<int32_t>(layerStack.id)};
+}
+} // namespace
+namespace test {
 
 using Transaction = SurfaceComposerClient::Transaction;
 
@@ -68,7 +74,9 @@
     sp<IBinder> input(defaultServiceManager()->waitForService(String16("inputflinger")));
     if (input == nullptr) {
         ALOGE("Failed to link to input service");
-    } else { ALOGE("Linked to input"); }
+    } else {
+        ALOGE("Linked to input");
+    }
     return interface_cast<IInputFlinger>(input);
 }
 
@@ -99,7 +107,7 @@
 
 class InputSurface {
 public:
-    InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) {
+    InputSurface(const sp<SurfaceControl>& sc, int width, int height, bool noInputChannel = false) {
         mSurfaceControl = sc;
 
         mInputFlinger = getInputFlinger();
@@ -130,7 +138,7 @@
         mInputInfo.applicationInfo = aInfo;
     }
 
-    static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc,
+    static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient>& scc,
                                                                int width, int height) {
         sp<SurfaceControl> surfaceControl =
                 scc->createSurface(String8("Test Surface"), 0 /* bufHeight */, 0 /* bufWidth */,
@@ -140,7 +148,7 @@
     }
 
     static std::unique_ptr<InputSurface> makeBufferInputSurface(
-            const sp<SurfaceComposerClient> &scc, int width, int height) {
+            const sp<SurfaceComposerClient>& scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
                 scc->createSurface(String8("Test Buffer Surface"), width, height,
                                    PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
@@ -148,7 +156,7 @@
     }
 
     static std::unique_ptr<InputSurface> makeContainerInputSurface(
-            const sp<SurfaceComposerClient> &scc, int width, int height) {
+            const sp<SurfaceComposerClient>& scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
                 scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */,
                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
@@ -157,7 +165,7 @@
     }
 
     static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel(
-            const sp<SurfaceComposerClient> &scc, int width, int height) {
+            const sp<SurfaceComposerClient>& scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
                 scc->createSurface(String8("Test Container Surface"), 100 /* height */,
                                    100 /* width */, PIXEL_FORMAT_RGBA_8888,
@@ -167,7 +175,7 @@
     }
 
     static std::unique_ptr<InputSurface> makeCursorInputSurface(
-            const sp<SurfaceComposerClient> &scc, int width, int height) {
+            const sp<SurfaceComposerClient>& scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
                 scc->createSurface(String8("Test Cursor Surface"), 0 /* bufHeight */,
                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
@@ -178,7 +186,7 @@
     InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) {
         mClientChannel->waitForMessage(timeout);
 
-        InputEvent *ev;
+        InputEvent* ev;
         uint32_t seqId;
         status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
         if (consumed != OK) {
@@ -190,10 +198,10 @@
     }
 
     void assertFocusChange(bool hasFocus) {
-        InputEvent *ev = consumeEvent();
+        InputEvent* ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::FOCUS, ev->getType());
-        FocusEvent *focusEvent = static_cast<FocusEvent *>(ev);
+        FocusEvent* focusEvent = static_cast<FocusEvent*>(ev);
         EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
     }
 
@@ -216,10 +224,10 @@
     }
 
     void expectTapWithFlag(int x, int y, int32_t flags) {
-        InputEvent *ev = consumeEvent();
+        InputEvent* ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::MOTION, ev->getType());
-        MotionEvent *mev = static_cast<MotionEvent *>(ev);
+        MotionEvent* mev = static_cast<MotionEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
         EXPECT_EQ(x, mev->getX(0));
         EXPECT_EQ(y, mev->getY(0));
@@ -228,18 +236,18 @@
         ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::MOTION, ev->getType());
-        mev = static_cast<MotionEvent *>(ev);
+        mev = static_cast<MotionEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
         EXPECT_EQ(flags, mev->getFlags() & flags);
     }
 
     void expectTapInDisplayCoordinates(int displayX, int displayY) {
-        InputEvent *ev = consumeEvent();
+        InputEvent* ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::MOTION, ev->getType());
-        MotionEvent *mev = static_cast<MotionEvent *>(ev);
+        MotionEvent* mev = static_cast<MotionEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
-        const PointerCoords &coords = *mev->getRawPointerCoords(0 /*pointerIndex*/);
+        const PointerCoords& coords = *mev->getRawPointerCoords(0 /*pointerIndex*/);
         EXPECT_EQ(displayX, coords.getX());
         EXPECT_EQ(displayY, coords.getY());
         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
@@ -247,16 +255,16 @@
         ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::MOTION, ev->getType());
-        mev = static_cast<MotionEvent *>(ev);
+        mev = static_cast<MotionEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
     }
 
     void expectKey(int32_t keycode) {
-        InputEvent *ev = consumeEvent();
+        InputEvent* ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::KEY, ev->getType());
-        KeyEvent *keyEvent = static_cast<KeyEvent *>(ev);
+        KeyEvent* keyEvent = static_cast<KeyEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction());
         EXPECT_EQ(keycode, keyEvent->getKeyCode());
         EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS);
@@ -264,7 +272,7 @@
         ev = consumeEvent();
         ASSERT_NE(ev, nullptr);
         ASSERT_EQ(InputEventType::KEY, ev->getType());
-        keyEvent = static_cast<KeyEvent *>(ev);
+        keyEvent = static_cast<KeyEvent*>(ev);
         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction());
         EXPECT_EQ(keycode, keyEvent->getKeyCode());
         EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS);
@@ -282,7 +290,7 @@
     }
 
     virtual void doTransaction(
-            std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)>
+            std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)>
                     transactionBody) {
         SurfaceComposerClient::Transaction t;
         transactionBody(t, mSurfaceControl);
@@ -303,13 +311,13 @@
         reportedListener->wait();
     }
 
-    void requestFocus(int displayId = ADISPLAY_ID_DEFAULT) {
+    void requestFocus(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT) {
         SurfaceComposerClient::Transaction t;
         FocusRequest request;
         request.token = mInputInfo.token;
         request.windowName = mInputInfo.name;
         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-        request.displayId = displayId;
+        request.displayId = displayId.val();
         t.setFocusedWindow(request);
         t.apply(true);
     }
@@ -327,7 +335,7 @@
 
 class BlastInputSurface : public InputSurface {
 public:
-    BlastInputSurface(const sp<SurfaceControl> &sc, const sp<SurfaceControl> &parentSc, int width,
+    BlastInputSurface(const sp<SurfaceControl>& sc, const sp<SurfaceControl>& parentSc, int width,
                       int height)
           : InputSurface(sc, width, height) {
         mParentSurfaceControl = parentSc;
@@ -336,7 +344,7 @@
     ~BlastInputSurface() = default;
 
     static std::unique_ptr<BlastInputSurface> makeBlastInputSurface(
-            const sp<SurfaceComposerClient> &scc, int width, int height) {
+            const sp<SurfaceComposerClient>& scc, int width, int height) {
         sp<SurfaceControl> parentSc =
                 scc->createSurface(String8("Test Parent Surface"), 0 /* bufHeight */,
                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
@@ -351,7 +359,7 @@
     }
 
     void doTransaction(
-            std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)>
+            std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)>
                     transactionBody) override {
         SurfaceComposerClient::Transaction t;
         transactionBody(t, mParentSurfaceControl);
@@ -378,9 +386,7 @@
 
 class InputSurfacesTest : public ::testing::Test {
 public:
-    InputSurfacesTest() {
-        ProcessState::self()->startThreadPool();
-    }
+    InputSurfacesTest() { ProcessState::self()->startThreadPool(); }
 
     void SetUp() {
         mComposerClient = new SurfaceComposerClient;
@@ -400,15 +406,13 @@
         mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3;
     }
 
-    void TearDown() {
-        mComposerClient->dispose();
-    }
+    void TearDown() { mComposerClient->dispose(); }
 
     std::unique_ptr<InputSurface> makeSurface(int width, int height) {
         return InputSurface::makeColorInputSurface(mComposerClient, width, height);
     }
 
-    void postBuffer(const sp<SurfaceControl> &layer, int32_t w, int32_t h) {
+    void postBuffer(const sp<SurfaceControl>& layer, int32_t w, int32_t h) {
         int64_t usageFlags = BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                 BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
         sp<GraphicBuffer> buffer =
@@ -421,31 +425,31 @@
     int32_t mBufferPostDelay;
 };
 
-void injectTapOnDisplay(int x, int y, int displayId) {
+void injectTapOnDisplay(int x, int y, ui::LogicalDisplayId displayId) {
     char *buf1, *buf2, *bufDisplayId;
     asprintf(&buf1, "%d", x);
     asprintf(&buf2, "%d", y);
-    asprintf(&bufDisplayId, "%d", displayId);
+    asprintf(&bufDisplayId, "%d", displayId.val());
     if (fork() == 0) {
         execlp("input", "input", "-d", bufDisplayId, "tap", buf1, buf2, NULL);
     }
 }
 
 void injectTap(int x, int y) {
-    injectTapOnDisplay(x, y, ADISPLAY_ID_DEFAULT);
+    injectTapOnDisplay(x, y, ui::LogicalDisplayId::DEFAULT);
 }
 
-void injectKeyOnDisplay(uint32_t keycode, int displayId) {
+void injectKeyOnDisplay(uint32_t keycode, ui::LogicalDisplayId displayId) {
     char *buf1, *bufDisplayId;
     asprintf(&buf1, "%d", keycode);
-    asprintf(&bufDisplayId, "%d", displayId);
+    asprintf(&bufDisplayId, "%d", displayId.val());
     if (fork() == 0) {
         execlp("input", "input", "-d", bufDisplayId, "keyevent", buf1, NULL);
     }
 }
 
 void injectKey(uint32_t keycode) {
-    injectKeyOnDisplay(keycode, ADISPLAY_ID_NONE);
+    injectKeyOnDisplay(keycode, ui::LogicalDisplayId::INVALID);
 }
 
 TEST_F(InputSurfacesTest, can_receive_input) {
@@ -476,12 +480,8 @@
     injectTap(101, 101);
     surface->expectTap(1, 1);
 
-    surface2->doTransaction([](auto &t, auto &sc) {
-         t.setPosition(sc, 100, 100);
-    });
-    surface->doTransaction([](auto &t, auto &sc) {
-         t.setPosition(sc, 200, 200);
-    });
+    surface2->doTransaction([](auto& t, auto& sc) { t.setPosition(sc, 100, 100); });
+    surface->doTransaction([](auto& t, auto& sc) { t.setPosition(sc, 200, 200); });
 
     injectTap(101, 101);
     surface2->expectTap(1, 1);
@@ -497,23 +497,17 @@
     surface->showAt(10, 10);
     surface2->showAt(10, 10);
 
-    surface->doTransaction([](auto &t, auto &sc) {
-         t.setLayer(sc, LAYER_BASE + 1);
-    });
+    surface->doTransaction([](auto& t, auto& sc) { t.setLayer(sc, LAYER_BASE + 1); });
 
     injectTap(11, 11);
     surface->expectTap(1, 1);
 
-    surface2->doTransaction([](auto &t, auto &sc) {
-         t.setLayer(sc, LAYER_BASE + 1);
-    });
+    surface2->doTransaction([](auto& t, auto& sc) { t.setLayer(sc, LAYER_BASE + 1); });
 
     injectTap(11, 11);
     surface2->expectTap(1, 1);
 
-    surface2->doTransaction([](auto &t, auto &sc) {
-         t.hide(sc);
-    });
+    surface2->doTransaction([](auto& t, auto& sc) { t.hide(sc); });
 
     injectTap(11, 11);
     surface->expectTap(1, 1);
@@ -562,7 +556,7 @@
     childSurface->mInputInfo.surfaceInset = 10;
     childSurface->showAt(100, 100);
 
-    childSurface->doTransaction([&](auto &t, auto &sc) {
+    childSurface->doTransaction([&](auto& t, auto& sc) {
         t.setPosition(sc, -5, -5);
         t.reparent(sc, parentSurface->mSurfaceControl);
     });
@@ -583,7 +577,7 @@
     fgSurface->mInputInfo.surfaceInset = 5;
     fgSurface->showAt(100, 100);
 
-    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });
+    fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });
 
     // expect = touch / scale - inset
     injectTap(112, 124);
@@ -602,7 +596,7 @@
     fgSurface->mInputInfo.surfaceInset = INT32_MAX;
     fgSurface->showAt(100, 100);
 
-    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
+    fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
 
     // expect no crash for overflow, and inset size to be clamped to surface size
     injectTap(112, 124);
@@ -651,7 +645,7 @@
     fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX});
     fgSurface->showAt(0, 0);
 
-    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
+    fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
 
     // Expect no crash for overflow.
     injectTap(12, 24);
@@ -661,7 +655,7 @@
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
 TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         Region transparentRegion(Rect(0, 0, 10, 10));
         t.setTransparentRegionHint(sc, transparentRegion);
     });
@@ -702,7 +696,7 @@
     injectTap(11, 11);
     bufferSurface->expectTap(1, 1);
 
-    bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
+    bufferSurface->doTransaction([](auto& t, auto& sc) { t.setAlpha(sc, 0.0); });
 
     injectTap(11, 11);
     bgSurface->expectTap(1, 1);
@@ -718,7 +712,7 @@
     injectTap(11, 11);
     fgSurface->expectTap(1, 1);
 
-    fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
+    fgSurface->doTransaction([](auto& t, auto& sc) { t.setAlpha(sc, 0.0); });
 
     injectTap(11, 11);
     fgSurface->expectTap(1, 1);
@@ -735,7 +729,7 @@
     injectTap(11, 11);
     containerSurface->expectTap(1, 1);
 
-    containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); });
+    containerSurface->doTransaction([](auto& t, auto& sc) { t.hide(sc); });
 
     injectTap(11, 11);
     bgSurface->expectTap(1, 1);
@@ -775,19 +769,19 @@
 TEST_F(InputSurfacesTest, rotate_surface) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(10, 10);
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, 1, -1, 0); // 90 degrees
     });
     injectTap(8, 11);
     surface->expectTap(1, 2);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, -1, 0, 0, -1); // 180 degrees
     });
     injectTap(9, 8);
     surface->expectTap(1, 2);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, -1, 1, 0); // 270 degrees
     });
     injectTap(12, 9);
@@ -797,19 +791,19 @@
 TEST_F(InputSurfacesTest, rotate_surface_with_scale) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(10, 10);
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees
     });
     injectTap(2, 12);
     surface->expectTap(1, 2);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees
     });
     injectTap(8, 2);
     surface->expectTap(1, 2);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees
     });
     injectTap(18, 8);
@@ -821,19 +815,19 @@
     surface->mInputInfo.surfaceInset = 5;
     surface->showAt(100, 100);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees
     });
     injectTap(40, 120);
     surface->expectTap(5, 10);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees
     });
     injectTap(80, 40);
     surface->expectTap(5, 10);
 
-    surface->doTransaction([](auto &t, auto &sc) {
+    surface->doTransaction([](auto& t, auto& sc) {
         t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees
     });
     injectTap(160, 80);
@@ -874,7 +868,7 @@
     nonTouchableSurface->showAt(0, 0);
     parentSurface->showAt(100, 100);
 
-    nonTouchableSurface->doTransaction([&](auto &t, auto &sc) {
+    nonTouchableSurface->doTransaction([&](auto& t, auto& sc) {
         t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50));
         t.reparent(sc, parentSurface->mSurfaceControl);
     });
@@ -898,7 +892,7 @@
     nonTouchableSurface->showAt(0, 0);
     parentSurface->showAt(50, 50);
 
-    nonTouchableSurface->doTransaction([&](auto &t, auto &sc) {
+    nonTouchableSurface->doTransaction([&](auto& t, auto& sc) {
         t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50));
         t.reparent(sc, parentSurface->mSurfaceControl);
     });
@@ -940,7 +934,7 @@
 TEST_F(InputSurfacesTest, strict_unobscured_input_unobscured_window) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->doTransaction(
-            [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
+            [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
     surface->showAt(100, 100);
 
     injectTap(101, 101);
@@ -954,7 +948,7 @@
 
 TEST_F(InputSurfacesTest, strict_unobscured_input_scaled_without_crop_window) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) {
+    surface->doTransaction([&](auto& t, auto& sc) {
         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED);
         t.setMatrix(sc, 2.0, 0, 0, 2.0);
     });
@@ -973,7 +967,7 @@
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->mInputInfo.ownerUid = gui::Uid{11111};
     surface->doTransaction(
-            [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
+            [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
     surface->showAt(100, 100);
     std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
     obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
@@ -992,7 +986,7 @@
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->mInputInfo.ownerUid = gui::Uid{11111};
     surface->doTransaction(
-            [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
+            [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
     surface->showAt(100, 100);
     std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
     obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
@@ -1015,7 +1009,7 @@
 
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) {
+    surface->doTransaction([&](auto& t, auto& sc) {
         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED);
         t.reparent(sc, parentSurface->mSurfaceControl);
         t.setAlpha(parentSurface->mSurfaceControl, 0.9f);
@@ -1036,7 +1030,7 @@
     parentSurface->showAt(0, 0, Rect(0, 0, 300, 300));
 
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) {
+    surface->doTransaction([&](auto& t, auto& sc) {
         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED);
         t.reparent(sc, parentSurface->mSurfaceControl);
         t.setCrop(parentSurface->mSurfaceControl, Rect(10, 10, 100, 100));
@@ -1070,7 +1064,7 @@
 TEST_F(InputSurfacesTest, drop_input_policy) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->doTransaction(
-            [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); });
+            [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); });
     surface->showAt(100, 100);
 
     injectTap(101, 101);
@@ -1102,7 +1096,7 @@
     std::unique_ptr<InputSurface> containerSurface =
             InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
     containerSurface->doTransaction(
-            [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
+            [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
     containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
     containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
     parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
@@ -1127,7 +1121,7 @@
     std::unique_ptr<InputSurface> containerSurface =
             InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
     containerSurface->doTransaction(
-            [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
+            [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
     containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
     containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
     parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
@@ -1179,7 +1173,7 @@
             InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100);
     childContainerSurface->showAt(0, 0);
     childContainerSurface->doTransaction(
-            [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl); });
+            [&](auto& t, auto& sc) { t.reparent(sc, parent->mSurfaceControl); });
     injectTap(101, 101);
 
     parent->assertNoEvent();
@@ -1188,10 +1182,10 @@
 class MultiDisplayTests : public InputSurfacesTest {
 public:
     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();
     }
 
@@ -1206,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);
@@ -1226,18 +1220,18 @@
     ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
     // Do not create a display associated with the LayerStack.
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); });
+    surface->doTransaction([&](auto& t, auto& sc) { t.setLayerStack(sc, layerStack); });
     surface->showAt(100, 100);
 
     // Touches should be dropped if the layer is on an invalid display.
-    injectTapOnDisplay(101, 101, layerStack.id);
+    injectTapOnDisplay(101, 101, toDisplayId(layerStack));
     surface->assertNoEvent();
 
     // However, we still let the window be focused and receive keys.
-    surface->requestFocus(layerStack.id);
+    surface->requestFocus(toDisplayId(layerStack));
     surface->assertFocusChange(true);
 
-    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+    injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack));
     surface->expectKey(AKEYCODE_V);
 }
 
@@ -1245,15 +1239,15 @@
     ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
     createDisplay(1000, 1000, false /*isSecure*/, layerStack);
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); });
+    surface->doTransaction([&](auto& t, auto& sc) { t.setLayerStack(sc, layerStack); });
     surface->showAt(100, 100);
 
-    injectTapOnDisplay(101, 101, layerStack.id);
+    injectTapOnDisplay(101, 101, toDisplayId(layerStack));
     surface->expectTap(1, 1);
 
-    surface->requestFocus(layerStack.id);
+    surface->requestFocus(toDisplayId(layerStack));
     surface->assertFocusChange(true);
-    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+    injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack));
     surface->expectKey(AKEYCODE_V);
 }
 
@@ -1261,19 +1255,19 @@
     ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
     createDisplay(1000, 1000, false /*isSecure*/, layerStack);
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) {
+    surface->doTransaction([&](auto& t, auto& sc) {
         t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
         t.setLayerStack(sc, layerStack);
     });
     surface->showAt(100, 100);
 
-    injectTapOnDisplay(101, 101, layerStack.id);
+    injectTapOnDisplay(101, 101, toDisplayId(layerStack));
 
     surface->assertNoEvent();
 
-    surface->requestFocus(layerStack.id);
+    surface->requestFocus(toDisplayId(layerStack));
     surface->assertFocusChange(true);
-    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+    injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack));
     surface->assertNoEvent();
 }
 
@@ -1287,20 +1281,21 @@
     seteuid(AID_ROOT);
 
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
-    surface->doTransaction([&](auto &t, auto &sc) {
+    surface->doTransaction([&](auto& t, auto& sc) {
         t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
         t.setLayerStack(sc, layerStack);
     });
     surface->showAt(100, 100);
 
-    injectTapOnDisplay(101, 101, layerStack.id);
+    injectTapOnDisplay(101, 101, toDisplayId(layerStack));
     surface->expectTap(1, 1);
 
-    surface->requestFocus(layerStack.id);
+    surface->requestFocus(toDisplayId(layerStack));
     surface->assertFocusChange(true);
-    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+    injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack));
 
     surface->expectKey(AKEYCODE_V);
 }
 
-} // namespace android::test
+} // namespace test
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index f4b059c..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 /*secure*/,
-                                 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/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index 5eb5d3b..ce22082 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -64,7 +64,7 @@
     i.ownerUid = gui::Uid{24};
     i.packageName = "com.example.package";
     i.inputConfig = WindowInfo::InputConfig::NOT_FOCUSABLE;
-    i.displayId = 34;
+    i.displayId = ui::LogicalDisplayId{34};
     i.replaceTouchableRegionWithCrop = true;
     i.touchableRegionCropHandle = touchableRegionCropHandle;
     i.applicationInfo.name = "ApplicationFooBar";
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index cc0649c..8f44b3a 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -289,6 +289,10 @@
                 "motion_predictor_model_prebuilt",
                 "motion_predictor_model_config",
             ],
+            static_libs: [
+                "libstatslog_libinput",
+                "libstatssocket_lazy",
+            ],
         },
         host: {
             include_dirs: [
@@ -299,6 +303,46 @@
     },
 }
 
+cc_library_static {
+    name: "libstatslog_libinput",
+    generated_sources: ["statslog_libinput.cpp"],
+    generated_headers: ["statslog_libinput.h"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    export_generated_headers: ["statslog_libinput.h"],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "libstatssocket_lazy",
+    ],
+}
+
+genrule {
+    name: "statslog_libinput.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_libinput.h " +
+        "--module libinput --namespace android,libinput",
+    out: [
+        "statslog_libinput.h",
+    ],
+}
+
+genrule {
+    name: "statslog_libinput.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_libinput.cpp " +
+        "--module libinput --namespace android,libinput " +
+        "--importHeader statslog_libinput.h",
+    out: [
+        "statslog_libinput.cpp",
+    ],
+}
+
 cc_defaults {
     name: "libinput_fuzz_defaults",
     cpp_std: "c++20",
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 61a964e..ee121d5 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -27,15 +27,12 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <cutils/compiler.h>
-#include <gui/constants.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 
-#ifdef __linux__
 #include <binder/Parcel.h>
-#endif
 #if defined(__ANDROID__)
 #include <sys/random.h>
 #endif
@@ -293,8 +290,8 @@
             event.getButtonState()};
 }
 
-void InputEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
-                            std::array<uint8_t, 32> hmac) {
+void InputEvent::initialize(int32_t id, int32_t deviceId, uint32_t source,
+                            ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac) {
     mId = id;
     mDeviceId = deviceId;
     mSource = source;
@@ -356,10 +353,11 @@
     return InputEventLookup::getKeyCodeByLabel(label);
 }
 
-void KeyEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
-                          std::array<uint8_t, 32> hmac, int32_t action, int32_t flags,
-                          int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
-                          nsecs_t downTime, nsecs_t eventTime) {
+void KeyEvent::initialize(int32_t id, int32_t deviceId, uint32_t source,
+                          ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac,
+                          int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+                          int32_t metaState, int32_t repeatCount, nsecs_t downTime,
+                          nsecs_t eventTime) {
     InputEvent::initialize(id, deviceId, source, displayId, hmac);
     mAction = action;
     mFlags = flags;
@@ -483,7 +481,6 @@
     scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);
 }
 
-#ifdef __linux__
 status_t PointerCoords::readFromParcel(Parcel* parcel) {
     bits = parcel->readInt64();
 
@@ -511,7 +508,6 @@
     parcel->writeBool(isResampled);
     return OK;
 }
-#endif
 
 void PointerCoords::tooManyAxes(int axis) {
     ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
@@ -556,14 +552,15 @@
 
 // --- MotionEvent ---
 
-void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
-                             std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
-                             int32_t flags, int32_t edgeFlags, int32_t metaState,
-                             int32_t buttonState, MotionClassification classification,
-                             const ui::Transform& transform, float xPrecision, float yPrecision,
-                             float rawXCursorPosition, float rawYCursorPosition,
-                             const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
-                             size_t pointerCount, const PointerProperties* pointerProperties,
+void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source,
+                             ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac,
+                             int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags,
+                             int32_t metaState, int32_t buttonState,
+                             MotionClassification classification, const ui::Transform& transform,
+                             float xPrecision, float yPrecision, float rawXCursorPosition,
+                             float rawYCursorPosition, const ui::Transform& rawTransform,
+                             nsecs_t downTime, nsecs_t eventTime, size_t pointerCount,
+                             const PointerProperties* pointerProperties,
                              const PointerCoords* pointerCoords) {
     InputEvent::initialize(id, deviceId, source, displayId, hmac);
     mAction = action;
@@ -800,7 +797,6 @@
     }
 }
 
-#ifdef __linux__
 static status_t readFromParcel(ui::Transform& transform, const Parcel& parcel) {
     float dsdx, dtdx, tx, dtdy, dsdy, ty;
     status_t status = parcel.readFloat(&dsdx);
@@ -835,7 +831,7 @@
     mId = parcel->readInt32();
     mDeviceId = parcel->readInt32();
     mSource = parcel->readUint32();
-    mDisplayId = parcel->readInt32();
+    mDisplayId = ui::LogicalDisplayId{parcel->readInt32()};
     std::vector<uint8_t> hmac;
     status_t result = parcel->readByteVector(&hmac);
     if (result != OK || hmac.size() != 32) {
@@ -903,7 +899,7 @@
     parcel->writeInt32(mId);
     parcel->writeInt32(mDeviceId);
     parcel->writeUint32(mSource);
-    parcel->writeInt32(mDisplayId);
+    parcel->writeInt32(mDisplayId.val());
     std::vector<uint8_t> hmac(mHmac.begin(), mHmac.end());
     parcel->writeByteVector(hmac);
     parcel->writeInt32(mAction);
@@ -947,7 +943,6 @@
     }
     return OK;
 }
-#endif
 
 bool MotionEvent::isTouchEvent(uint32_t source, int32_t action) {
     if (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER)) {
@@ -1203,7 +1198,7 @@
 
 void FocusEvent::initialize(int32_t id, bool hasFocus) {
     InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
-                           ADISPLAY_ID_NONE, INVALID_HMAC);
+                           ui::LogicalDisplayId::INVALID, INVALID_HMAC);
     mHasFocus = hasFocus;
 }
 
@@ -1216,7 +1211,7 @@
 
 void CaptureEvent::initialize(int32_t id, bool pointerCaptureEnabled) {
     InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
-                           ADISPLAY_ID_NONE, INVALID_HMAC);
+                           ui::LogicalDisplayId::INVALID, INVALID_HMAC);
     mPointerCaptureEnabled = pointerCaptureEnabled;
 }
 
@@ -1229,7 +1224,7 @@
 
 void DragEvent::initialize(int32_t id, float x, float y, bool isExiting) {
     InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
-                           ADISPLAY_ID_NONE, INVALID_HMAC);
+                           ui::LogicalDisplayId::INVALID, INVALID_HMAC);
     mIsExiting = isExiting;
     mX = x;
     mY = y;
@@ -1246,7 +1241,7 @@
 
 void TouchModeEvent::initialize(int32_t id, bool isInTouchMode) {
     InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
-                           ADISPLAY_ID_NONE, INVALID_HMAC);
+                           ui::LogicalDisplayId::INVALID, INVALID_HMAC);
     mIsInTouchMode = isInTouchMode;
 }
 
diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp
index be2110e..abc0392 100644
--- a/libs/input/InputConsumer.cpp
+++ b/libs/input/InputConsumer.cpp
@@ -81,10 +81,10 @@
 
 void initializeKeyEvent(KeyEvent& event, const InputMessage& msg) {
     event.initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
-                     msg.body.key.displayId, msg.body.key.hmac, msg.body.key.action,
-                     msg.body.key.flags, msg.body.key.keyCode, msg.body.key.scanCode,
-                     msg.body.key.metaState, msg.body.key.repeatCount, msg.body.key.downTime,
-                     msg.body.key.eventTime);
+                     ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
+                     msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
+                     msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
+                     msg.body.key.downTime, msg.body.key.eventTime);
 }
 
 void initializeFocusEvent(FocusEvent& event, const InputMessage& msg) {
@@ -117,13 +117,14 @@
                           msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
                           0, 0, 1});
     event.initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
-                     msg.body.motion.displayId, msg.body.motion.hmac, msg.body.motion.action,
-                     msg.body.motion.actionButton, msg.body.motion.flags, msg.body.motion.edgeFlags,
-                     msg.body.motion.metaState, msg.body.motion.buttonState,
-                     msg.body.motion.classification, transform, msg.body.motion.xPrecision,
-                     msg.body.motion.yPrecision, msg.body.motion.xCursorPosition,
-                     msg.body.motion.yCursorPosition, displayTransform, msg.body.motion.downTime,
-                     msg.body.motion.eventTime, pointerCount, pointerProperties, pointerCoords);
+                     ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
+                     msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
+                     msg.body.motion.edgeFlags, msg.body.motion.metaState,
+                     msg.body.motion.buttonState, msg.body.motion.classification, transform,
+                     msg.body.motion.xPrecision, msg.body.motion.yPrecision,
+                     msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
+                     displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
+                     pointerCount, pointerProperties, pointerCoords);
 }
 
 void addSample(MotionEvent& event, const InputMessage& msg) {
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index 76f2b4a..15d992f 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -47,10 +47,10 @@
 std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
     std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
     event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
-                      msg.body.key.displayId, msg.body.key.hmac, msg.body.key.action,
-                      msg.body.key.flags, msg.body.key.keyCode, msg.body.key.scanCode,
-                      msg.body.key.metaState, msg.body.key.repeatCount, msg.body.key.downTime,
-                      msg.body.key.eventTime);
+                      ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
+                      msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
+                      msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
+                      msg.body.key.downTime, msg.body.key.eventTime);
     return event;
 }
 
@@ -93,8 +93,8 @@
                           msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
                           0, 0, 1});
     event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
-                      msg.body.motion.displayId, msg.body.motion.hmac, msg.body.motion.action,
-                      msg.body.motion.actionButton, msg.body.motion.flags,
+                      ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
+                      msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
                       msg.body.motion.edgeFlags, msg.body.motion.metaState,
                       msg.body.motion.buttonState, msg.body.motion.classification, transform,
                       msg.body.motion.xPrecision, msg.body.motion.yPrecision,
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 222647d..bc67810 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -23,7 +23,6 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <ftl/enum.h>
-#include <gui/constants.h>
 #include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 
@@ -170,7 +169,7 @@
 // --- InputDeviceInfo ---
 
 InputDeviceInfo::InputDeviceInfo() {
-    initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false, ADISPLAY_ID_NONE);
+    initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false, ui::LogicalDisplayId::INVALID);
 }
 
 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other)
@@ -202,7 +201,8 @@
 
 void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
                                  const InputDeviceIdentifier& identifier, const std::string& alias,
-                                 bool isExternal, bool hasMic, int32_t associatedDisplayId,
+                                 bool isExternal, bool hasMic,
+                                 ui::LogicalDisplayId associatedDisplayId,
                                  InputDeviceViewBehavior viewBehavior, bool enabled) {
     mId = id;
     mGeneration = generation;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 3ca6ccc..47b4228 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -530,7 +530,7 @@
 }
 
 status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
-                                         int32_t source, int32_t displayId,
+                                         int32_t source, ui::LogicalDisplayId displayId,
                                          std::array<uint8_t, 32> hmac, int32_t action,
                                          int32_t flags, int32_t keyCode, int32_t scanCode,
                                          int32_t metaState, int32_t repeatCount, nsecs_t downTime,
@@ -558,7 +558,7 @@
     msg.body.key.eventId = eventId;
     msg.body.key.deviceId = deviceId;
     msg.body.key.source = source;
-    msg.body.key.displayId = displayId;
+    msg.body.key.displayId = displayId.val();
     msg.body.key.hmac = std::move(hmac);
     msg.body.key.action = action;
     msg.body.key.flags = flags;
@@ -572,11 +572,11 @@
 }
 
 status_t InputPublisher::publishMotionEvent(
-        uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
-        std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
-        int32_t edgeFlags, int32_t metaState, int32_t buttonState,
-        MotionClassification classification, const ui::Transform& transform, float xPrecision,
-        float yPrecision, float xCursorPosition, float yCursorPosition,
+        uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source,
+        ui::LogicalDisplayId displayId, std::array<uint8_t, 32> hmac, int32_t action,
+        int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
+        int32_t buttonState, MotionClassification classification, const ui::Transform& transform,
+        float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition,
         const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
         uint32_t pointerCount, const PointerProperties* pointerProperties,
         const PointerCoords* pointerCoords) {
@@ -596,13 +596,13 @@
         std::string transformString;
         transform.dump(transformString, "transform", "        ");
         ALOGD("channel '%s' publisher ~ %s: seq=%u, id=%d, deviceId=%d, source=%s, "
-              "displayId=%" PRId32 ", "
+              "displayId=%s, "
               "action=%s, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
               "metaState=0x%x, buttonState=0x%x, classification=%s,"
               "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
               "pointerCount=%" PRIu32 "\n%s",
               mChannel->getName().c_str(), __func__, seq, eventId, deviceId,
-              inputEventSourceToString(source).c_str(), displayId,
+              inputEventSourceToString(source).c_str(), displayId.toString().c_str(),
               MotionEvent::actionToString(action).c_str(), actionButton, flags, edgeFlags,
               metaState, buttonState, motionClassificationToString(classification), xPrecision,
               yPrecision, downTime, eventTime, pointerCount, transformString.c_str());
@@ -625,7 +625,7 @@
     msg.body.motion.eventId = eventId;
     msg.body.motion.deviceId = deviceId;
     msg.body.motion.source = source;
-    msg.body.motion.displayId = displayId;
+    msg.body.motion.displayId = displayId.val();
     msg.body.motion.hmac = std::move(hmac);
     msg.body.motion.action = action;
     msg.body.motion.actionButton = actionButton;
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index e2feabc..1cf5612 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -19,16 +19,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef __linux__
-#include <binder/Parcel.h>
-#endif
 #include <android/keycodes.h>
 #include <attestation/HmacKeyManager.h>
+#include <binder/Parcel.h>
 #include <input/InputEventLabels.h>
 #include <input/KeyCharacterMap.h>
 #include <input/Keyboard.h>
 
-#include <gui/constants.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/Timers.h>
@@ -496,13 +493,14 @@
     return false;
 }
 
-void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents,
-        int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) {
+void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents, int32_t deviceId, int32_t keyCode,
+                             int32_t metaState, bool down, nsecs_t time) {
     outEvents.push();
     KeyEvent& event = outEvents.editTop();
-    event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
-                     INVALID_HMAC, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode,
-                     0, metaState, 0, time, time);
+    event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD,
+                     ui::LogicalDisplayId::INVALID, INVALID_HMAC,
+                     down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, 0, metaState,
+                     0, time, time);
 }
 
 void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents,
@@ -612,7 +610,6 @@
     }
 }
 
-#ifdef __linux__
 std::unique_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
     if (parcel == nullptr) {
         ALOGE("%s: Null parcel", __func__);
@@ -745,7 +742,6 @@
         parcel->writeInt32(toAndroidKeyCode);
     }
 }
-#endif // __linux__
 
 // --- KeyCharacterMap::Parser ---
 
diff --git a/libs/input/MotionPredictorMetricsManager.cpp b/libs/input/MotionPredictorMetricsManager.cpp
index cda39ce..ccf018e 100644
--- a/libs/input/MotionPredictorMetricsManager.cpp
+++ b/libs/input/MotionPredictorMetricsManager.cpp
@@ -21,6 +21,9 @@
 #include <algorithm>
 
 #include <android-base/logging.h>
+#ifdef __ANDROID__
+#include <statslog_libinput.h>
+#endif // __ANDROID__
 
 #include "Eigen/Core"
 #include "Eigen/Geometry"
@@ -44,9 +47,20 @@
 
 void MotionPredictorMetricsManager::defaultReportAtomFunction(
         const MotionPredictorMetricsManager::AtomFields& atomFields) {
-    // TODO(b/338106546): Fix bootanimation build dependency issue, then re-add
-    // the stats_write function call here.
-    (void)atomFields;
+#ifdef __ANDROID__
+    android::libinput::stats_write(android::libinput::STYLUS_PREDICTION_METRICS_REPORTED,
+                                   /*stylus_vendor_id=*/0,
+                                   /*stylus_product_id=*/0,
+                                   atomFields.deltaTimeBucketMilliseconds,
+                                   atomFields.alongTrajectoryErrorMeanMillipixels,
+                                   atomFields.alongTrajectoryErrorStdMillipixels,
+                                   atomFields.offTrajectoryRmseMillipixels,
+                                   atomFields.pressureRmseMilliunits,
+                                   atomFields.highVelocityAlongTrajectoryRmse,
+                                   atomFields.highVelocityOffTrajectoryRmse,
+                                   atomFields.scaleInvariantAlongTrajectoryRmse,
+                                   atomFields.scaleInvariantOffTrajectoryRmse);
+#endif // __ANDROID__
 }
 
 MotionPredictorMetricsManager::MotionPredictorMetricsManager(
diff --git a/libs/input/android/os/InputConfig.aidl b/libs/input/android/os/InputConfig.aidl
index 6b97cbb..da62e03 100644
--- a/libs/input/android/os/InputConfig.aidl
+++ b/libs/input/android/os/InputConfig.aidl
@@ -159,10 +159,12 @@
     GLOBAL_STYLUS_BLOCKS_TOUCH   = 1 << 17,
 
     /**
-     * InputConfig used to indicate that this window is sensitive for tracing.
+     * InputConfig used to indicate that this window is privacy sensitive. This may be used to
+     * redact input interactions from tracing or screen mirroring.
+     *
      * This must be set on windows that use {@link WindowManager.LayoutParams#FLAG_SECURE},
      * but it may also be set without setting FLAG_SECURE. The tracing configuration will
      * determine how these sensitive events are eventually traced.
      */
-     SENSITIVE_FOR_TRACING       = 1 << 18,
+     SENSITIVE_FOR_PRIVACY       = 1 << 18,
 }
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 5c4b889..560166c 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -16,13 +16,6 @@
 }
 
 flag {
-  name: "enable_pointer_choreographer"
-  namespace: "input"
-  description: "Set to true to enable PointerChoreographer: the new pipeline for showing pointer icons"
-  bug: "293587049"
-}
-
-flag {
   name: "enable_gestures_library_timer_provider"
   namespace: "input"
   description: "Set to true to enable timer support for the touchpad Gestures library"
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 6e724ac..e9d799e 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -79,6 +79,12 @@
     },
     test_suites: ["device-tests"],
     target: {
+        android: {
+            static_libs: [
+                "libstatslog_libinput",
+                "libstatssocket_lazy",
+            ],
+        },
         host: {
             sanitize: {
                 address: true,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 0df06b7..476b5cf 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -21,14 +21,13 @@
 #include <attestation/HmacKeyManager.h>
 #include <binder/Parcel.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 #include <input/InputEventBuilders.h>
 
 namespace android {
 
 // Default display id.
-static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 
 static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
 
@@ -229,7 +228,7 @@
     ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
 
     // Set display id.
-    constexpr int32_t newDisplayId = 2;
+    constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
     event.setDisplayId(newDisplayId);
     ASSERT_EQ(newDisplayId, event.getDisplayId());
 }
@@ -528,7 +527,7 @@
     ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
 
     // Set displayId.
-    constexpr int32_t newDisplayId = 2;
+    constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
     event.setDisplayId(newDisplayId);
     ASSERT_EQ(newDisplayId, event.getDisplayId());
 
@@ -859,11 +858,10 @@
     pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
     nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
     MotionEvent event;
-    event.initialize(InputEvent::nextId(), /* deviceId */ 1, source,
-                     /* displayId */ 0, INVALID_HMAC, action,
-                     /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
-                     /* buttonState */ 0, MotionClassification::NONE, transform,
-                     /* xPrecision */ 0, /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+    event.initialize(InputEvent::nextId(), /*deviceId=*/1, source, ui::LogicalDisplayId::DEFAULT,
+                     INVALID_HMAC, action, /*actionButton=*/0, /*flags=*/0, /*edgeFlags=*/0,
+                     AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE, transform,
+                     /*xPrecision=*/0, /*yPrecision=*/0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, rawTransform, eventTime, eventTime,
                      pointerCoords.size(), pointerProperties.data(), pointerCoords.data());
     return event;
diff --git a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
index 6593497..70529bb 100644
--- a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
@@ -18,7 +18,6 @@
 #include <attestation/HmacKeyManager.h>
 #include <ftl/enum.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/BlockingQueue.h>
 #include <input/InputConsumerNoResampling.h>
 #include <input/InputTransport.h>
@@ -56,7 +55,7 @@
     const int32_t eventId;
     const int32_t deviceId = 1;
     const uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
-    const int32_t displayId = ADISPLAY_ID_DEFAULT;
+    const ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
     const int32_t actionButton = 0;
     const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
@@ -446,7 +445,7 @@
     int32_t eventId = InputEvent::nextId();
     constexpr int32_t deviceId = 1;
     constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
-    constexpr int32_t displayId = ADISPLAY_ID_DEFAULT;
+    constexpr ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
     constexpr std::array<uint8_t, 32> hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
                                               20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
                                               9,  8,  7,  6,  5,  4,  3,  2,  1,  0};
@@ -738,9 +737,10 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
@@ -755,9 +755,10 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
@@ -776,9 +777,10 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 332831f..48512f7 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -16,7 +16,6 @@
 
 #include <attestation/HmacKeyManager.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/InputConsumer.h>
 #include <input/InputTransport.h>
 
@@ -49,7 +48,7 @@
     const int32_t eventId;
     const int32_t deviceId = 1;
     const uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
-    const int32_t displayId = ADISPLAY_ID_DEFAULT;
+    const ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
     const int32_t actionButton = 0;
     const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
@@ -263,7 +262,7 @@
     int32_t eventId = InputEvent::nextId();
     constexpr int32_t deviceId = 1;
     constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
-    constexpr int32_t displayId = ADISPLAY_ID_DEFAULT;
+    constexpr ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
     constexpr std::array<uint8_t, 32> hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
                                               20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
                                               9,  8,  7,  6,  5,  4,  3,  2,  1,  0};
@@ -623,13 +622,13 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
-    ASSERT_EQ(BAD_VALUE, status)
-            << "publisher publishMotionEvent should return BAD_VALUE";
+    ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
 }
 
 TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
@@ -640,17 +639,17 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
-    ASSERT_EQ(BAD_VALUE, status)
-            << "publisher publishMotionEvent should return BAD_VALUE";
+    ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
 }
 
 TEST_F(InputPublisherAndConsumerTest,
-        PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
+       PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
     status_t status;
     const size_t pointerCount = MAX_POINTERS + 1;
     PointerProperties pointerProperties[pointerCount];
@@ -662,13 +661,13 @@
 
     ui::Transform identityTransform;
     status =
-            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
-                                           0, 0, 0, MotionClassification::NONE, identityTransform,
-                                           0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+            mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
+                                           ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
+                                           0, 0, MotionClassification::NONE, identityTransform, 0,
+                                           0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                            0, 0, pointerCount, pointerProperties, pointerCoords);
-    ASSERT_EQ(BAD_VALUE, status)
-            << "publisher publishMotionEvent should return BAD_VALUE";
+    ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
 }
 
 TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) {
diff --git a/libs/input/tests/MotionPredictor_test.cpp b/libs/input/tests/MotionPredictor_test.cpp
index b8f1caa..d077760 100644
--- a/libs/input/tests/MotionPredictor_test.cpp
+++ b/libs/input/tests/MotionPredictor_test.cpp
@@ -22,7 +22,6 @@
 #include <flag_macros.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 #include <input/MotionPredictor.h>
 
@@ -59,9 +58,10 @@
     }
 
     ui::Transform identityTransform;
-    event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT, {0},
-                     action, /*actionButton=*/0, /*flags=*/0, AMOTION_EVENT_EDGE_FLAG_NONE,
-                     AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE, identityTransform,
+    event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_STYLUS,
+                     ui::LogicalDisplayId::DEFAULT, {0}, action, /*actionButton=*/0, /*flags=*/0,
+                     AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, /*buttonState=*/0,
+                     MotionClassification::NONE, identityTransform,
                      /*xPrecision=*/0.1,
                      /*yPrecision=*/0.2, /*xCursorPosition=*/280, /*yCursorPosition=*/540,
                      identityTransform, /*downTime=*/100, eventTime.count(), pointerCount,
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index 6e23d4e..2dc9fdb 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -84,10 +84,11 @@
         ADD_FAILURE() << "Downtime should be equal to 0 (hardcoded for convenience)";
     }
     return mPublisher->publishMotionEvent(mSeq++, InputEvent::nextId(), /*deviceId=*/1,
-                                          AINPUT_SOURCE_TOUCHSCREEN, /*displayId=*/0, INVALID_HMAC,
-                                          action, /*actionButton=*/0, /*flags=*/0, /*edgeFlags=*/0,
-                                          AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
-                                          identityTransform, /*xPrecision=*/0, /*yPrecision=*/0,
+                                          AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
+                                          INVALID_HMAC, action, /*actionButton=*/0, /*flags=*/0,
+                                          /*edgeFlags=*/0, AMETA_NONE, /*buttonState=*/0,
+                                          MotionClassification::NONE, identityTransform,
+                                          /*xPrecision=*/0, /*yPrecision=*/0,
                                           AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
                                           downTime, eventTime, properties.size(), properties.data(),
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index f9ca280..f50a3cd 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -24,7 +24,6 @@
 #include <android-base/stringprintf.h>
 #include <attestation/HmacKeyManager.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/VelocityTracker.h>
 
 using std::literals::chrono_literals::operator""ms;
@@ -34,7 +33,7 @@
 
 namespace android {
 
-constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; // default display id
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; // default display id
 
 constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually defined tests
 
@@ -156,7 +155,7 @@
         MotionEvent event;
         ui::Transform identityTransform;
         event.initialize(InputEvent::nextId(), /*deviceId=*/5, AINPUT_SOURCE_ROTARY_ENCODER,
-                         ADISPLAY_ID_NONE, INVALID_HMAC, AMOTION_EVENT_ACTION_SCROLL,
+                         ui::LogicalDisplayId::INVALID, INVALID_HMAC, AMOTION_EVENT_ACTION_SCROLL,
                          /*actionButton=*/0, /*flags=*/0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
                          /*buttonState=*/0, MotionClassification::NONE, identityTransform,
                          /*xPrecision=*/0, /*yPrecision=*/0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp
index 277d74d..df5fe9d 100644
--- a/libs/input/tests/VerifiedInputEvent_test.cpp
+++ b/libs/input/tests/VerifiedInputEvent_test.cpp
@@ -16,7 +16,6 @@
 
 #include <attestation/HmacKeyManager.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 
 namespace android {
@@ -24,7 +23,7 @@
 static KeyEvent getKeyEventWithFlags(int32_t flags) {
     KeyEvent event;
     event.initialize(InputEvent::nextId(), /*deviceId=*/2, AINPUT_SOURCE_GAMEPAD,
-                     ADISPLAY_ID_DEFAULT, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, flags,
+                     ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, flags,
                      AKEYCODE_BUTTON_X, /*scanCode=*/121, AMETA_ALT_ON, /*repeatCount=*/1,
                      /*downTime=*/1000, /*eventTime=*/2000);
     return event;
@@ -44,10 +43,11 @@
     ui::Transform transform;
     transform.set({2, 0, 4, 0, 3, 5, 0, 0, 1});
     ui::Transform identity;
-    event.initialize(InputEvent::nextId(), /*deviceId=*/0, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT,
-                     INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, /*actionButton=*/0, flags,
-                     AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, /*buttonState=*/0,
-                     MotionClassification::NONE, transform, /*xPrecision=*/0.1, /*yPrecision=*/0.2,
+    event.initialize(InputEvent::nextId(), /*deviceId=*/0, AINPUT_SOURCE_MOUSE,
+                     ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
+                     /*actionButton=*/0, flags, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                     /*buttonState=*/0, MotionClassification::NONE, transform, /*xPrecision=*/0.1,
+                     /*yPrecision=*/0.2,
                      /*xCursorPosition=*/280, /*yCursorPosition=*/540, identity, /*downTime=*/100,
                      /*eventTime=*/200, pointerCount, pointerProperties, pointerCoords);
     return event;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index befca35..d344164 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -91,7 +91,6 @@
 // Debugging settings
 static const bool kPrintLayerSettings = false;
 static const bool kGaneshFlushAfterEveryLayer = kPrintLayerSettings;
-static constexpr bool kEnableLayerBrightening = true;
 
 } // namespace
 
@@ -714,8 +713,7 @@
 
     // ...and compute the dimming ratio if dimming is requested
     const float displayDimmingRatio = display.targetLuminanceNits > 0.f &&
-                    maxLayerWhitePoint > 0.f &&
-                    (kEnableLayerBrightening || display.targetLuminanceNits > maxLayerWhitePoint)
+                    maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint
             ? maxLayerWhitePoint / display.targetLuminanceNits
             : 1.f;
 
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index 82e5427..0908ae8 100644
--- a/libs/ui/DisplayIdentification.cpp
+++ b/libs/ui/DisplayIdentification.cpp
@@ -23,67 +23,13 @@
 #include <optional>
 #include <span>
 
+#include <ftl/hash.h>
 #include <log/log.h>
-
 #include <ui/DisplayIdentification.h>
 
 namespace android {
 namespace {
 
-template <class T>
-inline T load(const void* p) {
-    static_assert(std::is_integral<T>::value, "T must be integral");
-
-    T r;
-    std::memcpy(&r, p, sizeof(r));
-    return r;
-}
-
-uint64_t rotateByAtLeast1(uint64_t val, uint8_t shift) {
-    return (val >> shift) | (val << (64 - shift));
-}
-
-uint64_t shiftMix(uint64_t val) {
-    return val ^ (val >> 47);
-}
-
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-uint64_t hash64Len16(uint64_t u, uint64_t v) {
-    constexpr uint64_t kMul = 0x9ddfea08eb382d69;
-    uint64_t a = (u ^ v) * kMul;
-    a ^= (a >> 47);
-    uint64_t b = (v ^ a) * kMul;
-    b ^= (b >> 47);
-    b *= kMul;
-    return b;
-}
-
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-uint64_t hash64Len0To16(const char* s, uint64_t len) {
-    constexpr uint64_t k2 = 0x9ae16a3b2f90404f;
-    constexpr uint64_t k3 = 0xc949d7c7509e6557;
-
-    if (len > 8) {
-        const uint64_t a = load<uint64_t>(s);
-        const uint64_t b = load<uint64_t>(s + len - 8);
-        return hash64Len16(a, rotateByAtLeast1(b + len, static_cast<uint8_t>(len))) ^ b;
-    }
-    if (len >= 4) {
-        const uint32_t a = load<uint32_t>(s);
-        const uint32_t b = load<uint32_t>(s + len - 4);
-        return hash64Len16(len + (a << 3), b);
-    }
-    if (len > 0) {
-        const unsigned char a = static_cast<unsigned char>(s[0]);
-        const unsigned char b = static_cast<unsigned char>(s[len >> 1]);
-        const unsigned char c = static_cast<unsigned char>(s[len - 1]);
-        const uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
-        const uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
-        return shiftMix(y * k2 ^ z * k3) * k2;
-    }
-    return k2;
-}
-
 using byte_view = std::span<const uint8_t>;
 
 constexpr size_t kEdidBlockSize = 128;
@@ -320,7 +266,7 @@
     // Hash model string instead of using product code or (integer) serial number, since the latter
     // have been observed to change on some displays with multiple inputs. Use a stable hash instead
     // of std::hash which is only required to be same within a single execution of a program.
-    const uint32_t modelHash = static_cast<uint32_t>(cityHash64Len0To16(modelString));
+    const uint32_t modelHash = static_cast<uint32_t>(*ftl::stable_hash(modelString));
 
     // Parse extension blocks.
     std::optional<Cea861ExtensionBlock> cea861Block;
@@ -394,13 +340,4 @@
     return PhysicalDisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
 }
 
-uint64_t cityHash64Len0To16(std::string_view sv) {
-    auto len = sv.length();
-    if (len > 16) {
-        ALOGE("%s called with length %zu. Only hashing the first 16 chars", __FUNCTION__, len);
-        len = 16;
-    }
-    return hash64Len0To16(sv.data(), len);
-}
-
 } // namespace android
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
index 3a31fa0..8a14db8 100644
--- a/libs/ui/include/ui/DisplayId.h
+++ b/libs/ui/include/ui/DisplayId.h
@@ -20,6 +20,7 @@
 #include <ostream>
 #include <string>
 
+#include <ftl/hash.h>
 #include <ftl/optional.h>
 
 namespace android {
@@ -38,6 +39,9 @@
     constexpr DisplayId(const DisplayId&) = default;
     DisplayId& operator=(const DisplayId&) = default;
 
+    constexpr bool isVirtual() const { return value & FLAG_VIRTUAL; }
+    constexpr bool isStable() const { return value & FLAG_STABLE; }
+
     uint64_t value;
 
     // For deserialization.
@@ -76,10 +80,10 @@
 // DisplayId of a physical display, such as the internal display or externally connected display.
 struct PhysicalDisplayId : DisplayId {
     static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) {
-        if (id.value & FLAG_VIRTUAL) {
+        if (id.isVirtual()) {
             return std::nullopt;
         }
-        return {PhysicalDisplayId(id)};
+        return PhysicalDisplayId(id);
     }
 
     // Returns a stable ID based on EDID information.
@@ -117,25 +121,23 @@
     static constexpr uint64_t FLAG_GPU = 1ULL << 61;
 
     static constexpr std::optional<VirtualDisplayId> tryCast(DisplayId id) {
-        if (id.value & FLAG_VIRTUAL) {
-            return {VirtualDisplayId(id)};
+        if (id.isVirtual()) {
+            return VirtualDisplayId(id);
         }
         return std::nullopt;
     }
 
 protected:
-    constexpr VirtualDisplayId(uint64_t flags, BaseId baseId)
-          : DisplayId(DisplayId::FLAG_VIRTUAL | flags | baseId) {}
-
+    explicit constexpr VirtualDisplayId(uint64_t value) : DisplayId(FLAG_VIRTUAL | value) {}
     explicit constexpr VirtualDisplayId(DisplayId other) : DisplayId(other) {}
 };
 
 struct HalVirtualDisplayId : VirtualDisplayId {
-    explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(0, baseId) {}
+    explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(baseId) {}
 
     static constexpr std::optional<HalVirtualDisplayId> tryCast(DisplayId id) {
-        if ((id.value & FLAG_VIRTUAL) && !(id.value & VirtualDisplayId::FLAG_GPU)) {
-            return {HalVirtualDisplayId(id)};
+        if (id.isVirtual() && !(id.value & FLAG_GPU)) {
+            return HalVirtualDisplayId(id);
         }
         return std::nullopt;
     }
@@ -145,17 +147,27 @@
 };
 
 struct GpuVirtualDisplayId : VirtualDisplayId {
-    explicit constexpr GpuVirtualDisplayId(BaseId baseId)
-          : VirtualDisplayId(VirtualDisplayId::FLAG_GPU, baseId) {}
+    explicit constexpr GpuVirtualDisplayId(BaseId baseId) : VirtualDisplayId(FLAG_GPU | baseId) {}
+
+    static constexpr std::optional<GpuVirtualDisplayId> fromUniqueId(const std::string& uniqueId) {
+        if (const auto hashOpt = ftl::stable_hash(uniqueId)) {
+            return GpuVirtualDisplayId(HashTag{}, *hashOpt);
+        }
+        return {};
+    }
 
     static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) {
-        if ((id.value & FLAG_VIRTUAL) && (id.value & VirtualDisplayId::FLAG_GPU)) {
-            return {GpuVirtualDisplayId(id)};
+        if (id.isVirtual() && (id.value & FLAG_GPU)) {
+            return GpuVirtualDisplayId(id);
         }
         return std::nullopt;
     }
 
 private:
+    struct HashTag {}; // Disambiguate with BaseId constructor.
+    constexpr GpuVirtualDisplayId(HashTag, uint64_t hash)
+          : VirtualDisplayId(FLAG_STABLE | FLAG_GPU | hash) {}
+
     explicit constexpr GpuVirtualDisplayId(DisplayId other) : VirtualDisplayId(other) {}
 };
 
@@ -169,7 +181,7 @@
         if (GpuVirtualDisplayId::tryCast(id)) {
             return std::nullopt;
         }
-        return {HalDisplayId(id)};
+        return HalDisplayId(id);
     }
 
 private:
diff --git a/libs/ui/include/ui/DisplayIdentification.h b/libs/ui/include/ui/DisplayIdentification.h
index fc9c0f4..8bc2017 100644
--- a/libs/ui/include/ui/DisplayIdentification.h
+++ b/libs/ui/include/ui/DisplayIdentification.h
@@ -80,7 +80,4 @@
 
 PhysicalDisplayId getVirtualDisplayId(uint32_t id);
 
-// CityHash64 implementation that only hashes at most the first 16 characters of the given string.
-uint64_t cityHash64Len0To16(std::string_view sv);
-
 } // namespace android
diff --git a/libs/ui/include/ui/LogicalDisplayId.h b/libs/ui/include/ui/LogicalDisplayId.h
new file mode 100644
index 0000000..fd84b12
--- /dev/null
+++ b/libs/ui/include/ui/LogicalDisplayId.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <ftl/mixins.h>
+#include <sys/types.h>
+#include <string>
+
+#include <ostream>
+
+namespace android::ui {
+
+// Type-safe wrapper for a logical display id.
+struct LogicalDisplayId : ftl::Constructible<LogicalDisplayId, int32_t>,
+                          ftl::Equatable<LogicalDisplayId>,
+                          ftl::Orderable<LogicalDisplayId> {
+    using Constructible::Constructible;
+
+    constexpr auto val() const { return ftl::to_underlying(*this); }
+
+    constexpr bool isValid() const { return val() >= 0; }
+
+    std::string toString() const { return std::to_string(val()); }
+
+    static const LogicalDisplayId INVALID;
+    static const LogicalDisplayId DEFAULT;
+};
+
+constexpr inline LogicalDisplayId LogicalDisplayId::INVALID{-1};
+constexpr inline LogicalDisplayId LogicalDisplayId::DEFAULT{0};
+
+inline std::ostream& operator<<(std::ostream& stream, LogicalDisplayId displayId) {
+    return stream << displayId.val();
+}
+
+} // namespace android::ui
+
+namespace std {
+template <>
+struct hash<android::ui::LogicalDisplayId> {
+    size_t operator()(const android::ui::LogicalDisplayId& displayId) const {
+        return hash<int32_t>()(displayId.val());
+    }
+};
+} // namespace std
\ No newline at end of file
diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp
index 8ddee7e..1115804 100644
--- a/libs/ui/tests/DisplayId_test.cpp
+++ b/libs/ui/tests/DisplayId_test.cpp
@@ -24,7 +24,7 @@
     constexpr uint8_t port = 1;
     constexpr uint16_t manufacturerId = 13;
     constexpr uint32_t modelHash = 42;
-    PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash);
+    const PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash);
     EXPECT_EQ(port, id.getPort());
     EXPECT_EQ(manufacturerId, id.getManufacturerId());
     EXPECT_FALSE(VirtualDisplayId::tryCast(id));
@@ -39,7 +39,7 @@
 
 TEST(DisplayIdTest, createPhysicalIdFromPort) {
     constexpr uint8_t port = 3;
-    PhysicalDisplayId id = PhysicalDisplayId::fromPort(port);
+    const PhysicalDisplayId id = PhysicalDisplayId::fromPort(port);
     EXPECT_EQ(port, id.getPort());
     EXPECT_FALSE(VirtualDisplayId::tryCast(id));
     EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
@@ -52,7 +52,22 @@
 }
 
 TEST(DisplayIdTest, createGpuVirtualId) {
-    GpuVirtualDisplayId id(42);
+    const GpuVirtualDisplayId id(42);
+    EXPECT_TRUE(VirtualDisplayId::tryCast(id));
+    EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
+    EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
+    EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
+    EXPECT_FALSE(HalDisplayId::tryCast(id));
+
+    EXPECT_EQ(id, DisplayId::fromValue(id.value));
+    EXPECT_EQ(id, DisplayId::fromValue<GpuVirtualDisplayId>(id.value));
+}
+
+TEST(DisplayIdTest, createGpuVirtualIdFromUniqueId) {
+    static const std::string kUniqueId("virtual:ui:DisplayId_test");
+    const auto idOpt = GpuVirtualDisplayId::fromUniqueId(kUniqueId);
+    ASSERT_TRUE(idOpt.has_value());
+    const GpuVirtualDisplayId id = idOpt.value();
     EXPECT_TRUE(VirtualDisplayId::tryCast(id));
     EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
     EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
@@ -64,7 +79,7 @@
 }
 
 TEST(DisplayIdTest, createHalVirtualId) {
-    HalVirtualDisplayId id(42);
+    const HalVirtualDisplayId id(42);
     EXPECT_TRUE(VirtualDisplayId::tryCast(id));
     EXPECT_TRUE(HalVirtualDisplayId::tryCast(id));
     EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
diff --git a/libs/ui/tests/DisplayIdentification_test.cpp b/libs/ui/tests/DisplayIdentification_test.cpp
index 736979a..721b466 100644
--- a/libs/ui/tests/DisplayIdentification_test.cpp
+++ b/libs/ui/tests/DisplayIdentification_test.cpp
@@ -21,9 +21,9 @@
 #include <functional>
 #include <string_view>
 
+#include <ftl/hash.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-
 #include <ui/DisplayIdentification.h>
 
 using ::testing::ElementsAre;
@@ -135,7 +135,7 @@
 }
 
 uint32_t hash(const char* str) {
-    return static_cast<uint32_t>(cityHash64Len0To16(str));
+    return static_cast<uint32_t>(*ftl::stable_hash(str));
 }
 
 } // namespace
@@ -188,6 +188,7 @@
     EXPECT_STREQ("SEC", edid->pnpId.data());
     // ASCII text should be used as fallback if display name and serial number are missing.
     EXPECT_EQ(hash("121AT11-801"), edid->modelHash);
+    EXPECT_EQ(hash("121AT11-801"), 626564263);
     EXPECT_TRUE(edid->displayName.empty());
     EXPECT_EQ(12610, edid->productId);
     EXPECT_EQ(21, edid->manufactureOrModelYear);
@@ -199,6 +200,7 @@
     EXPECT_EQ(0x22f0u, edid->manufacturerId);
     EXPECT_STREQ("HWP", edid->pnpId.data());
     EXPECT_EQ(hash("HP ZR30w"), edid->modelHash);
+    EXPECT_EQ(hash("HP ZR30w"), 918492362);
     EXPECT_EQ("HP ZR30w", edid->displayName);
     EXPECT_EQ(10348, edid->productId);
     EXPECT_EQ(22, edid->manufactureOrModelYear);
@@ -210,6 +212,7 @@
     EXPECT_EQ(0x4c2du, edid->manufacturerId);
     EXPECT_STREQ("SAM", edid->pnpId.data());
     EXPECT_EQ(hash("SAMSUNG"), edid->modelHash);
+    EXPECT_EQ(hash("SAMSUNG"), 1201368132);
     EXPECT_EQ("SAMSUNG", edid->displayName);
     EXPECT_EQ(2302, edid->productId);
     EXPECT_EQ(21, edid->manufactureOrModelYear);
@@ -227,6 +230,7 @@
     EXPECT_EQ(13481, edid->manufacturerId);
     EXPECT_STREQ("MEI", edid->pnpId.data());
     EXPECT_EQ(hash("Panasonic-TV"), edid->modelHash);
+    EXPECT_EQ(hash("Panasonic-TV"), 3876373262);
     EXPECT_EQ("Panasonic-TV", edid->displayName);
     EXPECT_EQ(41622, edid->productId);
     EXPECT_EQ(29, edid->manufactureOrModelYear);
@@ -244,6 +248,7 @@
     EXPECT_EQ(8355, edid->manufacturerId);
     EXPECT_STREQ("HEC", edid->pnpId.data());
     EXPECT_EQ(hash("Hisense"), edid->modelHash);
+    EXPECT_EQ(hash("Hisense"), 2859844809);
     EXPECT_EQ("Hisense", edid->displayName);
     EXPECT_EQ(0, edid->productId);
     EXPECT_EQ(29, edid->manufactureOrModelYear);
@@ -261,6 +266,7 @@
     EXPECT_EQ(3724, edid->manufacturerId);
     EXPECT_STREQ("CTL", edid->pnpId.data());
     EXPECT_EQ(hash("LP2361"), edid->modelHash);
+    EXPECT_EQ(hash("LP2361"), 1523181158);
     EXPECT_EQ("LP2361", edid->displayName);
     EXPECT_EQ(9373, edid->productId);
     EXPECT_EQ(23, edid->manufactureOrModelYear);
@@ -281,6 +287,7 @@
     // Serial number should be used as fallback if display name is invalid.
     const auto modelHash = hash("CN4202137Q");
     EXPECT_EQ(modelHash, edid->modelHash);
+    EXPECT_EQ(modelHash, 3582951527);
     EXPECT_TRUE(edid->displayName.empty());
 
     // Parsing should succeed even if EDID is truncated.
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index a481c62..fadb1fd 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -100,6 +100,12 @@
     mGpuStats->insertTargetStatsArray(appPackageName, driverVersionCode, stats, values, valueCount);
 }
 
+void GpuService::addVulkanEngineName(const std::string& appPackageName,
+                                     const uint64_t driverVersionCode,
+                                     const char* engineName) {
+    mGpuStats->addVulkanEngineName(appPackageName, driverVersionCode, engineName);
+}
+
 void GpuService::toggleAngleAsSystemDriver(bool enabled) {
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 11b636d..6d758bc 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -181,6 +181,33 @@
     return insertTargetStatsArray(appPackageName, driverVersionCode, stats, &value, 1);
 }
 
+void GpuStats::addVulkanEngineName(const std::string& appPackageName,
+                                   const uint64_t driverVersionCode,
+                                   const char* engineNameCStr) {
+    ATRACE_CALL();
+
+    const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+    const size_t engineNameLen = std::min(strlen(engineNameCStr),
+                                          GpuStatsAppInfo::MAX_VULKAN_ENGINE_NAME_LENGTH);
+    const std::string engineName{engineNameCStr, engineNameLen};
+
+    std::lock_guard<std::mutex> lock(mLock);
+    registerStatsdCallbacksIfNeeded();
+
+    const auto foundApp = mAppStats.find(appStatsKey);
+    if (foundApp == mAppStats.end()) {
+        return;
+    }
+
+    // Storing in std::set<> is not efficient for serialization tasks. Use
+    // vector instead and filter out dups
+    std::vector<std::string>& engineNames = foundApp->second.vulkanEngineNames;
+    if (engineNames.size() < GpuStatsAppInfo::MAX_VULKAN_ENGINE_NAMES
+        && std::find(engineNames.cbegin(), engineNames.cend(), engineName) == engineNames.cend()) {
+        engineNames.push_back(engineName);
+    }
+}
+
 void GpuStats::insertTargetStatsArray(const std::string& appPackageName,
                                  const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
                                  const uint64_t* values, const uint32_t valueCount) {
@@ -389,6 +416,11 @@
             std::string angleDriverBytes = int64VectorToProtoByteString(
                 ele.second.angleDriverLoadingTime);
 
+            std::vector<const char*> engineNames;
+            for (const std::string &engineName : ele.second.vulkanEngineNames) {
+                engineNames.push_back(engineName.c_str());
+            }
+
             android::util::addAStatsEvent(
                     data,
                     android::util::GPU_STATS_APP_INFO,
@@ -410,7 +442,8 @@
                     ele.second.vulkanApiVersion,
                     ele.second.vulkanDeviceFeaturesEnabled,
                     ele.second.vulkanInstanceExtensions,
-                    ele.second.vulkanDeviceExtensions);
+                    ele.second.vulkanDeviceExtensions,
+                    engineNames);
         }
     }
 
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 22c64db..961f011 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -44,6 +44,9 @@
     void insertTargetStatsArray(const std::string& appPackageName,
                            const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
                            const uint64_t* values, const uint32_t valueCount);
+    // Add the engine name passed in VkApplicationInfo during CreateInstance
+    void addVulkanEngineName(const std::string& appPackageName,
+                             const uint64_t driverVersionCode, const char* engineName);
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
 
diff --git a/services/gpuservice/include/gpuservice/GpuService.h b/services/gpuservice/include/gpuservice/GpuService.h
index 54f8f66..3072885 100644
--- a/services/gpuservice/include/gpuservice/GpuService.h
+++ b/services/gpuservice/include/gpuservice/GpuService.h
@@ -64,6 +64,8 @@
     void setUpdatableDriverPath(const std::string& driverPath) override;
     std::string getUpdatableDriverPath() override;
     void toggleAngleAsSystemDriver(bool enabled) override;
+    void addVulkanEngineName(const std::string& appPackageName, const uint64_t driverVersionCode,
+                             const char *engineName) override;
 
     /*
      * IBinder interface
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 4ce533f..b367457 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -46,6 +46,8 @@
 #define UPDATED_DRIVER_VER_CODE   1
 #define UPDATED_DRIVER_BUILD_TIME 234
 #define VULKAN_VERSION            345
+#define VULKAN_ENGINE_NAME_1      "testVulkanEngine1"
+#define VULKAN_ENGINE_NAME_2      "testVulkanEngine2"
 #define APP_PKG_NAME_1            "testapp1"
 #define APP_PKG_NAME_2            "testapp2"
 #define DRIVER_LOADING_TIME_1     678
@@ -243,6 +245,8 @@
     mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
                                  GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                  VULKAN_DEVICE_EXTENSION_1);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                             VULKAN_ENGINE_NAME_1);
 
     EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
 }
@@ -282,6 +286,8 @@
     mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
                                  GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                  VULKAN_DEVICE_EXTENSION_2);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                             VULKAN_ENGINE_NAME_1);
 
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1"));
@@ -302,6 +308,64 @@
     expectedResult.str("");
     expectedResult << "vulkanDeviceExtensions: 0x" << std::hex << VULKAN_DEVICE_EXTENSION_1
                     << " 0x" << std::hex << VULKAN_DEVICE_EXTENSION_2;
+    expectedResult.str("");
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ",";
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+// Verify the vulkanEngineNames list behaves like a set and dedupes additions
+TEST_F(GpuStatsTest, vulkanEngineNamesBehavesLikeSet) {
+    mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+                                 BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+                                 VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+                                 DRIVER_LOADING_TIME_1);
+    for (int i = 0; i < 4; i++) {
+        mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                       VULKAN_ENGINE_NAME_1);
+    }
+
+    std::stringstream wrongResult, expectedResult;
+    wrongResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", " <<
+                   VULKAN_ENGINE_NAME_1;
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1;
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), Not(HasSubstr(wrongResult.str())));
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+TEST_F(GpuStatsTest, vulkanEngineNamesCheckEmptyEngineNameAlone) {
+    mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+                                 BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+                                 VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+                                 DRIVER_LOADING_TIME_1);
+
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   "");
+
+    std::stringstream expectedResult;
+    expectedResult << "vulkanEngineNames: ,";
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+TEST_F(GpuStatsTest, vulkanEngineNamesCheckEmptyEngineNameWithOthers) {
+    mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+                                 BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+                                 VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+                                 DRIVER_LOADING_TIME_1);
+
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   VULKAN_ENGINE_NAME_1);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   "");
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   VULKAN_ENGINE_NAME_2);
+
+    std::stringstream expectedResult;
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", "
+                   << ", " <<  VULKAN_ENGINE_NAME_2;
+
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
 }
 
@@ -350,6 +414,10 @@
         mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
                                     GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                     VULKAN_DEVICE_EXTENSION_2);
+        mGpuStats->addVulkanEngineName(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                 VULKAN_ENGINE_NAME_1);
+        mGpuStats->addVulkanEngineName(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                 VULKAN_ENGINE_NAME_2);
 
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
@@ -371,6 +439,9 @@
         expectedResult.str("");
         expectedResult << "vulkanDeviceExtensions: 0x" << std::hex << VULKAN_DEVICE_EXTENSION_1
                         << " 0x" << std::hex << VULKAN_DEVICE_EXTENSION_2;
+        expectedResult.str("");
+        expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", "
+                       << VULKAN_ENGINE_NAME_2 << ",";
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
     }
 
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index a03055f..70801dc 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -56,6 +56,16 @@
         host: {
             sanitize: {
                 address: true,
+                diag: {
+                    cfi: true,
+                    integer_overflow: true,
+                    memtag_heap: true,
+                    undefined: true,
+                    misc_undefined: [
+                        "bounds",
+                        "all",
+                    ],
+                },
             },
             include_dirs: [
                 "bionic/libc/kernel/android/uapi/",
diff --git a/services/inputflinger/InputCommonConverter.cpp b/services/inputflinger/InputCommonConverter.cpp
index 417c1f3..e376734 100644
--- a/services/inputflinger/InputCommonConverter.cpp
+++ b/services/inputflinger/InputCommonConverter.cpp
@@ -314,7 +314,7 @@
     common::MotionEvent event;
     event.deviceId = args.deviceId;
     event.source = getSource(args.source);
-    event.displayId = args.displayId;
+    event.displayId = args.displayId.val();
     event.downTime = args.downTime;
     event.eventTime = args.eventTime;
     event.deviceTimestamp = 0;
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
index 1ada5e5..8e73ce5 100644
--- a/services/inputflinger/InputFilter.cpp
+++ b/services/inputflinger/InputFilter.cpp
@@ -32,7 +32,7 @@
     event.eventTime = args.eventTime;
     event.deviceId = args.deviceId;
     event.source = static_cast<Source>(args.source);
-    event.displayId = args.displayId;
+    event.displayId = args.displayId.val();
     event.policyFlags = args.policyFlags;
     event.action = static_cast<KeyEventAction>(args.action);
     event.flags = args.flags;
diff --git a/services/inputflinger/InputFilterCallbacks.cpp b/services/inputflinger/InputFilterCallbacks.cpp
index a9bdbec..5fbdc84 100644
--- a/services/inputflinger/InputFilterCallbacks.cpp
+++ b/services/inputflinger/InputFilterCallbacks.cpp
@@ -30,9 +30,9 @@
 
 NotifyKeyArgs keyEventToNotifyKeyArgs(const AidlKeyEvent& event) {
     return NotifyKeyArgs(event.id, event.eventTime, event.readTime, event.deviceId,
-                         static_cast<uint32_t>(event.source), event.displayId, event.policyFlags,
-                         static_cast<int32_t>(event.action), event.flags, event.keyCode,
-                         event.scanCode, event.metaState, event.downTime);
+                         static_cast<uint32_t>(event.source), ui::LogicalDisplayId{event.displayId},
+                         event.policyFlags, static_cast<int32_t>(event.action), event.flags,
+                         event.keyCode, event.scanCode, event.metaState, event.downTime);
 }
 
 namespace {
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index ae066c0..41e5247 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -41,7 +41,6 @@
 const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
         sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
 
-const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
 const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
 
 int32_t exceptionCodeFromStatusT(status_t status) {
@@ -152,12 +151,10 @@
     mTracingStages.emplace_back(
             std::make_unique<TracedInputListener>("InputProcessor", *mProcessor));
 
-    if (ENABLE_POINTER_CHOREOGRAPHER) {
-        mChoreographer =
-                std::make_unique<PointerChoreographer>(*mTracingStages.back(), choreographerPolicy);
-        mTracingStages.emplace_back(
-                std::make_unique<TracedInputListener>("PointerChoreographer", *mChoreographer));
-    }
+    mChoreographer =
+            std::make_unique<PointerChoreographer>(*mTracingStages.back(), choreographerPolicy);
+    mTracingStages.emplace_back(
+            std::make_unique<TracedInputListener>("PointerChoreographer", *mChoreographer));
 
     mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mTracingStages.back());
     mTracingStages.emplace_back(
@@ -245,10 +242,8 @@
     dump += '\n';
     mBlocker->dump(dump);
     dump += '\n';
-    if (ENABLE_POINTER_CHOREOGRAPHER) {
-        mChoreographer->dump(dump);
-        dump += '\n';
-    }
+    mChoreographer->dump(dump);
+    dump += '\n';
     mProcessor->dump(dump);
     dump += '\n';
     if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index 4ec5b89..6b2627c 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -68,7 +68,7 @@
         if (currentViewport.type == type) {
             if (!result ||
                 (type == ViewportType::INTERNAL &&
-                 currentViewport.displayId == ADISPLAY_ID_DEFAULT)) {
+                 currentViewport.displayId == ui::LogicalDisplayId::DEFAULT)) {
                 result = std::make_optional(currentViewport);
             }
             count++;
@@ -93,7 +93,7 @@
 }
 
 std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportById(
-        int32_t displayId) const {
+        ui::LogicalDisplayId displayId) const {
     for (const DisplayViewport& currentViewport : mDisplays) {
         if (currentViewport.displayId == displayId) {
             return std::make_optional(currentViewport);
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
index de836e9..19a4f26 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -43,7 +43,7 @@
 // --- NotifyKeyArgs ---
 
 NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
-                             uint32_t source, int32_t displayId, uint32_t policyFlags,
+                             uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
                              int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
                              int32_t metaState, nsecs_t downTime)
       : id(id),
@@ -64,7 +64,7 @@
 
 NotifyMotionArgs::NotifyMotionArgs(
         int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, uint32_t source,
-        int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+        ui::LogicalDisplayId displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
         int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
         int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
         const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 4dc2737..8a1eed6 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -17,7 +17,12 @@
 #define LOG_TAG "PointerChoreographer"
 
 #include <android-base/logging.h>
+#include <com_android_input_flags.h>
+#if defined(__ANDROID__)
+#include <gui/SurfaceComposerClient.h>
+#endif
 #include <input/PrintTools.h>
+#include <unordered_set>
 
 #include "PointerChoreographer.h"
 
@@ -25,6 +30,10 @@
 
 namespace android {
 
+namespace input_flags = com::android::input::flags;
+static const bool HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS =
+        input_flags::hide_pointer_indicators_for_secure_windows();
+
 namespace {
 
 bool isFromMouse(const NotifyMotionArgs& args) {
@@ -58,8 +67,9 @@
              !isFromSource(sources, AINPUT_SOURCE_STYLUS));
 }
 
-inline void notifyPointerDisplayChange(std::optional<std::tuple<int32_t, FloatPoint>> change,
-                                       PointerChoreographerPolicyInterface& policy) {
+inline void notifyPointerDisplayChange(
+        std::optional<std::tuple<ui::LogicalDisplayId, FloatPoint>> change,
+        PointerChoreographerPolicyInterface& policy) {
     if (!change) {
         return;
     }
@@ -91,11 +101,19 @@
         }),
         mNextListener(listener),
         mPolicy(policy),
-        mDefaultMouseDisplayId(ADISPLAY_ID_DEFAULT),
-        mNotifiedPointerDisplayId(ADISPLAY_ID_NONE),
+        mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT),
+        mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID),
         mShowTouchesEnabled(false),
         mStylusPointerIconEnabled(false) {}
 
+PointerChoreographer::~PointerChoreographer() {
+    std::scoped_lock _l(mLock);
+    if (mWindowInfoListener == nullptr) {
+        return;
+    }
+    mWindowInfoListener->onPointerChoreographerDestroyed();
+}
+
 void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
     PointerDisplayChange pointerDisplayChange;
 
@@ -218,7 +236,7 @@
 }
 
 void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
-    if (args.displayId == ADISPLAY_ID_NONE) {
+    if (args.displayId == ui::LogicalDisplayId::INVALID) {
         return;
     }
 
@@ -231,6 +249,7 @@
     auto [it, _] = mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
                                                               getMouseControllerConstructor(
                                                                       args.displayId));
+    // TODO (b/325252005): Add handing for drawing tablets mouse pointer controller
 
     PointerControllerInterface& pc = *it->second;
 
@@ -254,7 +273,7 @@
  * For touch events, we do not need to populate the cursor position.
  */
 void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
-    if (args.displayId == ADISPLAY_ID_NONE) {
+    if (!args.displayId.isValid()) {
         return;
     }
 
@@ -268,7 +287,11 @@
     }
 
     // Get the touch pointer controller for the device, or create one if it doesn't exist.
-    auto [it, _] = mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
+    auto [it, controllerAdded] =
+            mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
+    if (controllerAdded) {
+        onControllerAddedOrRemoved();
+    }
 
     PointerControllerInterface& pc = *it->second;
 
@@ -293,7 +316,7 @@
 }
 
 void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
-    if (args.displayId == ADISPLAY_ID_NONE) {
+    if (!args.displayId.isValid()) {
         return;
     }
 
@@ -306,6 +329,7 @@
     auto [it, _] =
             mStylusPointersByDevice.try_emplace(args.deviceId,
                                                 getStylusControllerConstructor(args.displayId));
+    // TODO (b/325252005): Add handing for stylus pointer controller
 
     PointerControllerInterface& pc = *it->second;
 
@@ -345,6 +369,31 @@
     mTouchPointersByDevice.erase(args.deviceId);
     mStylusPointersByDevice.erase(args.deviceId);
     mDrawingTabletPointersByDevice.erase(args.deviceId);
+    onControllerAddedOrRemoved();
+}
+
+void PointerChoreographer::onControllerAddedOrRemoved() {
+    if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
+        return;
+    }
+    bool requireListener = !mTouchPointersByDevice.empty();
+    // TODO (b/325252005): Update for other types of pointer controllers
+
+    if (requireListener && mWindowInfoListener == nullptr) {
+        mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
+        auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
+                                          std::vector<android::gui::DisplayInfo>{});
+#if defined(__ANDROID__)
+        SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
+                                                                    &initialInfo);
+#endif
+        onWindowInfosChangedLocked(initialInfo.first);
+    } else if (!requireListener && mWindowInfoListener != nullptr) {
+#if defined(__ANDROID__)
+        SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
+#endif
+        mWindowInfoListener = nullptr;
+    }
 }
 
 void PointerChoreographer::notifyPointerCaptureChanged(
@@ -358,6 +407,12 @@
     mNextListener.notify(args);
 }
 
+void PointerChoreographer::onWindowInfosChanged(
+        const std::vector<android::gui::WindowInfo>& windowInfos) {
+    std::scoped_lock _l(mLock);
+    onWindowInfosChangedLocked(windowInfos);
+}
+
 void PointerChoreographer::dump(std::string& dump) {
     std::scoped_lock _l(mLock);
 
@@ -369,7 +424,7 @@
     dump += INDENT "MousePointerControllers:\n";
     for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
         std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
-        dump += INDENT + std::to_string(displayId) + " : " + pointerControllerDump;
+        dump += INDENT + displayId.toString() + " : " + pointerControllerDump;
     }
     dump += INDENT "TouchPointerControllers:\n";
     for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
@@ -389,7 +444,8 @@
     dump += "\n";
 }
 
-const DisplayViewport* PointerChoreographer::findViewportByIdLocked(int32_t displayId) const {
+const DisplayViewport* PointerChoreographer::findViewportByIdLocked(
+        ui::LogicalDisplayId displayId) const {
     for (auto& viewport : mViewports) {
         if (viewport.displayId == displayId) {
             return &viewport;
@@ -398,18 +454,20 @@
     return nullptr;
 }
 
-int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisplayId) const {
-    return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
+ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked(
+        ui::LogicalDisplayId associatedDisplayId) const {
+    return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId;
 }
 
-std::pair<int32_t, PointerControllerInterface&> PointerChoreographer::ensureMouseControllerLocked(
-        int32_t associatedDisplayId) {
-    const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
+std::pair<ui::LogicalDisplayId, PointerControllerInterface&>
+PointerChoreographer::ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) {
+    const ui::LogicalDisplayId displayId = getTargetMouseDisplayLocked(associatedDisplayId);
 
     auto it = mMousePointersByDisplay.find(displayId);
     if (it == mMousePointersByDisplay.end()) {
         it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
                      .first;
+        // TODO (b/325252005): Add handing for mouse pointer controller
     }
 
     return {displayId, *it->second};
@@ -421,12 +479,12 @@
     return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
 }
 
-bool PointerChoreographer::canUnfadeOnDisplay(int32_t displayId) {
+bool PointerChoreographer::canUnfadeOnDisplay(ui::LogicalDisplayId displayId) {
     return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
 }
 
 PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
-    std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
+    std::set<ui::LogicalDisplayId /*displayId*/> mouseDisplaysToKeep;
     std::set<DeviceId> touchDevicesToKeep;
     std::set<DeviceId> stylusDevicesToKeep;
     std::set<DeviceId> drawingTabletDevicesToKeep;
@@ -443,28 +501,31 @@
         const bool isKnownMouse = mMouseDevices.count(info.getId()) != 0;
 
         if (isMouseOrTouchpad(sources) || isKnownMouse) {
-            const int32_t displayId = getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
+            const ui::LogicalDisplayId displayId =
+                    getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
             mouseDisplaysToKeep.insert(displayId);
             // For mice, show the cursor immediately when the device is first connected or
             // when it moves to a new display.
             auto [mousePointerIt, isNewMousePointer] =
                     mMousePointersByDisplay.try_emplace(displayId,
                                                         getMouseControllerConstructor(displayId));
+            // TODO (b/325252005): Add handing for mouse pointer controller
+
             mMouseDevices.emplace(info.getId());
             if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
                 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
             }
         }
         if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
-            info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
+            info.getAssociatedDisplayId().isValid()) {
             touchDevicesToKeep.insert(info.getId());
         }
         if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
-            info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
+            info.getAssociatedDisplayId().isValid()) {
             stylusDevicesToKeep.insert(info.getId());
         }
         if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE) &&
-            info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
+            info.getAssociatedDisplayId().isValid()) {
             drawingTabletDevicesToKeep.insert(info.getId());
         }
     }
@@ -488,13 +549,15 @@
                 mInputDeviceInfos.end();
     });
 
+    onControllerAddedOrRemoved();
+
     // Check if we need to notify the policy if there's a change on the pointer display ID.
     return calculatePointerDisplayChangeToNotify();
 }
 
 PointerChoreographer::PointerDisplayChange
 PointerChoreographer::calculatePointerDisplayChangeToNotify() {
-    int32_t displayIdToNotify = ADISPLAY_ID_NONE;
+    ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID;
     FloatPoint cursorPosition = {0, 0};
     if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
         it != mMousePointersByDisplay.end()) {
@@ -512,7 +575,7 @@
     return {{displayIdToNotify, cursorPosition}};
 }
 
-void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
+void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
     PointerDisplayChange pointerDisplayChange;
 
     { // acquire lock
@@ -531,7 +594,7 @@
     { // acquire lock
         std::scoped_lock _l(mLock);
         for (const auto& viewport : viewports) {
-            const int32_t displayId = viewport.displayId;
+            const ui::LogicalDisplayId displayId = viewport.displayId;
             if (const auto it = mMousePointersByDisplay.find(displayId);
                 it != mMousePointersByDisplay.end()) {
                 it->second->setDisplayViewport(viewport);
@@ -557,18 +620,18 @@
 }
 
 std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
-        int32_t associatedDisplayId) {
+        ui::LogicalDisplayId associatedDisplayId) {
     std::scoped_lock _l(mLock);
-    const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
+    const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
     if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
         return *viewport;
     }
     return std::nullopt;
 }
 
-FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
+FloatPoint PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
     std::scoped_lock _l(mLock);
-    const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
+    const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
     if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
         it != mMousePointersByDisplay.end()) {
         return it->second->getPosition();
@@ -607,8 +670,8 @@
 }
 
 bool PointerChoreographer::setPointerIcon(
-        std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
-        DeviceId deviceId) {
+        std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
+        ui::LogicalDisplayId displayId, DeviceId deviceId) {
     std::scoped_lock _l(mLock);
     if (deviceId < 0) {
         LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
@@ -652,7 +715,32 @@
     return false;
 }
 
-void PointerChoreographer::setPointerIconVisibility(int32_t displayId, bool visible) {
+void PointerChoreographer::onWindowInfosChangedLocked(
+        const std::vector<android::gui::WindowInfo>& windowInfos) {
+    // Mark all spot controllers secure on displays containing secure windows and
+    // remove secure flag from others if required
+    std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
+    std::unordered_set<ui::LogicalDisplayId> allDisplayIds;
+    for (const auto& windowInfo : windowInfos) {
+        allDisplayIds.insert(windowInfo.displayId);
+        if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
+            windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
+            privacySensitiveDisplays.insert(windowInfo.displayId);
+        }
+    }
+
+    for (auto& it : mTouchPointersByDevice) {
+        auto& pc = it.second;
+        for (ui::LogicalDisplayId displayId : allDisplayIds) {
+            pc->setSkipScreenshot(displayId,
+                                  privacySensitiveDisplays.find(displayId) !=
+                                          privacySensitiveDisplays.end());
+        }
+    }
+    // TODO (b/325252005): update skip screenshot flag for other types of pointer controllers
+}
+
+void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
     std::scoped_lock lock(mLock);
     if (visible) {
         mDisplaysWithPointersHidden.erase(displayId);
@@ -675,7 +763,7 @@
 }
 
 PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
-        int32_t displayId) {
+        ui::LogicalDisplayId displayId) {
     std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
             [this, displayId]() REQUIRES(mLock) {
                 auto pc = mPolicy.createPointerController(
@@ -689,7 +777,7 @@
 }
 
 PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
-        int32_t displayId) {
+        ui::LogicalDisplayId displayId) {
     std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
             [this, displayId]() REQUIRES(mLock) {
                 auto pc = mPolicy.createPointerController(
@@ -702,4 +790,18 @@
     return ConstructorDelegate(std::move(ctor));
 }
 
+void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
+        const gui::WindowInfosUpdate& windowInfosUpdate) {
+    std::scoped_lock _l(mListenerLock);
+    if (mPointerChoreographer != nullptr) {
+        mPointerChoreographer->onWindowInfosChanged(windowInfosUpdate.windowInfos);
+    }
+}
+
+void PointerChoreographer::PointerChoreographerDisplayInfoListener::
+        onPointerChoreographerDestroyed() {
+    std::scoped_lock _l(mListenerLock);
+    mPointerChoreographer = nullptr;
+}
+
 } // namespace android
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index a3c210e..12316c0 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -21,6 +21,7 @@
 #include "PointerChoreographerPolicyInterface.h"
 
 #include <android-base/thread_annotations.h>
+#include <gui/WindowInfosListener.h>
 #include <type_traits>
 
 namespace android {
@@ -53,11 +54,11 @@
      * Set the display that pointers, like the mouse cursor and drawing tablets,
      * should be drawn on.
      */
-    virtual void setDefaultMouseDisplayId(int32_t displayId) = 0;
+    virtual void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) = 0;
     virtual void setDisplayViewports(const std::vector<DisplayViewport>& viewports) = 0;
     virtual std::optional<DisplayViewport> getViewportForPointerDevice(
-            int32_t associatedDisplayId = ADISPLAY_ID_NONE) = 0;
-    virtual FloatPoint getMouseCursorPosition(int32_t displayId) = 0;
+            ui::LogicalDisplayId associatedDisplayId = ui::LogicalDisplayId::INVALID) = 0;
+    virtual FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) = 0;
     virtual void setShowTouchesEnabled(bool enabled) = 0;
     virtual void setStylusPointerIconEnabled(bool enabled) = 0;
     /**
@@ -66,12 +67,12 @@
      * Returns true if the icon was changed successfully, false otherwise.
      */
     virtual bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
-                                int32_t displayId, DeviceId deviceId) = 0;
+                                ui::LogicalDisplayId displayId, DeviceId deviceId) = 0;
     /**
      * Set whether pointer icons for mice, touchpads, and styluses should be visible on the
      * given display.
      */
-    virtual void setPointerIconVisibility(int32_t displayId, bool visible) = 0;
+    virtual void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) = 0;
 
     /**
      * This method may be called on any thread (usually by the input manager on a binder thread).
@@ -83,18 +84,18 @@
 public:
     explicit PointerChoreographer(InputListenerInterface& listener,
                                   PointerChoreographerPolicyInterface&);
-    ~PointerChoreographer() override = default;
+    ~PointerChoreographer() override;
 
-    void setDefaultMouseDisplayId(int32_t displayId) override;
+    void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) override;
     void setDisplayViewports(const std::vector<DisplayViewport>& viewports) override;
     std::optional<DisplayViewport> getViewportForPointerDevice(
-            int32_t associatedDisplayId) override;
-    FloatPoint getMouseCursorPosition(int32_t displayId) override;
+            ui::LogicalDisplayId associatedDisplayId) override;
+    FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) override;
     void setShowTouchesEnabled(bool enabled) override;
     void setStylusPointerIconEnabled(bool enabled) override;
     bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
-                        int32_t displayId, DeviceId deviceId) override;
-    void setPointerIconVisibility(int32_t displayId, bool visible) override;
+                        ui::LogicalDisplayId displayId, DeviceId deviceId) override;
+    void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
 
     void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
     void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
@@ -106,19 +107,24 @@
     void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
     void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
 
+    // Public because it's also used by tests to simulate the WindowInfosListener callback
+    void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos);
+
     void dump(std::string& dump) override;
 
 private:
-    using PointerDisplayChange =
-            std::optional<std::tuple<int32_t /*displayId*/, FloatPoint /*cursorPosition*/>>;
+    using PointerDisplayChange = std::optional<
+            std::tuple<ui::LogicalDisplayId /*displayId*/, FloatPoint /*cursorPosition*/>>;
     [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(mLock);
     [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(mLock);
-    const DisplayViewport* findViewportByIdLocked(int32_t displayId) const REQUIRES(mLock);
-    int32_t getTargetMouseDisplayLocked(int32_t associatedDisplayId) const REQUIRES(mLock);
-    std::pair<int32_t /*displayId*/, PointerControllerInterface&> ensureMouseControllerLocked(
-            int32_t associatedDisplayId) REQUIRES(mLock);
+    const DisplayViewport* findViewportByIdLocked(ui::LogicalDisplayId displayId) const
+            REQUIRES(mLock);
+    ui::LogicalDisplayId getTargetMouseDisplayLocked(ui::LogicalDisplayId associatedDisplayId) const
+            REQUIRES(mLock);
+    std::pair<ui::LogicalDisplayId /*displayId*/, PointerControllerInterface&>
+    ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) REQUIRES(mLock);
     InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(mLock);
-    bool canUnfadeOnDisplay(int32_t displayId) REQUIRES(mLock);
+    bool canUnfadeOnDisplay(ui::LogicalDisplayId displayId) REQUIRES(mLock);
 
     NotifyMotionArgs processMotion(const NotifyMotionArgs& args);
     NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
@@ -127,20 +133,38 @@
     void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
     void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
     void processDeviceReset(const NotifyDeviceResetArgs& args);
+    void onControllerAddedOrRemoved() REQUIRES(mLock);
+    void onWindowInfosChangedLocked(const std::vector<android::gui::WindowInfo>& windowInfos)
+            REQUIRES(mLock);
+
+    class PointerChoreographerDisplayInfoListener : public gui::WindowInfosListener {
+    public:
+        explicit PointerChoreographerDisplayInfoListener(PointerChoreographer* pc)
+              : mPointerChoreographer(pc){};
+        void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
+        void onPointerChoreographerDestroyed();
+
+    private:
+        std::mutex mListenerLock;
+        PointerChoreographer* mPointerChoreographer GUARDED_BY(mListenerLock);
+    };
+    sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener GUARDED_BY(mLock);
 
     using ControllerConstructor =
             ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
     ControllerConstructor mTouchControllerConstructor GUARDED_BY(mLock);
-    ControllerConstructor getMouseControllerConstructor(int32_t displayId) REQUIRES(mLock);
-    ControllerConstructor getStylusControllerConstructor(int32_t displayId) REQUIRES(mLock);
+    ControllerConstructor getMouseControllerConstructor(ui::LogicalDisplayId displayId)
+            REQUIRES(mLock);
+    ControllerConstructor getStylusControllerConstructor(ui::LogicalDisplayId displayId)
+            REQUIRES(mLock);
 
     std::mutex mLock;
 
     InputListenerInterface& mNextListener;
     PointerChoreographerPolicyInterface& mPolicy;
 
-    std::map<int32_t, std::shared_ptr<PointerControllerInterface>> mMousePointersByDisplay
-            GUARDED_BY(mLock);
+    std::map<ui::LogicalDisplayId, std::shared_ptr<PointerControllerInterface>>
+            mMousePointersByDisplay GUARDED_BY(mLock);
     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mTouchPointersByDevice
             GUARDED_BY(mLock);
     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mStylusPointersByDevice
@@ -148,14 +172,14 @@
     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mDrawingTabletPointersByDevice
             GUARDED_BY(mLock);
 
-    int32_t mDefaultMouseDisplayId GUARDED_BY(mLock);
-    int32_t mNotifiedPointerDisplayId GUARDED_BY(mLock);
+    ui::LogicalDisplayId mDefaultMouseDisplayId GUARDED_BY(mLock);
+    ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(mLock);
     std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(mLock);
     std::set<DeviceId> mMouseDevices GUARDED_BY(mLock);
     std::vector<DisplayViewport> mViewports GUARDED_BY(mLock);
     bool mShowTouchesEnabled GUARDED_BY(mLock);
     bool mStylusPointerIconEnabled GUARDED_BY(mLock);
-    std::set<int32_t /*displayId*/> mDisplaysWithPointersHidden;
+    std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden;
 };
 
 } // namespace android
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 5f95590..96c8640 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -18,7 +18,6 @@
 
 #include <android/os/IInputConstants.h>
 #include <binder/Binder.h>
-#include <gui/constants.h>
 #include "../dispatcher/InputDispatcher.h"
 #include "../tests/FakeApplicationHandle.h"
 #include "../tests/FakeInputDispatcherPolicy.h"
@@ -38,7 +37,7 @@
 constexpr DeviceId DEVICE_ID = 1;
 
 // An arbitrary display id
-constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 
 static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
 
@@ -63,7 +62,7 @@
     ui::Transform identityTransform;
     MotionEvent event;
     event.initialize(IInputConstants::INVALID_INPUT_EVENT_ID, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-                     ADISPLAY_ID_DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
+                     ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
                      /* actionButton */ 0, /* flags */ 0,
                      /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
                      identityTransform, /* xPrecision */ 0,
@@ -89,7 +88,7 @@
     const nsecs_t currentTime = now();
     // Define a valid motion event.
     NotifyMotionArgs args(IInputConstants::INVALID_INPUT_EVENT_ID, currentTime, currentTime,
-                          DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                          DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           POLICY_FLAG_PASS_TO_USER, AMOTION_EVENT_ACTION_DOWN,
                           /* actionButton */ 0, /* flags */ 0, AMETA_NONE, /* buttonState */ 0,
                           MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
index 9c73f03..4a0889f 100644
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ b/services/inputflinger/dispatcher/CancelationOptions.h
@@ -48,7 +48,7 @@
     std::optional<int32_t> deviceId = std::nullopt;
 
     // The specific display id of events to cancel, or nullopt to cancel events on any display.
-    std::optional<int32_t> displayId = std::nullopt;
+    std::optional<ui::LogicalDisplayId> displayId = std::nullopt;
 
     // The specific pointers to cancel, or nullopt to cancel all pointer events
     std::optional<std::bitset<MAX_POINTER_ID + 1>> pointerIds = std::nullopt;
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index c8bc87f..ad9cec1 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -132,9 +132,9 @@
 // --- KeyEntry ---
 
 KeyEntry::KeyEntry(int32_t id, std::shared_ptr<InjectionState> injectionState, nsecs_t eventTime,
-                   int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
-                   int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
-                   int32_t metaState, int32_t repeatCount, nsecs_t downTime)
+                   int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId,
+                   uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+                   int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime)
       : EventEntry(id, Type::KEY, eventTime, policyFlags),
         deviceId(deviceId),
         source(source),
@@ -156,13 +156,14 @@
     if (!IS_DEBUGGABLE_BUILD) {
         return "KeyEvent";
     }
-    return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64 ", source=%s, displayId=%" PRId32
-                        ", action=%s, "
+    return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64 ", source=%s, displayId=%s, "
+                        "action=%s, "
                         "flags=0x%08x, keyCode=%s(%d), scanCode=%d, metaState=0x%08x, "
                         "repeatCount=%d), policyFlags=0x%08x",
-                        deviceId, eventTime, inputEventSourceToString(source).c_str(), displayId,
-                        KeyEvent::actionToString(action), flags, KeyEvent::getLabel(keyCode),
-                        keyCode, scanCode, metaState, repeatCount, policyFlags);
+                        deviceId, eventTime, inputEventSourceToString(source).c_str(),
+                        displayId.toString().c_str(), KeyEvent::actionToString(action), flags,
+                        KeyEvent::getLabel(keyCode), keyCode, scanCode, metaState, repeatCount,
+                        policyFlags);
 }
 
 std::ostream& operator<<(std::ostream& out, const KeyEntry& keyEntry) {
@@ -172,7 +173,8 @@
 
 // --- TouchModeEntry ---
 
-TouchModeEntry::TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, int displayId)
+TouchModeEntry::TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode,
+                               ui::LogicalDisplayId displayId)
       : EventEntry(id, Type::TOUCH_MODE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER),
         inTouchMode(inTouchMode),
         displayId(displayId) {}
@@ -184,12 +186,13 @@
 // --- MotionEntry ---
 
 MotionEntry::MotionEntry(int32_t id, std::shared_ptr<InjectionState> injectionState,
-                         nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
-                         uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
-                         int32_t metaState, int32_t buttonState,
-                         MotionClassification classification, int32_t edgeFlags, float xPrecision,
-                         float yPrecision, float xCursorPosition, float yCursorPosition,
-                         nsecs_t downTime, const std::vector<PointerProperties>& pointerProperties,
+                         nsecs_t eventTime, int32_t deviceId, uint32_t source,
+                         ui::LogicalDisplayId displayId, uint32_t policyFlags, int32_t action,
+                         int32_t actionButton, int32_t flags, int32_t metaState,
+                         int32_t buttonState, MotionClassification classification,
+                         int32_t edgeFlags, float xPrecision, float yPrecision,
+                         float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+                         const std::vector<PointerProperties>& pointerProperties,
                          const std::vector<PointerCoords>& pointerCoords)
       : EventEntry(id, Type::MOTION, eventTime, policyFlags),
         deviceId(deviceId),
@@ -218,15 +221,16 @@
     }
     std::string msg;
     msg += StringPrintf("MotionEvent(deviceId=%d, eventTime=%" PRIu64
-                        ", source=%s, displayId=%" PRId32
-                        ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
+                        ", source=%s, displayId=%s, action=%s, actionButton=0x%08x, flags=0x%08x,"
+                        " metaState=0x%08x, "
                         "buttonState=0x%08x, "
                         "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
                         "xCursorPosition=%0.1f, yCursorPosition=%0.1f, pointers=[",
-                        deviceId, eventTime, inputEventSourceToString(source).c_str(), displayId,
-                        MotionEvent::actionToString(action).c_str(), actionButton, flags, metaState,
-                        buttonState, motionClassificationToString(classification), edgeFlags,
-                        xPrecision, yPrecision, xCursorPosition, yCursorPosition);
+                        deviceId, eventTime, inputEventSourceToString(source).c_str(),
+                        displayId.toString().c_str(), MotionEvent::actionToString(action).c_str(),
+                        actionButton, flags, metaState, buttonState,
+                        motionClassificationToString(classification), edgeFlags, xPrecision,
+                        yPrecision, xCursorPosition, yCursorPosition);
 
     for (uint32_t i = 0; i < getPointerCount(); i++) {
         if (i) {
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 06d5c7d..f2f31d8 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -120,7 +120,7 @@
 struct KeyEntry : EventEntry {
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
     int32_t action;
     int32_t keyCode;
     int32_t scanCode;
@@ -144,9 +144,9 @@
     mutable int32_t repeatCount;
 
     KeyEntry(int32_t id, std::shared_ptr<InjectionState> injectionState, nsecs_t eventTime,
-             int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
-             int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-             int32_t repeatCount, nsecs_t downTime);
+             int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId,
+             uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+             int32_t metaState, int32_t repeatCount, nsecs_t downTime);
     std::string getDescription() const override;
 };
 
@@ -155,7 +155,7 @@
 struct MotionEntry : EventEntry {
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
     int32_t action;
     int32_t actionButton;
     int32_t flags;
@@ -175,11 +175,12 @@
     size_t getPointerCount() const { return pointerProperties.size(); }
 
     MotionEntry(int32_t id, std::shared_ptr<InjectionState> injectionState, nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
-                int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
-                int32_t buttonState, MotionClassification classification, int32_t edgeFlags,
-                float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition,
-                nsecs_t downTime, const std::vector<PointerProperties>& pointerProperties,
+                int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId,
+                uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
+                int32_t metaState, int32_t buttonState, MotionClassification classification,
+                int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
+                float yCursorPosition, nsecs_t downTime,
+                const std::vector<PointerProperties>& pointerProperties,
                 const std::vector<PointerCoords>& pointerCoords);
     std::string getDescription() const override;
 };
@@ -205,9 +206,9 @@
 
 struct TouchModeEntry : EventEntry {
     bool inTouchMode;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
 
-    TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, int32_t displayId);
+    TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, ui::LogicalDisplayId displayId);
     std::string getDescription() const override;
 };
 
diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp
index 0e4e79e..b374fad 100644
--- a/services/inputflinger/dispatcher/FocusResolver.cpp
+++ b/services/inputflinger/dispatcher/FocusResolver.cpp
@@ -41,12 +41,12 @@
     size_t operator()(const sp<T>& k) const { return std::hash<T*>()(k.get()); }
 };
 
-sp<IBinder> FocusResolver::getFocusedWindowToken(int32_t displayId) const {
+sp<IBinder> FocusResolver::getFocusedWindowToken(ui::LogicalDisplayId displayId) const {
     auto it = mFocusedWindowTokenByDisplay.find(displayId);
     return it != mFocusedWindowTokenByDisplay.end() ? it->second.second : nullptr;
 }
 
-std::optional<FocusRequest> FocusResolver::getFocusRequest(int32_t displayId) {
+std::optional<FocusRequest> FocusResolver::getFocusRequest(ui::LogicalDisplayId displayId) {
     auto it = mFocusRequestByDisplay.find(displayId);
     return it != mFocusRequestByDisplay.end() ? std::make_optional<>(it->second) : std::nullopt;
 }
@@ -58,7 +58,7 @@
  * we will check if the previous focus request is eligible to receive focus.
  */
 std::optional<FocusResolver::FocusChanges> FocusResolver::setInputWindows(
-        int32_t displayId, const std::vector<sp<WindowInfoHandle>>& windows) {
+        ui::LogicalDisplayId displayId, const std::vector<sp<WindowInfoHandle>>& windows) {
     std::string removeFocusReason;
 
     const std::optional<FocusRequest> request = getFocusRequest(displayId);
@@ -94,12 +94,11 @@
 
 std::optional<FocusResolver::FocusChanges> FocusResolver::setFocusedWindow(
         const FocusRequest& request, const std::vector<sp<WindowInfoHandle>>& windows) {
-    const int32_t displayId = request.displayId;
+    const ui::LogicalDisplayId displayId = ui::LogicalDisplayId{request.displayId};
     const sp<IBinder> currentFocus = getFocusedWindowToken(displayId);
     if (currentFocus == request.token) {
-        ALOGD_IF(DEBUG_FOCUS,
-                 "setFocusedWindow %s on display %" PRId32 " ignored, reason: already focused",
-                 request.windowName.c_str(), displayId);
+        ALOGD_IF(DEBUG_FOCUS, "setFocusedWindow %s on display %s ignored, reason: already focused",
+                 request.windowName.c_str(), displayId.toString().c_str());
         return std::nullopt;
     }
 
@@ -193,7 +192,7 @@
 }
 
 std::optional<FocusResolver::FocusChanges> FocusResolver::updateFocusedWindow(
-        int32_t displayId, const std::string& reason, const sp<IBinder>& newFocus,
+        ui::LogicalDisplayId displayId, const std::string& reason, const sp<IBinder>& newFocus,
         const std::string& tokenName) {
     sp<IBinder> oldFocus = getFocusedWindowToken(displayId);
     if (newFocus == oldFocus) {
@@ -216,8 +215,8 @@
     std::string dump;
     dump += INDENT "FocusedWindows:\n";
     for (const auto& [displayId, namedToken] : mFocusedWindowTokenByDisplay) {
-        dump += base::StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n", displayId,
-                                   namedToken.first.c_str());
+        dump += base::StringPrintf(INDENT2 "displayId=%s, name='%s'\n",
+                                   displayId.toString().c_str(), namedToken.first.c_str());
     }
     return dump;
 }
@@ -233,13 +232,14 @@
         auto it = mLastFocusResultByDisplay.find(displayId);
         std::string result =
                 it != mLastFocusResultByDisplay.end() ? ftl::enum_string(it->second) : "";
-        dump += base::StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s' result='%s'\n",
-                                   displayId, request.windowName.c_str(), result.c_str());
+        dump += base::StringPrintf(INDENT2 "displayId=%s, name='%s' result='%s'\n",
+                                   displayId.toString().c_str(), request.windowName.c_str(),
+                                   result.c_str());
     }
     return dump;
 }
 
-void FocusResolver::displayRemoved(int32_t displayId) {
+void FocusResolver::displayRemoved(ui::LogicalDisplayId displayId) {
     mFocusRequestByDisplay.erase(displayId);
     mLastFocusResultByDisplay.erase(displayId);
 }
diff --git a/services/inputflinger/dispatcher/FocusResolver.h b/services/inputflinger/dispatcher/FocusResolver.h
index 5bb157b..2910ba4 100644
--- a/services/inputflinger/dispatcher/FocusResolver.h
+++ b/services/inputflinger/dispatcher/FocusResolver.h
@@ -49,22 +49,23 @@
 class FocusResolver {
 public:
     // Returns the focused window token on the specified display.
-    sp<IBinder> getFocusedWindowToken(int32_t displayId) const;
+    sp<IBinder> getFocusedWindowToken(ui::LogicalDisplayId displayId) const;
 
     struct FocusChanges {
         sp<IBinder> oldFocus;
         sp<IBinder> newFocus;
-        int32_t displayId;
+        ui::LogicalDisplayId displayId;
         std::string reason;
     };
     std::optional<FocusResolver::FocusChanges> setInputWindows(
-            int32_t displayId, const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
+            ui::LogicalDisplayId displayId,
+            const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
     std::optional<FocusResolver::FocusChanges> setFocusedWindow(
             const android::gui::FocusRequest& request,
             const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
 
     // Display has been removed from the system, clean up old references.
-    void displayRemoved(int32_t displayId);
+    void displayRemoved(ui::LogicalDisplayId displayId);
 
     // exposed for debugging
     bool hasFocusedWindowTokens() const { return !mFocusedWindowTokenByDisplay.empty(); }
@@ -105,20 +106,23 @@
     // the same token. Focus is tracked by the token per display and the events are dispatched
     // to the channel associated by this token.
     typedef std::pair<std::string /* name */, sp<IBinder>> NamedToken;
-    std::unordered_map<int32_t /* displayId */, NamedToken> mFocusedWindowTokenByDisplay;
+    std::unordered_map<ui::LogicalDisplayId /* displayId */, NamedToken>
+            mFocusedWindowTokenByDisplay;
 
     // This map will store the focus request per display. When the input window handles are updated,
     // the current request will be checked to see if it can be processed at that time.
-    std::unordered_map<int32_t /* displayId */, android::gui::FocusRequest> mFocusRequestByDisplay;
+    std::unordered_map<ui::LogicalDisplayId /* displayId */, android::gui::FocusRequest>
+            mFocusRequestByDisplay;
 
     // Last reason for not granting a focus request. This is used to add more debug information
     // in the event logs.
-    std::unordered_map<int32_t /* displayId */, Focusability> mLastFocusResultByDisplay;
+    std::unordered_map<ui::LogicalDisplayId /* displayId */, Focusability>
+            mLastFocusResultByDisplay;
 
     std::optional<FocusResolver::FocusChanges> updateFocusedWindow(
-            int32_t displayId, const std::string& reason, const sp<IBinder>& token,
+            ui::LogicalDisplayId displayId, const std::string& reason, const sp<IBinder>& token,
             const std::string& tokenName = "");
-    std::optional<android::gui::FocusRequest> getFocusRequest(int32_t displayId);
+    std::optional<android::gui::FocusRequest> getFocusRequest(ui::LogicalDisplayId displayId);
 };
 
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index de841ba..dae2b61 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -571,8 +571,8 @@
 }
 
 // Returns true if the given window can accept pointer events at the given display location.
-bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, float x, float y,
-                          bool isStylus, const ui::Transform& displayTransform) {
+bool windowAcceptsTouchAt(const WindowInfo& windowInfo, ui::LogicalDisplayId displayId, float x,
+                          float y, bool isStylus, const ui::Transform& displayTransform) {
     const auto inputConfig = windowInfo.inputConfig;
     if (windowInfo.displayId != displayId ||
         inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
@@ -600,8 +600,8 @@
 
 // Returns true if the given window's frame can occlude pointer events at the given display
 // location.
-bool windowOccludesTouchAt(const WindowInfo& windowInfo, int displayId, float x, float y,
-                           const ui::Transform& displayTransform) {
+bool windowOccludesTouchAt(const WindowInfo& windowInfo, ui::LogicalDisplayId displayId, float x,
+                           float y, const ui::Transform& displayTransform) {
     if (windowInfo.displayId != displayId) {
         return false;
     }
@@ -815,9 +815,9 @@
 /**
  * Return true if stylus is currently down anywhere on the specified display, and false otherwise.
  */
-bool isStylusActiveInDisplay(
-        int32_t displayId,
-        const std::unordered_map<int32_t /*displayId*/, TouchState>& touchStatesByDisplay) {
+bool isStylusActiveInDisplay(ui::LogicalDisplayId displayId,
+                             const std::unordered_map<ui::LogicalDisplayId /*displayId*/,
+                                                      TouchState>& touchStatesByDisplay) {
     const auto it = touchStatesByDisplay.find(displayId);
     if (it == touchStatesByDisplay.end()) {
         return false;
@@ -918,8 +918,9 @@
         mDispatchFrozen(false),
         mInputFilterEnabled(false),
         mMaximumObscuringOpacityForTouch(1.0f),
-        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
+        mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT),
         mWindowTokenWithPointerCapture(nullptr),
+        mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID),
         mLatencyAggregator(),
         mLatencyTracker(&mLatencyAggregator) {
     mLooper = sp<Looper>::make(false);
@@ -1286,7 +1287,7 @@
     // If the application takes too long to catch up then we drop all events preceding
     // the touch into the other window.
     if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
-        const int32_t displayId = motionEntry.displayId;
+        const ui::LogicalDisplayId displayId = motionEntry.displayId;
         const auto [x, y] = resolveTouchedPosition(motionEntry);
         const bool isStylus = isPointerFromStylus(motionEntry, /*pointerIndex=*/0);
 
@@ -1411,8 +1412,8 @@
     }
 }
 
-sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, float x, float y,
-                                                                bool isStylus,
+sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(ui::LogicalDisplayId displayId,
+                                                                float x, float y, bool isStylus,
                                                                 bool ignoreDragWindow) const {
     // Traverse windows from front to back to find touched window.
     const auto& windowHandles = getWindowHandlesLocked(displayId);
@@ -1431,7 +1432,8 @@
 }
 
 std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
-        int32_t displayId, const sp<WindowInfoHandle>& touchedWindow, int32_t pointerId) const {
+        ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow,
+        int32_t pointerId) const {
     if (touchedWindow == nullptr) {
         return {};
     }
@@ -1458,7 +1460,7 @@
 }
 
 std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
-        int32_t displayId, float x, float y, bool isStylus) const {
+        ui::LogicalDisplayId displayId, float x, float y, bool isStylus) const {
     // Traverse windows from front to back and gather the touched spy windows.
     std::vector<sp<WindowInfoHandle>> spyWindows;
     const auto& windowHandles = getWindowHandlesLocked(displayId);
@@ -1951,12 +1953,12 @@
 
 void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& entry) {
     if (DEBUG_OUTBOUND_EVENT_DETAILS) {
-        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", "
+        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%s, "
               "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
               "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
-              prefix, entry.eventTime, entry.deviceId, entry.source, entry.displayId,
-              entry.policyFlags, entry.action, entry.flags, entry.keyCode, entry.scanCode,
-              entry.metaState, entry.repeatCount, entry.downTime);
+              prefix, entry.eventTime, entry.deviceId, entry.source,
+              entry.displayId.toString().c_str(), entry.policyFlags, entry.action, entry.flags,
+              entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount, entry.downTime);
     }
 }
 
@@ -2105,16 +2107,15 @@
 
 void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) {
     if (DEBUG_OUTBOUND_EVENT_DETAILS) {
-        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%" PRId32
-              ", policyFlags=0x%x, "
+        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, "
               "action=%s, actionButton=0x%x, flags=0x%x, "
               "metaState=0x%x, buttonState=0x%x,"
               "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
               prefix, entry.eventTime, entry.deviceId,
-              inputEventSourceToString(entry.source).c_str(), entry.displayId, entry.policyFlags,
-              MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags,
-              entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision,
-              entry.yPrecision, entry.downTime);
+              inputEventSourceToString(entry.source).c_str(), entry.displayId.toString().c_str(),
+              entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(),
+              entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags,
+              entry.xPrecision, entry.yPrecision, entry.downTime);
 
         for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
             ALOGD("  Pointer %d: id=%d, toolType=%s, "
@@ -2199,8 +2200,8 @@
  * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
  * Focused display is the display that the user most recently interacted with.
  */
-int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) {
-    int32_t displayId;
+ui::LogicalDisplayId InputDispatcher::getTargetDisplayId(const EventEntry& entry) {
+    ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
     switch (entry.type) {
         case EventEntry::Type::KEY: {
             const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
@@ -2220,10 +2221,10 @@
         case EventEntry::Type::SENSOR:
         case EventEntry::Type::DRAG: {
             ALOGE("%s events do not have a target display", ftl::enum_string(entry.type).c_str());
-            return ADISPLAY_ID_NONE;
+            return ui::LogicalDisplayId::INVALID;
         }
     }
-    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
+    return displayId == ui::LogicalDisplayId::INVALID ? mFocusedDisplayId : displayId;
 }
 
 bool InputDispatcher::shouldWaitToSendKeyLocked(nsecs_t currentTime,
@@ -2262,7 +2263,7 @@
         InputEventInjectionResult& outInjectionResult) {
     outInjectionResult = InputEventInjectionResult::FAILED; // Default result
 
-    int32_t displayId = getTargetDisplayId(entry);
+    ui::LogicalDisplayId displayId = getTargetDisplayId(entry);
     sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
     std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
             getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
@@ -2271,8 +2272,8 @@
     // then drop the event.
     if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
         ALOGI("Dropping %s event because there is no focused window or focused application in "
-              "display %" PRId32 ".",
-              ftl::enum_string(entry.type).c_str(), displayId);
+              "display %s.",
+              ftl::enum_string(entry.type).c_str(), displayId.toString().c_str());
         return nullptr;
     }
 
@@ -2380,7 +2381,7 @@
     std::vector<InputTarget> targets;
     // For security reasons, we defer updating the touch state until we are sure that
     // event injection will be allowed.
-    const int32_t displayId = entry.displayId;
+    const ui::LogicalDisplayId displayId = entry.displayId;
     const int32_t action = entry.action;
     const int32_t maskedAction = MotionEvent::getActionMasked(action);
 
@@ -2450,7 +2451,8 @@
         }
         // Handle the case where we did not find a window.
         if (newTouchedWindowHandle == nullptr) {
-            ALOGD("No new touched window at (%.1f, %.1f) in display %" PRId32, x, y, displayId);
+            ALOGD("No new touched window at (%.1f, %.1f) in display %s", x, y,
+                  displayId.toString().c_str());
             // Try to assign the pointer to the first foreground window we find, if there is one.
             newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
         }
@@ -2491,8 +2493,8 @@
 
         if (newTouchedWindows.empty()) {
             ALOGI("Dropping event because there is no touchable window at (%.1f, %.1f) on display "
-                  "%d.",
-                  x, y, displayId);
+                  "%s.",
+                  x, y, displayId.toString().c_str());
             outInjectionResult = InputEventInjectionResult::FAILED;
             return {};
         }
@@ -2640,9 +2642,9 @@
 
             if (newTouchedWindowHandle != nullptr &&
                 !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
-                ALOGI("Touch is slipping out of window %s into window %s in display %" PRId32,
+                ALOGI("Touch is slipping out of window %s into window %s in display %s",
                       oldTouchedWindowHandle->getName().c_str(),
-                      newTouchedWindowHandle->getName().c_str(), displayId);
+                      newTouchedWindowHandle->getName().c_str(), displayId.toString().c_str());
 
                 // Make a slippery exit from the old window.
                 std::bitset<MAX_POINTER_ID + 1> pointerIds;
@@ -2827,7 +2829,7 @@
     // Save changes unless the action was scroll in which case the temporary touch
     // state was only valid for this one action.
     if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
-        if (displayId >= 0) {
+        if (displayId >= ui::LogicalDisplayId::DEFAULT) {
             tempTouchState.clearWindowsWithoutPointers();
             mTouchStatesByDisplay[displayId] = tempTouchState;
         } else {
@@ -2842,7 +2844,7 @@
     return targets;
 }
 
-void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) {
+void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, float y) {
     // Prevent stylus interceptor windows from affecting drag and drop behavior for now, until we
     // have an explicit reason to support it.
     constexpr bool isStylus = false;
@@ -3059,7 +3061,7 @@
 }
 
 void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
-                                                       int32_t displayId) {
+                                                       ui::LogicalDisplayId displayId) {
     auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
     if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
 
@@ -3131,7 +3133,7 @@
 InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked(
         const sp<WindowInfoHandle>& windowHandle, float x, float y) const {
     const WindowInfo* windowInfo = windowHandle->getInfo();
-    int32_t displayId = windowInfo->displayId;
+    ui::LogicalDisplayId displayId = windowInfo->displayId;
     const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
     TouchOcclusionInfo info;
     info.hasBlockingOcclusion = false;
@@ -3215,7 +3217,7 @@
 
 bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,
                                                     float x, float y) const {
-    int32_t displayId = windowHandle->getInfo()->displayId;
+    ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
     const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
     for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
         if (windowHandle == otherHandle) {
@@ -3231,7 +3233,7 @@
 }
 
 bool InputDispatcher::isWindowObscuredLocked(const sp<WindowInfoHandle>& windowHandle) const {
-    int32_t displayId = windowHandle->getInfo()->displayId;
+    ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
     const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
     const WindowInfo* windowInfo = windowHandle->getInfo();
     for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
@@ -3239,8 +3241,7 @@
             break; // All future windows are below us. Exit early.
         }
         const WindowInfo* otherInfo = otherHandle->getInfo();
-        if (canBeObscuredBy(windowHandle, otherHandle) &&
-            otherInfo->overlaps(windowInfo)) {
+        if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->overlaps(windowInfo)) {
             return true;
         }
     }
@@ -3282,7 +3283,7 @@
         }
     }
 
-    int32_t displayId = getTargetDisplayId(eventEntry);
+    ui::LogicalDisplayId displayId = getTargetDisplayId(eventEntry);
     sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
     const WindowInfo* windowDisablingUserActivityInfo = nullptr;
     if (focusedWindowHandle != nullptr) {
@@ -4465,12 +4466,13 @@
 void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
     ALOGD_IF(debugInboundEventDetails(),
              "notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
-             ", deviceId=%d, source=%s, displayId=%" PRId32
-             "policyFlags=0x%x, action=%s, flags=0x%x, keyCode=%s, scanCode=0x%x, metaState=0x%x, "
+             ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, action=%s, flags=0x%x, "
+             "keyCode=%s, scanCode=0x%x, metaState=0x%x, "
              "downTime=%" PRId64,
              args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
-             args.displayId, args.policyFlags, KeyEvent::actionToString(args.action), args.flags,
-             KeyEvent::getLabel(args.keyCode), args.scanCode, args.metaState, args.downTime);
+             args.displayId.toString().c_str(), args.policyFlags,
+             KeyEvent::actionToString(args.action), args.flags, KeyEvent::getLabel(args.keyCode),
+             args.scanCode, args.metaState, args.downTime);
     Result<void> keyCheck = validateKeyEvent(args.action);
     if (!keyCheck.ok()) {
         LOG(ERROR) << "invalid key event: " << keyCheck.error();
@@ -4546,15 +4548,15 @@
 void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
     if (debugInboundEventDetails()) {
         ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=%s, "
-              "displayId=%" PRId32 ", policyFlags=0x%x, "
+              "displayId=%s, policyFlags=0x%x, "
               "action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
               "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
               "yCursorPosition=%f, downTime=%" PRId64,
               args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
-              args.displayId, args.policyFlags, MotionEvent::actionToString(args.action).c_str(),
-              args.actionButton, args.flags, args.metaState, args.buttonState, args.edgeFlags,
-              args.xPrecision, args.yPrecision, args.xCursorPosition, args.yCursorPosition,
-              args.downTime);
+              args.displayId.toString().c_str(), args.policyFlags,
+              MotionEvent::actionToString(args.action).c_str(), args.actionButton, args.flags,
+              args.metaState, args.buttonState, args.edgeFlags, args.xPrecision, args.yPrecision,
+              args.xCursorPosition, args.yCursorPosition, args.downTime);
         for (uint32_t i = 0; i < args.getPointerCount(); i++) {
             ALOGD("  Pointer %d: id=%d, toolType=%s, x=%f, y=%f, pressure=%f, size=%f, "
                   "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f",
@@ -4583,7 +4585,8 @@
     if (DEBUG_VERIFY_EVENTS) {
         auto [it, _] =
                 mVerifiersByDisplay.try_emplace(args.displayId,
-                                                StringPrintf("display %" PRId32, args.displayId));
+                                                StringPrintf("display %s",
+                                                             args.displayId.toString().c_str()));
         Result<void> result =
                 it->second.processMovement(args.deviceId, args.source, args.action,
                                            args.getPointerCount(), args.pointerProperties.data(),
@@ -4729,6 +4732,7 @@
 }
 
 void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
+    // TODO(b/308677868) Remove device reset from the InputListener interface
     if (debugInboundEventDetails()) {
         ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime,
               args.deviceId);
@@ -4857,8 +4861,9 @@
             const bool isPointerEvent =
                     isFromSource(event->getSource(), AINPUT_SOURCE_CLASS_POINTER);
             // If a pointer event has no displayId specified, inject it to the default display.
-            const int32_t displayId = isPointerEvent && (event->getDisplayId() == ADISPLAY_ID_NONE)
-                    ? ADISPLAY_ID_DEFAULT
+            const ui::LogicalDisplayId displayId =
+                    isPointerEvent && (event->getDisplayId() == ui::LogicalDisplayId::INVALID)
+                    ? ui::LogicalDisplayId::DEFAULT
                     : event->getDisplayId();
             int32_t flags = motionEvent.getFlags();
 
@@ -4879,6 +4884,30 @@
             }
 
             mLock.lock();
+
+            if (policyFlags & POLICY_FLAG_FILTERED) {
+                // The events from InputFilter impersonate real hardware devices. Check these
+                // events for consistency and print an error. An inconsistent event sent from
+                // InputFilter could cause a crash in the later stages of dispatching pipeline.
+                auto [it, _] =
+                        mInputFilterVerifiersByDisplay.try_emplace(displayId,
+                                                                   std::string("Injection on ") +
+                                                                           displayId.toString());
+                InputVerifier& verifier = it->second;
+
+                Result<void> result =
+                        verifier.processMovement(resolvedDeviceId, motionEvent.getSource(),
+                                                 motionEvent.getAction(),
+                                                 motionEvent.getPointerCount(),
+                                                 motionEvent.getPointerProperties(),
+                                                 motionEvent.getSamplePointerCoords(), flags);
+                if (!result.ok()) {
+                    logDispatchStateLocked();
+                    LOG(ERROR) << "Inconsistent event: " << motionEvent
+                               << ", reason: " << result.error();
+                }
+            }
+
             const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
             const size_t pointerCount = motionEvent.getPointerCount();
             const std::vector<PointerProperties>
@@ -5125,22 +5154,21 @@
 }
 
 const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked(
-        int32_t displayId) const {
+        ui::LogicalDisplayId displayId) const {
     static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES;
     auto it = mWindowHandlesByDisplay.find(displayId);
     return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;
 }
 
 sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
-        const sp<IBinder>& windowHandleToken, std::optional<int32_t> displayId) const {
+        const sp<IBinder>& windowHandleToken, std::optional<ui::LogicalDisplayId> displayId) const {
     if (windowHandleToken == nullptr) {
         return nullptr;
     }
 
     if (!displayId) {
         // Look through all displays.
-        for (auto& it : mWindowHandlesByDisplay) {
-            const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second;
+        for (const auto& [_, windowHandles] : mWindowHandlesByDisplay) {
             for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
                 if (windowHandle->getToken() == windowHandleToken) {
                     return windowHandle;
@@ -5161,16 +5189,15 @@
 
 sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
         const sp<WindowInfoHandle>& windowHandle) const {
-    for (auto& it : mWindowHandlesByDisplay) {
-        const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second;
+    for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
         for (const sp<WindowInfoHandle>& handle : windowHandles) {
             if (handle->getId() == windowHandle->getId() &&
                 handle->getToken() == windowHandle->getToken()) {
-                if (windowHandle->getInfo()->displayId != it.first) {
-                    ALOGE("Found window %s in display %" PRId32
-                          ", but it should belong to display %" PRId32,
-                          windowHandle->getName().c_str(), it.first,
-                          windowHandle->getInfo()->displayId);
+                if (windowHandle->getInfo()->displayId != displayId) {
+                    ALOGE("Found window %s in display %s"
+                          ", but it should belong to display %s",
+                          windowHandle->getName().c_str(), displayId.toString().c_str(),
+                          windowHandle->getInfo()->displayId.toString().c_str());
                 }
                 return handle;
             }
@@ -5179,12 +5206,13 @@
     return nullptr;
 }
 
-sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const {
+sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(
+        ui::LogicalDisplayId displayId) const {
     sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
     return getWindowHandleLocked(focusedToken, displayId);
 }
 
-ui::Transform InputDispatcher::getTransformLocked(int32_t displayId) const {
+ui::Transform InputDispatcher::getTransformLocked(ui::LogicalDisplayId displayId) const {
     auto displayInfoIt = mDisplayInfos.find(displayId);
     return displayInfoIt != mDisplayInfos.end() ? displayInfoIt->second.transform
                                                 : kIdentityTransform;
@@ -5253,7 +5281,8 @@
 }
 
 void InputDispatcher::updateWindowHandlesForDisplayLocked(
-        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles, int32_t displayId) {
+        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
+        ui::LogicalDisplayId displayId) {
     if (windowInfoHandles.empty()) {
         // Remove all handles on a display if there are no windows left.
         mWindowHandlesByDisplay.erase(displayId);
@@ -5285,13 +5314,14 @@
         }
 
         if (info->displayId != displayId) {
-            ALOGE("Window %s updated by wrong display %d, should belong to display %d",
-                  handle->getName().c_str(), displayId, info->displayId);
+            ALOGE("Window %s updated by wrong display %s, should belong to display %s",
+                  handle->getName().c_str(), displayId.toString().c_str(),
+                  info->displayId.toString().c_str());
             continue;
         }
 
         if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&
-                (oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
+            (oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
             const sp<WindowInfoHandle>& oldHandle = oldHandlesById.at(handle->getId());
             oldHandle->updateFrom(handle);
             newHandles.push_back(oldHandle);
@@ -5312,7 +5342,8 @@
  * For removed handle, check if need to send a cancel event if already in touch.
  */
 void InputDispatcher::setInputWindowsLocked(
-        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles, int32_t displayId) {
+        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
+        ui::LogicalDisplayId displayId) {
     if (DEBUG_FOCUS) {
         std::string windowList;
         for (const sp<WindowInfoHandle>& iwh : windowInfoHandles) {
@@ -5363,31 +5394,32 @@
         onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
     }
 
-    std::unordered_map<int32_t, TouchState>::iterator stateIt =
-            mTouchStatesByDisplay.find(displayId);
-    if (stateIt != mTouchStatesByDisplay.end()) {
-        TouchState& state = stateIt->second;
+    if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
+        TouchState& state = it->second;
         for (size_t i = 0; i < state.windows.size();) {
             TouchedWindow& touchedWindow = state.windows[i];
-            if (getWindowHandleLocked(touchedWindow.windowHandle) == nullptr) {
-                LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
-                          << " in display %" << displayId;
-                CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
-                                           "touched window was removed", traceContext.getTracker());
-                synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
-                // Since we are about to drop the touch, cancel the events for the wallpaper as
-                // well.
-                if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
-                    touchedWindow.windowHandle->getInfo()->inputConfig.test(
-                            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
-                    if (const auto& ww = state.getWallpaperWindow(); ww) {
+            if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
+                i++;
+                continue;
+            }
+            LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
+                      << " in display %" << displayId;
+            CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+                                       "touched window was removed", traceContext.getTracker());
+            synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
+            // Since we are about to drop the touch, cancel the events for the wallpaper as
+            // well.
+            if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
+                touchedWindow.windowHandle->getInfo()->inputConfig.test(
+                        gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
+                for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
+                    if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
+                        options.deviceId = deviceId;
                         synthesizeCancelationEventsForWindowLocked(ww, options);
                     }
                 }
-                state.windows.erase(state.windows.begin() + i);
-            } else {
-                ++i;
             }
+            state.windows.erase(state.windows.begin() + i);
         }
 
         // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
@@ -5416,9 +5448,10 @@
 }
 
 void InputDispatcher::setFocusedApplication(
-        int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
+        ui::LogicalDisplayId displayId,
+        const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
     if (DEBUG_FOCUS) {
-        ALOGD("setFocusedApplication displayId=%" PRId32 " %s", displayId,
+        ALOGD("setFocusedApplication displayId=%s %s", displayId.toString().c_str(),
               inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
     }
     { // acquire lock
@@ -5431,7 +5464,8 @@
 }
 
 void InputDispatcher::setFocusedApplicationLocked(
-        int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
+        ui::LogicalDisplayId displayId,
+        const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
     std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
             getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
 
@@ -5468,9 +5502,9 @@
  * cancel all the unreleased display-unspecified events for the focused window on the old focused
  * display. The display-specified events won't be affected.
  */
-void InputDispatcher::setFocusedDisplay(int32_t displayId) {
+void InputDispatcher::setFocusedDisplay(ui::LogicalDisplayId displayId) {
     if (DEBUG_FOCUS) {
-        ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
+        ALOGD("setFocusedDisplay displayId=%s", displayId.toString().c_str());
     }
     { // acquire lock
         std::scoped_lock _l(mLock);
@@ -5489,7 +5523,7 @@
                         options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS,
                                 "The display which contains this window no longer has focus.",
                                 traceContext.getTracker());
-                options.displayId = ADISPLAY_ID_NONE;
+                options.displayId = ui::LogicalDisplayId::INVALID;
                 synthesizeCancelationEventsForWindowLocked(windowHandle, options);
             }
             mFocusedDisplayId = displayId;
@@ -5499,7 +5533,8 @@
             sendFocusChangedCommandLocked(oldFocusedWindowToken, newFocusedWindowToken);
 
             if (newFocusedWindowToken == nullptr) {
-                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
+                ALOGW("Focused display #%s does not have a focused window.",
+                      displayId.toString().c_str());
                 if (mFocusResolver.hasFocusedWindowTokens()) {
                     ALOGE("But another display has a focused window\n%s",
                           mFocusResolver.dumpFocusedWindows().c_str());
@@ -5565,15 +5600,15 @@
 }
 
 bool InputDispatcher::setInTouchMode(bool inTouchMode, gui::Pid pid, gui::Uid uid,
-                                     bool hasPermission, int32_t displayId) {
+                                     bool hasPermission, ui::LogicalDisplayId displayId) {
     bool needWake = false;
     {
         std::scoped_lock lock(mLock);
         ALOGD_IF(DEBUG_TOUCH_MODE,
                  "Request to change touch mode to %s (calling pid=%s, uid=%s, "
-                 "hasPermission=%s, target displayId=%d, mTouchModePerDisplay[displayId]=%s)",
+                 "hasPermission=%s, target displayId=%s, mTouchModePerDisplay[displayId]=%s)",
                  toString(inTouchMode), pid.toString().c_str(), uid.toString().c_str(),
-                 toString(hasPermission), displayId,
+                 toString(hasPermission), displayId.toString().c_str(),
                  mTouchModePerDisplay.count(displayId) == 0
                          ? "not set"
                          : std::to_string(mTouchModePerDisplay[displayId]).c_str());
@@ -5631,7 +5666,7 @@
     mMaximumObscuringOpacityForTouch = opacity;
 }
 
-std::tuple<TouchState*, TouchedWindow*, int32_t /*displayId*/>
+std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId /*displayId*/>
 InputDispatcher::findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) {
     for (auto& [displayId, state] : mTouchStatesByDisplay) {
         for (TouchedWindow& w : state.windows) {
@@ -5640,7 +5675,7 @@
             }
         }
     }
-    return std::make_tuple(nullptr, nullptr, ADISPLAY_ID_DEFAULT);
+    return std::make_tuple(nullptr, nullptr, ui::LogicalDisplayId::DEFAULT);
 }
 
 bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
@@ -5662,13 +5697,13 @@
             ALOGD("Touch transfer failed because from window is not being touched.");
             return false;
         }
-        std::set<int32_t> deviceIds = touchedWindow->getTouchingDeviceIds();
+        std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
         if (deviceIds.size() != 1) {
             LOG(INFO) << "Can't transfer touch. Currently touching devices: " << dumpSet(deviceIds)
                       << " for window: " << touchedWindow->dump();
             return false;
         }
-        const int32_t deviceId = *deviceIds.begin();
+        const DeviceId deviceId = *deviceIds.begin();
 
         const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
         const sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId);
@@ -5722,13 +5757,18 @@
                                        "transferring touch from this window to another window",
                                        traceContext.getTracker());
             synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
-            synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
-                                                           newTargetFlags,
-                                                           traceContext.getTracker());
 
             // Check if the wallpaper window should deliver the corresponding event.
             transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
                                    *state, deviceId, pointers, traceContext.getTracker());
+
+            // Because new window may have a wallpaper window, it will merge input state from it
+            // parent window, after this the firstNewPointerIdx in input state will be reset, then
+            // it will cause new move event be thought inconsistent, so we should synthesize the
+            // down event after it reset.
+            synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
+                                                           newTargetFlags,
+                                                           traceContext.getTracker());
         }
     } // release lock
 
@@ -5742,10 +5782,11 @@
  * Return null if there are no windows touched on that display, or if more than one foreground
  * window is being touched.
  */
-sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindowLocked(int32_t displayId) const {
+sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindowLocked(
+        ui::LogicalDisplayId displayId) const {
     auto stateIt = mTouchStatesByDisplay.find(displayId);
     if (stateIt == mTouchStatesByDisplay.end()) {
-        ALOGI("No touch state on display %" PRId32, displayId);
+        ALOGI("No touch state on display %s", displayId.toString().c_str());
         return nullptr;
     }
 
@@ -5768,14 +5809,14 @@
 
 // Binder call
 bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken,
-                                             int32_t displayId) {
+                                             ui::LogicalDisplayId displayId) {
     sp<IBinder> fromToken;
     { // acquire lock
         std::scoped_lock _l(mLock);
         sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(destChannelToken, displayId);
         if (toWindowHandle == nullptr) {
-            ALOGW("Could not find window associated with token=%p on display %" PRId32,
-                  destChannelToken.get(), displayId);
+            ALOGW("Could not find window associated with token=%p on display %s",
+                  destChannelToken.get(), displayId.toString().c_str());
             return false;
         }
 
@@ -5844,18 +5885,19 @@
     dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
     dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
     dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
-    dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
+    dump += StringPrintf(INDENT "FocusedDisplayId: %s\n", mFocusedDisplayId.toString().c_str());
 
     if (!mFocusedApplicationHandlesByDisplay.empty()) {
         dump += StringPrintf(INDENT "FocusedApplications:\n");
         for (auto& it : mFocusedApplicationHandlesByDisplay) {
-            const int32_t displayId = it.first;
+            const ui::LogicalDisplayId displayId = it.first;
             const std::shared_ptr<InputApplicationHandle>& applicationHandle = it.second;
             const std::chrono::duration timeout =
                     applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
-            dump += StringPrintf(INDENT2 "displayId=%" PRId32
-                                         ", name='%s', dispatchingTimeout=%" PRId64 "ms\n",
-                                 displayId, applicationHandle->getName().c_str(), millis(timeout));
+            dump += StringPrintf(INDENT2 "displayId=%s, name='%s', dispatchingTimeout=%" PRId64
+                                         "ms\n",
+                                 displayId.toString().c_str(), applicationHandle->getName().c_str(),
+                                 millis(timeout));
         }
     } else {
         dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
@@ -5868,7 +5910,7 @@
         dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
         for (const auto& [displayId, state] : mTouchStatesByDisplay) {
             std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
-            dump += INDENT2 + std::to_string(displayId) + " : " + touchStateDump;
+            dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
         }
     } else {
         dump += INDENT "TouchStates: <no displays touched>\n";
@@ -5881,7 +5923,7 @@
 
     if (!mWindowHandlesByDisplay.empty()) {
         for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
-            dump += StringPrintf(INDENT "Display: %" PRId32 "\n", displayId);
+            dump += StringPrintf(INDENT "Display: %s\n", displayId.toString().c_str());
             if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
                 const auto& displayInfo = it->second;
                 dump += StringPrintf(INDENT2 "logicalSize=%dx%d\n", displayInfo.logicalWidth,
@@ -5907,7 +5949,8 @@
 
     if (!mGlobalMonitorsByDisplay.empty()) {
         for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
-            dump += StringPrintf(INDENT "Global monitors on display %d:\n", displayId);
+            dump += StringPrintf(INDENT "Global monitors on display %s:\n",
+                                 displayId.toString().c_str());
             dumpMonitors(dump, monitors);
         }
     } else {
@@ -5996,8 +6039,8 @@
     if (!mTouchModePerDisplay.empty()) {
         dump += INDENT "TouchModePerDisplay:\n";
         for (const auto& [displayId, touchMode] : mTouchModePerDisplay) {
-            dump += StringPrintf(INDENT2 "Display: %" PRId32 " TouchMode: %s\n", displayId,
-                                 std::to_string(touchMode).c_str());
+            dump += StringPrintf(INDENT2 "Display: %s TouchMode: %s\n",
+                                 displayId.toString().c_str(), std::to_string(touchMode).c_str());
         }
     } else {
         dump += INDENT "TouchModePerDisplay: <none>\n";
@@ -6070,9 +6113,8 @@
     return clientChannel;
 }
 
-Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_t displayId,
-                                                                          const std::string& name,
-                                                                          gui::Pid pid) {
+Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(
+        ui::LogicalDisplayId displayId, const std::string& name, gui::Pid pid) {
     std::unique_ptr<InputChannel> serverChannel;
     std::unique_ptr<InputChannel> clientChannel;
     status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
@@ -6083,7 +6125,7 @@
     { // acquire lock
         std::scoped_lock _l(mLock);
 
-        if (displayId < 0) {
+        if (displayId < ui::LogicalDisplayId::DEFAULT) {
             return base::Error(BAD_VALUE) << "Attempted to create input monitor with name " << name
                                           << " without a specified display.";
         }
@@ -6268,7 +6310,8 @@
     mLooper->wake();
 }
 
-void InputDispatcher::setDisplayEligibilityForPointerCapture(int32_t displayId, bool isEligible) {
+void InputDispatcher::setDisplayEligibilityForPointerCapture(ui::LogicalDisplayId displayId,
+                                                             bool isEligible) {
     { // acquire lock
         std::scoped_lock _l(mLock);
         std::erase(mIneligibleDisplaysForPointerCapture, displayId);
@@ -6844,7 +6887,9 @@
     { // acquire lock
         std::scoped_lock _l(mLock);
         std::optional<FocusResolver::FocusChanges> changes =
-                mFocusResolver.setFocusedWindow(request, getWindowHandlesLocked(request.displayId));
+                mFocusResolver.setFocusedWindow(request,
+                                                getWindowHandlesLocked(
+                                                        ui::LogicalDisplayId{request.displayId}));
         ScopedSyntheticEventTracer traceContext(mTracer);
         if (changes) {
             onFocusChangedLocked(*changes, traceContext.getTracker());
@@ -6928,7 +6973,7 @@
     postCommandLocked(std::move(command));
 }
 
-void InputDispatcher::displayRemoved(int32_t displayId) {
+void InputDispatcher::displayRemoved(ui::LogicalDisplayId displayId) {
     { // acquire lock
         std::scoped_lock _l(mLock);
         // Set an empty list to remove all handles from the specific display.
@@ -6942,6 +6987,7 @@
         // Remove the associated touch mode state.
         mTouchModePerDisplay.erase(displayId);
         mVerifiersByDisplay.erase(displayId);
+        mInputFilterVerifiersByDisplay.erase(displayId);
     } // release lock
 
     // Wake up poll loop since it may need to make new input dispatching choices.
@@ -6960,7 +7006,7 @@
     };
     // The listener sends the windows as a flattened array. Separate the windows by display for
     // more convenient parsing.
-    std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
+    std::unordered_map<ui::LogicalDisplayId, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
     for (const auto& info : update.windowInfos) {
         handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
         handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
@@ -7002,10 +7048,10 @@
                  WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) &&
          isWindowObscuredLocked(windowHandle))) {
         ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on "
-              "display %" PRId32 ".",
+              "display %s.",
               ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(),
               windowHandle->getInfo()->inputConfig.string().c_str(),
-              windowHandle->getInfo()->displayId);
+              windowHandle->getInfo()->displayId.toString().c_str());
         return true;
     }
     return false;
@@ -7039,7 +7085,7 @@
 void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                                          const sp<WindowInfoHandle>& oldWindowHandle,
                                          const sp<WindowInfoHandle>& newWindowHandle,
-                                         TouchState& state, int32_t deviceId,
+                                         TouchState& state, DeviceId deviceId,
                                          const PointerProperties& pointerProperties,
                                          std::vector<InputTarget>& targets) const {
     std::vector<PointerProperties> pointers{pointerProperties};
@@ -7049,7 +7095,7 @@
             newWindowHandle->getInfo()->inputConfig.test(
                     gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
     const sp<WindowInfoHandle> oldWallpaper =
-            oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
+            oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
     const sp<WindowInfoHandle> newWallpaper =
             newHasWallpaper ? findWallpaperWindowBelow(newWindowHandle) : nullptr;
     if (oldWallpaper == newWallpaper) {
@@ -7075,7 +7121,7 @@
 void InputDispatcher::transferWallpaperTouch(
         ftl::Flags<InputTarget::Flags> oldTargetFlags,
         ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<WindowInfoHandle> fromWindowHandle,
-        const sp<WindowInfoHandle> toWindowHandle, TouchState& state, int32_t deviceId,
+        const sp<WindowInfoHandle> toWindowHandle, TouchState& state, DeviceId deviceId,
         const std::vector<PointerProperties>& pointers,
         const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
     const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
@@ -7086,7 +7132,7 @@
                     gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
 
     const sp<WindowInfoHandle> oldWallpaper =
-            oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
+            oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
     const sp<WindowInfoHandle> newWallpaper =
             newHasWallpaper ? findWallpaperWindowBelow(toWindowHandle) : nullptr;
     if (oldWallpaper == newWallpaper) {
@@ -7149,8 +7195,9 @@
     mConfig.keyRepeatDelay = delay.count();
 }
 
-bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token, int32_t displayId,
-                                        DeviceId deviceId, int32_t pointerId) {
+bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token,
+                                        ui::LogicalDisplayId displayId, DeviceId deviceId,
+                                        int32_t pointerId) {
     std::scoped_lock _l(mLock);
     auto touchStateIt = mTouchStatesByDisplay.find(displayId);
     if (touchStateIt == mTouchStatesByDisplay.end()) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 3579a67..6240e7f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -114,35 +114,37 @@
     std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
 
     void setFocusedApplication(
-            int32_t displayId,
+            ui::LogicalDisplayId displayId,
             const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) override;
-    void setFocusedDisplay(int32_t displayId) override;
+    void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
     void setMinTimeBetweenUserActivityPokes(std::chrono::milliseconds interval) override;
     void setInputDispatchMode(bool enabled, bool frozen) override;
     void setInputFilterEnabled(bool enabled) override;
     bool setInTouchMode(bool inTouchMode, gui::Pid pid, gui::Uid uid, bool hasPermission,
-                        int32_t displayId) override;
+                        ui::LogicalDisplayId displayId) override;
     void setMaximumObscuringOpacityForTouch(float opacity) override;
 
     bool transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
                               bool isDragDrop = false) override;
-    bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken, int32_t displayId) override;
+    bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken,
+                                ui::LogicalDisplayId displayId) override;
 
     base::Result<std::unique_ptr<InputChannel>> createInputChannel(
             const std::string& name) override;
     void setFocusedWindow(const android::gui::FocusRequest&) override;
-    base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId,
+    base::Result<std::unique_ptr<InputChannel>> createInputMonitor(ui::LogicalDisplayId displayId,
                                                                    const std::string& name,
                                                                    gui::Pid pid) override;
     status_t removeInputChannel(const sp<IBinder>& connectionToken) override;
     status_t pilferPointers(const sp<IBinder>& token) override;
     void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) override;
     bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override;
-    void setDisplayEligibilityForPointerCapture(int displayId, bool isEligible) override;
+    void setDisplayEligibilityForPointerCapture(ui::LogicalDisplayId displayId,
+                                                bool isEligible) override;
 
     std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
 
-    void displayRemoved(int32_t displayId) override;
+    void displayRemoved(ui::LogicalDisplayId displayId) override;
 
     // Public because it's also used by tests to simulate the WindowInfosListener callback
     void onWindowInfosChanged(const gui::WindowInfosUpdate&);
@@ -155,8 +157,8 @@
     void setKeyRepeatConfiguration(std::chrono::nanoseconds timeout,
                                    std::chrono::nanoseconds delay) override;
 
-    bool isPointerInWindow(const sp<IBinder>& token, int32_t displayId, DeviceId deviceId,
-                           int32_t pointerId) override;
+    bool isPointerInWindow(const sp<IBinder>& token, ui::LogicalDisplayId displayId,
+                           DeviceId deviceId, int32_t pointerId) override;
 
     void setInputMethodConnectionIsActive(bool isActive) override;
 
@@ -249,17 +251,17 @@
     std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
 
     sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
-            int32_t displayId, float x, float y, bool isStylus = false,
+            ui::LogicalDisplayId displayId, float x, float y, bool isStylus = false,
             bool ignoreDragWindow = false) const REQUIRES(mLock);
     std::vector<InputTarget> findOutsideTargetsLocked(
-            int32_t displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
+            ui::LogicalDisplayId displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
             int32_t pointerId) const REQUIRES(mLock);
 
     std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
-            int32_t displayId, float x, float y, bool isStylus) const REQUIRES(mLock);
+            ui::LogicalDisplayId displayId, float x, float y, bool isStylus) const REQUIRES(mLock);
 
-    sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(int32_t displayId) const
-            REQUIRES(mLock);
+    sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(
+            ui::LogicalDisplayId displayId) const REQUIRES(mLock);
 
     std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
             REQUIRES(mLock);
@@ -283,7 +285,8 @@
     std::optional<gui::Pid> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
 
     // Input channels that will receive a copy of all input events sent to the provided display.
-    std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock);
+    std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay
+            GUARDED_BY(mLock);
 
     const HmacKeyManager mHmacKeyManager;
     const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry,
@@ -298,7 +301,9 @@
     void transformMotionEntryForInjectionLocked(MotionEntry&,
                                                 const ui::Transform& injectedTransform) const
             REQUIRES(mLock);
-
+    // Per-display correction of injected events
+    std::map<android::ui::LogicalDisplayId, InputVerifier> mInputFilterVerifiersByDisplay
+            GUARDED_BY(mLock);
     std::condition_variable mInjectionSyncFinished;
     void incrementPendingForegroundDispatches(const EventEntry& entry);
     void decrementPendingForegroundDispatches(const EventEntry& entry);
@@ -342,7 +347,8 @@
     // This map is not really needed, but it helps a lot with debugging (dumpsys input).
     // In the java layer, touch mode states are spread across multiple DisplayContent objects,
     // making harder to snapshot and retrieve them.
-    std::map<int32_t /*displayId*/, bool /*inTouchMode*/> mTouchModePerDisplay GUARDED_BY(mLock);
+    std::map<ui::LogicalDisplayId /*displayId*/, bool /*inTouchMode*/> mTouchModePerDisplay
+            GUARDED_BY(mLock);
 
     class DispatcherWindowListener : public gui::WindowInfosListener {
     public:
@@ -354,25 +360,26 @@
     };
     sp<gui::WindowInfosListener> mWindowInfoListener;
 
-    std::unordered_map<int32_t /*displayId*/, std::vector<sp<android::gui::WindowInfoHandle>>>
+    std::unordered_map<ui::LogicalDisplayId /*displayId*/,
+                       std::vector<sp<android::gui::WindowInfoHandle>>>
             mWindowHandlesByDisplay GUARDED_BY(mLock);
-    std::unordered_map<int32_t /*displayId*/, android::gui::DisplayInfo> mDisplayInfos
+    std::unordered_map<ui::LogicalDisplayId /*displayId*/, android::gui::DisplayInfo> mDisplayInfos
             GUARDED_BY(mLock);
     void setInputWindowsLocked(
             const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
-            int32_t displayId) REQUIRES(mLock);
+            ui::LogicalDisplayId displayId) REQUIRES(mLock);
     // Get a reference to window handles by display, return an empty vector if not found.
     const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesLocked(
-            int32_t displayId) const REQUIRES(mLock);
-    ui::Transform getTransformLocked(int32_t displayId) const REQUIRES(mLock);
+            ui::LogicalDisplayId displayId) const REQUIRES(mLock);
+    ui::Transform getTransformLocked(ui::LogicalDisplayId displayId) const REQUIRES(mLock);
 
     sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
-            const sp<IBinder>& windowHandleToken, std::optional<int32_t> displayId = {}) const
-            REQUIRES(mLock);
+            const sp<IBinder>& windowHandleToken,
+            std::optional<ui::LogicalDisplayId> displayId = {}) const REQUIRES(mLock);
     sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
             const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
-    sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(int displayId) const
-            REQUIRES(mLock);
+    sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(
+            ui::LogicalDisplayId displayId) const REQUIRES(mLock);
     bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window,
                                       const MotionEntry& motionEntry) const REQUIRES(mLock);
 
@@ -387,20 +394,21 @@
      */
     void updateWindowHandlesForDisplayLocked(
             const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
-            int32_t displayId) REQUIRES(mLock);
+            ui::LogicalDisplayId displayId) REQUIRES(mLock);
 
-    std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
+    std::unordered_map<ui::LogicalDisplayId /*displayId*/, TouchState> mTouchStatesByDisplay
+            GUARDED_BY(mLock);
     std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);
 
     void setFocusedApplicationLocked(
-            int32_t displayId,
+            ui::LogicalDisplayId displayId,
             const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) REQUIRES(mLock);
     // Focused applications.
-    std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
+    std::unordered_map<ui::LogicalDisplayId /*displayId*/, std::shared_ptr<InputApplicationHandle>>
             mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);
 
     // Top focused display.
-    int32_t mFocusedDisplayId GUARDED_BY(mLock);
+    ui::LogicalDisplayId mFocusedDisplayId GUARDED_BY(mLock);
 
     // Keeps track of the focused window per display and determines focus changes.
     FocusResolver mFocusResolver GUARDED_BY(mLock);
@@ -417,7 +425,8 @@
 
     // Displays that are ineligible for pointer capture.
     // TODO(b/214621487): Remove or move to a display flag.
-    std::vector<int32_t> mIneligibleDisplaysForPointerCapture GUARDED_BY(mLock);
+    std::vector<ui::LogicalDisplayId /*displayId*/> mIneligibleDisplaysForPointerCapture
+            GUARDED_BY(mLock);
 
     // Disable Pointer Capture as a result of loss of window focus.
     void disablePointerCaptureForcedLocked() REQUIRES(mLock);
@@ -492,7 +501,7 @@
     /**
      * The displayId that the focused application is associated with.
      */
-    int32_t mAwaitedApplicationDisplayId GUARDED_BY(mLock);
+    ui::LogicalDisplayId mAwaitedApplicationDisplayId GUARDED_BY(mLock);
     void processNoFocusedWindowAnrLocked() REQUIRES(mLock);
 
     /**
@@ -526,7 +535,7 @@
     // shade is pulled down while we are counting down the timeout).
     void resetNoFocusedWindowTimeoutLocked() REQUIRES(mLock);
 
-    int32_t getTargetDisplayId(const EventEntry& entry);
+    ui::LogicalDisplayId getTargetDisplayId(const EventEntry& entry);
     sp<android::gui::WindowInfoHandle> findFocusedWindowTargetLocked(
             nsecs_t currentTime, const EventEntry& entry, nsecs_t& nextWakeupTime,
             android::os::InputEventInjectionResult& outInjectionResult) REQUIRES(mLock);
@@ -551,13 +560,13 @@
                                       std::bitset<MAX_POINTER_ID + 1> pointerIds,
                                       std::optional<nsecs_t> firstDownTimeInTarget,
                                       std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
-    void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId)
-            REQUIRES(mLock);
+    void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+                                          ui::LogicalDisplayId displayId) REQUIRES(mLock);
     void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
     // Enqueue a drag event if needed, and update the touch state.
     // Uses findTouchedWindowTargetsLocked to make the decision
     void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock);
-    void finishDragAndDrop(int32_t displayId, float x, float y) REQUIRES(mLock);
+    void finishDragAndDrop(ui::LogicalDisplayId displayId, float x, float y) REQUIRES(mLock);
 
     struct TouchOcclusionInfo {
         bool hasBlockingOcclusion;
@@ -675,14 +684,14 @@
                                   const std::string& reason) REQUIRES(mLock);
     void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason)
             REQUIRES(mLock);
-    std::map<int32_t /*displayId*/, InputVerifier> mVerifiersByDisplay;
+    std::map<ui::LogicalDisplayId /*displayId*/, InputVerifier> mVerifiersByDisplay;
     // Returns a fallback KeyEntry that should be sent to the connection, if required.
     std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable(
             const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
             const KeyEntry& keyEntry, bool handled) REQUIRES(mLock);
 
     // Find touched state and touched window by token.
-    std::tuple<TouchState*, TouchedWindow*, int32_t /*displayId*/>
+    std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId /*displayId*/>
     findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) REQUIRES(mLock);
 
     // Statistics gathering.
@@ -701,14 +710,14 @@
     void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                             const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                             const sp<android::gui::WindowInfoHandle>& newWindowHandle,
-                            TouchState& state, int32_t deviceId,
+                            TouchState& state, DeviceId deviceId,
                             const PointerProperties& pointerProperties,
                             std::vector<InputTarget>& targets) const REQUIRES(mLock);
     void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
                                 ftl::Flags<InputTarget::Flags> newTargetFlags,
                                 const sp<android::gui::WindowInfoHandle> fromWindowHandle,
                                 const sp<android::gui::WindowInfoHandle> toWindowHandle,
-                                TouchState& state, int32_t deviceId,
+                                TouchState& state, DeviceId deviceId,
                                 const std::vector<PointerProperties>& pointers,
                                 const std::unique_ptr<trace::EventTrackerInterface>& traceTracker)
             REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 02bc368..46e7e8b 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -28,7 +28,8 @@
 
 InputState::~InputState() {}
 
-bool InputState::isHovering(DeviceId deviceId, uint32_t source, int32_t displayId) const {
+bool InputState::isHovering(DeviceId deviceId, uint32_t source,
+                            ui::LogicalDisplayId displayId) const {
     for (const MotionMemento& memento : mMotionMementos) {
         if (memento.deviceId == deviceId && memento.source == source &&
             memento.displayId == displayId && memento.hovering) {
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index d49469d..2808ba7 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -36,7 +36,7 @@
 
     // Returns true if the specified source is known to have received a hover enter
     // motion event.
-    bool isHovering(DeviceId deviceId, uint32_t source, int32_t displayId) const;
+    bool isHovering(DeviceId deviceId, uint32_t source, ui::LogicalDisplayId displayId) const;
 
     // Records tracking information for a key event that has just been published.
     // Returns true if the event should be delivered, false if it is inconsistent
@@ -90,7 +90,7 @@
     struct KeyMemento {
         DeviceId deviceId;
         uint32_t source;
-        int32_t displayId;
+        ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
         int32_t keyCode;
         int32_t scanCode;
         int32_t metaState;
@@ -102,7 +102,7 @@
     struct MotionMemento {
         DeviceId deviceId;
         uint32_t source;
-        int32_t displayId;
+        ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
         int32_t flags;
         float xPrecision;
         float yPrecision;
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 60a75ee..90374f1 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -18,7 +18,6 @@
 
 #include <ftl/flags.h>
 #include <gui/WindowInfo.h>
-#include <gui/constants.h>
 #include <ui/Transform.h>
 #include <utils/BitSet.h>
 #include <bitset>
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 296c334..0c9ad3c 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -211,9 +211,11 @@
     return haveSlipperyForegroundWindow;
 }
 
-sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
-    for (size_t i = 0; i < windows.size(); i++) {
-        const TouchedWindow& window = windows[i];
+sp<WindowInfoHandle> TouchState::getWallpaperWindow(DeviceId deviceId) const {
+    for (const auto& window : windows) {
+        if (!window.hasTouchingPointers(deviceId)) {
+            continue;
+        }
         if (window.windowHandle->getInfo()->inputConfig.test(
                     gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
             return window.windowHandle;
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 9ddb4e2..9d4bb3d 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -66,7 +66,7 @@
 
     sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle(DeviceId deviceId) const;
     bool isSlippery(DeviceId deviceId) const;
-    sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
+    sp<android::gui::WindowInfoHandle> getWallpaperWindow(DeviceId deviceId) const;
     const TouchedWindow& getTouchedWindow(
             const sp<android::gui::WindowInfoHandle>& windowHandle) const;
     // Whether any of the windows are currently being touched
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 6b9262c..653f595 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -92,14 +92,14 @@
      * This method may be called on any thread (usually by the input manager).
      */
     virtual void setFocusedApplication(
-            int32_t displayId,
+            ui::LogicalDisplayId displayId,
             const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0;
 
     /* Sets the focused display.
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setFocusedDisplay(int32_t displayId) = 0;
+    virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;
 
     /** Sets the minimum time between user activity pokes. */
     virtual void setMinTimeBetweenUserActivityPokes(std::chrono::milliseconds interval) = 0;
@@ -130,7 +130,7 @@
      * Returns true when changing touch mode state.
      */
     virtual bool setInTouchMode(bool inTouchMode, gui::Pid pid, gui::Uid uid, bool hasPermission,
-                                int32_t displayId) = 0;
+                                ui::LogicalDisplayId displayId) = 0;
 
     /**
      * Sets the maximum allowed obscuring opacity by UID to propagate touches.
@@ -156,7 +156,8 @@
      * Returns true on success, false if there was no on-going touch on the display.
      * @deprecated
      */
-    virtual bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken, int32_t displayId) = 0;
+    virtual bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken,
+                                        ui::LogicalDisplayId displayId) = 0;
 
     /**
      * Sets focus on the specified window.
@@ -179,9 +180,8 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId,
-                                                                           const std::string& name,
-                                                                           gui::Pid pid) = 0;
+    virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(
+            ui::LogicalDisplayId displayId, const std::string& name, gui::Pid pid) = 0;
 
     /* Removes input channels that will no longer receive input events.
      *
@@ -207,7 +207,8 @@
      * ineligible, all attempts to request pointer capture for windows on that display will fail.
      *  TODO(b/214621487): Remove or move to a display flag.
      */
-    virtual void setDisplayEligibilityForPointerCapture(int displayId, bool isEligible) = 0;
+    virtual void setDisplayEligibilityForPointerCapture(ui::LogicalDisplayId displayId,
+                                                        bool isEligible) = 0;
 
     /* Flush input device motion sensor.
      *
@@ -218,7 +219,7 @@
     /**
      * Called when a display has been removed from the system.
      */
-    virtual void displayRemoved(int32_t displayId) = 0;
+    virtual void displayRemoved(ui::LogicalDisplayId displayId) = 0;
 
     /*
      * Abort the current touch stream.
@@ -234,8 +235,8 @@
     /*
      * Determine if a pointer from a device is being dispatched to the given window.
      */
-    virtual bool isPointerInWindow(const sp<IBinder>& token, int32_t displayId, DeviceId deviceId,
-                                   int32_t pointerId) = 0;
+    virtual bool isPointerInWindow(const sp<IBinder>& token, ui::LogicalDisplayId displayId,
+                                   DeviceId deviceId, int32_t pointerId) = 0;
 
     /*
      * Notify the dispatcher that the state of the input method connection changed.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 62c2b02..0f03620 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -99,8 +99,9 @@
      * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
      * should be dispatched to applications.
      */
-    virtual void interceptMotionBeforeQueueing(int32_t displayId, uint32_t source, int32_t action,
-                                               nsecs_t when, uint32_t& policyFlags) = 0;
+    virtual void interceptMotionBeforeQueueing(ui::LogicalDisplayId displayId, uint32_t source,
+                                               int32_t action, nsecs_t when,
+                                               uint32_t& policyFlags) = 0;
 
     /* Allows the policy a chance to intercept a key before dispatching. */
     virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
@@ -119,7 +120,8 @@
                               uint32_t policyFlags) = 0;
 
     /* Poke user activity for an event dispatched to a window. */
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) = 0;
+    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType,
+                                  ui::LogicalDisplayId displayId) = 0;
 
     /*
      * Return true if the provided event is stale, and false otherwise. Used for determining
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
index c431fb7..2d7554c 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
@@ -47,7 +47,7 @@
     outProto.set_source(event.source);
     outProto.set_action(event.action);
     outProto.set_device_id(event.deviceId);
-    outProto.set_display_id(event.displayId);
+    outProto.set_display_id(event.displayId.val());
     outProto.set_classification(static_cast<int32_t>(event.classification));
     outProto.set_flags(event.flags);
     outProto.set_policy_flags(event.policyFlags);
@@ -88,7 +88,7 @@
     outProto.set_source(event.source);
     outProto.set_action(event.action);
     outProto.set_device_id(event.deviceId);
-    outProto.set_display_id(event.displayId);
+    outProto.set_display_id(event.displayId.val());
     outProto.set_repeat_count(event.repeatCount);
     outProto.set_flags(event.flags);
     outProto.set_policy_flags(event.policyFlags);
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.cpp b/services/inputflinger/dispatcher/trace/InputTracer.cpp
index 4931a5f..a1a87af 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracer.cpp
@@ -88,7 +88,7 @@
     }
     const auto& info = *target.windowHandle->getInfo();
     const bool isSensitiveTarget =
-            info.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING);
+            info.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY);
     return {target.windowHandle->getInfo()->ownerUid, isSensitiveTarget};
 }
 
diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
index 2b45e3a..25099c3 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
@@ -50,7 +50,7 @@
     uint32_t policyFlags;
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
     int32_t action;
     int32_t keyCode;
     int32_t scanCode;
@@ -70,7 +70,7 @@
     uint32_t policyFlags;
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId;
     int32_t action;
     int32_t actionButton;
     int32_t flags;
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 77e672c..889ee09 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -61,9 +61,6 @@
         // The display size or orientation changed.
         DISPLAY_INFO = 1u << 2,
 
-        // The visible touches option changed.
-        SHOW_TOUCHES = 1u << 3,
-
         // The keyboard layouts must be reloaded.
         KEYBOARD_LAYOUTS = 1u << 4,
 
@@ -109,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.
@@ -128,7 +125,7 @@
     std::unordered_map<std::string, KeyboardLayoutInfo> keyboardLayoutAssociations;
 
     // The suggested display ID to show the cursor.
-    int32_t defaultPointerDisplayId;
+    ui::LogicalDisplayId defaultPointerDisplayId;
 
     // The mouse pointer speed, as a number from -7 (slowest) to 7 (fastest).
     //
@@ -138,7 +135,7 @@
     // Displays on which an acceleration curve shouldn't be applied for pointer movements from mice.
     //
     // Currently only used when the enable_new_mouse_pointer_ballistics flag is enabled.
-    std::set<int32_t> displaysWithMousePointerAccelerationDisabled;
+    std::set<ui::LogicalDisplayId> displaysWithMousePointerAccelerationDisabled;
 
     // Velocity control parameters for mouse pointer movements.
     //
@@ -214,9 +211,6 @@
     // will cover this portion of the display diagonal.
     float pointerGestureZoomSpeedRatio;
 
-    // True to show the location of touches on the touch screen as spots.
-    bool showTouches;
-
     // The latest request to enable or disable Pointer Capture.
     PointerCaptureRequest pointerCaptureRequest;
 
@@ -249,6 +243,7 @@
 
     InputReaderConfiguration()
           : virtualKeyQuietTime(0),
+            defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT),
             mousePointerSpeed(0),
             displaysWithMousePointerAccelerationDisabled(),
             pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f,
@@ -268,7 +263,6 @@
             pointerGestureSwipeMaxWidthRatio(0.25f),
             pointerGestureMovementSpeedRatio(0.8f),
             pointerGestureZoomSpeedRatio(0.3f),
-            showTouches(false),
             pointerCaptureRequest(),
             touchpadPointerSpeed(0),
             touchpadNaturalScrollingEnabled(true),
@@ -282,7 +276,7 @@
     std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
             const;
     std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t physicalPort) const;
-    std::optional<DisplayViewport> getDisplayViewportById(int32_t displayId) const;
+    std::optional<DisplayViewport> getDisplayViewportById(ui::LogicalDisplayId displayId) const;
     void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
 
     void dump(std::string& dump) const;
@@ -316,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;
 
@@ -373,7 +364,7 @@
     virtual std::vector<InputDeviceSensorInfo> getSensors(int32_t deviceId) = 0;
 
     /* Return true if the device can send input events to the specified display. */
-    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
+    virtual bool canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) = 0;
 
     /* Enable sensor in input reader mapper. */
     virtual bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType,
@@ -400,6 +391,12 @@
 
     /* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */
     virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
+
+    /* Get the ID of the InputDevice that was used most recently.
+     *
+     * Returns ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID if no device has been used since boot.
+     */
+    virtual DeviceId getLastUsedInputDeviceId() = 0;
 };
 
 // --- TouchAffineTransformation ---
@@ -449,10 +446,6 @@
     /* Gets the input reader configuration. */
     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
 
-    /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
-    virtual std::shared_ptr<PointerControllerInterface> obtainPointerController(
-            int32_t deviceId) = 0;
-
     /* Notifies the input reader policy that some input devices have changed
      * and provides information about all current input devices.
      */
@@ -482,7 +475,7 @@
      * be used as the range of possible values for pointing devices, like mice and touchpads.
      */
     virtual std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
-            int32_t associatedDisplayId = ADISPLAY_ID_NONE) = 0;
+            ui::LogicalDisplayId associatedDisplayId = ui::LogicalDisplayId::INVALID) = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h
index 736b1e0..db417cf 100644
--- a/services/inputflinger/include/NotifyArgs.h
+++ b/services/inputflinger/include/NotifyArgs.h
@@ -61,7 +61,7 @@
 
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
     uint32_t policyFlags;
     int32_t action;
     int32_t flags;
@@ -74,9 +74,9 @@
     inline NotifyKeyArgs() {}
 
     NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
-                  uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
-                  int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-                  nsecs_t downTime);
+                  uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
+                  int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+                  int32_t metaState, nsecs_t downTime);
 
     bool operator==(const NotifyKeyArgs& rhs) const = default;
 
@@ -91,7 +91,7 @@
 
     int32_t deviceId;
     uint32_t source;
-    int32_t displayId;
+    ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
     uint32_t policyFlags;
     int32_t action;
     int32_t actionButton;
@@ -123,12 +123,12 @@
     inline NotifyMotionArgs() {}
 
     NotifyMotionArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
-                     uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
-                     int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
-                     MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
-                     const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-                     float xPrecision, float yPrecision, float xCursorPosition,
-                     float yCursorPosition, nsecs_t downTime,
+                     uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
+                     int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
+                     int32_t buttonState, MotionClassification classification, int32_t edgeFlags,
+                     uint32_t pointerCount, const PointerProperties* pointerProperties,
+                     const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+                     float xCursorPosition, float yCursorPosition, nsecs_t downTime,
                      const std::vector<TouchVideoFrame>& videoFrames);
 
     NotifyMotionArgs(const NotifyMotionArgs& other) = default;
diff --git a/services/inputflinger/include/NotifyArgsBuilders.h b/services/inputflinger/include/NotifyArgsBuilders.h
index 1bd5595..cae638f 100644
--- a/services/inputflinger/include/NotifyArgsBuilders.h
+++ b/services/inputflinger/include/NotifyArgsBuilders.h
@@ -19,7 +19,6 @@
 #include <NotifyArgs.h>
 #include <android/input.h>
 #include <attestation/HmacKeyManager.h>
-#include <gui/constants.h>
 #include <input/Input.h>
 #include <input/InputEventBuilders.h>
 #include <utils/Timers.h> // for nsecs_t, systemTime
@@ -55,7 +54,7 @@
         return *this;
     }
 
-    MotionArgsBuilder& displayId(int32_t displayId) {
+    MotionArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
     }
@@ -151,7 +150,7 @@
     uint32_t mSource;
     nsecs_t mDownTime;
     nsecs_t mEventTime;
-    int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
     uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
     int32_t mActionButton{0};
     int32_t mButtonState{0};
@@ -187,7 +186,7 @@
         return *this;
     }
 
-    KeyArgsBuilder& displayId(int32_t displayId) {
+    KeyArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
     }
@@ -230,7 +229,7 @@
     uint32_t mSource;
     nsecs_t mDownTime;
     nsecs_t mEventTime;
-    int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
     uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
     int32_t mFlags{0};
     int32_t mKeyCode{AKEYCODE_UNKNOWN};
diff --git a/services/inputflinger/include/PointerChoreographerPolicyInterface.h b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
index 462aedc..f6dc109 100644
--- a/services/inputflinger/include/PointerChoreographerPolicyInterface.h
+++ b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
@@ -53,7 +53,8 @@
      * @param displayId The updated display on which the mouse cursor is shown
      * @param position The new position of the mouse cursor on the logical display
      */
-    virtual void notifyPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) = 0;
+    virtual void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
+                                               const FloatPoint& position) = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index c44486f..cee44fc 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -61,8 +61,6 @@
      * TODO(b/293587049): Refactor the PointerController class into different controller types.
      */
     enum class ControllerType {
-        // The PointerController that is responsible for drawing all icons.
-        LEGACY,
         // Represents a single mouse pointer.
         MOUSE,
         // Represents multiple touch spots.
@@ -127,13 +125,13 @@
      * pressed (not hovering).
      */
     virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
-                          BitSet32 spotIdBits, int32_t displayId) = 0;
+                          BitSet32 spotIdBits, ui::LogicalDisplayId displayId) = 0;
 
     /* Removes all spots. */
     virtual void clearSpots() = 0;
 
     /* Gets the id of the display where the pointer should be shown. */
-    virtual int32_t getDisplayId() const = 0;
+    virtual ui::LogicalDisplayId getDisplayId() const = 0;
 
     /* Sets the associated display of this pointer. Pointer should show on that display. */
     virtual void setDisplayViewport(const DisplayViewport& displayViewport) = 0;
@@ -143,6 +141,11 @@
 
     /* Sets the custom pointer icon for mice or styluses. */
     virtual void setCustomPointerIcon(const SpriteIcon& icon) = 0;
+
+    /* Sets the flag to skip screenshot of the pointer indicators on the display matching the
+     * provided displayId.
+     */
+    virtual void setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 44dfd15..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;
@@ -442,7 +442,8 @@
 InputDeviceInfo InputDevice::getDeviceInfo() {
     InputDeviceInfo outDeviceInfo;
     outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
-                             mHasMic, getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE),
+                             mHasMic,
+                             getAssociatedDisplayId().value_or(ui::LogicalDisplayId::INVALID),
                              {mShouldSmoothScroll}, isEnabled());
 
     for_each_mapper(
@@ -699,14 +700,14 @@
     return NotifyDeviceResetArgs(mContext->getNextId(), when, mId);
 }
 
-std::optional<int32_t> InputDevice::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> InputDevice::getAssociatedDisplayId() {
     // Check if we had associated to the specific display.
     if (mAssociatedViewport) {
         return mAssociatedViewport->displayId;
     }
 
     // No associated display port, check if some InputMapper is associated.
-    return first_in_mappers<int32_t>(
+    return first_in_mappers<ui::LogicalDisplayId>(
             [](InputMapper& mapper) { return mapper.getAssociatedDisplayId(); });
 }
 
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 9608210..b9523ef 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -38,6 +38,8 @@
 
 namespace android {
 
+namespace {
+
 /**
  * Determines if the identifiers passed are a sub-devices. Sub-devices are physical devices
  * that expose multiple input device paths such a keyboard that also has a touchpad input.
@@ -49,8 +51,8 @@
  *    inputs versus the same device plugged into multiple ports.
  */
 
-static bool isSubDevice(const InputDeviceIdentifier& identifier1,
-                        const InputDeviceIdentifier& identifier2) {
+bool isSubDevice(const InputDeviceIdentifier& identifier1,
+                 const InputDeviceIdentifier& identifier2) {
     return (identifier1.vendor == identifier2.vendor &&
             identifier1.product == identifier2.product && identifier1.bus == identifier2.bus &&
             identifier1.version == identifier2.version &&
@@ -58,7 +60,7 @@
             identifier1.location == identifier2.location);
 }
 
-static bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
+bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
     const auto actionMasked = MotionEvent::getActionMasked(motionArgs.action);
     if (actionMasked != AMOTION_EVENT_ACTION_HOVER_ENTER &&
         actionMasked != AMOTION_EVENT_ACTION_DOWN &&
@@ -69,6 +71,28 @@
     return isStylusToolType(motionArgs.pointerProperties[actionIndex].toolType);
 }
 
+bool isNewGestureStart(const NotifyMotionArgs& motion) {
+    return motion.action == AMOTION_EVENT_ACTION_DOWN ||
+            motion.action == AMOTION_EVENT_ACTION_HOVER_ENTER;
+}
+
+bool isNewGestureStart(const NotifyKeyArgs& key) {
+    return key.action == AKEY_EVENT_ACTION_DOWN;
+}
+
+// Return the event's device ID if it marks the start of a new gesture.
+std::optional<DeviceId> getDeviceIdOfNewGesture(const NotifyArgs& args) {
+    if (const auto* motion = std::get_if<NotifyMotionArgs>(&args); motion != nullptr) {
+        return isNewGestureStart(*motion) ? std::make_optional(motion->deviceId) : std::nullopt;
+    }
+    if (const auto* key = std::get_if<NotifyKeyArgs>(&args); key != nullptr) {
+        return isNewGestureStart(*key) ? std::make_optional(key->deviceId) : std::nullopt;
+    }
+    return std::nullopt;
+}
+
+} // namespace
+
 // --- InputReader ---
 
 InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
@@ -162,6 +186,11 @@
         }
 
         std::swap(notifyArgs, mPendingArgs);
+
+        // Keep track of the last used device
+        for (const NotifyArgs& args : notifyArgs) {
+            mLastUsedDeviceId = getDeviceIdOfNewGesture(args).value_or(mLastUsedDeviceId);
+        }
     } // release lock
 
     // Flush queued events out to the listener.
@@ -402,10 +431,6 @@
     ALOGI("Reconfiguring input devices, changes=%s", changes.string().c_str());
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
 
-    if (changes.test(Change::DISPLAY_INFO)) {
-        updatePointerDisplayLocked();
-    }
-
     if (changes.test(Change::MUST_REOPEN)) {
         mEventHub->requestReopenDevices();
     } else {
@@ -490,47 +515,6 @@
     }
 }
 
-std::shared_ptr<PointerControllerInterface> InputReader::getPointerControllerLocked(
-        int32_t deviceId) {
-    std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
-    if (controller == nullptr) {
-        controller = mPolicy->obtainPointerController(deviceId);
-        mPointerController = controller;
-        updatePointerDisplayLocked();
-    }
-    return controller;
-}
-
-void InputReader::updatePointerDisplayLocked() {
-    std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
-    if (controller == nullptr) {
-        return;
-    }
-
-    std::optional<DisplayViewport> viewport =
-            mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
-    if (!viewport) {
-        ALOGW("Can't find the designated viewport with ID %" PRId32 " to update cursor input "
-              "mapper. Fall back to default display",
-              mConfig.defaultPointerDisplayId);
-        viewport = mConfig.getDisplayViewportById(ADISPLAY_ID_DEFAULT);
-    }
-    if (!viewport) {
-        ALOGE("Still can't find a viable viewport to update cursor input mapper. Skip setting it to"
-              " PointerController.");
-        return;
-    }
-
-    controller->setDisplayViewport(*viewport);
-}
-
-void InputReader::fadePointerLocked() {
-    std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
-    if (controller != nullptr) {
-        controller->fade(PointerControllerInterface::Transition::GRADUAL);
-    }
-}
-
 void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
     if (when < mNextTimeout) {
         mNextTimeout = when;
@@ -890,18 +874,7 @@
     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, int32_t displayId) {
+bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) {
     std::scoped_lock _l(mLock);
 
     InputDevice* device = findInputDeviceLocked(deviceId);
@@ -915,10 +888,9 @@
         return false;
     }
 
-    std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplayId();
+    std::optional<ui::LogicalDisplayId> associatedDisplayId = device->getAssociatedDisplayId();
     // No associated display. By default, can dispatch to all displays.
-    if (!associatedDisplayId ||
-            *associatedDisplayId == ADISPLAY_ID_NONE) {
+    if (!associatedDisplayId || !associatedDisplayId->isValid()) {
         return true;
     }
 
@@ -929,6 +901,11 @@
     mEventHub->sysfsNodeChanged(sysfsNodePath);
 }
 
+DeviceId InputReader::getLastUsedInputDeviceId() {
+    std::scoped_lock _l(mLock);
+    return mLastUsedDeviceId;
+}
+
 void InputReader::dump(std::string& dump) {
     std::scoped_lock _l(mLock);
 
@@ -1067,17 +1044,6 @@
     return mReader->shouldDropVirtualKeyLocked(now, keyCode, scanCode);
 }
 
-void InputReader::ContextImpl::fadePointer() {
-    // lock is already held by the input loop
-    mReader->fadePointerLocked();
-}
-
-std::shared_ptr<PointerControllerInterface> InputReader::ContextImpl::getPointerController(
-        int32_t deviceId) {
-    // lock is already held by the input loop
-    return mReader->getPointerControllerLocked(deviceId);
-}
-
 void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
     // lock is already held by the input loop
     mReader->requestTimeoutAtTimeLocked(when);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index feb4071..4c9af2e 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -131,7 +131,7 @@
     inline const PropertyMap& getConfiguration() { return mConfiguration; }
     inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
 
-    std::optional<int32_t> getAssociatedDisplayId();
+    std::optional<ui::LogicalDisplayId> getAssociatedDisplayId();
 
     void updateLedState(bool reset);
 
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 4c78db3..7e701c5 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <PointerControllerInterface.h>
 #include <android-base/thread_annotations.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
@@ -62,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;
@@ -87,7 +84,7 @@
 
     std::vector<int32_t> getVibratorIds(int32_t deviceId) override;
 
-    bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) override;
+    bool canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) override;
 
     bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType,
                       std::chrono::microseconds samplingPeriod,
@@ -119,6 +116,8 @@
 
     void sysfsNodeChanged(const std::string& sysfsNodePath) override;
 
+    DeviceId getLastUsedInputDeviceId() override;
+
 protected:
     // These members are protected so they can be instrumented by test cases.
     virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId,
@@ -141,9 +140,6 @@
         void disableVirtualKeysUntil(nsecs_t time) REQUIRES(mReader->mLock) override;
         bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode)
                 REQUIRES(mReader->mLock) override;
-        void fadePointer() REQUIRES(mReader->mLock) override;
-        std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId)
-                REQUIRES(mReader->mLock) override;
         void requestTimeoutAtTime(nsecs_t when) REQUIRES(mReader->mLock) override;
         int32_t bumpGeneration() NO_THREAD_SAFETY_ANALYSIS override;
         void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices)
@@ -204,6 +200,9 @@
     // records timestamp of the last key press on the physical keyboard
     nsecs_t mLastKeyDownTimestamp GUARDED_BY(mLock){0};
 
+    // The input device that produced a new gesture most recently.
+    DeviceId mLastUsedDeviceId GUARDED_BY(mLock){ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID};
+
     // low-level input event decoding and device management
     [[nodiscard]] std::list<NotifyArgs> processEventsLocked(const RawEvent* rawEvents, size_t count)
             REQUIRES(mLock);
@@ -230,13 +229,6 @@
     [[nodiscard]] std::list<NotifyArgs> dispatchExternalStylusStateLocked(const StylusState& state)
             REQUIRES(mLock);
 
-    // The PointerController that is shared among all the input devices that need it.
-    std::weak_ptr<PointerControllerInterface> mPointerController;
-    std::shared_ptr<PointerControllerInterface> getPointerControllerLocked(int32_t deviceId)
-            REQUIRES(mLock);
-    void updatePointerDisplayLocked() REQUIRES(mLock);
-    void fadePointerLocked() REQUIRES(mLock);
-
     int32_t mGeneration GUARDED_BY(mLock);
     int32_t bumpGenerationLocked() REQUIRES(mLock);
 
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index 69b2315..907a49f 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -28,7 +28,6 @@
 class InputListenerInterface;
 class InputMapper;
 class InputReaderPolicyInterface;
-class PointerControllerInterface;
 struct StylusState;
 
 /* Internal interface used by individual input devices to access global input device state
@@ -45,9 +44,6 @@
     virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
     virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) = 0;
 
-    virtual void fadePointer() = 0;
-    virtual std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) = 0;
-
     virtual void requestTimeoutAtTime(nsecs_t when) = 0;
     virtual int32_t bumpGeneration() = 0;
 
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index 061c6a3..09a5f08 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -19,7 +19,6 @@
 #include <sstream>
 
 #include <android-base/stringprintf.h>
-#include <gui/constants.h>
 #include <input/PrintTools.h>
 #include <linux/input-event-codes.h>
 #include <log/log_main.h>
@@ -279,7 +278,7 @@
     LOG_ALWAYS_FATAL_IF(coords.size() != properties.size(),
                         "Mismatched coords and properties arrays.");
     return NotifyMotionArgs(mReaderContext.getNextId(), when, readTime, mDeviceId, SOURCE,
-                            ADISPLAY_ID_NONE, /*policyFlags=*/POLICY_FLAG_WAKE, action,
+                            ui::LogicalDisplayId::INVALID, /*policyFlags=*/POLICY_FLAG_WAKE, action,
                             /*actionButton=*/actionButton, flags,
                             mReaderContext.getGlobalMetaState(), mButtonState,
                             MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, coords.size(),
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index c8cc5dc..c67314d 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -40,8 +40,6 @@
 // The default velocity control parameters that has no effect.
 static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{};
 
-static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
-
 // --- CursorMotionAccumulator ---
 
 CursorMotionAccumulator::CursorMotionAccumulator() {
@@ -78,22 +76,10 @@
 
 CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
                                      const InputReaderConfiguration& readerConfig)
-      : CursorInputMapper(deviceContext, readerConfig, ENABLE_POINTER_CHOREOGRAPHER) {}
-
-CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
-                                     const InputReaderConfiguration& readerConfig,
-                                     bool enablePointerChoreographer)
       : InputMapper(deviceContext, readerConfig),
         mLastEventTime(std::numeric_limits<nsecs_t>::min()),
-        mEnablePointerChoreographer(enablePointerChoreographer),
         mEnableNewMousePointerBallistics(input_flags::enable_new_mouse_pointer_ballistics()) {}
 
-CursorInputMapper::~CursorInputMapper() {
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
-    }
-}
-
 uint32_t CursorInputMapper::getSources() const {
     return mSource;
 }
@@ -143,7 +129,8 @@
                          mWheelXVelocityControl.getParameters().dump().c_str());
     dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
     dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
-    dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
+    dump += StringPrintf(INDENT3 "DisplayId: %s\n",
+                         toString(mDisplayId, streamableToString).c_str());
     dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(mOrientation).c_str());
     dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
     dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
@@ -304,22 +291,6 @@
     float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     if (mSource == AINPUT_SOURCE_MOUSE) {
-        if (!mEnablePointerChoreographer) {
-            if (moved || scrolled || buttonsChanged) {
-                mPointerController->setPresentation(
-                        PointerControllerInterface::Presentation::POINTER);
-
-                if (moved) {
-                    mPointerController->move(deltaX, deltaY);
-                }
-                mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-            }
-
-            std::tie(xCursorPosition, yCursorPosition) = mPointerController->getPosition();
-
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
-        }
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
     } else {
@@ -447,7 +418,7 @@
     }
 }
 
-std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() {
     return mDisplayId;
 }
 
@@ -470,7 +441,6 @@
             mYPrecision = 1.0f;
             mXScale = 1.0f;
             mYScale = 1.0f;
-            mPointerController = getContext()->getPointerController(getDeviceId());
             break;
         case Parameters::Mode::NAVIGATION:
             mSource = AINPUT_SOURCE_TRACKBALL;
@@ -490,8 +460,6 @@
         if (mParameters.mode == Parameters::Mode::POINTER) {
             mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
             mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
-            // Keep PointerController around in order to preserve the pointer position.
-            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
         } else {
             ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
         }
@@ -520,13 +488,13 @@
         if (mEnableNewMousePointerBallistics) {
             mNewPointerVelocityControl.setAccelerationEnabled(
                     config.displaysWithMousePointerAccelerationDisabled.count(
-                            mDisplayId.value_or(ADISPLAY_ID_NONE)) == 0);
+                            mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0);
             mNewPointerVelocityControl.setCurve(
                     createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
         } else {
             mOldPointerVelocityControl.setParameters(
                     (config.displaysWithMousePointerAccelerationDisabled.count(
-                             mDisplayId.value_or(ADISPLAY_ID_NONE)) == 0)
+                             mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0)
                             ? config.pointerVelocityControlParameters
                             : FLAT_VELOCITY_CONTROL_PARAMS);
         }
@@ -538,40 +506,20 @@
 void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {
     const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
 
-    mDisplayId = ADISPLAY_ID_NONE;
+    mDisplayId = ui::LogicalDisplayId::INVALID;
     std::optional<DisplayViewport> resolvedViewport;
-    bool isBoundsSet = false;
     if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
         // This InputDevice is associated with a viewport.
         // Only generate events for the associated display.
         mDisplayId = assocViewport->displayId;
         resolvedViewport = *assocViewport;
-        if (!mEnablePointerChoreographer) {
-            const bool mismatchedPointerDisplay =
-                    isPointer && (assocViewport->displayId != mPointerController->getDisplayId());
-            if (mismatchedPointerDisplay) {
-                // This device's associated display doesn't match PointerController's current
-                // display. Do not associate it with any display.
-                mDisplayId.reset();
-            }
-        }
     } else if (isPointer) {
         // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
-        if (mEnablePointerChoreographer) {
-            // Always use DISPLAY_ID_NONE for mouse events.
-            // PointerChoreographer will make it target the correct the displayId later.
-            resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
-            mDisplayId = resolvedViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
-        } else {
-            mDisplayId = mPointerController->getDisplayId();
-            if (auto v = config.getDisplayViewportById(*mDisplayId); v) {
-                resolvedViewport = *v;
-            }
-            if (auto bounds = mPointerController->getBounds(); bounds) {
-                mBoundsInLogicalDisplay = *bounds;
-                isBoundsSet = true;
-            }
-        }
+        // Always use DISPLAY_ID_NONE for mouse events.
+        // PointerChoreographer will make it target the correct the displayId later.
+        resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
+        mDisplayId =
+                resolvedViewport ? std::make_optional(ui::LogicalDisplayId::INVALID) : std::nullopt;
     }
 
     mOrientation = (mParameters.orientationAware && mParameters.hasAssociatedDisplay) ||
@@ -579,14 +527,12 @@
             ? ui::ROTATION_0
             : getInverseRotation(resolvedViewport->orientation);
 
-    if (!isBoundsSet) {
-        mBoundsInLogicalDisplay = resolvedViewport
-                ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
-                            static_cast<float>(resolvedViewport->logicalTop),
-                            static_cast<float>(resolvedViewport->logicalRight - 1),
-                            static_cast<float>(resolvedViewport->logicalBottom - 1)}
-                : FloatRect{0, 0, 0, 0};
-    }
+    mBoundsInLogicalDisplay = resolvedViewport
+            ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
+                        static_cast<float>(resolvedViewport->logicalTop),
+                        static_cast<float>(resolvedViewport->logicalRight - 1),
+                        static_cast<float>(resolvedViewport->logicalBottom - 1)}
+            : FloatRect{0, 0, 0, 0};
 
     bumpGeneration();
 }
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index ca541d9..75ca9c0 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -20,14 +20,11 @@
 #include "CursorScrollAccumulator.h"
 #include "InputMapper.h"
 
-#include <PointerControllerInterface.h>
 #include <input/VelocityControl.h>
 #include <ui/Rotation.h>
 
 namespace android {
 
-class PointerControllerInterface;
-
 class CursorButtonAccumulator;
 class CursorScrollAccumulator;
 
@@ -56,7 +53,7 @@
     friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
                                                 const InputReaderConfiguration& readerConfig,
                                                 Args... args);
-    virtual ~CursorInputMapper();
+    virtual ~CursorInputMapper() = default;
 
     virtual uint32_t getSources() const override;
     virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
@@ -69,7 +66,7 @@
 
     virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
 
-    virtual std::optional<int32_t> getAssociatedDisplayId() override;
+    virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
 
 private:
     // Amount that trackball needs to move in order to generate a key event.
@@ -116,27 +113,20 @@
     SimpleVelocityControl mWheelYVelocityControl;
 
     // The display that events generated by this mapper should target. This can be set to
-    // ADISPLAY_ID_NONE to target the focused display. If there is no display target (i.e.
+    // LogicalDisplayId::INVALID to target the focused display. If there is no display target (i.e.
     // std::nullopt), all events will be ignored.
-    std::optional<int32_t> mDisplayId;
+    std::optional<ui::LogicalDisplayId> mDisplayId;
     ui::Rotation mOrientation{ui::ROTATION_0};
     FloatRect mBoundsInLogicalDisplay{};
 
-    std::shared_ptr<PointerControllerInterface> mPointerController;
-
     int32_t mButtonState;
     nsecs_t mDownTime;
     nsecs_t mLastEventTime;
 
-    const bool mEnablePointerChoreographer;
     const bool mEnableNewMousePointerBallistics;
 
     explicit CursorInputMapper(InputDeviceContext& deviceContext,
                                const InputReaderConfiguration& readerConfig);
-    // Constructor for testing.
-    explicit CursorInputMapper(InputDeviceContext& deviceContext,
-                               const InputReaderConfiguration& readerConfig,
-                               bool enablePointerChoreographer);
     void dumpParameters(std::string& dump);
     void configureBasicParams();
     void configureOnPointerCapture(const InputReaderConfiguration& config);
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 06de4c2..c7eea0e 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -117,7 +117,7 @@
 
     [[nodiscard]] virtual std::list<NotifyArgs> updateExternalStylusState(const StylusState& state);
 
-    virtual std::optional<int32_t> getAssociatedDisplayId() { return std::nullopt; }
+    virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() { return std::nullopt; }
     virtual void updateLedState(bool reset) {}
 
 protected:
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 8a9ea75..5ce4d30 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -341,7 +341,7 @@
     // button will likely wake the device.
     // TODO: Use the input device configuration to control this behavior more finely.
     uint32_t policyFlags = 0;
-    int32_t displayId = ADISPLAY_ID_NONE;
+    ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
     if (getDeviceContext().getAssociatedViewport()) {
         displayId = getDeviceContext().getAssociatedViewport()->displayId;
     }
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 738517b..2124555 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -110,11 +110,11 @@
     return ui::ROTATION_0;
 }
 
-int32_t KeyboardInputMapper::getDisplayId() {
+ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
     if (mViewport) {
         return mViewport->displayId;
     }
-    return ADISPLAY_ID_NONE;
+    return ui::LogicalDisplayId::INVALID;
 }
 
 std::optional<KeyboardLayoutInfo> KeyboardInputMapper::getKeyboardLayoutInfo() const {
@@ -457,7 +457,7 @@
     }
 }
 
-std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
     if (mViewport) {
         return std::make_optional(mViewport->displayId);
     }
@@ -483,16 +483,11 @@
 void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
     InputReaderContext& context = *getContext();
     context.setLastKeyDownTimestamp(downTime);
-    if (context.isPreventingTouchpadTaps()) {
-        // avoid pinging java service unnecessarily, just fade pointer again if it became visible
-        context.fadePointer();
-        return;
-    }
+    // TODO(b/338652288): Move cursor fading logic into PointerChoreographer.
     // Ignore meta keys or multiple simultaneous down keys as they are likely to be keyboard
     // shortcuts
     bool shouldHideCursor = mKeyDowns.size() == 1 && !isMetaKey(mKeyDowns[0].keyCode);
     if (shouldHideCursor && context.getPolicy()->isInputMethodConnectionActive()) {
-        context.fadePointer();
         context.setPreventingTouchpadTaps(true);
     }
 }
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 500256b..f2d3f4d 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -46,7 +46,7 @@
 
     int32_t getMetaState() override;
     bool updateMetaState(int32_t keyCode) override;
-    std::optional<int32_t> getAssociatedDisplayId() override;
+    std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
     void updateLedState(bool reset) override;
 
 private:
@@ -91,7 +91,7 @@
     void dumpParameters(std::string& dump) const;
 
     ui::Rotation getOrientation();
-    int32_t getDisplayId();
+    ui::LogicalDisplayId getDisplayId();
 
     [[nodiscard]] std::list<NotifyArgs> processKey(nsecs_t when, nsecs_t readTime, bool down,
                                                    int32_t scanCode, int32_t usageCode);
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 07ae5b1..0ddbc06 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -125,7 +125,7 @@
     if (scrolled) {
         int32_t metaState = getContext()->getGlobalMetaState();
         // This is not a pointer, so it's not associated with a display.
-        int32_t displayId = ADISPLAY_ID_NONE;
+        ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
 
         if (mOrientation == ui::ROTATION_180) {
             scroll = -scroll;
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.cpp b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.cpp
index c12e95d..d60dc55 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.cpp
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.cpp
@@ -28,7 +28,7 @@
 
 [[nodiscard]] std::list<NotifyArgs> synthesizeButtonKey(
         InputReaderContext* context, int32_t action, nsecs_t when, nsecs_t readTime,
-        int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+        int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
         int32_t lastButtonState, int32_t currentButtonState, int32_t buttonState, int32_t keyCode) {
     std::list<NotifyArgs> out;
     if ((action == AKEY_EVENT_ACTION_DOWN && !(lastButtonState & buttonState) &&
@@ -88,7 +88,7 @@
 
 [[nodiscard]] std::list<NotifyArgs> synthesizeButtonKeys(
         InputReaderContext* context, int32_t action, nsecs_t when, nsecs_t readTime,
-        int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+        int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
         int32_t lastButtonState, int32_t currentButtonState) {
     std::list<NotifyArgs> out;
     out += synthesizeButtonKey(context, action, when, readTime, deviceId, source, displayId,
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index 3023e68..13d952b 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -36,7 +36,7 @@
 
 [[nodiscard]] std::list<NotifyArgs> synthesizeButtonKeys(
         InputReaderContext* context, int32_t action, nsecs_t when, nsecs_t readTime,
-        int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+        int32_t deviceId, uint32_t source, ui::LogicalDisplayId displayId, uint32_t policyFlags,
         int32_t lastButtonState, int32_t currentButtonState);
 
 // For devices connected over Bluetooth, although they may produce events at a consistent rate,
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 81449d1..8b4b691 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -336,7 +336,6 @@
         changes.any(InputReaderConfiguration::Change::DISPLAY_INFO |
                     InputReaderConfiguration::Change::POINTER_CAPTURE |
                     InputReaderConfiguration::Change::POINTER_GESTURE_ENABLEMENT |
-                    InputReaderConfiguration::Change::SHOW_TOUCHES |
                     InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE |
                     InputReaderConfiguration::Change::DEVICE_TYPE)) {
         // Configure device sources, display dimensions, orientation and
@@ -556,8 +555,8 @@
             if (viewport) {
                 return viewport;
             } else {
-                ALOGW("Can't find designated display viewport with ID %" PRId32 " for pointers.",
-                      mConfig.defaultPointerDisplayId);
+                ALOGW("Can't find designated display viewport with ID %s for pointers.",
+                      mConfig.defaultPointerDisplayId.toString().c_str());
             }
         }
 
@@ -1042,38 +1041,12 @@
         mOrientedRanges.clear();
     }
 
-    // Create and preserve the pointer controller in the following cases:
-    const bool isPointerControllerNeeded =
-            // - when the device is in pointer mode, to show the mouse cursor;
-            (mDeviceMode == DeviceMode::POINTER) ||
-            // - when pointer capture is enabled, to preserve the mouse cursor position;
-            (mParameters.deviceType == Parameters::DeviceType::POINTER &&
-             mConfig.pointerCaptureRequest.isEnable()) ||
-            // - when we should be showing touches;
-            (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) ||
-            // - when we should be showing a pointer icon for direct styluses.
-            (mDeviceMode == DeviceMode::DIRECT && mConfig.stylusPointerIconEnabled && hasStylus());
-    if (isPointerControllerNeeded) {
-        if (mPointerController == nullptr) {
-            mPointerController = getContext()->getPointerController(getDeviceId());
-        }
-        if (mConfig.pointerCaptureRequest.isEnable()) {
-            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
-        }
-    } else {
-        if (mPointerController != nullptr && mDeviceMode == DeviceMode::DIRECT &&
-            !mConfig.showTouches) {
-            mPointerController->clearSpots();
-        }
-        mPointerController.reset();
-    }
-
     if ((viewportChanged && !skipViewportUpdate) || deviceModeChanged) {
         ALOGI("Device reconfigured: id=%d, name='%s', size %s, orientation %s, mode %s, "
-              "display id %d",
+              "display id %s",
               getDeviceId(), getDeviceName().c_str(), toString(mDisplayBounds).c_str(),
               ftl::enum_string(mInputDeviceOrientation).c_str(),
-              ftl::enum_string(mDeviceMode).c_str(), mViewport.displayId);
+              ftl::enum_string(mDeviceMode).c_str(), mViewport.displayId.toString().c_str());
 
         configureVirtualKeys();
 
@@ -1400,7 +1373,6 @@
 
 std::list<NotifyArgs> TouchInputMapper::reset(nsecs_t when) {
     std::list<NotifyArgs> out = cancelTouch(when, when);
-    updateTouchSpots();
 
     mCursorButtonAccumulator.reset(getDeviceContext());
     mCursorScrollAccumulator.reset(getDeviceContext());
@@ -1427,11 +1399,6 @@
     mPointerSimple.reset();
     resetExternalStylus();
 
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-        mPointerController->clearSpots();
-    }
-
     return out += InputMapper::reset(when);
 }
 
@@ -1586,11 +1553,6 @@
     uint32_t policyFlags = 0;
     bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
     if (initialDown || buttonsPressed) {
-        // If this is a touch screen, hide the pointer on an initial down.
-        if (mDeviceMode == DeviceMode::DIRECT) {
-            getContext()->fadePointer();
-        }
-
         if (mParameters.wake) {
             policyFlags |= POLICY_FLAG_WAKE;
         }
@@ -1658,7 +1620,6 @@
         out += dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
     } else {
         if (!mCurrentMotionAborted) {
-            updateTouchSpots();
             out += dispatchButtonRelease(when, readTime, policyFlags);
             out += dispatchHoverExit(when, readTime, policyFlags);
             out += dispatchTouches(when, readTime, policyFlags);
@@ -1690,28 +1651,6 @@
     return out;
 }
 
-void TouchInputMapper::updateTouchSpots() {
-    if (!mConfig.showTouches || mPointerController == nullptr) {
-        return;
-    }
-
-    // Update touch spots when this is a touchscreen even when it's not enabled so that we can
-    // clear touch spots.
-    if (mDeviceMode != DeviceMode::DIRECT &&
-        (mDeviceMode != DeviceMode::DISABLED || !isTouchScreen())) {
-        return;
-    }
-
-    mPointerController->setPresentation(PointerControllerInterface::Presentation::SPOT);
-    mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-
-    mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords.cbegin(),
-                                 mCurrentCookedState.cookedPointerData.idToIndex.cbegin(),
-                                 mCurrentCookedState.cookedPointerData.touchingIdBits |
-                                         mCurrentCookedState.cookedPointerData.hoveringIdBits,
-                                 mViewport.displayId);
-}
-
 bool TouchInputMapper::isTouchScreen() {
     return mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN &&
             mParameters.hasAssociatedDisplay;
@@ -2560,54 +2499,6 @@
         cancelPreviousGesture = false;
     }
 
-    // Update the pointer presentation and spots.
-    if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
-        mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
-        if (finishPreviousGesture || cancelPreviousGesture) {
-            mPointerController->clearSpots();
-        }
-
-        if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
-            mPointerController->setSpots(mPointerGesture.currentGestureCoords.cbegin(),
-                                         mPointerGesture.currentGestureIdToIndex.cbegin(),
-                                         mPointerGesture.currentGestureIdBits,
-                                         mPointerController->getDisplayId());
-        }
-    } else {
-        mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
-    }
-
-    // Show or hide the pointer if needed.
-    switch (mPointerGesture.currentGestureMode) {
-        case PointerGesture::Mode::NEUTRAL:
-        case PointerGesture::Mode::QUIET:
-            if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH &&
-                mPointerGesture.lastGestureMode == PointerGesture::Mode::FREEFORM) {
-                // Remind the user of where the pointer is after finishing a gesture with spots.
-                mPointerController->unfade(PointerControllerInterface::Transition::GRADUAL);
-            }
-            break;
-        case PointerGesture::Mode::TAP:
-        case PointerGesture::Mode::TAP_DRAG:
-        case PointerGesture::Mode::BUTTON_CLICK_OR_DRAG:
-        case PointerGesture::Mode::HOVER:
-        case PointerGesture::Mode::PRESS:
-        case PointerGesture::Mode::SWIPE:
-            // Unfade the pointer when the current gesture manipulates the
-            // area directly under the pointer.
-            mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-            break;
-        case PointerGesture::Mode::FREEFORM:
-            // Fade the pointer when the current gesture manipulates a different
-            // area and there are spots to guide the user experience.
-            if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
-                mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-            } else {
-                mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-            }
-            break;
-    }
-
     // Send events!
     int32_t metaState = getContext()->getGlobalMetaState();
     int32_t buttonState = mCurrentCookedState.buttonState;
@@ -2746,7 +2637,6 @@
         // the pointer is hovering again even if the user is not currently touching
         // the touch pad.  This ensures that a view will receive a fresh hover enter
         // event after a tap.
-        const auto [x, y] = mPointerController->getPosition();
 
         PointerProperties pointerProperties;
         pointerProperties.clear();
@@ -2755,16 +2645,12 @@
 
         PointerCoords pointerCoords;
         pointerCoords.clear();
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-
-        const int32_t displayId = mPointerController->getDisplayId();
         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
-                                       mSource, displayId, policyFlags,
+                                       mSource, ui::LogicalDisplayId::INVALID, policyFlags,
                                        AMOTION_EVENT_ACTION_HOVER_MOVE, 0, flags, metaState,
                                        buttonState, MotionClassification::NONE,
                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
-                                       &pointerCoords, 0, 0, x, y, mPointerGesture.downTime,
+                                       &pointerCoords, 0, 0, 0.f, 0.f, mPointerGesture.downTime,
                                        /*videoFrames=*/{}));
     }
 
@@ -2810,12 +2696,6 @@
     // Reset the current pointer gesture.
     mPointerGesture.reset();
     mPointerVelocityControl.reset();
-
-    // Remove any current spots.
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-        mPointerController->clearSpots();
-    }
     return out;
 }
 
@@ -2951,8 +2831,6 @@
             mPointerVelocityControl.reset();
         }
 
-        const auto [x, y] = mPointerController->getPosition();
-
         mPointerGesture.currentGestureMode = PointerGesture::Mode::BUTTON_CLICK_OR_DRAG;
         mPointerGesture.currentGestureIdBits.clear();
         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
@@ -2961,8 +2839,6 @@
         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
         mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
         mPointerGesture.currentGestureCoords[0].clear();
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
     } else if (currentFingerCount == 0) {
         // Case 3. No fingers down and button is not pressed. (NEUTRAL)
@@ -2977,9 +2853,8 @@
              mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) &&
             lastFingerCount == 1) {
             if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
-                const auto [x, y] = mPointerController->getPosition();
-                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
-                    fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+                if (fabs(0.f - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
+                    fabs(0.f - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
                     ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP");
 
                     mPointerGesture.tapUpTime = when;
@@ -3006,7 +2881,7 @@
                     tapped = true;
                 } else {
                     ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP, deltaX=%f, deltaY=%f",
-                             x - mPointerGesture.tapX, y - mPointerGesture.tapY);
+                             0.f - mPointerGesture.tapX, 0.f - mPointerGesture.tapY);
                 }
             } else {
                 if (DEBUG_GESTURES) {
@@ -3038,13 +2913,12 @@
         mPointerGesture.currentGestureMode = PointerGesture::Mode::HOVER;
         if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
-                const auto [x, y] = mPointerController->getPosition();
-                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
-                    fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+                if (fabs(0.f - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
+                    fabs(0.f - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
                     mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
                 } else {
                     ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
-                             x - mPointerGesture.tapX, y - mPointerGesture.tapY);
+                             0.f - mPointerGesture.tapX, 0.f - mPointerGesture.tapY);
                 }
             } else {
                 ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, %0.3fms time since up",
@@ -3074,8 +2948,6 @@
             down = false;
         }
 
-        const auto [x, y] = mPointerController->getPosition();
-
         mPointerGesture.currentGestureIdBits.clear();
         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
@@ -3083,16 +2955,14 @@
         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
         mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
         mPointerGesture.currentGestureCoords[0].clear();
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
                                                              down ? 1.0f : 0.0f);
 
         if (lastFingerCount == 0 && currentFingerCount != 0) {
             mPointerGesture.resetTap();
             mPointerGesture.tapDownTime = when;
-            mPointerGesture.tapX = x;
-            mPointerGesture.tapY = y;
+            mPointerGesture.tapX = 0.f;
+            mPointerGesture.tapY = 0.f;
         }
     } else {
         // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
@@ -3243,8 +3113,8 @@
         mCurrentRawState.rawPointerData
                 .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX,
                                                &mPointerGesture.referenceTouchY);
-        std::tie(mPointerGesture.referenceGestureX, mPointerGesture.referenceGestureY) =
-                mPointerController->getPosition();
+        mPointerGesture.referenceGestureX = 0.f;
+        mPointerGesture.referenceGestureY = 0.f;
     }
 
     // Clear the reference deltas for fingers not yet included in the reference calculation.
@@ -3539,8 +3409,6 @@
 
     rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY);
     mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
-    mPointerController->move(deltaX, deltaY);
 }
 
 std::list<NotifyArgs> TouchInputMapper::dispatchPointerStylus(nsecs_t when, nsecs_t readTime,
@@ -3557,13 +3425,6 @@
 
         float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
         float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
-        // Styluses are configured specifically for one display. We only update the
-        // PointerController for this stylus if the PointerController is configured for
-        // the same display as this stylus,
-        if (getAssociatedDisplayId() == mViewport.displayId) {
-            mPointerController->setPosition(x, y);
-            std::tie(x, y) = mPointerController->getPosition();
-        }
 
         mPointerSimple.currentCoords = mCurrentCookedState.cookedPointerData.pointerCoords[index];
         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
@@ -3601,12 +3462,9 @@
         down = isPointerDown(mCurrentRawState.buttonState);
         hovering = !down;
 
-        const auto [x, y] = mPointerController->getPosition();
         const uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
         mPointerSimple.currentCoords =
                 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex];
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
                                                   hovering ? 0.0f : 1.0f);
         mPointerSimple.currentProperties.id = 0;
@@ -3619,8 +3477,8 @@
         hovering = false;
     }
 
-    const int32_t displayId = mPointerController->getDisplayId();
-    return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, displayId);
+    return dispatchPointerSimple(when, readTime, policyFlags, down, hovering,
+                                 ui::LogicalDisplayId::INVALID);
 }
 
 std::list<NotifyArgs> TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime,
@@ -3634,24 +3492,14 @@
 
 std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
                                                               uint32_t policyFlags, bool down,
-                                                              bool hovering, int32_t displayId) {
+                                                              bool hovering,
+                                                              ui::LogicalDisplayId displayId) {
     LOG_ALWAYS_FATAL_IF(mDeviceMode != DeviceMode::POINTER,
                         "%s cannot be used when the device is not in POINTER mode.", __func__);
     std::list<NotifyArgs> out;
     int32_t metaState = getContext()->getGlobalMetaState();
     auto cursorPosition = mPointerSimple.currentCoords.getXYValue();
 
-    if (displayId == mPointerController->getDisplayId()) {
-        std::tie(cursorPosition.x, cursorPosition.y) = mPointerController->getPosition();
-        if (down || hovering) {
-            mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
-            mPointerController->clearSpots();
-            mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
-            mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-        }
-    }
-
     if (mPointerSimple.down && !down) {
         mPointerSimple.down = false;
 
@@ -3787,9 +3635,6 @@
                                        mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
                                        mPointerSimple.downTime,
                                        /*videoFrames=*/{}));
-        if (mPointerController != nullptr) {
-            mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-        }
     }
     mPointerSimple.reset();
     return out;
@@ -3840,35 +3685,15 @@
         source |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
     }
 
-    const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
-    const bool showDirectStylusPointer = mConfig.stylusPointerIconEnabled &&
-            mDeviceMode == DeviceMode::DIRECT && isStylusEvent(source, pointerProperties) &&
-            mPointerController && displayId != ADISPLAY_ID_NONE &&
-            displayId == mPointerController->getDisplayId();
-    if (showDirectStylusPointer) {
-        switch (action & AMOTION_EVENT_ACTION_MASK) {
-            case AMOTION_EVENT_ACTION_HOVER_ENTER:
-            case AMOTION_EVENT_ACTION_HOVER_MOVE:
-                mPointerController->setPresentation(
-                        PointerControllerInterface::Presentation::STYLUS_HOVER);
-                mPointerController
-                        ->setPosition(mCurrentCookedState.cookedPointerData.pointerCoords[0].getX(),
-                                      mCurrentCookedState.cookedPointerData.pointerCoords[0]
-                                              .getY());
-                mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-                break;
-            case AMOTION_EVENT_ACTION_HOVER_EXIT:
-                mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
-                break;
-        }
-    }
+    const ui::LogicalDisplayId displayId =
+            getAssociatedDisplayId().value_or(ui::LogicalDisplayId::INVALID);
 
     float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     if (mDeviceMode == DeviceMode::POINTER) {
-        std::tie(xCursorPosition, yCursorPosition) = mPointerController->getPosition();
+        xCursorPosition = yCursorPosition = 0.f;
     }
-    const int32_t deviceId = getDeviceId();
+    const DeviceId deviceId = getDeviceId();
     std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
     std::for_each(frames.begin(), frames.end(),
                   [this](TouchVideoFrame& frame) { frame.rotate(this->mInputDeviceOrientation); });
@@ -4135,10 +3960,10 @@
     return true;
 }
 
-std::optional<int32_t> TouchInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> TouchInputMapper::getAssociatedDisplayId() {
     if (mParameters.hasAssociatedDisplay) {
         if (mDeviceMode == DeviceMode::POINTER) {
-            return std::make_optional(mPointerController->getDisplayId());
+            return ui::LogicalDisplayId::INVALID;
         } else {
             return std::make_optional(mViewport.displayId);
         }
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 9b7fe93..b24f2ff 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -26,13 +26,12 @@
 #include <utility>
 #include <vector>
 
-#include <stdint.h>
-#include <gui/constants.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <input/InputDevice.h>
 #include <input/VelocityControl.h>
 #include <input/VelocityTracker.h>
+#include <stdint.h>
 #include <ui/Rect.h>
 #include <ui/Rotation.h>
 #include <ui/Size.h>
@@ -46,7 +45,6 @@
 #include "InputMapper.h"
 #include "InputReaderBase.h"
 #include "NotifyArgs.h"
-#include "PointerControllerInterface.h"
 #include "StylusState.h"
 #include "TouchButtonAccumulator.h"
 
@@ -187,7 +185,7 @@
     [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override;
     [[nodiscard]] std::list<NotifyArgs> updateExternalStylusState(
             const StylusState& state) override;
-    std::optional<int32_t> getAssociatedDisplayId() override;
+    std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
 
 protected:
     CursorButtonAccumulator mCursorButtonAccumulator;
@@ -392,9 +390,6 @@
     // The time the primary pointer last went down.
     nsecs_t mDownTime{0};
 
-    // The pointer controller, or null if the device is not a pointer.
-    std::shared_ptr<PointerControllerInterface> mPointerController;
-
     std::vector<VirtualKey> mVirtualKeys;
 
     explicit TouchInputMapper(InputDeviceContext& deviceContext,
@@ -710,7 +705,7 @@
 
         // Values reported for the last pointer event.
         uint32_t source;
-        int32_t displayId;
+        ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
         float lastCursorX;
         float lastCursorY;
 
@@ -723,7 +718,7 @@
             hovering = false;
             downTime = 0;
             source = 0;
-            displayId = ADISPLAY_ID_NONE;
+            displayId = ui::LogicalDisplayId::INVALID;
             lastCursorX = 0.f;
             lastCursorY = 0.f;
         }
@@ -814,7 +809,8 @@
 
     [[nodiscard]] std::list<NotifyArgs> dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
                                                               uint32_t policyFlags, bool down,
-                                                              bool hovering, int32_t displayId);
+                                                              bool hovering,
+                                                              ui::LogicalDisplayId displayId);
     [[nodiscard]] std::list<NotifyArgs> abortPointerSimple(nsecs_t when, nsecs_t readTime,
                                                            uint32_t policyFlags);
 
@@ -837,9 +833,6 @@
 
     // Returns if this touch device is a touch screen with an associated display.
     bool isTouchScreen();
-    // Updates touch spots if they are enabled. Should only be used when this device is a
-    // touchscreen.
-    void updateTouchSpots();
 
     bool isPointInsidePhysicalFrame(int32_t x, int32_t y) const;
     const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index f558ba1..b8911db 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -47,8 +47,6 @@
 
 namespace {
 
-static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
-
 /**
  * Log details of each gesture output by the gestures library.
  * Enable this via "adb shell setprop log.tag.TouchpadInputMapperGestures DEBUG" (requires
@@ -185,7 +183,6 @@
     static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag,
                                                                  AStatsEventList* outEventList,
                                                                  void* cookie) {
-        ALOGI("Received pull request for touchpad usage atom");
         LOG_ALWAYS_FATAL_IF(atomTag != android::util::TOUCHPAD_USAGE);
         MetricsAccumulator& accumulator = MetricsAccumulator::getInstance();
         accumulator.produceAtomsAndReset(*outEventList);
@@ -193,14 +190,12 @@
     }
 
     void produceAtomsAndReset(AStatsEventList& outEventList) {
-        ALOGI("Acquiring lock for touchpad usage metrics...");
         std::scoped_lock lock(mLock);
         produceAtomsLocked(outEventList);
         resetCountersLocked();
     }
 
     void produceAtomsLocked(AStatsEventList& outEventList) const REQUIRES(mLock) {
-        ALOGI("Producing touchpad usage atoms for %zu counters", mCounters.size());
         for (auto& [id, counters] : mCounters) {
             auto [busId, vendorId, productId, versionId] = id;
             addAStatsEvent(&outEventList, android::util::TOUCHPAD_USAGE, vendorId, productId,
@@ -237,20 +232,13 @@
 
 TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext,
                                          const InputReaderConfiguration& readerConfig)
-      : TouchpadInputMapper(deviceContext, readerConfig, ENABLE_POINTER_CHOREOGRAPHER) {}
-
-TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext,
-                                         const InputReaderConfiguration& readerConfig,
-                                         bool enablePointerChoreographer)
       : InputMapper(deviceContext, readerConfig),
         mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter),
-        mPointerController(getContext()->getPointerController(getDeviceId())),
         mTimerProvider(*getContext()),
         mStateConverter(deviceContext, mMotionAccumulator),
         mGestureConverter(*getContext(), deviceContext, getDeviceId()),
         mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()),
-        mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())),
-        mEnablePointerChoreographer(enablePointerChoreographer) {
+        mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) {
     RawAbsoluteAxisInfo slotAxisInfo;
     deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
     if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) {
@@ -277,10 +265,6 @@
 }
 
 TouchpadInputMapper::~TouchpadInputMapper() {
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
-    }
-
     // The gesture interpreter's destructor will try to free its property and timer providers,
     // calling PropertyProvider::freeProperty and TimerProvider::freeTimer using a raw pointers.
     // Depending on the declaration order in TouchpadInputMapper.h, those providers may have already
@@ -322,7 +306,8 @@
     }
     dump += INDENT3 "Captured event converter:\n";
     dump += addLinePrefix(mCapturedEventConverter.dump(), INDENT4);
-    dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
+    dump += StringPrintf(INDENT3 "DisplayId: %s\n",
+                         toString(mDisplayId, streamableToString).c_str());
 }
 
 std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when,
@@ -334,7 +319,7 @@
     }
 
     if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
-        mDisplayId = ADISPLAY_ID_NONE;
+        mDisplayId = ui::LogicalDisplayId::INVALID;
         std::optional<DisplayViewport> resolvedViewport;
         std::optional<FloatRect> boundsInLogicalDisplay;
         if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
@@ -342,33 +327,13 @@
             // Only generate events for the associated display.
             mDisplayId = assocViewport->displayId;
             resolvedViewport = *assocViewport;
-            if (!mEnablePointerChoreographer) {
-                const bool mismatchedPointerDisplay =
-                        (assocViewport->displayId != mPointerController->getDisplayId());
-                if (mismatchedPointerDisplay) {
-                    ALOGW("Touchpad \"%s\" associated viewport display does not match pointer "
-                          "controller",
-                          mDeviceContext.getName().c_str());
-                    mDisplayId.reset();
-                }
-            }
         } else {
             // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
-            if (mEnablePointerChoreographer) {
-                // Always use DISPLAY_ID_NONE for touchpad events.
-                // PointerChoreographer will make it target the correct the displayId later.
-                resolvedViewport =
-                        getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
-                mDisplayId = resolvedViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
-            } else {
-                mDisplayId = mPointerController->getDisplayId();
-                if (auto v = config.getDisplayViewportById(*mDisplayId); v) {
-                    resolvedViewport = *v;
-                }
-                if (auto bounds = mPointerController->getBounds(); bounds) {
-                    boundsInLogicalDisplay = *bounds;
-                }
-            }
+            // Always use DISPLAY_ID_NONE for touchpad events.
+            // PointerChoreographer will make it target the correct the displayId later.
+            resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
+            mDisplayId = resolvedViewport ? std::make_optional(ui::LogicalDisplayId::INVALID)
+                                          : std::nullopt;
         }
 
         mGestureConverter.setDisplayId(mDisplayId);
@@ -422,7 +387,6 @@
             // The touchpad is being captured, so we need to tidy up any fake fingers etc. that are
             // still being reported for a gesture in progress.
             out += reset(when);
-            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
         } else {
             // We're transitioning from captured to uncaptured.
             mCapturedEventConverter.reset();
@@ -532,7 +496,7 @@
     return out;
 }
 
-std::optional<int32_t> TouchpadInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> TouchpadInputMapper::getAssociatedDisplayId() {
     return mDisplayId;
 }
 
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 9f272cf..546fa5b 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -66,16 +66,12 @@
     using MetricsIdentifier = std::tuple<uint16_t /*busId*/, uint16_t /*vendorId*/,
                                          uint16_t /*productId*/, uint16_t /*version*/>;
 
-    std::optional<int32_t> getAssociatedDisplayId() override;
+    std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
 
 private:
     void resetGestureInterpreter(nsecs_t when);
     explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
                                  const InputReaderConfiguration& readerConfig);
-    // Constructor for testing.
-    explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
-                                 const InputReaderConfiguration& readerConfig,
-                                 bool enablePointerChoreographer);
     void updatePalmDetectionMetrics();
     [[nodiscard]] std::list<NotifyArgs> sendHardwareState(nsecs_t when, nsecs_t readTime,
                                                           SelfContainedHardwareState schs);
@@ -83,7 +79,6 @@
 
     std::unique_ptr<gestures::GestureInterpreter, void (*)(gestures::GestureInterpreter*)>
             mGestureInterpreter;
-    std::shared_ptr<PointerControllerInterface> mPointerController;
 
     PropertyProvider mPropertyProvider;
     TimerProvider mTimerProvider;
@@ -111,12 +106,10 @@
     // Tracking IDs for touches that have at some point been reported as palms by the touchpad.
     std::set<int32_t> mPalmTrackingIds;
 
-    const bool mEnablePointerChoreographer;
-
     // The display that events generated by this mapper should target. This can be set to
-    // ADISPLAY_ID_NONE to target the focused display. If there is no display target (i.e.
+    // LogicalDisplayId::INVALID to target the focused display. If there is no display target (i.e.
     // std::nullopt), all events will be ignored.
-    std::optional<int32_t> mDisplayId;
+    std::optional<ui::LogicalDisplayId> mDisplayId;
 
     nsecs_t mGestureStartTime{0};
 };
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 39a88e5..e8e7376 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -66,7 +66,6 @@
                                    const InputDeviceContext& deviceContext, int32_t deviceId)
       : mDeviceId(deviceId),
         mReaderContext(readerContext),
-        mPointerController(readerContext.getPointerController(deviceId)),
         mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) {
     deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo);
     deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo);
@@ -174,7 +173,6 @@
                                                    const Gesture& gesture) {
     float deltaX = gesture.details.move.dx;
     float deltaY = gesture.details.move.dy;
-    const auto [oldXCursorPosition, oldYCursorPosition] = mPointerController->getPosition();
     if (ENABLE_TOUCHPAD_PALM_REJECTION_V2) {
         bool wasHoverCancelled = mIsHoverCancelled;
         // Gesture will be cancelled if it started before the user started typing and
@@ -185,8 +183,7 @@
         if (!wasHoverCancelled && mIsHoverCancelled) {
             // This is the first event of the cancelled gesture, we won't return because we need to
             // generate a HOVER_EXIT event
-            mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-            return exitHover(when, readTime, oldXCursorPosition, oldYCursorPosition);
+            return exitHover(when, readTime);
         } else if (mIsHoverCancelled) {
             return {};
         }
@@ -202,30 +199,23 @@
             (std::abs(deltaX) > 0 || std::abs(deltaY) > 0)) {
             enableTapToClick(when);
         }
-        mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
-        mPointerController->move(deltaX, deltaY);
-        mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
     }
 
     std::list<NotifyArgs> out;
     const bool down = isPointerDown(mButtonState);
     if (!down) {
-        out += enterHover(when, readTime, oldXCursorPosition, oldYCursorPosition);
+        out += enterHover(when, readTime);
     }
-    const auto [newXCursorPosition, newYCursorPosition] = mPointerController->getPosition();
 
     PointerCoords coords;
     coords.clear();
-    coords.setAxisValue(AMOTION_EVENT_AXIS_X, newXCursorPosition);
-    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, newYCursorPosition);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
     coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
 
     const int32_t action = down ? AMOTION_EVENT_ACTION_MOVE : AMOTION_EVENT_ACTION_HOVER_MOVE;
     out.push_back(makeMotionArgs(when, readTime, action, /*actionButton=*/0, mButtonState,
-                                 /*pointerCount=*/1, &coords, newXCursorPosition,
-                                 newYCursorPosition));
+                                 /*pointerCount=*/1, &coords));
     return out;
 }
 
@@ -233,15 +223,8 @@
                                                             const Gesture& gesture) {
     std::list<NotifyArgs> out = {};
 
-    mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
-    mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
-
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
-
     PointerCoords coords;
     coords.clear();
-    coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0);
 
@@ -274,16 +257,15 @@
             newButtonState |= actionButton;
             pressEvents.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS,
                                                  actionButton, newButtonState,
-                                                 /*pointerCount=*/1, &coords, xCursorPosition,
-                                                 yCursorPosition));
+                                                 /*pointerCount=*/1, &coords));
         }
     }
     if (!isPointerDown(mButtonState) && isPointerDown(newButtonState)) {
         mDownTime = when;
-        out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
+        out += exitHover(when, readTime);
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
                                      /* actionButton= */ 0, newButtonState, /* pointerCount= */ 1,
-                                     &coords, xCursorPosition, yCursorPosition));
+                                     &coords));
     }
     out.splice(out.end(), pressEvents);
 
@@ -299,16 +281,15 @@
             newButtonState &= ~actionButton;
             out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
                                          actionButton, newButtonState, /* pointerCount= */ 1,
-                                         &coords, xCursorPosition, yCursorPosition));
+                                         &coords));
         }
     }
     if (isPointerDown(mButtonState) && !isPointerDown(newButtonState)) {
         coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f);
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0,
-                                     newButtonState, /* pointerCount= */ 1, &coords,
-                                     xCursorPosition, yCursorPosition));
+                                     newButtonState, /* pointerCount= */ 1, &coords));
         mButtonState = newButtonState;
-        out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+        out += enterHover(when, readTime);
     }
     mButtonState = newButtonState;
     return out;
@@ -316,12 +297,9 @@
 
 std::list<NotifyArgs> GestureConverter::releaseAllButtons(nsecs_t when, nsecs_t readTime) {
     std::list<NotifyArgs> out;
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
 
     PointerCoords coords;
     coords.clear();
-    coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0);
     const bool pointerDown = isPointerDown(mButtonState);
@@ -332,17 +310,15 @@
         if (mButtonState & button) {
             newButtonState &= ~button;
             out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
-                                         button, newButtonState, /*pointerCount=*/1, &coords,
-                                         xCursorPosition, yCursorPosition));
+                                         button, newButtonState, /*pointerCount=*/1, &coords));
         }
     }
     mButtonState = 0;
     if (pointerDown) {
         coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f);
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /*actionButton=*/0,
-                                     mButtonState, /*pointerCount=*/1, &coords, xCursorPosition,
-                                     yCursorPosition));
-        out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+                                     mButtonState, /*pointerCount=*/1, &coords));
+        out += enterHover(when, readTime);
     }
     return out;
 }
@@ -351,19 +327,16 @@
                                                      const Gesture& gesture) {
     std::list<NotifyArgs> out;
     PointerCoords& coords = mFakeFingerCoords[0];
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
     if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
-        out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
+        out += exitHover(when, readTime);
 
         mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
-        coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-        coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
+        coords.clear();
         coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
         mDownTime = when;
         NotifyMotionArgs args =
                 makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN, /* actionButton= */ 0,
-                               mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data(),
-                               xCursorPosition, yCursorPosition);
+                               mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data());
         args.flags |= AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
         out.push_back(args);
     }
@@ -378,8 +351,7 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE, -gesture.details.scroll.dy);
     NotifyMotionArgs args =
             makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, /* actionButton= */ 0,
-                           mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data(),
-                           xCursorPosition, yCursorPosition);
+                           mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data());
     args.flags |= AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
     out.push_back(args);
     return out;
@@ -409,28 +381,22 @@
                     // avoid side effects (e.g. activation of UI elements).
                     // TODO(b/326056750): add an API for fling stops.
                     mFlingMayBeInProgress = false;
-                    const auto [xCursorPosition, yCursorPosition] =
-                            mPointerController->getPosition();
                     PointerCoords coords;
                     coords.clear();
-                    coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-                    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
                     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
                     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0);
 
                     std::list<NotifyArgs> out;
                     mDownTime = when;
                     mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
-                    out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
+                    out += exitHover(when, readTime);
                     out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
                                                  /*actionButton=*/0, /*buttonState=*/0,
-                                                 /*pointerCount=*/1, &coords, xCursorPosition,
-                                                 yCursorPosition));
+                                                 /*pointerCount=*/1, &coords));
                     out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_CANCEL,
                                                  /*actionButton=*/0, /*buttonState=*/0,
-                                                 /*pointerCount=*/1, &coords, xCursorPosition,
-                                                 yCursorPosition));
-                    out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+                                                 /*pointerCount=*/1, &coords));
+                    out += enterHover(when, readTime);
                     mCurrentClassification = MotionClassification::NONE;
                     return out;
                 } else {
@@ -455,17 +421,15 @@
 
 std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime) {
     std::list<NotifyArgs> out;
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE, 0);
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE, 0);
     NotifyMotionArgs args =
             makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0,
-                           mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data(),
-                           xCursorPosition, yCursorPosition);
+                           mButtonState, /* pointerCount= */ 1, mFakeFingerCoords.data());
     args.flags |= AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
     out.push_back(args);
     mCurrentClassification = MotionClassification::NONE;
-    out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+    out += enterHover(when, readTime);
     return out;
 }
 
@@ -475,26 +439,26 @@
                                                                              float dx, float dy) {
     std::list<NotifyArgs> out = {};
 
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
     if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
         // If the user changes the number of fingers mid-way through a swipe (e.g. they start with
         // three and then put a fourth finger down), the gesture library will treat it as two
         // separate swipes with an appropriate lift event between them, so we don't have to worry
         // about the finger count changing mid-swipe.
 
-        out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
+        out += exitHover(when, readTime);
 
         mCurrentClassification = MotionClassification::MULTI_FINGER_SWIPE;
 
         mSwipeFingerCount = fingerCount;
 
         constexpr float FAKE_FINGER_SPACING = 100;
-        float xCoord = xCursorPosition - FAKE_FINGER_SPACING * (mSwipeFingerCount - 1) / 2;
+        float xCoord = 0.f - FAKE_FINGER_SPACING * (mSwipeFingerCount - 1) / 2;
         for (size_t i = 0; i < mSwipeFingerCount; i++) {
             PointerCoords& coords = mFakeFingerCoords[i];
             coords.clear();
+            // PointerChoreographer will add the cursor position to these pointers.
             coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCoord);
-            coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
+            coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 0.f);
             coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
             xCoord += FAKE_FINGER_SPACING;
         }
@@ -504,14 +468,13 @@
                                           fingerCount);
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
                                      /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1,
-                                     mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                     mFakeFingerCoords.data()));
         for (size_t i = 1; i < mSwipeFingerCount; i++) {
             out.push_back(makeMotionArgs(when, readTime,
                                          AMOTION_EVENT_ACTION_POINTER_DOWN |
                                                  (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
                                          /* actionButton= */ 0, mButtonState,
-                                         /* pointerCount= */ i + 1, mFakeFingerCoords.data(),
-                                         xCursorPosition, yCursorPosition));
+                                         /* pointerCount= */ i + 1, mFakeFingerCoords.data()));
         }
     }
     float rotatedDeltaX = dx, rotatedDeltaY = -dy;
@@ -529,7 +492,7 @@
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset);
     out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, /* actionButton= */ 0,
                                  mButtonState, /* pointerCount= */ mSwipeFingerCount,
-                                 mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                 mFakeFingerCoords.data()));
     return out;
 }
 
@@ -539,7 +502,6 @@
     if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
         return out;
     }
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0);
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0);
 
@@ -548,22 +510,20 @@
                                      AMOTION_EVENT_ACTION_POINTER_UP |
                                              ((i - 1) << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
                                      /* actionButton= */ 0, mButtonState, /* pointerCount= */ i,
-                                     mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                     mFakeFingerCoords.data()));
     }
     out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP,
                                  /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1,
-                                 mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                 mFakeFingerCoords.data()));
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SWIPE_FINGER_COUNT, 0);
     mCurrentClassification = MotionClassification::NONE;
-    out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+    out += enterHover(when, readTime);
     mSwipeFingerCount = 0;
     return out;
 }
 
 [[nodiscard]] std::list<NotifyArgs> GestureConverter::handlePinch(nsecs_t when, nsecs_t readTime,
                                                                   const Gesture& gesture) {
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
-
     // Pinch gesture phases are reported a little differently from others, in that the same details
     // struct is used for all phases of the gesture, just with different zoom_state values. When
     // zoom_state is START or END, dz will always be 1, so we don't need to move the pointers in
@@ -575,28 +535,27 @@
                             gesture.details.pinch.zoom_state);
         std::list<NotifyArgs> out;
 
-        out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
+        out += exitHover(when, readTime);
 
         mCurrentClassification = MotionClassification::PINCH;
         mPinchFingerSeparation = INITIAL_PINCH_SEPARATION_PX;
+        // PointerChoreographer will add the cursor position to these pointers.
         mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 1.0);
-        mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                          xCursorPosition - mPinchFingerSeparation / 2);
-        mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
+        mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 0.f - mPinchFingerSeparation / 2);
+        mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 0.f);
         mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-        mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                          xCursorPosition + mPinchFingerSeparation / 2);
-        mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
+        mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 0.f + mPinchFingerSeparation / 2);
+        mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 0.f);
         mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
         mDownTime = when;
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
                                      /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1,
-                                     mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                     mFakeFingerCoords.data()));
         out.push_back(makeMotionArgs(when, readTime,
                                      AMOTION_EVENT_ACTION_POINTER_DOWN |
                                              1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT,
                                      /* actionButton= */ 0, mButtonState, /* pointerCount= */ 2,
-                                     mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                     mFakeFingerCoords.data()));
         return out;
     }
 
@@ -605,77 +564,65 @@
     }
 
     mPinchFingerSeparation *= gesture.details.pinch.dz;
+    // PointerChoreographer will add the cursor position to these pointers.
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR,
                                       gesture.details.pinch.dz);
-    mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                      xCursorPosition - mPinchFingerSeparation / 2);
-    mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
-    mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                      xCursorPosition + mPinchFingerSeparation / 2);
-    mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
+    mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 0.f - mPinchFingerSeparation / 2);
+    mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 0.f);
+    mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 0.f + mPinchFingerSeparation / 2);
+    mFakeFingerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 0.f);
     return {makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, /*actionButton=*/0,
-                           mButtonState, /*pointerCount=*/2, mFakeFingerCoords.data(),
-                           xCursorPosition, yCursorPosition)};
+                           mButtonState, /*pointerCount=*/2, mFakeFingerCoords.data())};
 }
 
 std::list<NotifyArgs> GestureConverter::endPinch(nsecs_t when, nsecs_t readTime) {
     std::list<NotifyArgs> out;
-    const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
 
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 1.0);
     out.push_back(makeMotionArgs(when, readTime,
                                  AMOTION_EVENT_ACTION_POINTER_UP |
                                          1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT,
                                  /*actionButton=*/0, mButtonState, /*pointerCount=*/2,
-                                 mFakeFingerCoords.data(), xCursorPosition, yCursorPosition));
+                                 mFakeFingerCoords.data()));
     out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /*actionButton=*/0,
-                                 mButtonState, /*pointerCount=*/1, mFakeFingerCoords.data(),
-                                 xCursorPosition, yCursorPosition));
+                                 mButtonState, /*pointerCount=*/1, mFakeFingerCoords.data()));
     mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 0);
     mCurrentClassification = MotionClassification::NONE;
-    out += enterHover(when, readTime, xCursorPosition, yCursorPosition);
+    out += enterHover(when, readTime);
     return out;
 }
 
-std::list<NotifyArgs> GestureConverter::enterHover(nsecs_t when, nsecs_t readTime,
-                                                   float xCursorPosition, float yCursorPosition) {
+std::list<NotifyArgs> GestureConverter::enterHover(nsecs_t when, nsecs_t readTime) {
     if (!mIsHovering) {
         mIsHovering = true;
-        return {makeHoverEvent(when, readTime, AMOTION_EVENT_ACTION_HOVER_ENTER, xCursorPosition,
-                               yCursorPosition)};
+        return {makeHoverEvent(when, readTime, AMOTION_EVENT_ACTION_HOVER_ENTER)};
     } else {
         return {};
     }
 }
 
-std::list<NotifyArgs> GestureConverter::exitHover(nsecs_t when, nsecs_t readTime,
-                                                  float xCursorPosition, float yCursorPosition) {
+std::list<NotifyArgs> GestureConverter::exitHover(nsecs_t when, nsecs_t readTime) {
     if (mIsHovering) {
         mIsHovering = false;
-        return {makeHoverEvent(when, readTime, AMOTION_EVENT_ACTION_HOVER_EXIT, xCursorPosition,
-                               yCursorPosition)};
+        return {makeHoverEvent(when, readTime, AMOTION_EVENT_ACTION_HOVER_EXIT)};
     } else {
         return {};
     }
 }
 
-NotifyMotionArgs GestureConverter::makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action,
-                                                  float xCursorPosition, float yCursorPosition) {
+NotifyMotionArgs GestureConverter::makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action) {
     PointerCoords coords;
     coords.clear();
-    coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
-    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
     coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0);
     return makeMotionArgs(when, readTime, action, /*actionButton=*/0, mButtonState,
-                          /*pointerCount=*/1, &coords, xCursorPosition, yCursorPosition);
+                          /*pointerCount=*/1, &coords);
 }
 
 NotifyMotionArgs GestureConverter::makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action,
                                                   int32_t actionButton, int32_t buttonState,
                                                   uint32_t pointerCount,
-                                                  const PointerCoords* pointerCoords,
-                                                  float xCursorPosition, float yCursorPosition) {
+                                                  const PointerCoords* pointerCoords) {
     return {mReaderContext.getNextId(),
             when,
             readTime,
@@ -695,8 +642,8 @@
             pointerCoords,
             /* xPrecision= */ 1.0f,
             /* yPrecision= */ 1.0f,
-            xCursorPosition,
-            yCursorPosition,
+            /* xCursorPosition= */ 0.f,
+            /* yCursorPosition= */ 0.f,
             /* downTime= */ mDownTime,
             /* videoFrames= */ {}};
 }
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
index c8f437e..829fb92 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
@@ -20,7 +20,6 @@
 #include <list>
 #include <memory>
 
-#include <PointerControllerInterface.h>
 #include <android/input.h>
 #include <utils/Timers.h>
 
@@ -41,8 +40,7 @@
  */
 constexpr std::chrono::nanoseconds TAP_ENABLE_DELAY_NANOS = 400ms;
 
-// Converts Gesture structs from the gestures library into NotifyArgs and the appropriate
-// PointerController calls.
+// Converts Gesture structs from the gestures library into NotifyArgs.
 class GestureConverter {
 public:
     GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext,
@@ -53,7 +51,7 @@
     void setOrientation(ui::Rotation orientation) { mOrientation = orientation; }
     [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when);
 
-    void setDisplayId(std::optional<int32_t> displayId) { mDisplayId = displayId; }
+    void setDisplayId(std::optional<ui::LogicalDisplayId> displayId) { mDisplayId = displayId; }
 
     void setBoundsInLogicalDisplay(FloatRect bounds) { mBoundsInLogicalDisplay = bounds; }
 
@@ -85,18 +83,14 @@
                                                     const Gesture& gesture);
     [[nodiscard]] std::list<NotifyArgs> endPinch(nsecs_t when, nsecs_t readTime);
 
-    [[nodiscard]] std::list<NotifyArgs> enterHover(nsecs_t when, nsecs_t readTime,
-                                                   float xCursorPosition, float yCursorPosition);
-    [[nodiscard]] std::list<NotifyArgs> exitHover(nsecs_t when, nsecs_t readTime,
-                                                  float xCursorPosition, float yCursorPosition);
+    [[nodiscard]] std::list<NotifyArgs> enterHover(nsecs_t when, nsecs_t readTime);
+    [[nodiscard]] std::list<NotifyArgs> exitHover(nsecs_t when, nsecs_t readTime);
 
-    NotifyMotionArgs makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action,
-                                    float xCursorPosition, float yCursorPosition);
+    NotifyMotionArgs makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action);
 
     NotifyMotionArgs makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action,
                                     int32_t actionButton, int32_t buttonState,
-                                    uint32_t pointerCount, const PointerCoords* pointerCoords,
-                                    float xCursorPosition, float yCursorPosition);
+                                    uint32_t pointerCount, const PointerCoords* pointerCoords);
 
     void enableTapToClick(nsecs_t when);
     bool mIsHoverCancelled{false};
@@ -104,10 +98,9 @@
 
     const int32_t mDeviceId;
     InputReaderContext& mReaderContext;
-    std::shared_ptr<PointerControllerInterface> mPointerController;
     const bool mEnableFlingStop;
 
-    std::optional<int32_t> mDisplayId;
+    std::optional<ui::LogicalDisplayId> mDisplayId;
     FloatRect mBoundsInLogicalDisplay{};
     ui::Rotation mOrientation = ui::ROTATION_0;
     RawAbsoluteAxisInfo mXAxisInfo;
diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp
index c44f880..83074ff 100644
--- a/services/inputflinger/tests/CursorInputMapper_test.cpp
+++ b/services/inputflinger/tests/CursorInputMapper_test.cpp
@@ -29,7 +29,6 @@
 #include <linux/input.h>
 #include <utils/Timers.h>
 
-#include "FakePointerController.h"
 #include "InputMapperTest.h"
 #include "InputReaderBase.h"
 #include "InterfaceMocks.h"
@@ -51,8 +50,8 @@
 constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
 constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
 constexpr auto INVALID_CURSOR_POSITION = AMOTION_EVENT_INVALID_CURSOR_POSITION;
-constexpr int32_t DISPLAY_ID = 0;
-constexpr int32_t SECONDARY_DISPLAY_ID = DISPLAY_ID + 1;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
+constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
 constexpr int32_t DISPLAY_WIDTH = 480;
 constexpr int32_t DISPLAY_HEIGHT = 800;
 
@@ -157,12 +156,9 @@
         mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
     }
 
-    virtual bool isPointerChoreographerEnabled() { return false; }
-
     void createMapper() {
         createDevice();
-        mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration,
-                                                       isPointerChoreographerEnabled());
+        mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
     }
 
     void setPointerCapture(bool enabled) {
@@ -200,8 +196,6 @@
         input_flags::enable_new_mouse_pointer_ballistics(false);
         CursorInputMapperUnitTestBase::SetUp();
     }
-
-    bool isPointerChoreographerEnabled() override { return false; }
 };
 
 TEST_F(CursorInputMapperUnitTest, GetSourcesReturnsMouseInPointerMode) {
@@ -325,12 +319,9 @@
 
     // Disable pointer capture. Afterwards, events should be generated the usual way.
     setPointerCapture(false);
-    const auto expectedCoords = CursorInputMapperUnitTest::isPointerChoreographerEnabled()
-            ? WithCoords(0, 0)
-            : WithCoords(INITIAL_CURSOR_X + 10.0f, INITIAL_CURSOR_Y + 20.0f);
-    const auto expectedCursorPosition = CursorInputMapperUnitTest::isPointerChoreographerEnabled()
-            ? WithCursorPosition(INVALID_CURSOR_POSITION, INVALID_CURSOR_POSITION)
-            : WithCursorPosition(INITIAL_CURSOR_X + 10.0f, INITIAL_CURSOR_Y + 20.0f);
+    const auto expectedCoords = WithCoords(0, 0);
+    const auto expectedCursorPosition =
+            WithCursorPosition(INVALID_CURSOR_POSITION, INVALID_CURSOR_POSITION);
     args.clear();
     args += process(EV_REL, REL_X, 10);
     args += process(EV_REL, REL_Y, 20);
@@ -342,42 +333,6 @@
                               WithRelativeMotion(10.0f, 20.0f)))));
 }
 
-TEST_F(CursorInputMapperUnitTest,
-       PopulateDeviceInfoReturnsRangeFromPointerControllerInPointerMode) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    mFakePolicy->clearViewports();
-    mFakePointerController->clearBounds();
-    createMapper();
-
-    InputDeviceInfo info;
-    mMapper->populateDeviceInfo(info);
-
-    // Initially there should not be a valid motion range because there's no viewport or pointer
-    // bounds.
-    ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE));
-    ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE));
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
-                                              AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
-
-    // When the bounds are set, then there should be a valid motion range.
-    mFakePointerController->setBounds(1, 2, 800 - 1, 480 - 1);
-    mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
-    std::list<NotifyArgs> args =
-            mMapper->reconfigure(systemTime(), mReaderConfiguration,
-                                 InputReaderConfiguration::Change::DISPLAY_INFO);
-    ASSERT_THAT(args, testing::IsEmpty());
-
-    InputDeviceInfo info2;
-    mMapper->populateDeviceInfo(info2);
-
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE, 1,
-                                              800 - 1, 0.0f, 0.0f));
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE, 2,
-                                              480 - 1, 0.0f, 0.0f));
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE,
-                                              AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
-}
-
 TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsScaledRangeInNavigationMode) {
     mPropertyMap.addProperty("cursor.mode", "navigation");
     createMapper();
@@ -649,334 +604,9 @@
     ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1,  1,  1,  1));
 }
 
-TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesOrientationChanges) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    DisplayViewport viewport = createPrimaryViewport(ui::Rotation::Rotation90);
-    mFakePointerController->setDisplayViewport(viewport);
-    mReaderConfiguration.setDisplayViewports({viewport});
-    createMapper();
-
-    // Verify that the coordinates are rotated.
-    std::list<NotifyArgs> args;
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
-                              WithRelativeMotion(-20.0f, 10.0f)))));
-
-    // Enable Pointer Capture.
-    setPointerCapture(true);
-
-    // Move and verify rotation is not applied.
-    args = process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(ACTION_MOVE),
-                              WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
-                              WithCoords(10.0f, 20.0f)))));
-}
-
-TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) {
-    DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
-    DisplayViewport secondaryViewport = createSecondaryViewport();
-    mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
-    // Set up the secondary display as the display on which the pointer should be shown. The
-    // InputDevice is not associated with any display.
-    mFakePointerController->setDisplayViewport(secondaryViewport);
-    mFakePointerController->setPosition(100, 200);
-    createMapper();
-
-    // Ensure input events are generated for the secondary display.
-    std::list<NotifyArgs> args;
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
-                              WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(110.0f, 220.0f)))));
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(110.0f, 220.0f));
-}
-
-TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) {
-    DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
-    DisplayViewport secondaryViewport = createSecondaryViewport();
-    mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
-    // Set up the secondary display as the display on which the pointer should be shown.
-    mFakePointerController->setDisplayViewport(secondaryViewport);
-    mFakePointerController->setPosition(100, 200);
-    createDevice();
-    // Associate the InputDevice with the secondary display.
-    ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport);
-    mMapper = createInputMapper<
-            CursorInputMapper>(deviceContext, mReaderConfiguration,
-                               CursorInputMapperUnitTest::isPointerChoreographerEnabled());
-
-    // Ensure input events are generated for the secondary display.
-    std::list<NotifyArgs> args;
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
-                              WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(110.0f, 220.0f)))));
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(110.0f, 220.0f));
-}
-
-TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdIgnoresEventsForMismatchedPointerDisplay) {
-    DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
-    DisplayViewport secondaryViewport = createSecondaryViewport();
-    mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
-    // Set up the primary display as the display on which the pointer should be shown.
-    mFakePointerController->setDisplayViewport(primaryViewport);
-    createDevice();
-    // Associate the InputDevice with the secondary display.
-    ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport);
-    mMapper = createInputMapper<
-            CursorInputMapper>(deviceContext, mReaderConfiguration,
-                               CursorInputMapperUnitTest::isPointerChoreographerEnabled());
-
-    // The mapper should not generate any events because it is associated with a display that is
-    // different from the pointer display.
-    std::list<NotifyArgs> args;
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args, testing::IsEmpty());
-}
-
-TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleAllButtons) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
-    std::list<NotifyArgs> args;
-
-    // press BTN_LEFT, release BTN_LEFT
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f)))));
-    args.clear();
-
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 0);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f)))));
-    args.clear();
-
-    // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 1);
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 1);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
-                                                          AMOTION_EVENT_BUTTON_TERTIARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
-                                                          AMOTION_EVENT_BUTTON_TERTIARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f)))));
-    args.clear();
-
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 0);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
-                                          WithCoords(100.0f, 200.0f), WithPressure(1.0f)))));
-    args.clear();
-
-    args += process(ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithButtonState(0),
-                                          WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(100.0f, 200.0f), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithButtonState(0),
-                                          WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithCoords(100.0f, 200.0f), WithPressure(0.0f)))));
-}
-
-class CursorInputMapperButtonKeyTest
-      : public CursorInputMapperUnitTest,
-        public testing::WithParamInterface<
-                std::tuple<int32_t /*evdevCode*/, int32_t /*expectedButtonState*/,
-                           int32_t /*expectedKeyCode*/>> {
-    virtual bool isPointerChoreographerEnabled() override { return false; }
-};
-
-TEST_P(CursorInputMapperButtonKeyTest, ProcessShouldHandleButtonKey) {
-    auto [evdevCode, expectedButtonState, expectedKeyCode] = GetParam();
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
-    std::list<NotifyArgs> args;
-
-    args += process(ARBITRARY_TIME, EV_KEY, evdevCode, 1);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
-                                                             WithKeyCode(expectedKeyCode))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithButtonState(expectedButtonState),
-                                          WithCoords(100.0f, 200.0f), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithButtonState(expectedButtonState),
-                                          WithCoords(100.0f, 200.0f), WithPressure(0.0f)))));
-    args.clear();
-
-    args += process(ARBITRARY_TIME, EV_KEY, evdevCode, 0);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithButtonState(0), WithCoords(100.0f, 200.0f),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
-                                                             WithKeyCode(expectedKeyCode)))));
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        SideExtraBackAndForward, CursorInputMapperButtonKeyTest,
-        testing::Values(std::make_tuple(BTN_SIDE, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
-                        std::make_tuple(BTN_EXTRA, AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD),
-                        std::make_tuple(BTN_BACK, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
-                        std::make_tuple(BTN_FORWARD, AMOTION_EVENT_BUTTON_FORWARD,
-                                        AKEYCODE_FORWARD)));
-
-TEST_F(CursorInputMapperUnitTest, ProcessShouldMoveThePointerAroundInPointerMode) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
-    std::list<NotifyArgs> args;
-
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithSource(AINPUT_SOURCE_MOUSE),
-                              WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithCoords(110.0f, 220.0f), WithPressure(0.0f), WithSize(0.0f),
-                              WithTouchDimensions(0.0f, 0.0f), WithToolDimensions(0.0f, 0.0f),
-                              WithOrientation(0.0f), WithDistance(0.0f)))));
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(110.0f, 220.0f));
-}
-
-/**
- * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any
- * pointer acceleration or speed processing should not be applied.
- */
-TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesVelocityProcessing) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    const VelocityControlParameters testParams(/*scale=*/5.f, /*lowThreshold=*/0.f,
-                                               /*highThreshold=*/100.f, /*acceleration=*/10.f);
-    mReaderConfiguration.pointerVelocityControlParameters = testParams;
-    mFakePolicy->setVelocityControlParams(testParams);
-    createMapper();
-
-    std::list<NotifyArgs> args;
-
-    // Move and verify scale is applied.
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithSource(AINPUT_SOURCE_MOUSE),
-                              WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)))));
-    NotifyMotionArgs motionArgs = std::get<NotifyMotionArgs>(args.front());
-    const float relX = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
-    const float relY = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
-    ASSERT_GT(relX, 10);
-    ASSERT_GT(relY, 20);
-    args.clear();
-
-    // Enable Pointer Capture
-    setPointerCapture(true);
-
-    // Move and verify scale is not applied.
-    args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
-    args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
-    args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
-                              WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(10, 20)))));
-}
-
-// TODO(b/311416205): De-duplicate the test cases after the refactoring is complete and the flagging
-//   logic can be removed.
-class CursorInputMapperUnitTestWithChoreographer : public CursorInputMapperUnitTestBase {
-protected:
-    void SetUp() override {
-        input_flags::enable_new_mouse_pointer_ballistics(false);
-        CursorInputMapperUnitTestBase::SetUp();
-    }
-
-    bool isPointerChoreographerEnabled() override { return true; }
-};
-
-TEST_F(CursorInputMapperUnitTestWithChoreographer, PopulateDeviceInfoReturnsRangeFromPolicy) {
+TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsRangeFromPolicy) {
     mPropertyMap.addProperty("cursor.mode", "pointer");
     mFakePolicy->clearViewports();
-    mFakePointerController->clearBounds();
     createMapper();
 
     InputDeviceInfo info;
@@ -1009,14 +639,12 @@
                                               AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
 }
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer, ConfigureDisplayIdWithAssociatedViewport) {
+TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) {
     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
     DisplayViewport secondaryViewport = createSecondaryViewport();
     mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
     // Set up the secondary display as the display on which the pointer should be shown.
     // The InputDevice is not associated with any display.
-    mFakePointerController->setDisplayViewport(secondaryViewport);
-    mFakePointerController->setPosition(100, 200);
     createDevice();
     ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport);
     mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration);
@@ -1032,13 +660,12 @@
                               WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(0.0f, 0.0f)))));
 }
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer,
+TEST_F(CursorInputMapperUnitTest,
        ConfigureDisplayIdShouldGenerateEventForMismatchedPointerDisplay) {
     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
     DisplayViewport secondaryViewport = createSecondaryViewport();
     mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
     // Set up the primary display as the display on which the pointer should be shown.
-    mFakePointerController->setDisplayViewport(primaryViewport);
     createDevice();
     // Associate the InputDevice with the secondary display.
     ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport);
@@ -1057,13 +684,10 @@
                               WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(0.0f, 0.0f)))));
 }
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer, ProcessShouldHandleAllButtonsWithZeroCoords) {
+TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleAllButtonsWithZeroCoords) {
     mPropertyMap.addProperty("cursor.mode", "pointer");
     createMapper();
 
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
     std::list<NotifyArgs> args;
 
     // press BTN_LEFT, release BTN_LEFT
@@ -1147,21 +771,17 @@
                                           WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
 }
 
-class CursorInputMapperButtonKeyTestWithChoreographer
-      : public CursorInputMapperUnitTestWithChoreographer,
+class CursorInputMapperButtonKeyTest
+      : public CursorInputMapperUnitTest,
         public testing::WithParamInterface<
                 std::tuple<int32_t /*evdevCode*/, int32_t /*expectedButtonState*/,
                            int32_t /*expectedKeyCode*/>> {};
 
-TEST_P(CursorInputMapperButtonKeyTestWithChoreographer,
-       ProcessShouldHandleButtonKeyWithZeroCoords) {
+TEST_P(CursorInputMapperButtonKeyTest, ProcessShouldHandleButtonKeyWithZeroCoords) {
     auto [evdevCode, expectedButtonState, expectedKeyCode] = GetParam();
     mPropertyMap.addProperty("cursor.mode", "pointer");
     createMapper();
 
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
     std::list<NotifyArgs> args;
 
     args += process(ARBITRARY_TIME, EV_KEY, evdevCode, 1);
@@ -1195,20 +815,17 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        SideExtraBackAndForward, CursorInputMapperButtonKeyTestWithChoreographer,
+        SideExtraBackAndForward, CursorInputMapperButtonKeyTest,
         testing::Values(std::make_tuple(BTN_SIDE, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
                         std::make_tuple(BTN_EXTRA, AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD),
                         std::make_tuple(BTN_BACK, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
                         std::make_tuple(BTN_FORWARD, AMOTION_EVENT_BUTTON_FORWARD,
                                         AKEYCODE_FORWARD)));
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer, ProcessWhenModeIsPointerShouldKeepZeroCoords) {
+TEST_F(CursorInputMapperUnitTest, ProcessWhenModeIsPointerShouldKeepZeroCoords) {
     mPropertyMap.addProperty("cursor.mode", "pointer");
     createMapper();
 
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(100, 200);
-
     std::list<NotifyArgs> args;
 
     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
@@ -1223,7 +840,11 @@
                               WithOrientation(0.0f), WithDistance(0.0f)))));
 }
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer, PointerCaptureDisablesVelocityProcessing) {
+/**
+ * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any
+ * pointer acceleration or speed processing should not be applied.
+ */
+TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesVelocityProcessing) {
     mPropertyMap.addProperty("cursor.mode", "pointer");
     const VelocityControlParameters testParams(/*scale=*/5.f, /*lowThreshold=*/0.f,
                                                /*highThreshold=*/100.f, /*acceleration=*/10.f);
@@ -1267,7 +888,7 @@
     ASSERT_EQ(20, relY2);
 }
 
-TEST_F(CursorInputMapperUnitTestWithChoreographer, ConfigureDisplayIdNoAssociatedViewport) {
+TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) {
     // Set up the default display.
     mFakePolicy->clearViewports();
     mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
@@ -1279,9 +900,6 @@
 
     createMapper();
 
-    mFakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
-    mFakePointerController->setPosition(100, 200);
-
     // Ensure input events are generated without display ID or coords, because they will be decided
     // later by PointerChoreographer.
     std::list<NotifyArgs> args;
@@ -1291,7 +909,8 @@
     EXPECT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithSource(AINPUT_SOURCE_MOUSE), WithDisplayId(ADISPLAY_ID_NONE),
+                              WithSource(AINPUT_SOURCE_MOUSE),
+                              WithDisplayId(ui::LogicalDisplayId::INVALID),
                               WithCoords(0.0f, 0.0f)))));
 }
 
@@ -1302,8 +921,6 @@
         input_flags::enable_new_mouse_pointer_ballistics(true);
         CursorInputMapperUnitTestBase::SetUp();
     }
-
-    bool isPointerChoreographerEnabled() override { return true; }
 };
 
 TEST_F(CursorInputMapperUnitTestWithNewBallistics, PointerCaptureDisablesVelocityProcessing) {
@@ -1422,14 +1039,11 @@
 
 } // namespace
 
+// --- BluetoothCursorInputMapperUnitTest ---
+
 class BluetoothCursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
 protected:
-    void SetUp() override {
-        SetUpWithBus(BUS_BLUETOOTH);
-
-        mFakePointerController = std::make_shared<FakePointerController>();
-        mFakePolicy->setPointerController(mFakePointerController);
-    }
+    void SetUp() override { SetUpWithBus(BUS_BLUETOOTH); }
 };
 
 TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmoothening) {
@@ -1537,123 +1151,4 @@
     argsList.clear();
 }
 
-// --- BluetoothCursorInputMapperUnitTestWithChoreographer ---
-
-class BluetoothCursorInputMapperUnitTestWithChoreographer : public CursorInputMapperUnitTestBase {
-protected:
-    void SetUp() override {
-        SetUpWithBus(BUS_BLUETOOTH);
-
-        mFakePointerController = std::make_shared<FakePointerController>();
-        mFakePolicy->setPointerController(mFakePointerController);
-    }
-
-    bool isPointerChoreographerEnabled() override { return true; }
-};
-
-TEST_F(BluetoothCursorInputMapperUnitTestWithChoreographer, TimestampSmoothening) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-    std::list<NotifyArgs> argsList;
-
-    nsecs_t kernelEventTime = ARBITRARY_TIME;
-    nsecs_t expectedEventTime = ARBITRARY_TIME;
-    argsList += process(kernelEventTime, EV_REL, REL_X, 1);
-    argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(argsList,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithEventTime(expectedEventTime)))));
-    argsList.clear();
-
-    // Process several events that come in quick succession, according to their timestamps.
-    for (int i = 0; i < 3; i++) {
-        constexpr static nsecs_t delta = ms2ns(1);
-        static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
-        kernelEventTime += delta;
-        expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
-
-        argsList += process(kernelEventTime, EV_REL, REL_X, 1);
-        argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
-        EXPECT_THAT(argsList,
-                    ElementsAre(VariantWith<NotifyMotionArgs>(
-                            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                  WithEventTime(expectedEventTime)))));
-        argsList.clear();
-    }
-}
-
-TEST_F(BluetoothCursorInputMapperUnitTestWithChoreographer, TimestampSmootheningIsCapped) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-    std::list<NotifyArgs> argsList;
-
-    nsecs_t expectedEventTime = ARBITRARY_TIME;
-    argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
-    argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(argsList,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithEventTime(expectedEventTime)))));
-    argsList.clear();
-
-    // Process several events with the same timestamp from the kernel.
-    // Ensure that we do not generate events too far into the future.
-    constexpr static int32_t numEvents =
-            MAX_BLUETOOTH_SMOOTHING_DELTA / MIN_BLUETOOTH_TIMESTAMP_DELTA;
-    for (int i = 0; i < numEvents; i++) {
-        expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
-
-        argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
-        argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-        EXPECT_THAT(argsList,
-                    ElementsAre(VariantWith<NotifyMotionArgs>(
-                            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                  WithEventTime(expectedEventTime)))));
-        argsList.clear();
-    }
-
-    // By processing more events with the same timestamp, we should not generate events with a
-    // timestamp that is more than the specified max time delta from the timestamp at its injection.
-    const nsecs_t cappedEventTime = ARBITRARY_TIME + MAX_BLUETOOTH_SMOOTHING_DELTA;
-    for (int i = 0; i < 3; i++) {
-        argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
-        argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-        EXPECT_THAT(argsList,
-                    ElementsAre(VariantWith<NotifyMotionArgs>(
-                            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                  WithEventTime(cappedEventTime)))));
-        argsList.clear();
-    }
-}
-
-TEST_F(BluetoothCursorInputMapperUnitTestWithChoreographer, TimestampSmootheningNotUsed) {
-    mPropertyMap.addProperty("cursor.mode", "pointer");
-    createMapper();
-    std::list<NotifyArgs> argsList;
-
-    nsecs_t kernelEventTime = ARBITRARY_TIME;
-    nsecs_t expectedEventTime = ARBITRARY_TIME;
-    argsList += process(kernelEventTime, EV_REL, REL_X, 1);
-    argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(argsList,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithEventTime(expectedEventTime)))));
-    argsList.clear();
-
-    // If the next event has a timestamp that is sufficiently spaced out so that Bluetooth timestamp
-    // smoothening is not needed, its timestamp is not affected.
-    kernelEventTime += MAX_BLUETOOTH_SMOOTHING_DELTA + ms2ns(1);
-    expectedEventTime = kernelEventTime;
-
-    argsList += process(kernelEventTime, EV_REL, REL_X, 1);
-    argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
-    EXPECT_THAT(argsList,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithEventTime(expectedEventTime)))));
-    argsList.clear();
-}
-
 } // namespace android
diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
index 36491ab..530416c 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
@@ -396,8 +396,8 @@
     }
 }
 
-void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t,
-                                                              uint32_t&) {}
+void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t,
+                                                              int32_t, nsecs_t, uint32_t&) {}
 
 nsecs_t FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&,
                                                                  const KeyEvent&, uint32_t) {
@@ -426,7 +426,7 @@
 }
 
 void FakeInputDispatcherPolicy::pokeUserActivity(nsecs_t eventTime, int32_t eventType,
-                                                 int32_t displayId) {
+                                                 ui::LogicalDisplayId displayId) {
     std::scoped_lock lock(mLock);
     mNotifyUserActivity.notify_all();
     mUserActivityPokeEvents.push({eventTime, eventType, displayId});
diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.h b/services/inputflinger/tests/FakeInputDispatcherPolicy.h
index 25d3d3c..2c86146 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.h
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.h
@@ -53,7 +53,7 @@
     struct UserActivityPokeEvent {
         nsecs_t eventTime;
         int32_t eventType;
-        int32_t displayId;
+        ui::LogicalDisplayId displayId;
 
         bool operator==(const UserActivityPokeEvent& rhs) const = default;
         inline friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
@@ -183,13 +183,15 @@
     void notifyVibratorState(int32_t deviceId, bool isOn) override;
     bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override;
     void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override;
-    void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override;
+    void interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t, int32_t, nsecs_t,
+                                       uint32_t&) override;
     nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override;
     std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
                                                  uint32_t) override;
     void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
                       uint32_t policyFlags) override;
-    void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override;
+    void pokeUserActivity(nsecs_t eventTime, int32_t eventType,
+                          ui::LogicalDisplayId displayId) override;
     bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override;
     void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override;
     void setPointerCapture(const PointerCaptureRequest& request) override;
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index e9118a9..d2cb0ac 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -82,9 +82,9 @@
     mConfig.setDisplayViewports(mViewports);
 }
 
-void FakeInputReaderPolicy::addDisplayViewport(int32_t displayId, int32_t width, int32_t height,
-                                               ui::Rotation orientation, bool isActive,
-                                               const std::string& uniqueId,
+void FakeInputReaderPolicy::addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width,
+                                               int32_t height, ui::Rotation orientation,
+                                               bool isActive, const std::string& uniqueId,
                                                std::optional<uint8_t> physicalPort,
                                                ViewportType type) {
     const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
@@ -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,
@@ -155,11 +155,6 @@
     mConfig.disabledDevices.erase(deviceId);
 }
 
-void FakeInputReaderPolicy::setPointerController(
-        std::shared_ptr<FakePointerController> controller) {
-    mPointerController = std::move(controller);
-}
-
 const InputReaderConfiguration& FakeInputReaderPolicy::getReaderConfiguration() const {
     return mConfig;
 }
@@ -183,11 +178,7 @@
     return mConfig.pointerCaptureRequest;
 }
 
-void FakeInputReaderPolicy::setShowTouches(bool enabled) {
-    mConfig.showTouches = enabled;
-}
-
-void FakeInputReaderPolicy::setDefaultPointerDisplayId(int32_t pointerDisplayId) {
+void FakeInputReaderPolicy::setDefaultPointerDisplayId(ui::LogicalDisplayId pointerDisplayId) {
     mConfig.defaultPointerDisplayId = pointerDisplayId;
 }
 
@@ -228,11 +219,6 @@
     *outConfig = mConfig;
 }
 
-std::shared_ptr<PointerControllerInterface> FakeInputReaderPolicy::obtainPointerController(
-        int32_t /*deviceId*/) {
-    return mPointerController;
-}
-
 void FakeInputReaderPolicy::notifyInputDevicesChanged(
         const std::vector<InputDeviceInfo>& inputDevices) {
     std::scoped_lock lock(mLock);
@@ -269,8 +255,8 @@
 }
 
 std::optional<DisplayViewport> FakeInputReaderPolicy::getPointerViewportForAssociatedDisplay(
-        int32_t associatedDisplayId) {
-    if (associatedDisplayId == ADISPLAY_ID_NONE) {
+        ui::LogicalDisplayId associatedDisplayId) {
+    if (!associatedDisplayId.isValid()) {
         associatedDisplayId = mConfig.defaultPointerDisplayId;
     }
     for (auto& viewport : mViewports) {
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 710bb54..94f1311 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -26,7 +26,6 @@
 #include <InputDevice.h>
 #include <InputReaderBase.h>
 
-#include "FakePointerController.h"
 #include "input/DisplayViewport.h"
 #include "input/InputDevice.h"
 
@@ -49,7 +48,7 @@
     std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
     std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const;
     void addDisplayViewport(DisplayViewport viewport);
-    void addDisplayViewport(int32_t displayId, int32_t width, int32_t height,
+    void addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
                             ui::Rotation orientation, bool isActive, const std::string& uniqueId,
                             std::optional<uint8_t> physicalPort, ViewportType type);
     bool updateViewport(const DisplayViewport& viewport);
@@ -62,15 +61,13 @@
                                       const KeyboardLayoutInfo& layoutInfo);
     void addDisabledDevice(int32_t deviceId);
     void removeDisabledDevice(int32_t deviceId);
-    void setPointerController(std::shared_ptr<FakePointerController> controller);
     const InputReaderConfiguration& getReaderConfiguration() const;
     const std::vector<InputDeviceInfo> getInputDevices() const;
     TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
                                                            ui::Rotation surfaceRotation);
     void setTouchAffineTransformation(const TouchAffineTransformation t);
     PointerCaptureRequest setPointerCapture(const sp<IBinder>& window);
-    void setShowTouches(bool enabled);
-    void setDefaultPointerDisplayId(int32_t pointerDisplayId);
+    void setDefaultPointerDisplayId(ui::LogicalDisplayId pointerDisplayId);
     void setPointerGestureEnabled(bool enabled);
     float getPointerGestureMovementSpeedRatio();
     float getPointerGestureZoomSpeedRatio();
@@ -80,12 +77,10 @@
     void setIsInputMethodConnectionActive(bool active);
     bool isInputMethodConnectionActive() override;
     std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
-            int32_t associatedDisplayId) override;
+            ui::LogicalDisplayId associatedDisplayId) override;
 
 private:
     void getReaderConfiguration(InputReaderConfiguration* outConfig) override;
-    std::shared_ptr<PointerControllerInterface> obtainPointerController(
-            int32_t /*deviceId*/) override;
     void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
     std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
             const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) override;
@@ -97,7 +92,6 @@
     std::condition_variable mDevicesChangedCondition;
 
     InputReaderConfiguration mConfig;
-    std::shared_ptr<FakePointerController> mPointerController;
     std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
     bool mInputDevicesChanged GUARDED_BY(mLock){false};
     std::vector<DisplayViewport> mViewports;
diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp
index dc199e2..2bb57b3 100644
--- a/services/inputflinger/tests/FakePointerController.cpp
+++ b/services/inputflinger/tests/FakePointerController.cpp
@@ -32,7 +32,7 @@
     mHaveBounds = false;
 }
 
-const std::map<int32_t, std::vector<int32_t>>& FakePointerController::getSpots() {
+const std::map<ui::LogicalDisplayId, std::vector<int32_t>>& FakePointerController::getSpots() {
     return mSpotsByDisplay;
 }
 
@@ -51,9 +51,9 @@
     return {mX, mY};
 }
 
-int32_t FakePointerController::getDisplayId() const {
+ui::LogicalDisplayId FakePointerController::getDisplayId() const {
     if (!mEnabled || !mDisplayId) {
-        return ADISPLAY_ID_NONE;
+        return ui::LogicalDisplayId::INVALID;
     }
     return *mDisplayId;
 }
@@ -76,7 +76,15 @@
     mCustomIconStyle = icon.style;
 }
 
-void FakePointerController::assertViewportSet(int32_t displayId) {
+void FakePointerController::setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) {
+    if (skip) {
+        mDisplaysToSkipScreenshot.insert(displayId);
+    } else {
+        mDisplaysToSkipScreenshot.erase(displayId);
+    }
+};
+
+void FakePointerController::assertViewportSet(ui::LogicalDisplayId displayId) {
     ASSERT_TRUE(mDisplayId);
     ASSERT_EQ(displayId, mDisplayId);
 }
@@ -91,7 +99,7 @@
     ASSERT_NEAR(y, actualY, 1);
 }
 
-void FakePointerController::assertSpotCount(int32_t displayId, int32_t count) {
+void FakePointerController::assertSpotCount(ui::LogicalDisplayId displayId, int32_t count) {
     auto it = mSpotsByDisplay.find(displayId);
     ASSERT_TRUE(it != mSpotsByDisplay.end()) << "Spots not found for display " << displayId;
     ASSERT_EQ(static_cast<size_t>(count), it->second.size());
@@ -117,6 +125,15 @@
     ASSERT_EQ(std::nullopt, mCustomIconStyle);
 }
 
+void FakePointerController::assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId,
+                                                             bool isHidden) {
+    if (isHidden) {
+        ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) != mDisplaysToSkipScreenshot.end());
+    } else {
+        ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) == mDisplaysToSkipScreenshot.end());
+    }
+}
+
 bool FakePointerController::isPointerShown() {
     return mIsPointerShown;
 }
@@ -150,7 +167,7 @@
 }
 
 void FakePointerController::setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
-                                     int32_t displayId) {
+                                     ui::LogicalDisplayId displayId) {
     if (!mEnabled) return;
 
     std::vector<int32_t> newSpots;
diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h
index 536b447..5bc713f 100644
--- a/services/inputflinger/tests/FakePointerController.h
+++ b/services/inputflinger/tests/FakePointerController.h
@@ -17,10 +17,10 @@
 #pragma once
 
 #include <PointerControllerInterface.h>
-#include <gui/constants.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <utils/BitSet.h>
+#include <unordered_set>
 
 namespace android {
 
@@ -37,24 +37,26 @@
 
     void setBounds(float minX, float minY, float maxX, float maxY);
     void clearBounds();
-    const std::map<int32_t, std::vector<int32_t>>& getSpots();
+    const std::map<ui::LogicalDisplayId, std::vector<int32_t>>& getSpots();
 
     void setPosition(float x, float y) override;
     FloatPoint getPosition() const override;
-    int32_t getDisplayId() const override;
+    ui::LogicalDisplayId getDisplayId() const override;
     void setDisplayViewport(const DisplayViewport& viewport) override;
     void updatePointerIcon(PointerIconStyle iconId) override;
     void setCustomPointerIcon(const SpriteIcon& icon) override;
+    void setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) override;
     void fade(Transition) override;
 
-    void assertViewportSet(int32_t displayId);
+    void assertViewportSet(ui::LogicalDisplayId displayId);
     void assertViewportNotSet();
     void assertPosition(float x, float y);
-    void assertSpotCount(int32_t displayId, int32_t count);
+    void assertSpotCount(ui::LogicalDisplayId displayId, int32_t count);
     void assertPointerIconSet(PointerIconStyle iconId);
     void assertPointerIconNotSet();
     void assertCustomPointerIconSet(PointerIconStyle iconId);
     void assertCustomPointerIconNotSet();
+    void assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId, bool isHidden);
     bool isPointerShown();
 
 private:
@@ -64,19 +66,20 @@
     void unfade(Transition) override;
     void setPresentation(Presentation) override {}
     void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
-                  int32_t displayId) override;
+                  ui::LogicalDisplayId displayId) override;
     void clearSpots() override;
 
     const bool mEnabled;
     bool mHaveBounds{false};
     float mMinX{0}, mMinY{0}, mMaxX{0}, mMaxY{0};
     float mX{0}, mY{0};
-    std::optional<int32_t> mDisplayId;
+    std::optional<ui::LogicalDisplayId> mDisplayId;
     bool mIsPointerShown{false};
     std::optional<PointerIconStyle> mIconStyle;
     std::optional<PointerIconStyle> mCustomIconStyle;
 
-    std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
+    std::map<ui::LogicalDisplayId, std::vector<int32_t>> mSpotsByDisplay;
+    std::unordered_set<ui::LogicalDisplayId> mDisplaysToSkipScreenshot;
 };
 
 } // namespace android
diff --git a/services/inputflinger/tests/FakeWindows.cpp b/services/inputflinger/tests/FakeWindows.cpp
index a6955ec..b116521 100644
--- a/services/inputflinger/tests/FakeWindows.cpp
+++ b/services/inputflinger/tests/FakeWindows.cpp
@@ -81,7 +81,7 @@
 }
 
 void FakeInputReceiver::consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
-                                     std::optional<int32_t> expectedDisplayId,
+                                     std::optional<ui::LogicalDisplayId> expectedDisplayId,
                                      std::optional<int32_t> expectedFlags) {
     std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
 
@@ -152,7 +152,7 @@
     ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
     ASSERT_EQ(InputEventType::FOCUS, event->getType()) << "Instead of FocusEvent, got " << *event;
 
-    ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
             << mName.c_str() << ": event displayId should always be NONE.";
 
     FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
@@ -165,7 +165,7 @@
     ASSERT_EQ(InputEventType::CAPTURE, event->getType())
             << "Instead of CaptureEvent, got " << *event;
 
-    ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
             << mName.c_str() << ": event displayId should always be NONE.";
 
     const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
@@ -177,7 +177,7 @@
     ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
     ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
 
-    EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
+    EXPECT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
             << mName.c_str() << ": event displayId should always be NONE.";
 
     const auto& dragEvent = static_cast<const DragEvent&>(*event);
@@ -192,7 +192,7 @@
     ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
             << "Instead of TouchModeEvent, got " << *event;
 
-    ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
             << mName.c_str() << ": event displayId should always be NONE.";
     const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
     EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
@@ -244,7 +244,7 @@
 FakeWindowHandle::FakeWindowHandle(
         const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
         const std::unique_ptr<inputdispatcher::InputDispatcher>& dispatcher, const std::string name,
-        int32_t displayId, bool createInputChannel)
+        ui::LogicalDisplayId displayId, bool createInputChannel)
       : mName(name) {
     sp<IBinder> token;
     if (createInputChannel) {
@@ -272,7 +272,7 @@
     mInfo.inputConfig = InputConfig::DEFAULT;
 }
 
-sp<FakeWindowHandle> FakeWindowHandle::clone(int32_t displayId) {
+sp<FakeWindowHandle> FakeWindowHandle::clone(ui::LogicalDisplayId displayId) {
     sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
     handle->mInfo = mInfo;
     handle->mInfo.displayId = displayId;
diff --git a/services/inputflinger/tests/FakeWindows.h b/services/inputflinger/tests/FakeWindows.h
index 26c2b4b..36a8f00 100644
--- a/services/inputflinger/tests/FakeWindows.h
+++ b/services/inputflinger/tests/FakeWindows.h
@@ -79,7 +79,7 @@
     void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);
 
     void consumeEvent(android::InputEventType expectedEventType, int32_t expectedAction,
-                      std::optional<int32_t> expectedDisplayId,
+                      std::optional<ui::LogicalDisplayId> expectedDisplayId,
                       std::optional<int32_t> expectedFlags);
 
     std::unique_ptr<MotionEvent> consumeMotion();
@@ -119,9 +119,10 @@
 
     FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
                      const std::unique_ptr<inputdispatcher::InputDispatcher>& dispatcher,
-                     const std::string name, int32_t displayId, bool createInputChannel = true);
+                     const std::string name, ui::LogicalDisplayId displayId,
+                     bool createInputChannel = true);
 
-    sp<FakeWindowHandle> clone(int32_t displayId);
+    sp<FakeWindowHandle> clone(ui::LogicalDisplayId displayId);
 
     inline void setTouchable(bool touchable) {
         mInfo.setInputConfig(InputConfig::NOT_TOUCHABLE, !touchable);
@@ -164,7 +165,7 @@
             using namespace ftl::flag_operators;
             mInfo.layoutParamsFlags &= ~gui::WindowInfo::Flag::SECURE;
         }
-        mInfo.setInputConfig(InputConfig::SENSITIVE_FOR_TRACING, secure);
+        mInfo.setInputConfig(InputConfig::SENSITIVE_FOR_PRIVACY, secure);
     }
 
     inline void setInterceptsStylus(bool interceptsStylus) {
@@ -249,37 +250,41 @@
         return keyEvent;
     }
 
-    inline void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    inline void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
     }
 
-    inline void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    inline void consumeKeyUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
     }
 
-    inline void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                    int32_t expectedFlags = 0) {
+    inline void consumeMotionCancel(
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
                                           WithDisplayId(expectedDisplayId),
                                           WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
     }
 
-    inline void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                  int32_t expectedFlags = 0) {
+    inline void consumeMotionMove(
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                                           WithDisplayId(expectedDisplayId),
                                           WithFlags(expectedFlags)));
     }
 
-    inline void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                  int32_t expectedFlags = 0) {
+    inline void consumeMotionDown(
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         consumeAnyMotionDown(expectedDisplayId, expectedFlags);
     }
 
-    inline void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
-                                     std::optional<int32_t> expectedFlags = std::nullopt) {
+    inline void consumeAnyMotionDown(
+            std::optional<ui::LogicalDisplayId> expectedDisplayId = std::nullopt,
+            std::optional<int32_t> expectedFlags = std::nullopt) {
         consumeMotionEvent(
                 testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                                testing::Conditional(expectedDisplayId.has_value(),
@@ -288,9 +293,10 @@
                                                     WithFlags(*expectedFlags), testing::_)));
     }
 
-    inline void consumeMotionPointerDown(int32_t pointerIdx,
-                                         int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                         int32_t expectedFlags = 0) {
+    inline void consumeMotionPointerDown(
+            int32_t pointerIdx,
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
         consumeMotionEvent(testing::AllOf(WithMotionAction(action),
@@ -298,9 +304,10 @@
                                           WithFlags(expectedFlags)));
     }
 
-    inline void consumeMotionPointerUp(int32_t pointerIdx,
-                                       int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                       int32_t expectedFlags = 0) {
+    inline void consumeMotionPointerUp(
+            int32_t pointerIdx,
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
         consumeMotionEvent(testing::AllOf(WithMotionAction(action),
@@ -308,15 +315,17 @@
                                           WithFlags(expectedFlags)));
     }
 
-    inline void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                int32_t expectedFlags = 0) {
+    inline void consumeMotionUp(
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                                           WithDisplayId(expectedDisplayId),
                                           WithFlags(expectedFlags)));
     }
 
-    inline void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
-                                     int32_t expectedFlags = 0) {
+    inline void consumeMotionOutside(
+            ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
+            int32_t expectedFlags = 0) {
         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
                                           WithDisplayId(expectedDisplayId),
                                           WithFlags(expectedFlags)));
diff --git a/services/inputflinger/tests/FocusResolver_test.cpp b/services/inputflinger/tests/FocusResolver_test.cpp
index cb8c3cb..f794da5 100644
--- a/services/inputflinger/tests/FocusResolver_test.cpp
+++ b/services/inputflinger/tests/FocusResolver_test.cpp
@@ -74,7 +74,7 @@
     std::optional<FocusResolver::FocusChanges> changes =
             focusResolver.setFocusedWindow(request, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ focusableWindowToken);
-    ASSERT_EQ(request.displayId, changes->displayId);
+    ASSERT_EQ(ui::LogicalDisplayId{request.displayId}, changes->displayId);
 
     // invisible window cannot get focused
     request.token = invisibleWindowToken;
@@ -169,19 +169,20 @@
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ focusableWindowToken);
 
     // The mirror window now comes on top, and the focus does not change
-    changes = focusResolver.setInputWindows(request.displayId, {mirror, window});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId},
+                                            {mirror, window});
     ASSERT_FALSE(changes.has_value());
 
     // The window now comes on top while the mirror is removed, and the focus does not change
-    changes = focusResolver.setInputWindows(request.displayId, {window});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, {window});
     ASSERT_FALSE(changes.has_value());
 
     // The window is removed but the mirror is on top, and focus does not change
-    changes = focusResolver.setInputWindows(request.displayId, {mirror});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, {mirror});
     ASSERT_FALSE(changes.has_value());
 
     // All windows removed
-    changes = focusResolver.setInputWindows(request.displayId, {});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, {});
     ASSERT_FOCUS_CHANGE(changes, /*from*/ focusableWindowToken, /*to*/ nullptr);
 }
 
@@ -203,12 +204,12 @@
     ASSERT_EQ(focusableWindowToken, changes->newFocus);
 
     // When there are no changes to the window, focus does not change
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FALSE(changes.has_value());
 
     // Window visibility changes and the window loses focus
     window->setVisible(false);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ focusableWindowToken, /*to*/ nullptr);
 }
 
@@ -232,7 +233,7 @@
 
     // Window visibility changes and the window gets focused
     invisibleWindow->setVisible(true);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ invisibleWindowToken);
 }
 
@@ -256,25 +257,25 @@
 
     // Focusability changes and the window gets focused
     window->setFocusable(true);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
 
     // Visibility changes and the window loses focus
     window->setVisible(false);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ windowToken, /*to*/ nullptr);
 
     // Visibility changes and the window gets focused
     window->setVisible(true);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
 
     // Window is gone and the window loses focus
-    changes = focusResolver.setInputWindows(request.displayId, {});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, {});
     ASSERT_FOCUS_CHANGE(changes, /*from*/ windowToken, /*to*/ nullptr);
 
     // Window returns and the window gains focus
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
 }
 
@@ -307,27 +308,27 @@
 
     // Embedded is now focusable so will gain focus
     embeddedWindow->setFocusable(true);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ hostWindowToken, /*to*/ embeddedWindowToken);
 
     // Embedded is not visible so host will get focus
     embeddedWindow->setVisible(false);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ embeddedWindowToken, /*to*/ hostWindowToken);
 
     // Embedded is now visible so will get focus
     embeddedWindow->setVisible(true);
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ hostWindowToken, /*to*/ embeddedWindowToken);
 
     // Remove focusTransferTarget from host. Host will gain focus.
     hostWindow->editInfo()->focusTransferTarget = nullptr;
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ embeddedWindowToken, /*to*/ hostWindowToken);
 
     // Set invalid token for focusTransferTarget. Host will remain focus
     hostWindow->editInfo()->focusTransferTarget = sp<BBinder>::make();
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FALSE(changes);
 }
 
@@ -415,16 +416,16 @@
     std::optional<FocusResolver::FocusChanges> changes =
             focusResolver.setFocusedWindow(request, windows);
     ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
-    ASSERT_EQ(request.displayId, changes->displayId);
+    ASSERT_EQ(ui::LogicalDisplayId{request.displayId}, changes->displayId);
 
     // When a display is removed, all windows are removed from the display
     // and our focused window loses focus
-    changes = focusResolver.setInputWindows(request.displayId, {});
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, {});
     ASSERT_FOCUS_CHANGE(changes, /*from*/ windowToken, /*to*/ nullptr);
-    focusResolver.displayRemoved(request.displayId);
+    focusResolver.displayRemoved(ui::LogicalDisplayId{request.displayId});
 
     // When a display is re-added, the window does not get focus since the request was cleared.
-    changes = focusResolver.setInputWindows(request.displayId, windows);
+    changes = focusResolver.setInputWindows(ui::LogicalDisplayId{request.displayId}, windows);
     ASSERT_FALSE(changes);
 }
 
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index 6a009b2..d0cd677 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -20,7 +20,6 @@
 #include <flag_macros.h>
 #include <gestures/GestureConverter.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 
 #include "FakeEventHub.h"
 #include "FakeInputReaderPolicy.h"
@@ -51,13 +50,11 @@
 using testing::ElementsAre;
 using testing::VariantWith;
 
-class GestureConverterTestBase : public testing::Test {
+class GestureConverterTest : public testing::Test {
 protected:
     static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
     static constexpr int32_t EVENTHUB_ID = 1;
     static constexpr stime_t ARBITRARY_GESTURE_TIME = 1.2;
-    static constexpr float POINTER_X = 500;
-    static constexpr float POINTER_Y = 200;
 
     void SetUp() {
         mFakeEventHub = std::make_unique<FakeEventHub>();
@@ -68,12 +65,6 @@
         mDevice = newDevice();
         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, -500, 500, 0, 0, 20);
         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, -500, 500, 0, 0, 20);
-
-        mFakePointerController = std::make_shared<FakePointerController>(
-                /*enabled=*/!input_flags::enable_pointer_choreographer());
-        mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-        mFakePointerController->setPosition(POINTER_X, POINTER_Y);
-        mFakePolicy->setPointerController(mFakePointerController);
     }
 
     std::shared_ptr<InputDevice> newDevice() {
@@ -96,21 +87,12 @@
     std::unique_ptr<TestInputListener> mFakeListener;
     std::unique_ptr<InstrumentedInputReader> mReader;
     std::shared_ptr<InputDevice> mDevice;
-    std::shared_ptr<FakePointerController> mFakePointerController;
-};
-
-class GestureConverterTest : public GestureConverterTestBase {
-protected:
-    void SetUp() override {
-        input_flags::enable_pointer_choreographer(false);
-        GestureConverterTestBase::SetUp();
-    }
 };
 
 TEST_F(GestureConverterTest, Move) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
     std::list<NotifyArgs> args =
@@ -118,38 +100,31 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
                                           WithRelativeMotion(0, 0))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithCoords(POINTER_X - 5, POINTER_Y + 10),
                                           WithRelativeMotion(-5, 10), WithButtonState(0),
                                           WithPressure(0.0f)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X - 5, POINTER_Y + 10));
-
-    // The same gesture again should only repeat the HOVER_MOVE and cursor position change, not the
-    // HOVER_ENTER.
+    // The same gesture again should only repeat the HOVER_MOVE, not the HOVER_ENTER.
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                              WithCoords(POINTER_X - 10, POINTER_Y + 20),
+                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithCoords(0, 0),
                               WithRelativeMotion(-5, 10), WithToolType(ToolType::FINGER),
                               WithButtonState(0), WithPressure(0.0f),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X - 10, POINTER_Y + 20));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Move_Rotated) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
     converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
     std::list<NotifyArgs> args =
@@ -157,24 +132,21 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
                                           WithRelativeMotion(0, 0))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithCoords(POINTER_X + 10, POINTER_Y + 5),
                                           WithRelativeMotion(10, 5), WithButtonState(0),
                                           WithPressure(0.0f)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X + 10, POINTER_Y + 5));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ButtonsChange) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     // Press left and right buttons at once
     Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
@@ -197,9 +169,9 @@
                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
                                                           AMOTION_EVENT_BUTTON_SECONDARY)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Then release the left button
     Gesture leftUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
@@ -210,9 +182,9 @@
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                               WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                              WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY),
-                              WithCoords(POINTER_X, POINTER_Y), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY), WithCoords(0, 0),
+                              WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Finally release the right button
     Gesture rightUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
@@ -228,16 +200,15 @@
                             VariantWith<NotifyMotionArgs>(
                                     WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithButtonState(0),
-                                                         WithCoords(POINTER_X, POINTER_Y),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithButtonState(0), WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ButtonDownAfterMoveExitsHover) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
     std::list<NotifyArgs> args =
@@ -250,14 +221,14 @@
     ASSERT_THAT(args.front(),
                 VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT), WithButtonState(0),
-                              WithCoords(POINTER_X - 5, POINTER_Y + 10),
-                              WithToolType(ToolType::FINGER), WithDisplayId(ADISPLAY_ID_DEFAULT))));
+                              WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT))));
 }
 
 TEST_F(GestureConverterTest, DragWithButton) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     // Press the button
     Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
@@ -274,22 +245,19 @@
                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Move
     Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                              WithCoords(POINTER_X - 5, POINTER_Y + 10), WithRelativeMotion(-5, 10),
-                              WithToolType(ToolType::FINGER),
+                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(0, 0),
+                              WithRelativeMotion(-5, 10), WithToolType(ToolType::FINGER),
                               WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithPressure(1.0f),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X - 5, POINTER_Y + 10));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Release the button
     Gesture upGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
@@ -305,17 +273,16 @@
                             VariantWith<NotifyMotionArgs>(
                                     WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithButtonState(0),
-                                                         WithCoords(POINTER_X - 5, POINTER_Y + 10),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithButtonState(0), WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Scroll) {
     const nsecs_t downTime = 12345;
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     std::list<NotifyArgs> args =
@@ -323,31 +290,30 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithGestureScrollDistance(0, 0, EPSILON),
                                           WithDownTime(downTime))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                          WithCoords(POINTER_X, POINTER_Y - 10),
+                                          WithCoords(0, -10),
                                           WithGestureScrollDistance(0, 10, EPSILON)))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
                               WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE),
                               WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                              WithCoords(POINTER_X, POINTER_Y - 15),
+                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(0, -15),
                               WithGestureScrollDistance(0, 5, EPSILON),
                               WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
                               WithToolType(ToolType::FINGER),
                               WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
                          GESTURES_FLING_START);
@@ -355,18 +321,19 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(POINTER_X, POINTER_Y - 15),
+                                          WithCoords(0, -15),
                                           WithGestureScrollDistance(0, 0, EPSILON),
                                           WithMotionClassification(
                                                   MotionClassification::TWO_FINGER_SWIPE),
                                           WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Scroll_Rotated) {
@@ -374,7 +341,7 @@
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
     converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     std::list<NotifyArgs> args =
@@ -382,52 +349,53 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithGestureScrollDistance(0, 0, EPSILON),
                                           WithDownTime(downTime))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                          WithCoords(POINTER_X - 10, POINTER_Y),
+                                          WithCoords(-10, 0),
                                           WithGestureScrollDistance(0, 10, EPSILON)))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
                               WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                              WithCoords(POINTER_X - 15, POINTER_Y),
+                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(-15, 0),
                               WithGestureScrollDistance(0, 5, EPSILON),
                               WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
                               WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
+
     Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
                          GESTURES_FLING_START);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(POINTER_X - 15, POINTER_Y),
+                                          WithCoords(-15, 0),
                                           WithGestureScrollDistance(0, 0, EPSILON),
                                           WithMotionClassification(
                                                   MotionClassification::TWO_FINGER_SWIPE))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Scroll_ClearsClassificationAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     std::list<NotifyArgs> args =
@@ -445,13 +413,13 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::NONE),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Scroll_ClearsScrollDistanceAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     std::list<NotifyArgs> args =
@@ -473,10 +441,47 @@
     EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()), WithGestureScrollDistance(0, 0, EPSILON));
 }
 
+TEST_F(GestureConverterTest, Scroll_ClearsFakeFingerPositionOnSubsequentScrollGestures) {
+    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
+    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+
+    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 15, -10);
+    std::list<NotifyArgs> args =
+            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
+
+    Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -2, -5);
+    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
+
+    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
+                         GESTURES_FLING_START);
+    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
+    Gesture flingGestureEnd(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, 0,
+                            GESTURES_FLING_TAP_DOWN);
+    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGestureEnd);
+
+    // Start a second scoll gesture, and ensure the fake finger is reset to (0, 0), instead of
+    // continuing from the position where the last scroll gesture's fake finger ended.
+    Gesture secondScrollStart(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 2,
+                              14);
+    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, secondScrollStart);
+    ASSERT_THAT(args,
+                ElementsAre(VariantWith<NotifyMotionArgs>(
+                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)),
+                            VariantWith<NotifyMotionArgs>(
+                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+                                          WithCoords(0, 0),
+                                          WithGestureScrollDistance(0, 0, EPSILON))),
+                            VariantWith<NotifyMotionArgs>(
+                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+                                          WithCoords(2, 14),
+                                          WithGestureScrollDistance(-2, -14, EPSILON)))));
+}
+
 TEST_F(GestureConverterTest, ThreeFingerSwipe_ClearsClassificationAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
                          /*dy=*/0);
@@ -497,7 +502,7 @@
 TEST_F(GestureConverterTest, ThreeFingerSwipe_ClearsGestureAxesAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/5,
                          /*dy=*/5);
@@ -524,7 +529,7 @@
     // only checks movement in one dimension.
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dx= */ 0,
                          /* dy= */ 10);
@@ -535,7 +540,7 @@
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
                               WithGestureSwipeFingerCount(3), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Three fake fingers should be created. We don't actually care where they are, so long as they
     // move appropriately.
@@ -581,7 +586,7 @@
                       WithGestureOffset(0, -0.005, EPSILON), WithGestureSwipeFingerCount(3),
                       WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
                       WithPointerCount(3u), WithToolType(ToolType::FINGER),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
+                      WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX());
     EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX());
     EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX());
@@ -619,25 +624,27 @@
                                           WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ThreeFingerSwipe_Rotated) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
     converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dx= */ 0,
                          /* dy= */ 10);
     std::list<NotifyArgs> args =
             converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
     ASSERT_EQ(4u, args.size());
-    ASSERT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ADISPLAY_ID_DEFAULT))));
+    ASSERT_THAT(args,
+                Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ui::LogicalDisplayId::DEFAULT))));
 
     // Three fake fingers should be created. We don't actually care where they are, so long as they
     // move appropriately.
@@ -681,7 +688,7 @@
     ASSERT_THAT(arg,
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                       WithGestureOffset(0, -0.005, EPSILON), WithPointerCount(3u),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
+                      WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() - 15);
     EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() - 15);
     EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() - 15);
@@ -706,14 +713,15 @@
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                                           WithGestureOffset(0, 0, EPSILON), WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
-    ASSERT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ADISPLAY_ID_DEFAULT))));
+                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)))));
+    ASSERT_THAT(args,
+                Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ui::LogicalDisplayId::DEFAULT))));
 }
 
 TEST_F(GestureConverterTest, FourFingerSwipe_Horizontal) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureFourFingerSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                          /* dx= */ 10, /* dy= */ 0);
@@ -724,7 +732,7 @@
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
                               WithGestureSwipeFingerCount(4), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Four fake fingers should be created. We don't actually care where they are, so long as they
     // move appropriately.
@@ -779,7 +787,7 @@
                       WithGestureOffset(0.005, 0, EPSILON), WithGestureSwipeFingerCount(4),
                       WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
                       WithPointerCount(4u), WithToolType(ToolType::FINGER),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
+                      WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() + 15);
     EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() + 15);
     EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() + 15);
@@ -828,17 +836,18 @@
                                           WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Pinch_Inwards) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
                          GESTURES_ZOOM_START);
@@ -847,20 +856,18 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(POINTER_X - 100, POINTER_Y),
-                                          WithPointerCount(1u))),
+                                          WithCoords(-100, 0), WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(
                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithPointerCoords(1, POINTER_X + 100, POINTER_Y),
-                                          WithPointerCount(2u)))));
+                                          WithPointerCoords(1, 100, 0), WithPointerCount(2u)))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::PINCH),
                               WithGesturePinchScaleFactor(1.0f, EPSILON),
                               WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                           /* dz= */ 0.8, GESTURES_ZOOM_UPDATE);
@@ -870,10 +877,9 @@
                         AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                               WithMotionClassification(MotionClassification::PINCH),
                               WithGesturePinchScaleFactor(0.8f, EPSILON),
-                              WithPointerCoords(0, POINTER_X - 80, POINTER_Y),
-                              WithPointerCoords(1, POINTER_X + 80, POINTER_Y), WithPointerCount(2u),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithPointerCoords(0, -80, 0), WithPointerCoords(1, 80, 0),
+                              WithPointerCount(2u), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
                        GESTURES_ZOOM_END);
@@ -893,17 +899,18 @@
                                           WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Pinch_Outwards) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
                          GESTURES_ZOOM_START);
@@ -912,33 +919,30 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(POINTER_X - 100, POINTER_Y),
-                                          WithPointerCount(1u))),
+                                          WithCoords(-100, 0), WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(
                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithPointerCoords(1, POINTER_X + 100, POINTER_Y),
-                                          WithPointerCount(2u)))));
+                                          WithPointerCoords(1, 100, 0), WithPointerCount(2u)))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionClassification(MotionClassification::PINCH),
                               WithGesturePinchScaleFactor(1.0f, EPSILON),
                               WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /* dz= */ 1.2, GESTURES_ZOOM_UPDATE);
+                          /* dz= */ 1.1, GESTURES_ZOOM_UPDATE);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, updateGesture);
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                         AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                               WithMotionClassification(MotionClassification::PINCH),
-                              WithGesturePinchScaleFactor(1.2f, EPSILON),
-                              WithPointerCoords(0, POINTER_X - 120, POINTER_Y),
-                              WithPointerCoords(1, POINTER_X + 120, POINTER_Y),
+                              WithGesturePinchScaleFactor(1.1f, EPSILON),
+                              WithPointerCoords(0, -110, 0), WithPointerCoords(1, 110, 0),
                               WithPointerCount(2u), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
                        GESTURES_ZOOM_END);
@@ -958,17 +962,18 @@
                                           WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Pinch_ClearsClassificationAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
                          GESTURES_ZOOM_START);
@@ -993,7 +998,7 @@
 TEST_F(GestureConverterTest, Pinch_ClearsScaleFactorAfterGesture) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
                          GESTURES_ZOOM_START);
@@ -1020,7 +1025,7 @@
 TEST_F(GestureConverterTest, ResetWithButtonPressed) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                         /*down=*/GESTURES_BUTTON_LEFT | GESTURES_BUTTON_RIGHT,
@@ -1044,15 +1049,15 @@
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                           WithButtonState(0)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ResetDuringScroll) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     (void)converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
@@ -1061,24 +1066,25 @@
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(POINTER_X, POINTER_Y - 10),
+                                          WithCoords(0, -10),
                                           WithGestureScrollDistance(0, 0, EPSILON),
                                           WithMotionClassification(
                                                   MotionClassification::TWO_FINGER_SWIPE),
                                           WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ResetDuringThreeFingerSwipe) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
                          /*dy=*/10);
@@ -1112,14 +1118,15 @@
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, ResetDuringPinch) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
                          GESTURES_ZOOM_START);
@@ -1141,17 +1148,18 @@
                                           WithPointerCount(1u))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(POINTER_X, POINTER_Y),
+                                          WithCoords(0, 0),
                                           WithMotionClassification(MotionClassification::NONE)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, FlingTapDown) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture tapDownGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                            /*vx=*/0.f, /*vy=*/0.f, GESTURES_FLING_TAP_DOWN);
@@ -1159,20 +1167,17 @@
             converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, tapDownGesture);
 
     ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                      WithCoords(POINTER_X, POINTER_Y), WithRelativeMotion(0.f, 0.f),
-                      WithToolType(ToolType::FINGER), WithButtonState(0), WithPressure(0.0f),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
-
-    ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X, POINTER_Y));
-    ASSERT_TRUE(mFakePointerController->isPointerShown());
+                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER), WithCoords(0, 0),
+                      WithRelativeMotion(0.f, 0.f), WithToolType(ToolType::FINGER),
+                      WithButtonState(0), WithPressure(0.0f),
+                      WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
 }
 
 TEST_F(GestureConverterTest, FlingTapDownAfterScrollStopsFling) {
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     input_flags::enable_touchpad_fling_stop(true);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture scrollGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
     std::list<NotifyArgs> args =
@@ -1195,8 +1200,8 @@
                                     WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithCoords(POINTER_X, POINTER_Y), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT),
+                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT),
                               WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE)))));
 }
 
@@ -1204,7 +1209,7 @@
     // Tap should produce button press/release events
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
                          /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
@@ -1241,17 +1246,17 @@
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                           WithButtonState(0), WithPressure(0.0f)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
+                              WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F(GestureConverterTest, Click) {
     // Click should produce button press/release events
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
                          /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
@@ -1278,15 +1283,16 @@
                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
                                           WithPressure(1.0f)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
+                              WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture buttonUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                             /* down= */ GESTURES_BUTTON_NONE,
                             /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ false);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonUpGesture);
+
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
@@ -1300,9 +1306,9 @@
                                           WithPressure(0.0f)))));
     ASSERT_THAT(args,
                 Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithButtonState(0), WithCoords(POINTER_X, POINTER_Y),
-                              WithRelativeMotion(0.f, 0.f), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                        AllOf(WithButtonState(0), WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
+                              WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 }
 
 TEST_F_WITH_FLAGS(GestureConverterTest, TapWithTapToClickDisabled,
@@ -1315,7 +1321,7 @@
 
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture flingGesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
                          /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
@@ -1344,7 +1350,7 @@
 
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture flingGesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
                          /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
@@ -1426,7 +1432,7 @@
 
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
                          /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
@@ -1438,6 +1444,7 @@
                               /* down= */ GESTURES_BUTTON_LEFT,
                               /* up= */ GESTURES_BUTTON_NONE, /* is_tap= */ false);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonDownGesture);
+
     ASSERT_THAT(args,
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
@@ -1452,10 +1459,10 @@
                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
                                           WithPressure(1.0f)))));
     ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                Each(VariantWith<NotifyMotionArgs>(
+                        AllOf(WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
+                              WithToolType(ToolType::FINGER),
+                              WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     Gesture buttonUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
                             /* down= */ GESTURES_BUTTON_NONE,
@@ -1466,18 +1473,23 @@
                 ElementsAre(VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(0), WithPressure(1.0f))),
+                                          WithButtonState(0), WithCoords(0, 0),
+                                          WithRelativeMotion(0.f, 0.f),
+                                          WithToolType(ToolType::FINGER), WithButtonState(0),
+                                          WithPressure(1.0f),
+                                          WithDisplayId(ui::LogicalDisplayId::DEFAULT))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithButtonState(0), WithPressure(0.0f))),
+                                          WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
+                                          WithToolType(ToolType::FINGER), WithButtonState(0),
+                                          WithPressure(0.0f),
+                                          WithDisplayId(ui::LogicalDisplayId::DEFAULT))),
                             VariantWith<NotifyMotionArgs>(
                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithButtonState(0), WithPressure(0.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(POINTER_X, POINTER_Y),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
+                                          WithCoords(0, 0), WithRelativeMotion(0, 0),
+                                          WithToolType(ToolType::FINGER), WithButtonState(0),
+                                          WithPressure(0.0f),
+                                          WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
 
     // Future taps should be re-enabled
     ASSERT_FALSE(mReader->getContext()->isPreventingTouchpadTaps());
@@ -1490,7 +1502,7 @@
 
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
     std::list<NotifyArgs> args =
@@ -1506,1433 +1518,7 @@
     const nsecs_t gestureStartTime = 1000;
     InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
     GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    // Start a move gesture at gestureStartTime
-    Gesture moveGesture(kGestureMove, gestureStartTime, gestureStartTime, -5, 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(gestureStartTime, READ_TIME, gestureStartTime, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
-
-    // Key presses with IME connection should cancel ongoing move gesture
-    nsecs_t currentTime = gestureStartTime + 100;
-    mFakePolicy->setIsInputMethodConnectionActive(true);
-    mReader->getContext()->setLastKeyDownTimestamp(currentTime);
-    moveGesture = Gesture(kGestureMove, currentTime, currentTime, -5, 10);
-    args = converter.handleGesture(currentTime, READ_TIME, gestureStartTime, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT))));
-
-    // any updates in existing move gesture should be ignored
-    moveGesture = Gesture(kGestureMove, currentTime, currentTime, -5, 10);
-    args = converter.handleGesture(currentTime, READ_TIME, gestureStartTime, moveGesture);
-    ASSERT_EQ(0u, args.size());
-
-    // New gesture should not be affected
-    currentTime += 100;
-    moveGesture = Gesture(kGestureMove, currentTime, currentTime, -5, 10);
-    args = converter.handleGesture(currentTime, READ_TIME, currentTime, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
-}
-
-// TODO(b/311416205): De-duplicate the test cases after the refactoring is complete and the flagging
-//   logic can be removed.
-class GestureConverterTestWithChoreographer : public GestureConverterTestBase {
-protected:
-    void SetUp() override {
-        input_flags::enable_pointer_choreographer(true);
-        GestureConverterTestBase::SetUp();
-    }
-};
-
-TEST_F(GestureConverterTestWithChoreographer, Move) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithRelativeMotion(0, 0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithRelativeMotion(-5, 10), WithButtonState(0),
-                                          WithPressure(0.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // The same gesture again should only repeat the HOVER_MOVE, not the HOVER_ENTER.
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithCoords(0, 0),
-                              WithRelativeMotion(-5, 10), WithToolType(ToolType::FINGER),
-                              WithButtonState(0), WithPressure(0.0f),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Move_Rotated) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithRelativeMotion(0, 0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
-                                          WithRelativeMotion(10, 5), WithButtonState(0),
-                                          WithPressure(0.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ButtonsChange) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    // Press left and right buttons at once
-    Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                        /* down= */ GESTURES_BUTTON_LEFT | GESTURES_BUTTON_RIGHT,
-                        /* up= */ GESTURES_BUTTON_NONE, /* is_tap= */ false);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, downGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
-                                                          AMOTION_EVENT_BUTTON_SECONDARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
-                                                          AMOTION_EVENT_BUTTON_SECONDARY)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Then release the left button
-    Gesture leftUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /* down= */ GESTURES_BUTTON_NONE, /* up= */ GESTURES_BUTTON_LEFT,
-                          /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, leftUpGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                              WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                              WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY), WithCoords(0, 0),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Finally release the right button
-    Gesture rightUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                           /* down= */ GESTURES_BUTTON_NONE, /* up= */ GESTURES_BUTTON_RIGHT,
-                           /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, rightUpGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_UP)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithButtonState(0), WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ButtonDownAfterMoveExitsHover) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-
-    Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                        /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE,
-                        /*is_tap=*/false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, downGesture);
-    ASSERT_THAT(args.front(),
-                VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT), WithButtonState(0),
-                              WithCoords(0, 0), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, DragWithButton) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    // Press the button
-    Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                        /* down= */ GESTURES_BUTTON_LEFT, /* up= */ GESTURES_BUTTON_NONE,
-                        /* is_tap= */ false);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, downGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Move
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(0, 0),
-                              WithRelativeMotion(-5, 10), WithToolType(ToolType::FINGER),
-                              WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithPressure(1.0f),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Release the button
-    Gesture upGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                      /* down= */ GESTURES_BUTTON_NONE, /* up= */ GESTURES_BUTTON_LEFT,
-                      /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, upGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_UP)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithButtonState(0), WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Scroll) {
-    const nsecs_t downTime = 12345;
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(downTime, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(0, 0),
-                                          WithGestureScrollDistance(0, 0, EPSILON),
-                                          WithDownTime(downTime))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                          WithCoords(0, -10),
-                                          WithGestureScrollDistance(0, 10, EPSILON)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
-                              WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(0, -15),
-                              WithGestureScrollDistance(0, 5, EPSILON),
-                              WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
-                              WithToolType(ToolType::FINGER),
-                              WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
-                         GESTURES_FLING_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(0, -15),
-                                          WithGestureScrollDistance(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::TWO_FINGER_SWIPE),
-                                          WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Scroll_Rotated) {
-    const nsecs_t downTime = 12345;
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(downTime, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(0, 0),
-                                          WithGestureScrollDistance(0, 0, EPSILON),
-                                          WithDownTime(downTime))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                          WithCoords(-10, 0),
-                                          WithGestureScrollDistance(0, 10, EPSILON)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(-15, 0),
-                              WithGestureScrollDistance(0, 5, EPSILON),
-                              WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
-                         GESTURES_FLING_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(-15, 0),
-                                          WithGestureScrollDistance(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::TWO_FINGER_SWIPE))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Scroll_ClearsClassificationAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
-                         GESTURES_FLING_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::NONE),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Scroll_ClearsScrollDistanceAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture continueGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
-                         GESTURES_FLING_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-
-    // Move gestures don't use the fake finger array, so to test that gesture axes are cleared we
-    // need to use another gesture type, like pinch.
-    Gesture pinchGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                         GESTURES_ZOOM_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, pinchGesture);
-    ASSERT_FALSE(args.empty());
-    EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()), WithGestureScrollDistance(0, 0, EPSILON));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ThreeFingerSwipe_ClearsClassificationAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
-                         /*dy=*/0);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/-5,
-                        /*dy=*/10);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        WithMotionClassification(MotionClassification::NONE))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ThreeFingerSwipe_ClearsGestureAxesAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/5,
-                         /*dy=*/5);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
-
-    // Move gestures don't use the fake finger array, so to test that gesture axes are cleared we
-    // need to use another gesture type, like pinch.
-    Gesture pinchGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                         GESTURES_ZOOM_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, pinchGesture);
-    ASSERT_FALSE(args.empty());
-    EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
-                AllOf(WithGestureOffset(0, 0, EPSILON), WithGestureSwipeFingerCount(0)));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ThreeFingerSwipe_Vertical) {
-    // The gestures library will "lock" a swipe into the dimension it starts in. For example, if you
-    // start swiping up and then start moving left or right, it'll return gesture events with only Y
-    // deltas until you lift your fingers and start swiping again. That's why each of these tests
-    // only checks movement in one dimension.
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dx= */ 0,
-                         /* dy= */ 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_EQ(4u, args.size());
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
-                              WithGestureSwipeFingerCount(3), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Three fake fingers should be created. We don't actually care where they are, so long as they
-    // move appropriately.
-    NotifyMotionArgs arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithGestureOffset(0, 0, EPSILON),
-                      WithPointerCount(1u)));
-    PointerCoords finger0Start = arg.pointerCoords[0];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(2u)));
-    PointerCoords finger1Start = arg.pointerCoords[1];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(3u)));
-    PointerCoords finger2Start = arg.pointerCoords[2];
-    args.pop_front();
-
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0, -0.01, EPSILON), WithPointerCount(3u)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX());
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX());
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX());
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY() - 10);
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY() - 10);
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY() - 10);
-
-    Gesture continueGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                            /* dx= */ 0, /* dy= */ 5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-    ASSERT_EQ(1u, args.size());
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0, -0.005, EPSILON), WithGestureSwipeFingerCount(3),
-                      WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
-                      WithPointerCount(3u), WithToolType(ToolType::FINGER),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX());
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX());
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX());
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY() - 15);
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY() - 15);
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY() - 15);
-
-    Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(3),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(3u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(3),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(3),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ThreeFingerSwipe_Rotated) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setOrientation(ui::ROTATION_90);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dx= */ 0,
-                         /* dy= */ 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_EQ(4u, args.size());
-    ASSERT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ADISPLAY_ID_DEFAULT))));
-
-    // Three fake fingers should be created. We don't actually care where they are, so long as they
-    // move appropriately.
-    NotifyMotionArgs arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithGestureOffset(0, 0, EPSILON),
-                      WithPointerCount(1u)));
-    PointerCoords finger0Start = arg.pointerCoords[0];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(2u)));
-    PointerCoords finger1Start = arg.pointerCoords[1];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(3u)));
-    PointerCoords finger2Start = arg.pointerCoords[2];
-    args.pop_front();
-
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0, -0.01, EPSILON), WithPointerCount(3u)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() - 10);
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() - 10);
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() - 10);
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY());
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY());
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY());
-
-    Gesture continueGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                            /* dx= */ 0, /* dy= */ 5);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-    ASSERT_EQ(1u, args.size());
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0, -0.005, EPSILON), WithPointerCount(3u),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() - 15);
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() - 15);
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() - 15);
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY());
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY());
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY());
-
-    Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON), WithPointerCount(3u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON), WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithGestureOffset(0, 0, EPSILON), WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)))));
-    ASSERT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithDisplayId(ADISPLAY_ID_DEFAULT))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, FourFingerSwipe_Horizontal) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureFourFingerSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                         /* dx= */ 10, /* dy= */ 0);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_EQ(5u, args.size());
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
-                              WithGestureSwipeFingerCount(4), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Four fake fingers should be created. We don't actually care where they are, so long as they
-    // move appropriately.
-    NotifyMotionArgs arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithGestureOffset(0, 0, EPSILON),
-                      WithPointerCount(1u)));
-    PointerCoords finger0Start = arg.pointerCoords[0];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(2u)));
-    PointerCoords finger1Start = arg.pointerCoords[1];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(3u)));
-    PointerCoords finger2Start = arg.pointerCoords[2];
-    args.pop_front();
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                       3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                      WithGestureOffset(0, 0, EPSILON), WithPointerCount(4u)));
-    PointerCoords finger3Start = arg.pointerCoords[3];
-    args.pop_front();
-
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0.01, 0, EPSILON), WithPointerCount(4u)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() + 10);
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() + 10);
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() + 10);
-    EXPECT_EQ(arg.pointerCoords[3].getX(), finger3Start.getX() + 10);
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY());
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY());
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY());
-    EXPECT_EQ(arg.pointerCoords[3].getY(), finger3Start.getY());
-
-    Gesture continueGesture(kGestureFourFingerSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                            /* dx= */ 5, /* dy= */ 0);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
-    ASSERT_EQ(1u, args.size());
-    arg = std::get<NotifyMotionArgs>(args.front());
-    ASSERT_THAT(arg,
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                      WithGestureOffset(0.005, 0, EPSILON), WithGestureSwipeFingerCount(4),
-                      WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE),
-                      WithPointerCount(4u), WithToolType(ToolType::FINGER),
-                      WithDisplayId(ADISPLAY_ID_DEFAULT)));
-    EXPECT_EQ(arg.pointerCoords[0].getX(), finger0Start.getX() + 15);
-    EXPECT_EQ(arg.pointerCoords[1].getX(), finger1Start.getX() + 15);
-    EXPECT_EQ(arg.pointerCoords[2].getX(), finger2Start.getX() + 15);
-    EXPECT_EQ(arg.pointerCoords[3].getX(), finger3Start.getX() + 15);
-    EXPECT_EQ(arg.pointerCoords[0].getY(), finger0Start.getY());
-    EXPECT_EQ(arg.pointerCoords[1].getY(), finger1Start.getY());
-    EXPECT_EQ(arg.pointerCoords[2].getY(), finger2Start.getY());
-    EXPECT_EQ(arg.pointerCoords[3].getY(), finger3Start.getY());
-
-    Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(4),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(4u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(4),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(3u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(4),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithGestureSwipeFingerCount(4),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Pinch_Inwards) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
-                         GESTURES_ZOOM_START);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(-100, 0), WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithPointerCoords(1, 100, 0), WithPointerCount(2u)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::PINCH),
-                              WithGesturePinchScaleFactor(1.0f, EPSILON),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /* dz= */ 0.8, GESTURES_ZOOM_UPDATE);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, updateGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                              WithMotionClassification(MotionClassification::PINCH),
-                              WithGesturePinchScaleFactor(0.8f, EPSILON),
-                              WithPointerCoords(0, -80, 0), WithPointerCoords(1, 80, 0),
-                              WithPointerCount(2u), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
-                       GESTURES_ZOOM_END);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, endGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Pinch_Outwards) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
-                         GESTURES_ZOOM_START);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithCoords(-100, 0), WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_DOWN |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithPointerCoords(1, 100, 0), WithPointerCount(2u)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionClassification(MotionClassification::PINCH),
-                              WithGesturePinchScaleFactor(1.0f, EPSILON),
-                              WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /* dz= */ 1.1, GESTURES_ZOOM_UPDATE);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, updateGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                              WithMotionClassification(MotionClassification::PINCH),
-                              WithGesturePinchScaleFactor(1.1f, EPSILON),
-                              WithPointerCoords(0, -110, 0), WithPointerCoords(1, 110, 0),
-                              WithPointerCount(2u), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* dz= */ 1,
-                       GESTURES_ZOOM_END);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, endGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Pinch_ClearsClassificationAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                         GESTURES_ZOOM_START);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /*dz=*/1.2, GESTURES_ZOOM_UPDATE);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, updateGesture);
-
-    Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                       GESTURES_ZOOM_END);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, endGesture);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                        WithMotionClassification(MotionClassification::NONE))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Pinch_ClearsScaleFactorAfterGesture) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                         GESTURES_ZOOM_START);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    Gesture updateGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                          /*dz=*/1.2, GESTURES_ZOOM_UPDATE);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, updateGesture);
-
-    Gesture endGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                       GESTURES_ZOOM_END);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, endGesture);
-
-    // Move gestures don't use the fake finger array, so to test that gesture axes are cleared we
-    // need to use another gesture type, like scroll.
-    Gesture scrollGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/1,
-                          /*dy=*/0);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, scrollGesture);
-    ASSERT_FALSE(args.empty());
-    EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()), WithGesturePinchScaleFactor(0, EPSILON));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ResetWithButtonPressed) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture downGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                        /*down=*/GESTURES_BUTTON_LEFT | GESTURES_BUTTON_RIGHT,
-                        /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false);
-    (void)converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, downGesture);
-
-    std::list<NotifyArgs> args = converter.reset(ARBITRARY_TIME);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
-                                          WithButtonState(0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithButtonState(0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithButtonState(0)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ResetDuringScroll) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    (void)converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    std::list<NotifyArgs> args = converter.reset(ARBITRARY_TIME);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(0, -10),
-                                          WithGestureScrollDistance(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::TWO_FINGER_SWIPE),
-                                          WithFlags(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ResetDuringThreeFingerSwipe) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
-                         /*dy=*/10);
-    (void)converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    std::list<NotifyArgs> args = converter.reset(ARBITRARY_TIME);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(3u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithGestureOffset(0, 0, EPSILON),
-                                          WithMotionClassification(
-                                                  MotionClassification::MULTI_FINGER_SWIPE),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, ResetDuringPinch) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture startGesture(kGesturePinch, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dz=*/1,
-                         GESTURES_ZOOM_START);
-    (void)converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
-
-    std::list<NotifyArgs> args = converter.reset(ARBITRARY_TIME);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(
-                                                  AMOTION_EVENT_ACTION_POINTER_UP |
-                                                  1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(2u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithMotionClassification(MotionClassification::PINCH),
-                                          WithGesturePinchScaleFactor(1.0f, EPSILON),
-                                          WithPointerCount(1u))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0),
-                                          WithMotionClassification(MotionClassification::NONE)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, FlingTapDown) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture tapDownGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                           /*vx=*/0.f, /*vy=*/0.f, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, tapDownGesture);
-
-    ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER), WithCoords(0, 0),
-                      WithRelativeMotion(0.f, 0.f), WithToolType(ToolType::FINGER),
-                      WithButtonState(0), WithPressure(0.0f), WithDisplayId(ADISPLAY_ID_DEFAULT)));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, FlingTapDownAfterScrollStopsFling) {
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    input_flags::enable_touchpad_fling_stop(true);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture scrollGesture(kGestureScroll, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 0, -10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, scrollGesture);
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, 1, 1,
-                         GESTURES_FLING_START);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-
-    Gesture tapDownGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                           /*vx=*/0.f, /*vy=*/0.f, GESTURES_FLING_TAP_DOWN);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, tapDownGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)),
-                            VariantWith<NotifyMotionArgs>(
-                                    WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(
-                        AllOf(WithCoords(0, 0), WithToolType(ToolType::FINGER),
-                              WithDisplayId(ADISPLAY_ID_DEFAULT),
-                              WithMotionClassification(MotionClassification::TWO_FINGER_SWIPE)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Tap) {
-    // Tap should produce button press/release events
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
-                         /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-    // We don't need to check args here, since it's covered by the FlingTapDown test.
-
-    Gesture tapGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                       /* down= */ GESTURES_BUTTON_LEFT,
-                       /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ true);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, tapGesture);
-
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
-                                          WithButtonState(0), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(0), WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithButtonState(0), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithButtonState(0), WithPressure(0.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F(GestureConverterTestWithChoreographer, Click) {
-    // Click should produce button press/release events
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
-                         /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-    // We don't need to check args here, since it's covered by the FlingTapDown test.
-
-    Gesture buttonDownGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                              /* down= */ GESTURES_BUTTON_LEFT,
-                              /* up= */ GESTURES_BUTTON_NONE, /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonDownGesture);
-
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
-                                          WithButtonState(0), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture buttonUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                            /* down= */ GESTURES_BUTTON_NONE,
-                            /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonUpGesture);
-
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithPressure(0.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithButtonState(0), WithCoords(0, 0),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-}
-
-TEST_F_WITH_FLAGS(GestureConverterTestWithChoreographer, TapWithTapToClickDisabled,
-                  REQUIRES_FLAGS_ENABLED(TOUCHPAD_PALM_REJECTION),
-                  REQUIRES_FLAGS_DISABLED(TOUCHPAD_PALM_REJECTION_V2)) {
-    nsecs_t currentTime = ARBITRARY_GESTURE_TIME;
-
-    // Tap should be ignored when disabled
-    mReader->getContext()->setPreventingTouchpadTaps(true);
-
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture flingGesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
-                         /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(currentTime, currentTime, currentTime, flingGesture);
-    // We don't need to check args here, since it's covered by the FlingTapDown test.
-
-    Gesture tapGesture(kGestureButtonsChange, currentTime, currentTime,
-                       /* down= */ GESTURES_BUTTON_LEFT,
-                       /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ true);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, tapGesture);
-
-    // no events should be generated
-    ASSERT_EQ(0u, args.size());
-
-    // Future taps should be re-enabled
-    ASSERT_FALSE(mReader->getContext()->isPreventingTouchpadTaps());
-}
-
-TEST_F_WITH_FLAGS(GestureConverterTestWithChoreographer, TapWithTapToClickDisabledWithDelay,
-                  REQUIRES_FLAGS_ENABLED(TOUCHPAD_PALM_REJECTION_V2)) {
-    nsecs_t currentTime = ARBITRARY_GESTURE_TIME;
-
-    // Tap should be ignored when disabled
-    mReader->getContext()->setPreventingTouchpadTaps(true);
-
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture flingGesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
-                         /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(currentTime, currentTime, currentTime, flingGesture);
-    // We don't need to check args here, since it's covered by the FlingTapDown test.
-
-    Gesture tapGesture(kGestureButtonsChange, currentTime, currentTime,
-                       /* down= */ GESTURES_BUTTON_LEFT,
-                       /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ true);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, tapGesture);
-
-    // no events should be generated
-    ASSERT_EQ(0u, args.size());
-
-    // Future taps should be re-enabled
-    ASSERT_FALSE(mReader->getContext()->isPreventingTouchpadTaps());
-
-    // taps before the threshold should still be ignored
-    currentTime += TAP_ENABLE_DELAY_NANOS.count();
-    flingGesture = Gesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
-                           /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, flingGesture);
-
-    ASSERT_EQ(1u, args.size());
-    ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithRelativeMotion(0, 0)));
-
-    tapGesture = Gesture(kGestureButtonsChange, currentTime, currentTime,
-                         /* down= */ GESTURES_BUTTON_LEFT,
-                         /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ true);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, tapGesture);
-
-    // no events should be generated
-    ASSERT_EQ(0u, args.size());
-
-    // taps after the threshold should be recognised
-    currentTime += 1;
-    flingGesture = Gesture(kGestureFling, currentTime, currentTime, /* vx= */ 0,
-                           /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, flingGesture);
-
-    ASSERT_EQ(1u, args.size());
-    ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
-                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithRelativeMotion(0, 0)));
-
-    tapGesture = Gesture(kGestureButtonsChange, currentTime, currentTime,
-                         /* down= */ GESTURES_BUTTON_LEFT,
-                         /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ true);
-    args = converter.handleGesture(currentTime, currentTime, currentTime, tapGesture);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
-                                          WithButtonState(0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithButtonState(0))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithButtonState(0)))));
-    ASSERT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithRelativeMotion(0.f, 0.f))));
-}
-
-TEST_F_WITH_FLAGS(GestureConverterTestWithChoreographer, ClickWithTapToClickDisabled,
-                  REQUIRES_FLAGS_ENABLED(TOUCHPAD_PALM_REJECTION)) {
-    // Click should still produce button press/release events
-    mReader->getContext()->setPreventingTouchpadTaps(true);
-
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /* vx= */ 0,
-                         /* vy= */ 0, GESTURES_FLING_TAP_DOWN);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
-    // We don't need to check args here, since it's covered by the FlingTapDown test.
-
-    Gesture buttonDownGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                              /* down= */ GESTURES_BUTTON_LEFT,
-                              /* up= */ GESTURES_BUTTON_NONE, /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonDownGesture);
-
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
-                                          WithButtonState(0), WithPressure(0.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithPressure(1.0f)))));
-    ASSERT_THAT(args,
-                Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(0, 0),
-                                                         WithRelativeMotion(0.f, 0.f),
-                                                         WithToolType(ToolType::FINGER),
-                                                         WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    Gesture buttonUpGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
-                            /* down= */ GESTURES_BUTTON_NONE,
-                            /* up= */ GESTURES_BUTTON_LEFT, /* is_tap= */ false);
-    args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, buttonUpGesture);
-
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
-                                          WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
-                                          WithButtonState(0), WithCoords(0, 0),
-                                          WithRelativeMotion(0.f, 0.f),
-                                          WithToolType(ToolType::FINGER), WithButtonState(0),
-                                          WithPressure(1.0f), WithDisplayId(ADISPLAY_ID_DEFAULT))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
-                                          WithCoords(0, 0), WithRelativeMotion(0.f, 0.f),
-                                          WithToolType(ToolType::FINGER), WithButtonState(0),
-                                          WithPressure(0.0f), WithDisplayId(ADISPLAY_ID_DEFAULT))),
-                            VariantWith<NotifyMotionArgs>(
-                                    AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                                          WithCoords(0, 0), WithRelativeMotion(0, 0),
-                                          WithToolType(ToolType::FINGER), WithButtonState(0),
-                                          WithPressure(0.0f),
-                                          WithDisplayId(ADISPLAY_ID_DEFAULT)))));
-
-    // Future taps should be re-enabled
-    ASSERT_FALSE(mReader->getContext()->isPreventingTouchpadTaps());
-}
-
-TEST_F_WITH_FLAGS(GestureConverterTestWithChoreographer, MoveEnablesTapToClick,
-                  REQUIRES_FLAGS_ENABLED(TOUCHPAD_PALM_REJECTION)) {
-    // initially disable tap-to-click
-    mReader->getContext()->setPreventingTouchpadTaps(true);
-
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
-
-    Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
-    std::list<NotifyArgs> args =
-            converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
-    // We don't need to check args here, since it's covered by the Move test.
-
-    // Future taps should be re-enabled
-    ASSERT_FALSE(mReader->getContext()->isPreventingTouchpadTaps());
-}
-
-TEST_F_WITH_FLAGS(GestureConverterTestWithChoreographer, KeypressCancelsHoverMove,
-                  REQUIRES_FLAGS_ENABLED(TOUCHPAD_PALM_REJECTION_V2)) {
-    const nsecs_t gestureStartTime = 1000;
-    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
-    GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
-    converter.setDisplayId(ADISPLAY_ID_DEFAULT);
+    converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
 
     // Start a move gesture at gestureStartTime
     Gesture moveGesture(kGestureMove, gestureStartTime, gestureStartTime, -5, 10);
diff --git a/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp b/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
index 85e055d..28699b8 100644
--- a/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
+++ b/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
@@ -18,7 +18,6 @@
 
 #include <NotifyArgsBuilders.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <input/InputEventBuilders.h>
 #include <linux/input.h>
 
@@ -64,7 +63,7 @@
                                        uint32_t sources = TOUCHSCREEN | STYLUS) {
     auto info = InputDeviceInfo();
     info.initialize(id, /*generation=*/1, /*controllerNumber=*/1, generateTestIdentifier(id),
-                    "alias", /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE);
+                    "alias", /*isExternal=*/false, /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
     info.addSource(sources);
     return info;
 }
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index bc173b1..8de28c6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -72,8 +72,8 @@
 static constexpr int32_t SECOND_DEVICE_ID = 2;
 
 // An arbitrary display id.
-static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
-static constexpr int32_t SECOND_DISPLAY_ID = 1;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
+constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
 
 // Ensure common actions are interchangeable between keys and motions for convenience.
 static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
@@ -117,7 +117,7 @@
 // An arbitrary pid of the gesture monitor window
 static constexpr gui::Pid MONITOR_PID{2001};
 
-static constexpr int expectedWallpaperFlags =
+static constexpr int EXPECTED_WALLPAPER_FLAGS =
         AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
 
 using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
@@ -128,9 +128,9 @@
 static KeyEvent getTestKeyEvent() {
     KeyEvent event;
 
-    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
-                     INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
-                     ARBITRARY_TIME, ARBITRARY_TIME);
+    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+                     ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
+                     AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
     return event;
 }
 
@@ -243,7 +243,7 @@
         request.token = window->getToken();
         request.windowName = window->getName();
         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-        request.displayId = window->getInfo()->displayId;
+        request.displayId = window->getInfo()->displayId.val();
         mDispatcher->setFocusedWindow(request);
     }
 };
@@ -252,8 +252,8 @@
     KeyEvent event;
 
     // Rejects undefined key actions.
-    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
-                     INVALID_HMAC,
+    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+                     ui::LogicalDisplayId::INVALID, INVALID_HMAC,
                      /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
                      ARBITRARY_TIME);
     ASSERT_EQ(InputEventInjectionResult::FAILED,
@@ -262,9 +262,9 @@
             << "Should reject key events with undefined action.";
 
     // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
-    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
-                     INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
-                     ARBITRARY_TIME, ARBITRARY_TIME);
+    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+                     ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
+                     AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
                                             0ms, 0))
@@ -438,12 +438,13 @@
 
 class FakeMonitorReceiver {
 public:
-    FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
+    FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
+                        ui::LogicalDisplayId displayId)
           : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
 
     sp<IBinder> getToken() { return mInputReceiver.getToken(); }
 
-    void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
                                     expectedFlags);
     }
@@ -455,22 +456,22 @@
 
     void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
 
-    void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
                                     expectedDisplayId, expectedFlags);
     }
 
-    void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
                                     expectedDisplayId, expectedFlags);
     }
 
-    void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
                                     expectedDisplayId, expectedFlags);
     }
 
-    void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+    void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
         mInputReceiver.consumeMotionEvent(
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
                       WithDisplayId(expectedDisplayId),
@@ -480,7 +481,7 @@
     void consumeMotionPointerDown(int32_t pointerIdx) {
         int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-        mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
+        mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
                                     /*expectedFlags=*/0);
     }
 
@@ -498,7 +499,7 @@
 
 static InputEventInjectionResult injectKey(
         InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
-        int32_t displayId = ADISPLAY_ID_NONE,
+        ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
         InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
         std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
         bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
@@ -520,30 +521,34 @@
 
 static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
     InputEventInjectionResult result =
-            injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
-                      InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
+            injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
+                      CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
     if (result != InputEventInjectionResult::TIMED_OUT) {
         FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
     }
 }
 
-static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
-                                               int32_t displayId = ADISPLAY_ID_NONE) {
+static InputEventInjectionResult injectKeyDown(
+        InputDispatcher& dispatcher,
+        ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
 }
 
 // Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
 // sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
 // has to be woken up to process the repeating key.
-static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
-                                                       int32_t displayId = ADISPLAY_ID_NONE) {
+static InputEventInjectionResult injectKeyDownNoRepeat(
+        InputDispatcher& dispatcher,
+        ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
                      InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
                      /*allowKeyRepeat=*/false);
 }
 
-static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
-                                             int32_t displayId = ADISPLAY_ID_NONE) {
+static InputEventInjectionResult injectKeyUp(
+        InputDispatcher& dispatcher,
+        ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
 }
 
@@ -557,7 +562,7 @@
 }
 
 static InputEventInjectionResult injectMotionEvent(
-        InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
+        InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
         const PointF& position = {100, 200},
         const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                         AMOTION_EVENT_INVALID_CURSOR_POSITION},
@@ -583,18 +588,19 @@
 }
 
 static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
-                                                  int32_t displayId,
+                                                  ui::LogicalDisplayId displayId,
                                                   const PointF& location = {100, 200}) {
     return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
 }
 
 static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
-                                                int32_t displayId,
+                                                ui::LogicalDisplayId displayId,
                                                 const PointF& location = {100, 200}) {
     return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
 }
 
-static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
+static NotifyKeyArgs generateKeyArgs(
+        int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid key event.
     NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
@@ -604,8 +610,8 @@
     return args;
 }
 
-static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
-                                                int32_t displayId = ADISPLAY_ID_NONE) {
+static NotifyKeyArgs generateSystemShortcutArgs(
+        int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid key event.
     NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
@@ -615,8 +621,8 @@
     return args;
 }
 
-static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
-                                              int32_t displayId = ADISPLAY_ID_NONE) {
+static NotifyKeyArgs generateAssistantKeyArgs(
+        int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid key event.
     NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
@@ -627,7 +633,7 @@
 }
 
 [[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
-                                                         int32_t displayId,
+                                                         ui::LogicalDisplayId displayId,
                                                          const std::vector<PointF>& points) {
     size_t pointerCount = points.size();
     if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
@@ -664,7 +670,8 @@
     return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
 }
 
-static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
+static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
+                                           ui::LogicalDisplayId displayId) {
     return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
 }
 
@@ -682,9 +689,9 @@
  */
 TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher,
-                                       "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
+                                                             "Window that breaks its input channel",
+                                                             ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -695,16 +702,18 @@
 
 TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Window should receive motion event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 using InputDispatcherDeathTest = InputDispatcherTest;
@@ -718,8 +727,9 @@
     ScopedSilentDeath _silentDeath;
 
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
                          {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
                  "Incorrect WindowInfosUpdate provided");
@@ -727,17 +737,19 @@
 
 TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     // Inject a MotionEvent to an unknown display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::INVALID))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Window should receive motion event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 /**
@@ -747,18 +759,19 @@
  */
 TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Window should receive motion event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 /**
@@ -766,37 +779,40 @@
  */
 TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Window should receive motion event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 // The foreground window should receive the first touch down event.
 TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> windowTop =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                                                ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> windowSecond =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged(
             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Top window should receive the touch down event. Second window should not receive anything.
-    windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     windowSecond->assertNoEvents();
 }
 
@@ -810,10 +826,12 @@
 TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> foregroundWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                       ui::LogicalDisplayId::DEFAULT);
     foregroundWindow->setDupTouchToWallpaper(true);
     sp<FakeWindowHandle> wallpaperWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaperWindow->setIsWallpaper(true);
 
     mDispatcher->onWindowInfosChanged(
@@ -827,7 +845,7 @@
 
     // Both foreground window and its wallpaper should receive the touch down
     foregroundWindow->consumeMotionDown();
-    wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher,
@@ -837,13 +855,13 @@
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
-    wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // Now the foreground window goes away, but the wallpaper stays
     mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
     foregroundWindow->consumeMotionCancel();
     // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
-    wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 }
 
 /**
@@ -853,8 +871,8 @@
  */
 TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     // First touch pointer down on right window
@@ -893,30 +911,32 @@
 TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> foregroundWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                       ui::LogicalDisplayId::DEFAULT);
     foregroundWindow->setDupTouchToWallpaper(true);
     sp<FakeWindowHandle> wallpaperWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaperWindow->setIsWallpaper(true);
 
     mDispatcher->onWindowInfosChanged(
             {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Both foreground window and its wallpaper should receive the touch down
     foregroundWindow->consumeMotionDown();
-    wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 200}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     foregroundWindow->consumeMotionMove();
-    wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // Wallpaper closes its channel, but the window remains.
     wallpaperWindow->destroyReceiver();
@@ -928,6 +948,301 @@
     foregroundWindow->consumeMotionCancel();
 }
 
+/**
+ * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
+ * down event to the left window. Device B sends a down event to the right window. Next, the right
+ * window disappears. Both the right window and its wallpaper window should receive cancel event.
+ * The left window and its wallpaper window should not receive any events.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> leftForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+    leftForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> leftWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+    leftWallpaperWindow->setIsWallpaper(true);
+
+    sp<FakeWindowHandle> rightForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+    rightForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> rightWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+    rightWallpaperWindow->setIsWallpaper(true);
+
+    mDispatcher->onWindowInfosChanged(
+            {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+              *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+             {},
+             0,
+             0});
+
+    const DeviceId deviceA = 9;
+    const DeviceId deviceB = 3;
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+                                      .deviceId(deviceA)
+                                      .build());
+    leftForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+    leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                  WithDeviceId(deviceA),
+                                                  WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+                                      .deviceId(deviceB)
+                                      .build());
+    rightForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+    rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                   WithDeviceId(deviceB),
+                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+    // Now right foreground window disappears, but right wallpaper window remains.
+    mDispatcher->onWindowInfosChanged(
+            {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+              *rightWallpaperWindow->getInfo()},
+             {},
+             0,
+             0});
+
+    // Left foreground window and left wallpaper window still exist, and should not receive any
+    // events.
+    leftForegroundWindow->assertNoEvents();
+    leftWallpaperWindow->assertNoEvents();
+    // Since right foreground window disappeared, right wallpaper window and right foreground window
+    // should receive cancel events.
+    rightForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+    rightWallpaperWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+                  WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+}
+
+/**
+ * Three windows arranged horizontally and without any overlap. Every window has a
+ * wallpaper window underneath. The middle window also has SLIPPERY flag.
+ * Device A sends a down event to the left window. Device B sends a down event to the middle window.
+ * Next, device B sends move event to the right window. Touch for device B should slip from the
+ * middle window to the right window. Also, the right wallpaper window should receive a down event.
+ * The middle window and its wallpaper window should receive a cancel event. The left window should
+ * not receive any events. If device B continues to report events, the right window and its
+ * wallpaper window should receive remaining events.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> leftForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+    leftForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> leftWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+    leftWallpaperWindow->setIsWallpaper(true);
+
+    sp<FakeWindowHandle> middleForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+    middleForegroundWindow->setDupTouchToWallpaper(true);
+    middleForegroundWindow->setSlippery(true);
+    sp<FakeWindowHandle> middleWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+    middleWallpaperWindow->setIsWallpaper(true);
+
+    sp<FakeWindowHandle> rightForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
+    rightForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> rightWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
+    rightWallpaperWindow->setIsWallpaper(true);
+
+    mDispatcher->onWindowInfosChanged(
+            {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+              *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
+              *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+             {},
+             0,
+             0});
+
+    const DeviceId deviceA = 9;
+    const DeviceId deviceB = 3;
+    // Device A sends a DOWN event to the left window
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+                                      .deviceId(deviceA)
+                                      .build());
+    leftForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+    leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                  WithDeviceId(deviceA),
+                                                  WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+    // Device B sends a DOWN event to the middle window
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+                                      .deviceId(deviceB)
+                                      .build());
+    middleForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+    middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                    WithDeviceId(deviceB),
+                                                    WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+    // Move the events of device B to the top of the right window.
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
+                                      .deviceId(deviceB)
+                                      .build());
+    middleForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+    middleWallpaperWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+                  WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+    rightForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+    rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                   WithDeviceId(deviceB),
+                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+    // Make sure the window on the right can receive the remaining events.
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
+                                      .deviceId(deviceB)
+                                      .build());
+    leftForegroundWindow->assertNoEvents();
+    leftWallpaperWindow->assertNoEvents();
+    middleForegroundWindow->assertNoEvents();
+    middleWallpaperWindow->assertNoEvents();
+    rightForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
+    rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+                                                   WithDeviceId(deviceB),
+                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+}
+
+/**
+ * Similar to the test above, we have three windows, they are arranged horizontally and without any
+ * overlap, and every window has a wallpaper window. The middle window is a simple window, without
+ * any special flags. Device A reports a down event that lands in left window. Device B sends a down
+ * event to the middle window and then touch is transferred from the middle window to the right
+ * window. The right window and its wallpaper window should receive a down event. The middle window
+ * and its wallpaper window should receive a cancel event. The left window should not receive any
+ * events. Subsequent events reported by device B should go to the right window and its wallpaper.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> leftForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+    leftForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> leftWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+    leftWallpaperWindow->setIsWallpaper(true);
+
+    sp<FakeWindowHandle> middleForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+    middleForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> middleWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+    middleWallpaperWindow->setIsWallpaper(true);
+
+    sp<FakeWindowHandle> rightForegroundWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
+    rightForegroundWindow->setDupTouchToWallpaper(true);
+    sp<FakeWindowHandle> rightWallpaperWindow =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+                                       ui::LogicalDisplayId::DEFAULT);
+    rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
+    rightWallpaperWindow->setIsWallpaper(true);
+
+    mDispatcher->onWindowInfosChanged(
+            {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+              *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
+              *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+             {},
+             0,
+             0});
+
+    const DeviceId deviceA = 9;
+    const DeviceId deviceB = 3;
+    // Device A touch down on the left window
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+                                      .deviceId(deviceA)
+                                      .build());
+    leftForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+    leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                  WithDeviceId(deviceA),
+                                                  WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+    // Device B touch down on the middle window
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+                                      .deviceId(deviceB)
+                                      .build());
+    middleForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+    middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                    WithDeviceId(deviceB),
+                                                    WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+    // Transfer touch from the middle window to the right window.
+    ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
+                                                  rightForegroundWindow->getToken()));
+
+    middleForegroundWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+    middleWallpaperWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+                  WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+    rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+                                                    WithDeviceId(deviceB),
+                                                    WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+    rightWallpaperWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
+                  WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+
+    // Make sure the right window can receive the remaining events.
+    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
+                                      .deviceId(deviceB)
+                                      .build());
+    leftForegroundWindow->assertNoEvents();
+    leftWallpaperWindow->assertNoEvents();
+    middleForegroundWindow->assertNoEvents();
+    middleWallpaperWindow->assertNoEvents();
+    rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+                                                    WithDeviceId(deviceB),
+                                                    WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+    rightWallpaperWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
+                  WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+}
+
 class ShouldSplitTouchFixture : public InputDispatcherTest,
                                 public ::testing::WithParamInterface<bool> {};
 INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
@@ -940,12 +1255,14 @@
 TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> foregroundWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                       ui::LogicalDisplayId::DEFAULT);
     foregroundWindow->setDupTouchToWallpaper(true);
     foregroundWindow->setPreventSplitting(GetParam());
 
     sp<FakeWindowHandle> wallpaperWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaperWindow->setIsWallpaper(true);
 
     mDispatcher->onWindowInfosChanged(
@@ -953,13 +1270,13 @@
 
     // Touch down on top window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 100}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Both top window and its wallpaper should receive the touch down
     foregroundWindow->consumeMotionDown();
-    wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // Second finger down on the top window
     const MotionEvent secondFingerDownEvent =
@@ -972,14 +1289,13 @@
               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
                                 InputEventInjectionSync::WAIT_FOR_RESULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-
     foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
-    wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
-                                              expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
+                                              EXPECTED_WALLPAPER_FLAGS);
 
     const MotionEvent secondFingerUpEvent =
             MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
@@ -989,13 +1305,14 @@
                                 InputEventInjectionSync::WAIT_FOR_RESULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     foregroundWindow->consumeMotionPointerUp(0);
-    wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionPointerUp(0, ui::LogicalDisplayId::DEFAULT,
+                                            EXPECTED_WALLPAPER_FLAGS);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher,
                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
                                                    AINPUT_SOURCE_TOUCHSCREEN)
-                                        .displayId(ADISPLAY_ID_DEFAULT)
+                                        .displayId(ui::LogicalDisplayId::DEFAULT)
                                         .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                                         .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
                                                          .x(100)
@@ -1003,8 +1320,8 @@
                                         .build(),
                                 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
-    wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
+    wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 }
 
 /**
@@ -1017,18 +1334,19 @@
  */
 TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
     leftWindow->setDupTouchToWallpaper(true);
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
     rightWindow->setDupTouchToWallpaper(true);
 
     sp<FakeWindowHandle> wallpaperWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
     wallpaperWindow->setIsWallpaper(true);
 
@@ -1040,13 +1358,13 @@
 
     // Touch down on left window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 100}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Both foreground window and its wallpaper should receive the touch down
     leftWindow->consumeMotionDown();
-    wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // Second finger down on the right window
     const MotionEvent secondFingerDownEvent =
@@ -1062,16 +1380,16 @@
 
     leftWindow->consumeMotionMove();
     // Since the touch is split, right window gets ACTION_DOWN
-    rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
-                                              expectedWallpaperFlags);
+    rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
+                                              EXPECTED_WALLPAPER_FLAGS);
 
     // Now, leftWindow, which received the first finger, disappears.
     mDispatcher->onWindowInfosChanged(
             {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
     leftWindow->consumeMotionCancel();
     // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
-    wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // The pointer that's still down on the right window moves, and goes to the right window only.
     // As far as the dispatcher's concerned though, both pointers are still present.
@@ -1098,18 +1416,19 @@
  */
 TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
     leftWindow->setDupTouchToWallpaper(true);
     leftWindow->setSlippery(true);
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     sp<FakeWindowHandle> wallpaperWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaperWindow->setIsWallpaper(true);
 
     mDispatcher->onWindowInfosChanged(
@@ -1120,23 +1439,23 @@
 
     // Touch down on left window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 100}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Both foreground window and its wallpaper should receive the touch down
     leftWindow->consumeMotionDown();
-    wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 
     // Move to right window, the left window should receive cancel.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {201, 100}))
+                                ui::LogicalDisplayId::DEFAULT, {201, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     leftWindow->consumeMotionCancel();
-    rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
 }
 
 /**
@@ -1157,14 +1476,14 @@
  */
 TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
 
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
@@ -1235,8 +1554,8 @@
 TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 300, 300));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -1297,12 +1616,12 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
 
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -1405,12 +1724,12 @@
     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", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -1494,8 +1813,8 @@
  */
 TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     // Only a single window is present at first
@@ -1510,7 +1829,7 @@
     // Now, an obscuring window appears!
     sp<FakeWindowHandle> obscuringWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
-                                       ADISPLAY_ID_DEFAULT,
+                                       ui::LogicalDisplayId::DEFAULT,
                                        /*createInputChannel=*/false);
     obscuringWindow->setFrame(Rect(0, 0, 200, 200));
     obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
@@ -1543,8 +1862,8 @@
  */
 TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     // Only a single window is present at first
@@ -1559,7 +1878,7 @@
     // Now, an obscuring window appears!
     sp<FakeWindowHandle> obscuringWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
-                                       ADISPLAY_ID_DEFAULT,
+                                       ui::LogicalDisplayId::DEFAULT,
                                        /*createInputChannel=*/false);
     obscuringWindow->setFrame(Rect(0, 0, 200, 200));
     obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
@@ -1601,8 +1920,8 @@
  */
 TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -1633,8 +1952,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -1680,8 +1999,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -1729,10 +2048,10 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
@@ -1788,10 +2107,10 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
@@ -1850,8 +2169,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -1902,8 +2221,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -1956,8 +2275,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2010,8 +2329,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2065,8 +2384,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2117,8 +2436,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2165,8 +2484,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2210,8 +2529,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2264,12 +2583,12 @@
 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -2349,12 +2668,12 @@
 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
     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", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -2427,12 +2746,12 @@
  */
 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -2486,18 +2805,18 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 400, 400));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
 
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
 
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
@@ -2562,18 +2881,18 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 400, 400));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
 
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
 
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
@@ -2641,18 +2960,18 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 400, 400));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
 
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -2717,18 +3036,18 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 400, 400));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
 
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -2794,8 +3113,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2874,8 +3193,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2949,8 +3268,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -2986,8 +3305,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -3030,12 +3349,12 @@
 TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -3116,12 +3435,12 @@
 TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
     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", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 200, 200));
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 400, 200));
 
     mDispatcher->onWindowInfosChanged(
@@ -3183,8 +3502,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -3250,8 +3569,8 @@
 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -3310,12 +3629,13 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
 
     sp<FakeWindowHandle> sbtRightWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher,
-                                       "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
+                                       "Stylus blocks touch (right) window",
+                                       ui::LogicalDisplayId::DEFAULT);
     sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
     sbtRightWindow->setGlobalStylusBlocksTouch(true);
 
@@ -3382,12 +3702,13 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
 
     sp<FakeWindowHandle> sbtRightWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher,
-                                       "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
+                                       "Stylus blocks touch (right) window",
+                                       ui::LogicalDisplayId::DEFAULT);
     sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
     sbtRightWindow->setGlobalStylusBlocksTouch(true);
 
@@ -3448,13 +3769,13 @@
  */
 TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setNoInputChannel(true);
     window->setFrame(Rect(0, 0, 200, 200));
 
@@ -3507,8 +3828,8 @@
 TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -3546,13 +3867,13 @@
 TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
@@ -3649,13 +3970,13 @@
 TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 200, 200));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
@@ -3873,14 +4194,14 @@
 
 TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> windowLeft =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     windowLeft->setFrame(Rect(0, 0, 600, 800));
-    sp<FakeWindowHandle> windowRight =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     windowRight->setFrame(Rect(600, 0, 1200, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged(
             {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
@@ -3940,7 +4261,7 @@
                                         .buttonState(0)
                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
                                         .build()));
-    windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
     // Move mouse cursor back to right window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -3964,8 +4285,8 @@
 TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 600, 800));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4024,8 +4345,8 @@
 TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 600, 800));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4078,16 +4399,16 @@
 TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 600, 800));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 600, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     // Send mouse cursor to the window
@@ -4111,16 +4432,16 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 600, 800));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 600, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     // Send mouse cursor to the window
@@ -4218,16 +4539,16 @@
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(0, 0, 600, 800));
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 600, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     // Send mouse cursor to the window
@@ -4314,11 +4635,11 @@
 // directly in this test.
 TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 1200, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -4365,7 +4686,7 @@
                                         .buttonState(0)
                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
                                         .build()));
-    window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
     // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
     // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
@@ -4384,11 +4705,11 @@
  */
 TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 1200, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -4412,11 +4733,11 @@
                   REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
                                                        a11y_crash_on_inconsistent_event_stream))) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 1200, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -4438,8 +4759,8 @@
 TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4472,8 +4793,8 @@
 TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4505,8 +4826,8 @@
 TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4545,8 +4866,8 @@
 TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4580,7 +4901,7 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> windowDefaultDisplay =
             sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
     sp<FakeWindowHandle> windowSecondDisplay =
             sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
@@ -4596,7 +4917,7 @@
               injectMotionEvent(*mDispatcher,
                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
                                                    AINPUT_SOURCE_MOUSE)
-                                        .displayId(ADISPLAY_ID_DEFAULT)
+                                        .displayId(ui::LogicalDisplayId::DEFAULT)
                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
                                         .build()));
     windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
@@ -4615,7 +4936,7 @@
               injectMotionEvent(*mDispatcher,
                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
                                                    AINPUT_SOURCE_MOUSE)
-                                        .displayId(ADISPLAY_ID_DEFAULT)
+                                        .displayId(ui::LogicalDisplayId::DEFAULT)
                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
                                         .build()));
     windowDefaultDisplay->consumeMotionEvent(
@@ -4627,14 +4948,14 @@
 TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> windowLeft =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     windowLeft->setFrame(Rect(0, 0, 600, 800));
-    sp<FakeWindowHandle> windowRight =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     windowRight->setFrame(Rect(600, 0, 1200, 800));
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged(
             {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
@@ -4643,15 +4964,16 @@
     // left window. This event should be dispatched to the left window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
-                                ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
-    windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+                                ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
+    windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     windowRight->assertNoEvents();
 }
 
 TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFocusable(true);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4659,41 +4981,44 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
 
     // Window should receive key down event.
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     // When device reset happens, that key stream should be terminated with FLAG_CANCELED
     // on the app side.
     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
 }
 
 TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
 
     // Window should receive motion down event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
     // on the app side.
     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
     window->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
 }
 
 TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -4716,8 +5041,9 @@
 
 TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFocusable(true);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4725,13 +5051,14 @@
 
     window->consumeFocusEvent(true);
 
-    const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+    const NotifyKeyArgs keyArgs =
+            generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
     const std::chrono::milliseconds interceptKeyTimeout = 50ms;
     const nsecs_t injectTime = keyArgs.eventTime;
     mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
     mDispatcher->notifyKey(keyArgs);
     // The dispatching time should be always greater than or equal to intercept key timeout.
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
                 std::chrono::nanoseconds(interceptKeyTimeout).count());
 }
@@ -4741,8 +5068,9 @@
  */
 TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFocusable(true);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4750,15 +5078,15 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     // Set a value that's significantly larger than the default consumption timeout. If the
     // implementation is correct, the actual value doesn't matter; it won't slow down the test.
     mFakePolicy->setInterceptKeyTimeout(600ms);
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
     // Window should receive key event immediately when same key up.
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
 }
 
 /**
@@ -4770,13 +5098,13 @@
  */
 TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect{0, 0, 100, 100});
 
     sp<FakeWindowHandle> outsideWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     outsideWindow->setFrame(Rect{100, 100, 200, 200});
     outsideWindow->setWatchOutsideTouch(true);
     // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
@@ -4784,8 +5112,8 @@
 
     // Tap on first window.
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {PointF{50, 50}}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
     window->consumeMotionDown();
     // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
     // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
@@ -4794,7 +5122,7 @@
 
     // Ensure outsideWindow doesn't get any more events for the gesture.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
+                                                 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
     window->consumeMotionMove();
     outsideWindow->assertNoEvents();
 }
@@ -4818,13 +5146,13 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect{0, 0, 100, 100});
     leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
 
     sp<FakeWindowHandle> outsideWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     outsideWindow->setFrame(Rect{100, 100, 200, 200});
     outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
     outsideWindow->setWatchOutsideTouch(true);
@@ -4833,7 +5161,7 @@
             std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> rightWindow =
             sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect{100, 0, 200, 100});
     rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
 
@@ -4897,32 +5225,33 @@
 TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
     // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "First Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setWatchOutsideTouch(true);
     window->setFrame(Rect{0, 0, 100, 100});
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setFrame(Rect{100, 100, 200, 200});
     sp<FakeWindowHandle> thirdWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     thirdWindow->setFrame(Rect{200, 200, 300, 300});
     mDispatcher->onWindowInfosChanged(
             {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
 
     // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
-    mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {PointF{-10, -10}}));
+    mDispatcher->notifyMotion(
+            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
     window->assertNoEvents();
     secondWindow->assertNoEvents();
 
     // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
     // Now, `window` should get ACTION_OUTSIDE.
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {PointF{-10, -10}, PointF{105, 105}}));
     const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
     window->consumeMotionEvent(
@@ -4933,7 +5262,8 @@
     // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
     // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
     mDispatcher->notifyMotion(
-            generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+            generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT,
                                {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
     window->assertNoEvents();
     secondWindow->consumeMotionMove();
@@ -4942,8 +5272,9 @@
 
 TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setFocusable(true);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -4951,13 +5282,15 @@
 
     window->consumeFocusEvent(true);
 
-    const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
-    const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+    const NotifyKeyArgs keyDown =
+            generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
+    const NotifyKeyArgs keyUp =
+            generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
     mDispatcher->notifyKey(keyDown);
     mDispatcher->notifyKey(keyUp);
 
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
 
     // All windows are removed from the display. Ensure that we can no longer dispatch to it.
     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
@@ -4971,22 +5304,23 @@
 
 TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     // Ensure window is non-split and have some transform.
     window->setPreventSplitting(true);
     window->setWindowOffset(20, 40);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
@@ -5017,12 +5351,12 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setPreventSplitting(false);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
     sp<FakeWindowHandle> rightWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     rightWindow->setPreventSplitting(true);
     rightWindow->setFrame(Rect(100, 100, 200, 200));
     mDispatcher->onWindowInfosChanged(
@@ -5045,12 +5379,12 @@
 
 TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
     sp<FakeWindowHandle> trustedOverlay =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     trustedOverlay->setSpy(true);
     trustedOverlay->setTrustedOverlay(true);
 
@@ -5113,8 +5447,8 @@
 
 TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -5170,8 +5504,8 @@
  */
 TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 400, 400));
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -5236,13 +5570,14 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> spyWindowDefaultDisplay =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                       ui::LogicalDisplayId::DEFAULT);
     spyWindowDefaultDisplay->setTrustedOverlay(true);
     spyWindowDefaultDisplay->setSpy(true);
 
     sp<FakeWindowHandle> windowDefaultDisplay =
             sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
 
     sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
@@ -5256,10 +5591,10 @@
              0,
              0});
 
-    // Send down to ADISPLAY_ID_DEFAULT
+    // Send down to ui::LogicalDisplayId::DEFAULT
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 100}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     spyWindowDefaultDisplay->consumeMotionDown();
@@ -5272,10 +5607,10 @@
     ASSERT_NE(nullptr, event);
     EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
 
-    // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
-    // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
-    // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
-    // SECOND_DISPLAY_ID, the x and y coordinates are 200
+    // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
+    // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
+    // the x and y coordinates are both 100, otherwise if the cancel event is sent to
+    // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
     EXPECT_EQ(100, event->getX(0));
     EXPECT_EQ(100, event->getY(0));
 }
@@ -5294,7 +5629,7 @@
         removeAllWindowsAndDisplays();
     }
 
-    void addDisplayInfo(int displayId, const ui::Transform& transform) {
+    void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
         gui::DisplayInfo info;
         info.displayId = displayId;
         info.transform = transform;
@@ -5319,7 +5654,7 @@
         // respectively.
         ui::Transform displayTransform;
         displayTransform.set(2, 0, 0, 4);
-        addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
+        addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
 
         std::shared_ptr<FakeApplicationHandle> application =
                 std::make_shared<FakeApplicationHandle>();
@@ -5327,13 +5662,13 @@
         // Add two windows to the display. Their frames are represented in the display space.
         sp<FakeWindowHandle> firstWindow =
                 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                           ADISPLAY_ID_DEFAULT);
+                                           ui::LogicalDisplayId::DEFAULT);
         firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
         addWindow(firstWindow);
 
         sp<FakeWindowHandle> secondWindow =
                 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                           ADISPLAY_ID_DEFAULT);
+                                           ui::LogicalDisplayId::DEFAULT);
         secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
         addWindow(secondWindow);
         return {std::move(firstWindow), std::move(secondWindow)};
@@ -5350,8 +5685,8 @@
     // selected so that if the hit test was performed with the point and the bounds being in
     // different coordinate spaces, the event would end up in the incorrect window.
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {PointF{75, 55}}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
 
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
@@ -5364,7 +5699,7 @@
     // Send down to the first window. The point is represented in the logical display space. The
     // point is selected so that if the hit test was done in logical display space, then it would
     // end up in the incorrect window.
-    injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                      PointF{75 * 2, 55 * 4});
 
     firstWindow->consumeMotionDown();
@@ -5383,7 +5718,7 @@
     const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
 
     MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                                .displayId(ADISPLAY_ID_DEFAULT)
+                                .displayId(ui::LogicalDisplayId::DEFAULT)
                                 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                                 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
                                                  .x(untransformedPoint.x)
@@ -5402,9 +5737,9 @@
     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
 
     // Send down to the second window.
-    mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {PointF{150, 220}}));
+    mDispatcher->notifyMotion(
+            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
 
     firstWindow->assertNoEvents();
     std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
@@ -5426,17 +5761,17 @@
     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
     // The monitor will always receive events in the logical display's coordinate space, because
     // it does not have a window.
-    FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
+    FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
 
     // Send down to the first window.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
+                                                 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
     monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
 
     // Second pointer goes down on second window.
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {PointF{50, 100}, PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
     const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
@@ -5457,7 +5792,7 @@
 
     // Send down to the first window.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
+                                                 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
 
     // The pointer is transferred to the second window, and the second window receives it in the
@@ -5472,13 +5807,15 @@
 
     // Send hover move to the second window, and ensure it shows up as hover enter.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                            WithCoords(100, 80), WithRawCoords(300, 880)));
 
     // Touch down at the same location and ensure a hover exit is synthesized.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
                                            WithRawCoords(300, 880)));
     secondWindow->consumeMotionEvent(
@@ -5503,14 +5840,16 @@
 
     // Send hover move to the second window, and ensure it shows up as hover enter.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                            WithCoords(100, 80), WithRawCoords(300, 880)));
 
     // Touch down at the same location and ensure a hover exit is synthesized for the correct
     // display.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
                                            WithRawCoords(300, 880)));
     secondWindow->consumeMotionEvent(
@@ -5524,7 +5863,8 @@
 
     // Send hover enter to second window
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                            WithCoords(100, 80), WithRawCoords(300, 880)));
 
@@ -5552,17 +5892,18 @@
 
     // Send hover enter to second window
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
-                                                 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {PointF{150, 220}}));
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                            WithCoords(100, 80), WithRawCoords(300, 880),
-                                           WithDisplayId(ADISPLAY_ID_DEFAULT)));
+                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
 
     mDispatcher->cancelCurrentTouch();
 
     // Ensure the cancelation happens with the correct displayId and the correct coordinates.
     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
                                            WithRawCoords(300, 880),
-                                           WithDisplayId(ADISPLAY_ID_DEFAULT)));
+                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     secondWindow->assertNoEvents();
     firstWindow->assertNoEvents();
 }
@@ -5589,13 +5930,13 @@
     const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
     const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
                                          logicalDisplayWidth, logicalDisplayHeight);
-    addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
+    addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
 
     // Create a window with its bounds determined in the logical display.
     const Rect frameInLogicalDisplay(100, 100, 200, 300);
     const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(frameInDisplay, displayTransform);
     addWindow(window);
 
@@ -5605,14 +5946,14 @@
     for (const auto pointInsideWindow : insidePoints) {
         const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
         const PointF pointInDisplaySpace{p.x, p.y};
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
         window->consumeMotionDown();
 
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
         window->consumeMotionUp();
     }
 
@@ -5622,13 +5963,13 @@
     for (const auto pointOutsideWindow : outsidePoints) {
         const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
         const PointF pointInDisplaySpace{p.x, p.y};
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
 
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
     }
     window->assertNoEvents();
 }
@@ -5652,7 +5993,7 @@
     const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
     const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
                                          logicalDisplayWidth, logicalDisplayHeight);
-    addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
+    addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
 
     // Create a window that not trusted.
     const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
@@ -5662,7 +6003,7 @@
 
     sp<FakeWindowHandle> untrustedWindow =
             sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
     untrustedWindow->setTrustedOverlay(false);
     untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
@@ -5678,7 +6019,7 @@
 
     sp<FakeWindowHandle> simpleAppWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
     simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
     addWindow(simpleAppWindow);
@@ -5691,12 +6032,12 @@
     for (const auto untrustedPoint : untrustedPoints) {
         const vec2 p = displayTransform.inverse().transform(untrustedPoint);
         const PointF pointInDisplaySpace{p.x, p.y};
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
     }
     untrustedWindow->assertNoEvents();
     simpleAppWindow->assertNoEvents();
@@ -5707,15 +6048,15 @@
     for (const auto trustedPoint : trustedPoints) {
         const vec2 p = displayTransform.inverse().transform(trustedPoint);
         const PointF pointInDisplaySpace{p.x, p.y};
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
-        simpleAppWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
+        simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
                                            AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
-        mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     {pointInDisplaySpace}));
-        simpleAppWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT,
+        mDispatcher->notifyMotion(
+                generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
+        simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
                                          AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
     }
     untrustedWindow->assertNoEvents();
@@ -5742,13 +6083,14 @@
     // Create a couple of windows
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setDupTouchToWallpaper(true);
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> wallpaper =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaper->setIsWallpaper(true);
     // Add the windows to the dispatcher, and ensure the first window is focused
     mDispatcher->onWindowInfosChanged(
@@ -5758,12 +6100,13 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
 
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
-    wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
     // Dispatcher reports pointer down outside focus for the wallpaper
     mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
 
@@ -5773,17 +6116,19 @@
     ASSERT_TRUE(success);
     // The first window gets cancel and the second gets down
     firstWindow->consumeMotionCancel();
-    secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
-    wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
     // There should not be any changes to the focused window when transferring touch
     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
 
     // Send up event to the second window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first window gets no events and the second gets up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                  AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     wallpaper->assertNoEvents();
 }
 
@@ -5803,14 +6148,15 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     // Create a couple of windows + a spy window
-    sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
+                                                                ui::LogicalDisplayId::DEFAULT);
     spyWindow->setTrustedOverlay(true);
     spyWindow->setSpy(true);
-    sp<FakeWindowHandle> firstWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> secondWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     // Add the windows to the dispatcher
     mDispatcher->onWindowInfosChanged(
@@ -5818,7 +6164,8 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
     // Only the first window and spy should get the down event
     spyWindow->consumeMotionDown();
     firstWindow->consumeMotionDown();
@@ -5830,15 +6177,17 @@
     ASSERT_TRUE(success);
     // The first window gets cancel and the second gets down
     firstWindow->consumeMotionCancel();
-    secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send up event to the second window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first  window gets no events and the second+spy get up
     firstWindow->assertNoEvents();
     spyWindow->consumeMotionUp();
-    secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                  AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 }
 
 TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
@@ -5849,11 +6198,11 @@
     // Create a couple of windows
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setPreventSplitting(true);
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setPreventSplitting(true);
 
     // Add the windows to the dispatcher
@@ -5862,15 +6211,16 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {touchPoint}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
 
     // Send pointer down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {touchPoint, touchPoint}));
     // Only the first window should get the pointer down event
     firstWindow->consumeMotionPointerDown(1);
     secondWindow->assertNoEvents();
@@ -5881,24 +6231,27 @@
     ASSERT_TRUE(success);
     // The first window gets cancel and the second gets down and pointer down
     firstWindow->consumeMotionCancel();
-    secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
-    secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
+    secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send pointer up to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
+                                                 ui::LogicalDisplayId::DEFAULT,
+                                                 {touchPoint, touchPoint}));
     // The first window gets nothing and the second gets pointer up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
+    secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
                                          AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send up event to the second window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first window gets nothing and the second gets up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                  AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 }
 
 TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
@@ -5907,19 +6260,21 @@
     // Create a couple of windows
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setDupTouchToWallpaper(true);
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setDupTouchToWallpaper(true);
 
     sp<FakeWindowHandle> wallpaper1 =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaper1->setIsWallpaper(true);
 
     sp<FakeWindowHandle> wallpaper2 =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
+                                       ui::LogicalDisplayId::DEFAULT);
     wallpaper2->setIsWallpaper(true);
     // Add the windows to the dispatcher
     mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
@@ -5930,12 +6285,13 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
 
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
-    wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+    wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
     wallpaper2->assertNoEvents();
 
     // Transfer touch focus to the second window
@@ -5945,20 +6301,22 @@
 
     // The first window gets cancel and the second gets down
     firstWindow->consumeMotionCancel();
-    secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
-    wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
-    wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
-                                  expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
+    wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                  EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send up event to the second window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first  window gets no events and the second gets up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                  AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     wallpaper1->assertNoEvents();
-    wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
-                                expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 }
 
 // For the cases of single pointer touch and two pointers non-split touch, the api's
@@ -5970,7 +6328,7 @@
                 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
                     sp<IBinder> destChannelToken) {
                     return dispatcher->transferTouchOnDisplay(destChannelToken,
-                                                              ADISPLAY_ID_DEFAULT);
+                                                              ui::LogicalDisplayId::DEFAULT);
                 },
                 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
                     sp<IBinder> to) {
@@ -5983,12 +6341,12 @@
 
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setFrame(Rect(0, 0, 600, 400));
 
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setFrame(Rect(0, 400, 600, 800));
 
     // Add the windows to the dispatcher
@@ -6000,15 +6358,15 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {pointInFirst}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
 
     // Send down to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {pointInFirst, pointInSecond}));
     // The first window gets a move and the second a down
     firstWindow->consumeMotionMove();
@@ -6018,24 +6376,25 @@
     mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
     // The first window gets cancel and the new gets pointer down (it already saw down)
     firstWindow->consumeMotionCancel();
-    secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
+    secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send pointer up to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {pointInFirst, pointInSecond}));
     // The first window gets nothing and the second gets pointer up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
+    secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
                                          AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     // Send up event to the second window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first window gets nothing and the second gets up
     firstWindow->assertNoEvents();
-    secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                  AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 }
 
 // Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
@@ -6047,12 +6406,12 @@
 
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setFrame(Rect(0, 0, 600, 400));
 
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setFrame(Rect(0, 400, 600, 800));
 
     // Add the windows to the dispatcher
@@ -6064,23 +6423,23 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {pointInFirst}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
 
     // Send down to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {pointInFirst, pointInSecond}));
     // The first window gets a move and the second a down
     firstWindow->consumeMotionMove();
     secondWindow->consumeMotionDown();
 
     // Transfer touch focus to the second window
-    const bool transferred =
-            mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
+    const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
+                                                                 ui::LogicalDisplayId::DEFAULT);
     // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
     ASSERT_FALSE(transferred);
     firstWindow->assertNoEvents();
@@ -6089,7 +6448,7 @@
     // The rest of the dispatch should proceed as normal
     // Send pointer up to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {pointInFirst, pointInSecond}));
     // The first window gets MOVE and the second gets pointer up
     firstWindow->consumeMotionMove();
@@ -6097,7 +6456,7 @@
 
     // Send up event to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first window gets nothing and the second gets up
     firstWindow->consumeMotionUp();
     secondWindow->assertNoEvents();
@@ -6109,13 +6468,16 @@
 TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> firstWindowInPrimary =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
     sp<FakeWindowHandle> secondWindowInPrimary =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
 
-    sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> mirrorWindowInPrimary =
+            firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
     mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
 
     sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
@@ -6134,35 +6496,36 @@
              0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Window should receive motion event.
-    firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     // Transfer touch
     ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
                                                   secondWindowInPrimary->getToken()));
     // The first window gets cancel.
     firstWindowInPrimary->consumeMotionCancel();
-    secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
+    secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {150, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     firstWindowInPrimary->assertNoEvents();
-    secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
+    secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     firstWindowInPrimary->assertNoEvents();
-    secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
+                                           AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 }
 
 // Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
@@ -6170,13 +6533,16 @@
 TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> firstWindowInPrimary =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
     sp<FakeWindowHandle> secondWindowInPrimary =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
 
-    sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> mirrorWindowInPrimary =
+            firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
     mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
 
     sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
@@ -6229,8 +6595,9 @@
 
 TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6238,10 +6605,10 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
 
     // Window should receive key down event.
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     // Should have poked user activity
     mDispatcher->waitForIdle();
@@ -6250,8 +6617,9 @@
 
 TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     window->setDisableUserActivity(true);
     window->setFocusable(true);
@@ -6260,10 +6628,10 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
 
     // Window should receive key down event.
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     // Should have poked user activity
     mDispatcher->waitForIdle();
@@ -6272,8 +6640,9 @@
 
 TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6281,7 +6650,8 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(
+            generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
 
     // System key is not passed down
@@ -6293,8 +6663,9 @@
 
 TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6302,7 +6673,8 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(
+            generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
 
     // System key is not passed down
@@ -6314,8 +6686,9 @@
 
 TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     window->setDisableUserActivity(true);
     window->setFocusable(true);
@@ -6324,7 +6697,8 @@
 
     window->consumeFocusEvent(true);
 
-    mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(
+            generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
 
     // System key is not passed down
@@ -6336,18 +6710,19 @@
 
 TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {100, 100}))
+                                ui::LogicalDisplayId::DEFAULT, {100, 100}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     window->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
 
     // Should have poked user activity
     mDispatcher->waitForIdle();
@@ -6356,12 +6731,13 @@
 
 TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
 
     window->assertNoEvents();
@@ -6370,19 +6746,21 @@
 // If a window is touchable, but does not have focus, it should receive motion events, but not keys
 TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     // Send key
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     // Send motion
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
 
     // Window should receive only the motion event
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     window->assertNoEvents(); // Key event or focus event will not be received
 }
 
@@ -6391,12 +6769,12 @@
 
     sp<FakeWindowHandle> firstWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     firstWindow->setFrame(Rect(0, 0, 600, 400));
 
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindow->setFrame(Rect(0, 400, 600, 800));
 
     // Add the windows to the dispatcher
@@ -6408,15 +6786,15 @@
 
     // Send down to the first window
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {pointInFirst}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
     // Only the first window should get the down event
     firstWindow->consumeMotionDown();
     secondWindow->assertNoEvents();
 
     // Send down to the second window
     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT,
+                                                 ui::LogicalDisplayId::DEFAULT,
                                                  {pointInFirst, pointInSecond}));
     // The first window gets a move and the second a down
     firstWindow->consumeMotionMove();
@@ -6424,17 +6802,17 @@
 
     // Send pointer cancel to the second window
     NotifyMotionArgs pointerUpMotionArgs =
-            generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {pointInFirst, pointInSecond});
+            generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
     pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
     mDispatcher->notifyMotion(pointerUpMotionArgs);
     // The first window gets move and the second gets cancel.
-    firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
-    secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
+    firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
+    secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
 
     // Send up event.
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     // The first window gets up and the second gets nothing.
     firstWindow->consumeMotionUp();
     secondWindow->assertNoEvents();
@@ -6443,8 +6821,8 @@
 TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
     graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
@@ -6467,28 +6845,29 @@
  */
 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                                             ui::LogicalDisplayId::DEFAULT);
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     // Both the foreground window and the global monitor should receive the touch down
     window->consumeMotionDown();
-    monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 200}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     window->consumeMotionMove();
-    monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
 
     // Now the foreground window goes away
     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
@@ -6499,41 +6878,47 @@
     // cause a cancel for the monitor, as well.
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {120, 200}))
+                                ui::LogicalDisplayId::DEFAULT, {120, 200}))
             << "Injection should fail because the window was removed";
     window->assertNoEvents();
     // Global monitor now gets the cancel
-    monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
 }
 
 TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     // Pilfer pointers from the monitor.
     // This should not do anything and the window should continue to receive events.
@@ -6541,27 +6926,30 @@
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT))
+                                ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
-    monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
-    window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
+    window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
 }
 
 TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     window->setWindowOffset(20, 40);
     window->setWindowTransform(0, 1, -1, 0);
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
     ASSERT_NE(nullptr, event);
     // Even though window has transform, gesture monitor must not.
@@ -6570,10 +6958,12 @@
 
 TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::FAILED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Injection should fail if there is a monitor, but no touchable window";
     monitor.assertNoEvents();
 }
@@ -6591,20 +6981,21 @@
  */
 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                                             ui::LogicalDisplayId::DEFAULT);
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
     FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "The down event injected into the first display should succeed";
 
     window->consumeMotionDown();
-    monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
@@ -6615,19 +7006,19 @@
     // Continue to inject event to first display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 220}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 220}))
             << "The move event injected into the first display should succeed";
 
     window->consumeMotionMove();
-    monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {110, 220}))
             << "The up event injected into the first display should succeed";
 
     window->consumeMotionUp();
-    monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
     window->assertNoEvents();
     monitor.assertNoEvents();
@@ -6651,24 +7042,25 @@
  */
 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                                             ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> secondWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
                                        SECOND_DISPLAY_ID);
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
     FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
 
     // There is a foreground window on both displays.
     mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "The down event injected into the first display should succeed";
 
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
@@ -6696,11 +7088,11 @@
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 200}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 200}))
             << "The move event injected into the first display should succeed";
 
     window->consumeMotionMove();
-    monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
@@ -6709,12 +7101,12 @@
                "touchable window";
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {110, 220}))
             << "The up event injected into the first display should succeed";
 
-    window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
-    monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
+    monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
     window->assertNoEvents();
     monitor.assertNoEvents();
@@ -6732,22 +7124,23 @@
  */
 TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
+                                                             ui::LogicalDisplayId::DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     ui::Transform transform;
     transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
 
     gui::DisplayInfo displayInfo;
-    displayInfo.displayId = ADISPLAY_ID_DEFAULT;
+    displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
     displayInfo.transform = transform;
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "The down event injected should succeed";
 
     window->consumeMotionDown();
@@ -6757,7 +7150,7 @@
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 220}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 220}))
             << "The move event injected should succeed";
 
     window->consumeMotionMove();
@@ -6773,19 +7166,19 @@
 
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 220}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 220}))
             << "The move event injected should failed";
     // Now foreground should not receive any events, but monitor should receive a cancel event
     // with transform that same as display's display.
     std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
     EXPECT_EQ(transform, cancelMotionEvent->getTransform());
-    EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
+    EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
     EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
 
     // Other event inject to this display should fail.
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 220}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 220}))
             << "The up event injected should fail because the touched window was removed";
     window->assertNoEvents();
     monitor.assertNoEvents();
@@ -6793,18 +7186,19 @@
 
 TEST_F(InputDispatcherTest, TestMoveEvent) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Fake Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
     NotifyMotionArgs motionArgs =
             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                               ADISPLAY_ID_DEFAULT);
+                               ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->notifyMotion(motionArgs);
     // Window should receive motion down event.
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
     motionArgs.id += 1;
@@ -6813,7 +7207,7 @@
                                              motionArgs.pointerCoords[0].getX() - 10);
 
     mDispatcher->notifyMotion(motionArgs);
-    window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
+    window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
 }
 
 /**
@@ -6823,12 +7217,13 @@
  */
 TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
     const WindowInfo& windowInfo = *window->getInfo();
 
     // Set focused application.
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     window->setFocusable(true);
 
     SCOPED_TRACE("Check default value of touch mode");
@@ -6843,7 +7238,7 @@
 
     SCOPED_TRACE("Disable touch mode");
     mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
-                                /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
+                                /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
     window->consumeTouchModeEvent(false);
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6857,7 +7252,7 @@
 
     SCOPED_TRACE("Enable touch mode again");
     mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
-                                /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
+                                /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
     window->consumeTouchModeEvent(true);
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6869,10 +7264,11 @@
 
 TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     window->setFocusable(true);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -6907,23 +7303,24 @@
 
 TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
 
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     ui::Transform transform;
     transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
 
     gui::DisplayInfo displayInfo;
-    displayInfo.displayId = ADISPLAY_ID_DEFAULT;
+    displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
     displayInfo.transform = transform;
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
 
     const NotifyMotionArgs motionArgs =
             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                               ADISPLAY_ID_DEFAULT);
+                               ui::LogicalDisplayId::DEFAULT);
     mDispatcher->notifyMotion(motionArgs);
 
     std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
@@ -6983,7 +7380,7 @@
     verifiedEvent.eventTimeNanos += 1;
     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
 
-    verifiedEvent.displayId += 1;
+    verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
 
     verifiedEvent.action += 1;
@@ -7010,11 +7407,12 @@
 
 TEST_F(InputDispatcherTest, SetFocusedWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> windowTop =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                                                ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> windowSecond =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     // Top window is also focusable but is not granted focus.
     windowTop->setFocusable(true);
@@ -7028,15 +7426,15 @@
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
 
     // Focused window should receive event.
-    windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
+    windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     windowTop->assertNoEvents();
 }
 
 TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
+                                                             ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     window->setFocusable(true);
     // Release channel for window is no longer valid.
@@ -7053,10 +7451,10 @@
 
 TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFocusable(false);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     setFocusedWindow(window);
@@ -7070,11 +7468,12 @@
 
 TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> windowTop =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                                                ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> windowSecond =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     windowTop->setFocusable(true);
     windowSecond->setFocusable(true);
@@ -7093,16 +7492,17 @@
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
 
     // Focused window should receive event.
-    windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
+    windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
 }
 
 TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> windowTop =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                                                ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> windowSecond =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     windowTop->setFocusable(true);
     windowSecond->setFocusable(false);
@@ -7116,18 +7516,18 @@
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
 
     // Event should be dropped.
-    windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
+    windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     windowSecond->assertNoEvents();
 }
 
 TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
+                                                             ui::LogicalDisplayId::DEFAULT);
     sp<FakeWindowHandle> previousFocusedWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
-                                       ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+                                       ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     window->setFocusable(true);
     previousFocusedWindow->setFocusable(true);
@@ -7144,7 +7544,7 @@
     // Injected key goes to pending queue.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
-                        ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
+                        ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
 
     // Window does not get focus event or key down.
     window->assertNoEvents();
@@ -7156,14 +7556,14 @@
     // Window receives focus event.
     window->consumeFocusEvent(true);
     // Focused window receives key down.
-    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 TEST_F(InputDispatcherTest, DisplayRemoved) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
+                                                             ui::LogicalDisplayId::DEFAULT);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     // window is granted focus.
     window->setFocusable(true);
@@ -7172,7 +7572,7 @@
     window->consumeFocusEvent(true);
 
     // When a display is removed window loses focus.
-    mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
+    mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
     window->consumeFocusEvent(false);
 }
 
@@ -7204,10 +7604,11 @@
     constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
 
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
     sp<FakeWindowHandle> slipperyExitWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                       ui::LogicalDisplayId::DEFAULT);
     slipperyExitWindow->setSlippery(true);
     // Make sure this one overlaps the bottom window
     slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
@@ -7216,7 +7617,8 @@
     slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
 
     sp<FakeWindowHandle> slipperyEnterWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                       ui::LogicalDisplayId::DEFAULT);
     slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
 
     mDispatcher->onWindowInfosChanged(
@@ -7224,20 +7626,20 @@
 
     // Use notifyMotion instead of injecting to avoid dealing with injection permissions
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {{50, 50}}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
     slipperyExitWindow->consumeMotionDown();
     slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
     mDispatcher->onWindowInfosChanged(
             {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {{51, 51}}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
 
     slipperyExitWindow->consumeMotionCancel();
 
-    slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
+    slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
                                            AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
 }
 
@@ -7252,12 +7654,14 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> leftSlipperyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                       ui::LogicalDisplayId::DEFAULT);
     leftSlipperyWindow->setSlippery(true);
     leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
 
     sp<FakeWindowHandle> rightDropTouchesWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                       ui::LogicalDisplayId::DEFAULT);
     rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
     rightDropTouchesWindow->setDropInput(true);
 
@@ -7288,12 +7692,14 @@
 TEST_F(InputDispatcherTest, InjectedTouchSlips) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> originalWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
+                                       ui::LogicalDisplayId::DEFAULT);
     originalWindow->setFrame(Rect(0, 0, 200, 200));
     originalWindow->setSlippery(true);
 
     sp<FakeWindowHandle> appearingWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
+                                       ui::LogicalDisplayId::DEFAULT);
     appearingWindow->setFrame(Rect(0, 0, 200, 200));
 
     mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
@@ -7347,17 +7753,18 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> leftWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
     leftWindow->setSlippery(true);
 
     sp<FakeWindowHandle> rightWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(100, 0, 200, 100));
 
     sp<FakeWindowHandle> spyWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     spyWindow->setFrame(Rect(200, 0, 300, 100));
     spyWindow->setSpy(true);
     spyWindow->setTrustedOverlay(true);
@@ -7407,21 +7814,22 @@
  * 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",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
     leftWindow->setSlippery(true);
 
     sp<FakeWindowHandle> middleWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     middleWindow->setFrame(Rect(100, 0, 200, 100));
 
     sp<FakeWindowHandle> rightWindow =
             sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(200, 0, 300, 100));
     rightWindow->setSlippery(true);
 
@@ -7480,20 +7888,21 @@
     using Uid = gui::Uid;
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> leftWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
+                                                                 ui::LogicalDisplayId::DEFAULT);
     leftWindow->setFrame(Rect(0, 0, 100, 100));
     leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
 
     sp<FakeWindowHandle> rightSpy =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
+                                       ui::LogicalDisplayId::DEFAULT);
     rightSpy->setFrame(Rect(100, 0, 200, 100));
     rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
     rightSpy->setSpy(true);
     rightSpy->setTrustedOverlay(true);
 
-    sp<FakeWindowHandle> rightWindow =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
+                                                                  ui::LogicalDisplayId::DEFAULT);
     rightWindow->setFrame(Rect(100, 0, 200, 100));
     rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
 
@@ -7558,8 +7967,8 @@
 TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
     window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
 
@@ -7568,14 +7977,14 @@
     ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
 
     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
-    ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
+    ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
     ASSERT_NO_FATAL_FAILURE(
             mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
 
     // The UP actions are not treated as device interaction.
     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
-    ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
+    ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
 }
@@ -7584,13 +7993,14 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                                           ADISPLAY_ID_DEFAULT);
+                                                           ui::LogicalDisplayId::DEFAULT);
     left->setFrame(Rect(0, 0, 100, 100));
-    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                            "Right Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> right =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     right->setFrame(Rect(100, 0, 200, 100));
-    sp<FakeWindowHandle> spy =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
+                                                          ui::LogicalDisplayId::DEFAULT);
     spy->setFrame(Rect(0, 0, 200, 100));
     spy->setTrustedOverlay(true);
     spy->setSpy(true);
@@ -7599,8 +8009,9 @@
             {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
 
     // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
-    NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
-                                                     ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
+    NotifyMotionArgs notifyArgs =
+            generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
+                               ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
     mDispatcher->notifyMotion(notifyArgs);
 
     std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
@@ -7613,8 +8024,8 @@
                                   WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
 
     // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
-    notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
-                                    {PointF{150, 50}});
+    notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
+                                    ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
     mDispatcher->notifyMotion(notifyArgs);
 
     std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
@@ -7636,8 +8047,8 @@
  */
 TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -7662,8 +8073,8 @@
  */
 TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
+                                                             ui::LogicalDisplayId::DEFAULT);
     window->setFrame(Rect(0, 0, 100, 100));
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
@@ -7693,7 +8104,8 @@
 
         mApp = std::make_shared<FakeApplicationHandle>();
 
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFrame(Rect(0, 0, 100, 100));
 
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
@@ -8005,7 +8417,8 @@
 
     void setUpWindow() {
         mApp = std::make_shared<FakeApplicationHandle>();
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
+                                             ui::LogicalDisplayId::DEFAULT);
 
         mWindow->setFocusable(true);
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
@@ -8014,13 +8427,14 @@
     }
 
     void sendAndConsumeKeyDown(int32_t deviceId) {
-        NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+        NotifyKeyArgs keyArgs =
+                generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
         keyArgs.deviceId = deviceId;
         keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
         mDispatcher->notifyKey(keyArgs);
 
         // Window should receive key down event.
-        mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+        mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     }
 
     void expectKeyRepeatOnce(int32_t repeatCount) {
@@ -8030,19 +8444,21 @@
     }
 
     void sendAndConsumeKeyUp(int32_t deviceId) {
-        NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+        NotifyKeyArgs keyArgs =
+                generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
         keyArgs.deviceId = deviceId;
         keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
         mDispatcher->notifyKey(keyArgs);
 
         // Window should receive key down event.
-        mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
+        mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
                               /*expectedFlags=*/0);
     }
 
     void injectKeyRepeat(int32_t repeatCount) {
         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-                  injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
+                  injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
+                            ui::LogicalDisplayId::DEFAULT))
                 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
     }
 };
@@ -8103,7 +8519,7 @@
     sendAndConsumeKeyDown(DEVICE_ID);
     expectKeyRepeatOnce(/*repeatCount=*/1);
     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
-    mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
                           AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
     mWindow->assertNoEvents();
 }
@@ -8135,7 +8551,7 @@
 
 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
     injectKeyRepeat(0);
-    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
         expectKeyRepeatOnce(repeatCount);
     }
@@ -8151,11 +8567,11 @@
         InputDispatcherTest::SetUp();
 
         application1 = std::make_shared<FakeApplicationHandle>();
-        windowInPrimary =
-                sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
+        windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
+                                                     ui::LogicalDisplayId::DEFAULT);
 
         // Set focus window for primary display, but focused display would be second one.
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
         windowInPrimary->setFocusable(true);
         mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
 
@@ -8196,9 +8612,10 @@
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
     // Test touch down on primary display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     windowInSecondary->assertNoEvents();
 
     // Test touch down on second display.
@@ -8212,22 +8629,22 @@
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
     // Test inject a key down with display id specified.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
+              injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     windowInSecondary->assertNoEvents();
 
     // Test inject a key down without display id specified.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
     windowInPrimary->assertNoEvents();
-    windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
+    windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
 
     // Remove all windows in secondary display.
     mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
 
     // Old focus should receive a cancel event.
-    windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
+    windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
 
     // Test inject a key down, should timeout because of no target window.
     ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
@@ -8239,16 +8656,17 @@
 // Test per-display input monitors for motion event.
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
     FakeMonitorReceiver monitorInPrimary =
-            FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
     FakeMonitorReceiver monitorInSecondary =
             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
 
     // Test touch down on primary display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     windowInSecondary->assertNoEvents();
     monitorInSecondary.assertNoEvents();
 
@@ -8272,19 +8690,20 @@
     // If specific a display, it will dispatch to the focused window of particular display,
     // or it will dispatch to the focused window of focused display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
+                               ui::LogicalDisplayId::INVALID))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     windowInPrimary->assertNoEvents();
     monitorInPrimary.assertNoEvents();
-    windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
-    monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
+    windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
+    monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
 }
 
 // Test per-display input monitors for key event.
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
     // Input monitor per display.
     FakeMonitorReceiver monitorInPrimary =
-            FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
     FakeMonitorReceiver monitorInSecondary =
             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
 
@@ -8293,13 +8712,14 @@
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
     windowInPrimary->assertNoEvents();
     monitorInPrimary.assertNoEvents();
-    windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
-    monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
+    windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
+    monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
 }
 
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
     sp<FakeWindowHandle> secondWindowInPrimary =
-            sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
+            sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
+                                       ui::LogicalDisplayId::DEFAULT);
     secondWindowInPrimary->setFocusable(true);
     mDispatcher->onWindowInfosChanged(
             {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
@@ -8313,25 +8733,26 @@
 
     // Test inject a key down.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
+              injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
     windowInPrimary->assertNoEvents();
     windowInSecondary->assertNoEvents();
-    secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
     FakeMonitorReceiver monitorInPrimary =
-            FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
     FakeMonitorReceiver monitorInSecondary =
             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
 
     // Test touch down on primary display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     // Test touch down on second display.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -8342,15 +8763,15 @@
 
     // Trigger cancel touch.
     mDispatcher->cancelCurrentTouch();
-    windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
-    monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
+    windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
+    monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
     windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
     monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
 
     // Test inject a move motion event, no window/monitor should receive the event.
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {110, 200}))
+                                ui::LogicalDisplayId::DEFAULT, {110, 200}))
             << "Inject motion event should return InputEventInjectionResult::FAILED";
     windowInPrimary->assertNoEvents();
     monitorInPrimary.assertNoEvents();
@@ -8373,11 +8794,11 @@
     // Send a key down on primary display
     mDispatcher->notifyKey(
             KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
                     .build());
-    windowInPrimary->consumeKeyEvent(
-            AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+    windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
+                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     windowInSecondary->assertNoEvents();
 
     // Send a key down on second display
@@ -8393,7 +8814,7 @@
     // Send a valid key up event on primary display that will be dropped because it is stale
     NotifyKeyArgs staleKeyUp =
             KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
                     .build();
     static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
@@ -8405,7 +8826,7 @@
     // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
     // receive any events.
     windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
-                                           WithDisplayId(ADISPLAY_ID_DEFAULT),
+                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT),
                                            WithFlags(AKEY_EVENT_FLAG_CANCELED)));
     windowInSecondary->assertNoEvents();
 }
@@ -8418,10 +8839,10 @@
     mDispatcher->notifyMotion(
             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .build());
     windowInPrimary->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     windowInSecondary->assertNoEvents();
 
     // Send touch down on second display.
@@ -8437,7 +8858,7 @@
     // inject a valid MotionEvent on primary display that will be stale when it arrives.
     NotifyMotionArgs staleMotionUp =
             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
                     .build();
     static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
@@ -8453,7 +8874,7 @@
 
 class InputFilterTest : public InputDispatcherTest {
 protected:
-    void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
+    void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
                           const ui::Transform& transform = ui::Transform()) {
         NotifyMotionArgs motionArgs;
 
@@ -8492,19 +8913,19 @@
 // Test InputFilter for MotionEvent
 TEST_F(InputFilterTest, MotionEvent_InputFilter) {
     // Since the InputFilter is disabled by default, check if touch events aren't filtered.
-    testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
+    testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
 
     // Enable InputFilter
     mDispatcher->setInputFilterEnabled(true);
     // Test touch on both primary and second display, and check if both events are filtered.
-    testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
+    testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
 
     // Disable InputFilter
     mDispatcher->setInputFilterEnabled(false);
     // Test touch on both primary and second display, and check if both events aren't filtered.
-    testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
+    testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
 }
 
@@ -8533,7 +8954,7 @@
     secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
 
     std::vector<gui::DisplayInfo> displayInfos(2);
-    displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
+    displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
     displayInfos[0].transform = firstDisplayTransform;
     displayInfos[1].displayId = SECOND_DISPLAY_ID;
     displayInfos[1].transform = secondDisplayTransform;
@@ -8544,7 +8965,8 @@
     mDispatcher->setInputFilterEnabled(true);
 
     // Ensure the correct transforms are used for the displays.
-    testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
+    testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
+                     firstDisplayTransform);
     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
 }
 
@@ -8563,9 +8985,9 @@
         std::shared_ptr<InputApplicationHandle> application =
                 std::make_shared<FakeApplicationHandle>();
         mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
-                                             ADISPLAY_ID_DEFAULT);
+                                             ui::LogicalDisplayId::DEFAULT);
 
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
         mWindow->setFocusable(true);
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
         setFocusedWindow(mWindow);
@@ -8578,8 +9000,8 @@
 
         const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
         event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
-                         ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
-                         KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
+                         ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
+                         AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
         const int32_t additionalPolicyFlags =
                 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -8659,20 +9081,20 @@
                 std::make_shared<FakeApplicationHandle>();
         application->setDispatchingTimeout(100ms);
         mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
-                                             ADISPLAY_ID_DEFAULT);
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFrame(Rect(0, 0, 100, 100));
         mWindow->setDispatchingTimeout(100ms);
         mWindow->setFocusable(true);
 
         // Set focused application.
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
 
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
         setFocusedWindow(mWindow);
         mWindow->consumeFocusEvent(true);
     }
 
-    void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
+    void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
                                 nsecs_t eventTime) {
         mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
                                           .displayId(displayId)
@@ -8693,50 +9115,55 @@
     mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
 
     // First event of type TOUCH. Should poke.
-    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(50));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
+              ui::LogicalDisplayId::DEFAULT}});
 
     // 80ns > 50ns has passed since previous TOUCH event. Should poke.
-    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(130));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
+              ui::LogicalDisplayId::DEFAULT}});
 
     // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
-    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
-                           milliseconds_to_nanoseconds(135));
+    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
+                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
+              ui::LogicalDisplayId::DEFAULT}});
 
     // Within 50ns of previous TOUCH event. Should NOT poke.
-    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(140));
     mFakePolicy->assertUserActivityNotPoked();
 
     // Within 50ns of previous OTHER event. Should NOT poke.
-    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
-                           milliseconds_to_nanoseconds(150));
+    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
+                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
     mFakePolicy->assertUserActivityNotPoked();
 
     // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
     // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
-    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(160));
     mFakePolicy->assertUserActivityNotPoked();
 
     // 65ns > 50ns has passed since previous OTHER event. Should poke.
-    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
-                           milliseconds_to_nanoseconds(200));
+    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
+                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
+              ui::LogicalDisplayId::DEFAULT}});
 
     // 170ns > 50ns has passed since previous TOUCH event. Should poke.
-    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(300));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
+              ui::LogicalDisplayId::DEFAULT}});
 
     // Assert that there's no more user activity poke event.
     mFakePolicy->assertUserActivityNotPoked();
@@ -8746,19 +9173,21 @@
         InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
         REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
                                             rate_limit_user_activity_poke_in_dispatcher))) {
-    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(200));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
+              ui::LogicalDisplayId::DEFAULT}});
 
-    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(280));
     mFakePolicy->assertUserActivityNotPoked();
 
-    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                            milliseconds_to_nanoseconds(340));
     mFakePolicy->assertUserActivityPoked(
-            {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
+            {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
+              ui::LogicalDisplayId::DEFAULT}});
 }
 
 TEST_F_WITH_FLAGS(
@@ -8767,10 +9196,12 @@
                                             rate_limit_user_activity_poke_in_dispatcher))) {
     mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
 
-    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
+    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
+                           20);
     mFakePolicy->assertUserActivityPoked();
 
-    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
+    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
+                           30);
     mFakePolicy->assertUserActivityPoked();
 }
 
@@ -8780,16 +9211,16 @@
 
         std::shared_ptr<FakeApplicationHandle> application =
                 std::make_shared<FakeApplicationHandle>();
-        mUnfocusedWindow =
-                sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
+        mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
+                                                      ui::LogicalDisplayId::DEFAULT);
         mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
 
-        mFocusedWindow =
-                sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
+        mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
+                                                    ui::LogicalDisplayId::DEFAULT);
         mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
 
         // Set focused application.
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
         mFocusedWindow->setFocusable(true);
 
         // Expect one focus window exist in display.
@@ -8817,8 +9248,8 @@
 // the onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {20, 20}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {20, 20}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     mUnfocusedWindow->consumeMotionDown();
 
@@ -8831,7 +9262,7 @@
 // onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
                                {20, 20}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     mFocusedWindow->consumeMotionDown();
@@ -8844,9 +9275,9 @@
 // have focus. Ensure no window received the onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
+              injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -8857,8 +9288,8 @@
 // onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               FOCUSED_WINDOW_TOUCH_POINT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     mFocusedWindow->consumeMotionDown();
 
@@ -8877,7 +9308,8 @@
                     .build();
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                           AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
 
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -8894,10 +9326,10 @@
         std::shared_ptr<FakeApplicationHandle> application =
                 std::make_shared<FakeApplicationHandle>();
         mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
-                                              ADISPLAY_ID_DEFAULT);
+                                              ui::LogicalDisplayId::DEFAULT);
         mWindow1->setFrame(Rect(0, 0, 100, 100));
 
-        mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
+        mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
         mWindow2->setFrame(Rect(100, 100, 200, 200));
 
         mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
@@ -8938,7 +9370,7 @@
                                  const std::vector<PointF>& touchedPoints,
                                  std::vector<PointF> expectedPoints) {
         mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
-                                                     ADISPLAY_ID_DEFAULT, touchedPoints));
+                                                     ui::LogicalDisplayId::DEFAULT, touchedPoints));
 
         consumeMotionEvent(touchedWindow, action, expectedPoints);
     }
@@ -9085,14 +9517,14 @@
 
     // Touch down in window 1
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {{50, 50}}));
+                                                 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
     consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
 
     // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
     // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
     // getting generated.
     mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT, {{150, 150}}));
+                                                 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
 
     consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
 }
@@ -9127,13 +9559,13 @@
         mApplication = std::make_shared<FakeApplicationHandle>();
         mApplication->setDispatchingTimeout(100ms);
         mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
-                                             ADISPLAY_ID_DEFAULT);
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFrame(Rect(0, 0, 30, 30));
         mWindow->setDispatchingTimeout(100ms);
         mWindow->setFocusable(true);
 
         // Set focused application.
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
 
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
         setFocusedWindow(mWindow);
@@ -9164,8 +9596,8 @@
     }
 
     sp<FakeWindowHandle> addSpyWindow() {
-        sp<FakeWindowHandle> spy =
-                sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+        sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
+                                                              ui::LogicalDisplayId::DEFAULT);
         spy->setTrustedOverlay(true);
         spy->setFocusable(false);
         spy->setSpy(true);
@@ -9187,7 +9619,7 @@
 // Send a regular key and respond, which should not cause an ANR.
 TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyAnrWasNotCalled();
 }
@@ -9198,15 +9630,16 @@
     mWindow->consumeFocusEvent(false);
 
     InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
+                      CONSUME_TIMEOUT_EVENT_EXPECTED,
                       /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
     // Key will not go to window because we have no focused window.
     // The 'no focused window' ANR timer should start instead.
 
     // Now, the focused application goes away.
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
     // The key should get dropped and there should be no ANR.
 
     ASSERT_TRUE(mDispatcher->waitForIdle());
@@ -9218,8 +9651,8 @@
 // So InputDispatcher will enqueue ACTION_CANCEL event as well.
 TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
 
     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
     ASSERT_TRUE(sequenceNum);
@@ -9228,7 +9661,7 @@
 
     mWindow->finishEvent(*sequenceNum);
     mWindow->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
 }
@@ -9252,8 +9685,8 @@
 
     // taps on the window work as normal
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
     mDispatcher->waitForIdle();
     mFakePolicy->assertNotifyAnrWasNotCalled();
@@ -9262,8 +9695,9 @@
     // We specify the injection timeout to be smaller than the application timeout, to ensure that
     // injection times out (instead of failing).
     const InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
+                      /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
     mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
@@ -9286,9 +9720,10 @@
             std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
 
     // Define a valid key down event that is stale (too old).
-    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
-                     INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
-                     AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
+    event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+                     ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
+                     /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
+                     eventTime);
 
     const int32_t policyFlags =
             POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
@@ -9310,7 +9745,7 @@
 TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
     const std::chrono::duration appTimeout = 400ms;
     mApplication->setDispatchingTimeout(appTimeout);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
 
     mWindow->setFocusable(false);
     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
@@ -9322,8 +9757,9 @@
     const std::chrono::duration eventInjectionTimeout = 100ms;
     ASSERT_LT(eventInjectionTimeout, appTimeout);
     const InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
+                      eventInjectionTimeout,
                       /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
             << "result=" << ftl::enum_string(result);
@@ -9371,20 +9807,20 @@
 TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                      ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
+                      ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
                       {AMOTION_EVENT_INVALID_CURSOR_POSITION,
                        AMOTION_EVENT_INVALID_CURSOR_POSITION},
                       500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
 
     // Now send ACTION_UP, with identical timestamp
     injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                      ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
+                      ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
                       {AMOTION_EVENT_INVALID_CURSOR_POSITION,
                        AMOTION_EVENT_INVALID_CURSOR_POSITION},
                       500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
 
     // We have now sent down and up. Let's consume first event and then ANR on the second.
-    mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
 }
@@ -9394,8 +9830,8 @@
     sp<FakeWindowHandle> spy = addSpyWindow();
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
     mWindow->consumeMotionDown();
 
     const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
@@ -9405,7 +9841,7 @@
 
     spy->finishEvent(*sequenceNum);
     spy->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
 }
@@ -9416,9 +9852,10 @@
     sp<FakeWindowHandle> spy = addSpyWindow();
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
-    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
-    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
+              injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
 
     // Stuck on the ACTION_UP
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
@@ -9426,10 +9863,10 @@
 
     // New tap will go to the spy window, but not to the window
     tapOnWindow();
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
-    mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
     mDispatcher->waitForIdle();
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
     mWindow->assertNoEvents();
@@ -9442,8 +9879,8 @@
     sp<FakeWindowHandle> spy = addSpyWindow();
 
     tapOnWindow();
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
     mWindow->consumeMotionDown();
     // Stuck on the ACTION_UP
@@ -9452,10 +9889,10 @@
 
     // New tap will go to the spy window, but not to the window
     tapOnWindow();
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 
-    mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
+    mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
     mDispatcher->waitForIdle();
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
     mWindow->assertNoEvents();
@@ -9465,13 +9902,14 @@
 TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
     mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
 
-    FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    FakeMonitorReceiver monitor =
+            FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
 
-    mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
     ASSERT_TRUE(consumeSeq);
 
@@ -9479,7 +9917,7 @@
                                                          MONITOR_PID);
 
     monitor.finishEvent(*consumeSeq);
-    monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
+    monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
 
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
@@ -9518,8 +9956,8 @@
 // it.
 TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
 
     const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
@@ -9529,7 +9967,7 @@
     // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
     mWindow->consumeMotionDown();
     mWindow->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     mWindow->assertNoEvents();
     mDispatcher->waitForIdle();
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
@@ -9566,7 +10004,7 @@
     std::this_thread::sleep_for(400ms);
     // if we wait long enough though, dispatcher will give up, and still send the key
     // to the focused window, even though we have not yet finished the motion event
-    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     mWindow->finishEvent(*downSequenceNum);
     mWindow->finishEvent(*upSequenceNum);
 }
@@ -9670,8 +10108,8 @@
 // So InputDispatcher will enqueue ACTION_CANCEL event as well.
 TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {WINDOW_LOCATION}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
 
     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
     ASSERT_TRUE(sequenceNum);
@@ -9688,7 +10126,7 @@
     mWindow->finishEvent(*sequenceNum);
     // The cancellation was generated when the window was removed, along with the focus event.
     mWindow->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     mWindow->consumeFocusEvent(false);
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
@@ -9698,8 +10136,8 @@
 // notified of the unresponsive window, then remove the app window.
 TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {WINDOW_LOCATION}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
 
     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
     ASSERT_TRUE(sequenceNum);
@@ -9712,7 +10150,7 @@
     mWindow->finishEvent(*sequenceNum);
     // The cancellation was generated during the ANR, and the window lost focus when it was removed.
     mWindow->consumeMotionEvent(
-            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
     mWindow->consumeFocusEvent(false);
     ASSERT_TRUE(mDispatcher->waitForIdle());
     // Since the window was removed, Dispatcher does not know the PID associated with the window
@@ -9727,18 +10165,18 @@
         mApplication = std::make_shared<FakeApplicationHandle>();
         mApplication->setDispatchingTimeout(100ms);
         mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
-                                                      ADISPLAY_ID_DEFAULT);
+                                                      ui::LogicalDisplayId::DEFAULT);
         mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
         // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
         mUnfocusedWindow->setWatchOutsideTouch(true);
 
         mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
-                                                    ADISPLAY_ID_DEFAULT);
+                                                    ui::LogicalDisplayId::DEFAULT);
         mFocusedWindow->setDispatchingTimeout(100ms);
         mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
 
         // Set focused application.
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
         mFocusedWindow->setFocusable(true);
 
         // Expect one focus window exist in display.
@@ -9770,11 +10208,11 @@
 private:
     void tap(const PointF& location) {
         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-                  injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                   location));
+                  injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                                   ui::LogicalDisplayId::DEFAULT, location));
         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-                  injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                 location));
+                  injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                                 ui::LogicalDisplayId::DEFAULT, location));
     }
 };
 
@@ -9799,7 +10237,7 @@
                                         .build()));
     mFocusedWindow->consumeMotionDown();
     mFocusedWindow->consumeMotionUp();
-    mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
+    mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
     // We consumed all events, so no ANR
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyAnrWasNotCalled();
@@ -9875,7 +10313,7 @@
 // At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
 TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
     tapOnFocusedWindow();
-    mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
+    mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
     // Receive the events, but don't respond
     const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
     ASSERT_TRUE(downEventSequenceNum);
@@ -9888,10 +10326,10 @@
     // Tap once again
     // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
     ASSERT_EQ(InputEventInjectionResult::FAILED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               FOCUSED_WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
     ASSERT_EQ(InputEventInjectionResult::FAILED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              FOCUSED_WINDOW_LOCATION));
     // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
     // valid touch target
@@ -9912,8 +10350,8 @@
 // If you tap outside of all windows, there will not be ANR
 TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
     ASSERT_EQ(InputEventInjectionResult::FAILED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               LOCATION_OUTSIDE_ALL_WINDOWS));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyAnrWasNotCalled();
 }
@@ -9925,8 +10363,8 @@
             {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::FAILED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               FOCUSED_WINDOW_LOCATION));
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
 
     std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
     ASSERT_TRUE(mDispatcher->waitForIdle());
@@ -9966,8 +10404,9 @@
     // window even if motions are still being processed.
 
     InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
+                      /*injectionTimeout=*/100ms);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
     // Key will not be sent to the window, yet, because the window is still processing events
     // and the key remains pending, waiting for the touch events to be processed.
@@ -9993,7 +10432,7 @@
 
     // Now that all queues are cleared and no backlog in the connections, the key event
     // can finally go to the newly focused "mUnfocusedWindow".
-    mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
     mFocusedWindow->assertNoEvents();
     mUnfocusedWindow->assertNoEvents();
     mFakePolicy->assertNotifyAnrWasNotCalled();
@@ -10004,14 +10443,15 @@
 // The other window should not be affected by that.
 TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
     // Touch Window 1
-    mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {FOCUSED_WINDOW_LOCATION}));
-    mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
+    mDispatcher->notifyMotion(
+            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
+    mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
 
     // Touch Window 2
     mDispatcher->notifyMotion(
-            generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+            generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT,
                                {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
 
     const std::chrono::duration timeout =
@@ -10057,7 +10497,7 @@
     std::shared_ptr<FakeApplicationHandle> focusedApplication =
             std::make_shared<FakeApplicationHandle>();
     focusedApplication->setDispatchingTimeout(300ms);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
     // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
     mFocusedWindow->setFocusable(false);
 
@@ -10069,8 +10509,9 @@
     // 'focusedApplication' will get blamed if this timer completes.
     // Key will not be sent anywhere because we have no focused window. It will remain pending.
     InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
+                      /*injectionTimeout=*/100ms,
                       /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
 
@@ -10084,9 +10525,9 @@
     std::this_thread::sleep_for(100ms);
 
     // Touch unfocused window. This should force the pending key to get dropped.
-    mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {UNFOCUSED_WINDOW_LOCATION}));
+    mDispatcher->notifyMotion(
+            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
 
     // We do not consume the motion right away, because that would require dispatcher to first
     // process (== drop) the key event, and by that time, ANR will be raised.
@@ -10139,20 +10580,20 @@
     mFakePolicy->setStaleEventTimeout(3000ms);
     sp<FakeWindowHandle> navigationBar =
             sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     navigationBar->setFocusable(false);
     navigationBar->setWatchOutsideTouch(true);
     navigationBar->setFrame(Rect(0, 0, 100, 100));
 
     mApplication->setDispatchingTimeout(3000ms);
     // 'mApplication' is already focused, but we call it again here to make it explicit.
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
 
     std::shared_ptr<FakeApplicationHandle> anotherApplication =
             std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> appWindow =
             sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     appWindow->setFocusable(false);
     appWindow->setFrame(Rect(100, 100, 200, 200));
 
@@ -10171,8 +10612,9 @@
     // Key will not be sent anywhere because we have no focused window. It will remain pending.
     // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
     InputEventInjectionResult result =
-            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                      InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
+            injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
+                      ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
+                      /*injectionTimeout=*/100ms,
                       /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
 
@@ -10180,8 +10622,9 @@
     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
                                       .build());
-    result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
-                       InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
+    result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
+                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
+                       /*injectionTimeout=*/100ms,
                        /*allowKeyRepeat=*/false);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
     // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
@@ -10216,16 +10659,16 @@
         InputDispatcherTest::SetUp();
 
         mApplication = std::make_shared<FakeApplicationHandle>();
-        mNoInputWindow =
-                sp<FakeWindowHandle>::make(mApplication, mDispatcher,
-                                           "Window without input channel", ADISPLAY_ID_DEFAULT,
-                                           /*createInputChannel=*/false);
+        mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
+                                                    "Window without input channel",
+                                                    ui::LogicalDisplayId::DEFAULT,
+                                                    /*createInputChannel=*/false);
         mNoInputWindow->setNoInputChannel(true);
         mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
         // It's perfectly valid for this window to not have an associated input channel
 
         mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
-                                                   ADISPLAY_ID_DEFAULT);
+                                                   ui::LogicalDisplayId::DEFAULT);
         mBottomWindow->setFrame(Rect(0, 0, 100, 100));
 
         mDispatcher->onWindowInfosChanged(
@@ -10242,8 +10685,8 @@
     PointF touchedPoint = {10, 10};
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {touchedPoint}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
 
     mNoInputWindow->assertNoEvents();
     // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
@@ -10260,7 +10703,7 @@
        NoInputChannelFeature_DropsTouchesWithValidChannel) {
     mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
                                                 "Window with input channel and NO_INPUT_CHANNEL",
-                                                ADISPLAY_ID_DEFAULT);
+                                                ui::LogicalDisplayId::DEFAULT);
 
     mNoInputWindow->setNoInputChannel(true);
     mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
@@ -10270,8 +10713,8 @@
     PointF touchedPoint = {10, 10};
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                 {touchedPoint}));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
 
     mNoInputWindow->assertNoEvents();
     mBottomWindow->assertNoEvents();
@@ -10286,9 +10729,10 @@
     virtual void SetUp() override {
         InputDispatcherTest::SetUp();
         mApp = std::make_shared<FakeApplicationHandle>();
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
-        mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
+                                             ui::LogicalDisplayId::DEFAULT);
+        mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
         mWindow->setFocusable(true);
         mMirror->setFocusable(true);
         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
@@ -10303,7 +10747,7 @@
     mWindow->consumeFocusEvent(true);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
 }
 
 // A focused & mirrored window remains focused only if the window and its mirror are both
@@ -10315,10 +10759,10 @@
     mWindow->consumeFocusEvent(true);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     mMirror->setFocusable(false);
     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
@@ -10340,20 +10784,20 @@
     mWindow->consumeFocusEvent(true);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     mMirror->setVisible(false);
     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     mWindow->setVisible(false);
     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
@@ -10374,20 +10818,20 @@
     mWindow->consumeFocusEvent(true);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
+    mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     // single window is removed but the window token remains focused
     mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
+    mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
+    mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     // Both windows are removed
     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
@@ -10409,7 +10853,7 @@
     // Injected key goes to pending queue.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
-                        ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
+                        ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
 
     mMirror->setVisible(true);
     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
@@ -10417,7 +10861,7 @@
     // window gets focused
     mWindow->consumeFocusEvent(true);
     // window gets the pending key event
-    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
@@ -10429,13 +10873,14 @@
     void SetUp() override {
         InputDispatcherTest::SetUp();
         mApp = std::make_shared<FakeApplicationHandle>();
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFocusable(true);
-        mSecondWindow =
-                sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
+        mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
+                                                   ui::LogicalDisplayId::DEFAULT);
         mSecondWindow->setFocusable(true);
 
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
         mDispatcher->onWindowInfosChanged(
                 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
 
@@ -10674,7 +11119,7 @@
     sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
         std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
         sp<FakeWindowHandle> window =
-                sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
+                sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
         // Generate an arbitrary PID based on the UID
         window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
         return window;
@@ -10682,8 +11127,8 @@
 
     void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
         mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                     AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                                                     points));
+                                                     AINPUT_SOURCE_TOUCHSCREEN,
+                                                     ui::LogicalDisplayId::DEFAULT, points));
     }
 };
 
@@ -11048,20 +11493,21 @@
     void SetUp() override {
         InputDispatcherTest::SetUp();
         mApp = std::make_shared<FakeApplicationHandle>();
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFrame(Rect(0, 0, 100, 100));
 
-        mSecondWindow =
-                sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
+        mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
+                                                   ui::LogicalDisplayId::DEFAULT);
         mSecondWindow->setFrame(Rect(100, 0, 200, 100));
 
-        mSpyWindow =
-                sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
+        mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
+                                                ui::LogicalDisplayId::DEFAULT);
         mSpyWindow->setSpy(true);
         mSpyWindow->setTrustedOverlay(true);
         mSpyWindow->setFrame(Rect(0, 0, 200, 100));
 
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
         mDispatcher->onWindowInfosChanged(
                 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
                  {},
@@ -11074,7 +11520,7 @@
             case AINPUT_SOURCE_TOUCHSCREEN:
                 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                           injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
-                                           ADISPLAY_ID_DEFAULT, {50, 50}))
+                                           ui::LogicalDisplayId::DEFAULT, {50, 50}))
                         << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
                 break;
             case AINPUT_SOURCE_STYLUS:
@@ -11106,9 +11552,9 @@
         }
 
         // Window should receive motion event.
-        mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+        mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
         // Spy window should also receive motion event
-        mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+        mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     }
 
     // Start performing drag, we will create a drag window and transfer touch to it.
@@ -11120,8 +11566,8 @@
         }
 
         // The drag window covers the entire display
-        mDragWindow =
-                sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
+        mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
+                                                 ui::LogicalDisplayId::DEFAULT);
         mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
         mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
                                             *mWindow->getInfo(), *mSecondWindow->getInfo()},
@@ -11135,7 +11581,8 @@
                                                   /*isDragDrop=*/true);
         if (transferred) {
             mWindow->consumeMotionCancel();
-            mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+            mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                                           AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
         }
         return transferred;
     }
@@ -11147,35 +11594,38 @@
     // Move on window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {50, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
     // Move to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {150, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(true, 150, 50);
     mSecondWindow->consumeDragEvent(false, 50, 50);
 
     // Move back to original window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {50, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->consumeDragEvent(true, -50, 50);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
 }
@@ -11210,27 +11660,29 @@
     // Move on window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {50, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
     // Move to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {150, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(true, 150, 50);
     mSecondWindow->consumeDragEvent(false, 50, 50);
 
     // drop to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
@@ -11292,7 +11744,8 @@
                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
@@ -11304,7 +11757,8 @@
                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
@@ -11317,7 +11771,7 @@
                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
 }
@@ -11333,27 +11787,29 @@
     // Move on window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {50, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
     // Move to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {150, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(true, 150, 50);
     mSecondWindow->assertNoEvents();
 
     // drop to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
@@ -11364,14 +11820,14 @@
     mWindow->setPreventSplitting(true);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
@@ -11389,16 +11845,16 @@
 TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
     // First down on second window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {150, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
-    mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     // Second down on first window.
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
@@ -11407,8 +11863,8 @@
               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
                                 InputEventInjectionSync::WAIT_FOR_RESULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
 
     // Perform drag and drop from first window.
     ASSERT_TRUE(startDrag(false));
@@ -11423,7 +11879,8 @@
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
                                 InputEventInjectionSync::WAIT_FOR_RESULT));
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->consumeMotionMove();
 
@@ -11437,7 +11894,7 @@
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
                                 InputEventInjectionSync::WAIT_FOR_RESULT));
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
     mWindow->assertNoEvents();
     mSecondWindow->consumeMotionMove();
@@ -11476,27 +11933,29 @@
     // Move on window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {50, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
     // Move to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT, {150, 50}))
+                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(true, 150, 50);
     mSecondWindow->consumeDragEvent(false, 50, 50);
 
     // drop to another window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
@@ -11514,7 +11973,8 @@
                                                          .y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(false, 50, 50);
     mSecondWindow->assertNoEvents();
 
@@ -11528,7 +11988,8 @@
                                                          .y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mWindow->consumeDragEvent(true, 150, 50);
     mSecondWindow->consumeDragEvent(false, 50, 50);
 
@@ -11542,7 +12003,7 @@
                                                          .y(50))
                                         .build()))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+    mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
@@ -11555,8 +12016,8 @@
 TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
     // Down on second window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {150, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {150, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
@@ -11565,7 +12026,7 @@
     // Down on first window
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
                     .build();
@@ -11583,7 +12044,7 @@
     // Trigger cancel
     mDispatcher->cancelCurrentTouch();
     ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
-    ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
+    ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
                                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
 
@@ -11596,14 +12057,14 @@
 
     // Inject a simple gesture, ensure dispatcher not crashed
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               PointF{50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
 
     const MotionEvent moveEvent =
             MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
                     .build();
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -11613,7 +12074,7 @@
     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                              {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
@@ -11623,7 +12084,7 @@
     // Start hovering over the window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
-                                ADISPLAY_ID_DEFAULT, {50, 50}));
+                                ui::LogicalDisplayId::DEFAULT, {50, 50}));
 
     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
@@ -11636,23 +12097,25 @@
 
 TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setDropInput(true);
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
     setFocusedWindow(window);
     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
 
     // With the flag set, window should not get any input
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     window->assertNoEvents();
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     mDispatcher->waitForIdle();
     window->assertNoEvents();
 
@@ -11660,12 +12123,13 @@
     window->setDropInput(false);
     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     window->assertNoEvents();
 }
 
@@ -11674,16 +12138,17 @@
             std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> obscuringWindow =
             sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     obscuringWindow->setFrame(Rect(0, 0, 50, 50));
     obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
     obscuringWindow->setTouchable(false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setDropInputIfObscured(true);
     window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged(
             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
@@ -11691,13 +12156,14 @@
     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
 
     // With the flag set, window should not get any input
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     window->assertNoEvents();
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     window->assertNoEvents();
 
     // With the flag cleared, the window should get input
@@ -11705,12 +12171,14 @@
     mDispatcher->onWindowInfosChanged(
             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
+                              AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
     window->assertNoEvents();
 }
 
@@ -11719,16 +12187,17 @@
             std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> obscuringWindow =
             sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
-                                       ADISPLAY_ID_DEFAULT);
+                                       ui::LogicalDisplayId::DEFAULT);
     obscuringWindow->setFrame(Rect(0, 0, 50, 50));
     obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
     obscuringWindow->setTouchable(false);
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
-    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                             "Test window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
+                                       ui::LogicalDisplayId::DEFAULT);
     window->setDropInputIfObscured(true);
     window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
     window->setFocusable(true);
     mDispatcher->onWindowInfosChanged(
             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
@@ -11736,25 +12205,27 @@
     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
 
     // With the flag set, window should not get any input
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
     window->assertNoEvents();
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
-                                                 ADISPLAY_ID_DEFAULT));
+                                                 ui::LogicalDisplayId::DEFAULT));
     window->assertNoEvents();
 
     // When the window is no longer obscured because it went on top, it should get input
     mDispatcher->onWindowInfosChanged(
             {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
 
-    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
-    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+    mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
+    window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
 
     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
-                                                 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+                                                 AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ui::LogicalDisplayId::DEFAULT));
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     window->assertNoEvents();
 }
 
@@ -11771,18 +12242,19 @@
 
         mApp = std::make_shared<FakeApplicationHandle>();
         mSecondaryApp = std::make_shared<FakeApplicationHandle>();
-        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+        mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
+                                             ui::LogicalDisplayId::DEFAULT);
         mWindow->setFocusable(true);
         setFocusedWindow(mWindow);
-        mSecondWindow =
-                sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
+        mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
+                                                   ui::LogicalDisplayId::DEFAULT);
         mSecondWindow->setFocusable(true);
         mThirdWindow =
                 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
                                            "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
         mThirdWindow->setFocusable(true);
 
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
         mDispatcher->onWindowInfosChanged(
                 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
                  {},
@@ -11793,7 +12265,8 @@
 
         // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
         if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
-                                        WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
+                                        WINDOW_UID, /*hasPermission=*/true,
+                                        ui::LogicalDisplayId::DEFAULT)) {
             mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
             mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
             mThirdWindow->assertNoEvents();
@@ -11812,7 +12285,7 @@
     void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
                                                    bool hasPermission) {
         ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
-                                                ADISPLAY_ID_DEFAULT));
+                                                ui::LogicalDisplayId::DEFAULT));
         mWindow->consumeTouchModeEvent(inTouchMode);
         mSecondWindow->consumeTouchModeEvent(inTouchMode);
         mThirdWindow->assertNoEvents();
@@ -11833,7 +12306,7 @@
     mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
     ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
                                              ownerUid, /*hasPermission=*/false,
-                                             ADISPLAY_ID_DEFAULT));
+                                             ui::LogicalDisplayId::DEFAULT));
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
 }
@@ -11851,7 +12324,8 @@
     const WindowInfo& windowInfo = *mWindow->getInfo();
     ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
                                              windowInfo.ownerPid, windowInfo.ownerUid,
-                                             /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
+                                             /*hasPermission=*/true,
+                                             ui::LogicalDisplayId::DEFAULT));
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
 }
@@ -11869,9 +12343,9 @@
 TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
     // Interact with the window first.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
+              injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
 
     // Then remove focus.
     mWindow->setFocusable(false);
@@ -11881,7 +12355,8 @@
     const WindowInfo& windowInfo = *mWindow->getInfo();
     ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
                                             windowInfo.ownerPid, windowInfo.ownerUid,
-                                            /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
+                                            /*hasPermission=*/false,
+                                            ui::LogicalDisplayId::DEFAULT));
 }
 
 class InputDispatcherSpyWindowTest : public InputDispatcherTest {
@@ -11891,8 +12366,9 @@
                 std::make_shared<FakeApplicationHandle>();
         std::string name = "Fake Spy ";
         name += std::to_string(mSpyCount++);
-        sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                              name.c_str(), ADISPLAY_ID_DEFAULT);
+        sp<FakeWindowHandle> spy =
+                sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
+                                           ui::LogicalDisplayId::DEFAULT);
         spy->setSpy(true);
         spy->setTrustedOverlay(true);
         return spy;
@@ -11903,7 +12379,7 @@
                 std::make_shared<FakeApplicationHandle>();
         sp<FakeWindowHandle> window =
                 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
-                                           ADISPLAY_ID_DEFAULT);
+                                           ui::LogicalDisplayId::DEFAULT);
         window->setFocusable(true);
         return window;
     }
@@ -11934,9 +12410,10 @@
     mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 }
 
 /**
@@ -11974,7 +12451,8 @@
     }
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
     std::vector<size_t> eventOrder;
@@ -12012,9 +12490,10 @@
     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     spy->assertNoEvents();
 }
 
@@ -12031,20 +12510,22 @@
 
     // Inject an event outside the spy window's touchable region.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy->assertNoEvents();
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                             ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionUp();
     spy->assertNoEvents();
 
     // Inject an event inside the spy window's touchable region.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {5, 10}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {5, 10}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy->consumeMotionDown();
@@ -12065,8 +12546,8 @@
 
     // Inject an event outside the spy window's frame and touchable region.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy->consumeMotionOutsideWithZeroedCoords();
@@ -12087,8 +12568,8 @@
             {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     windowLeft->consumeMotionDown();
     spy->consumeMotionDown();
@@ -12119,8 +12600,8 @@
     mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {50, 50}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {50, 50}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spyRight->assertNoEvents();
@@ -12156,16 +12637,16 @@
 
     // First finger down, no window touched.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     window->assertNoEvents();
 
     // Second finger down on window, the window should receive touch down.
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
@@ -12175,7 +12656,7 @@
                                 InputEventInjectionSync::WAIT_FOR_RESULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
 
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
     spy->consumeMotionPointerDown(/*pointerIndex=*/1);
 }
 
@@ -12194,11 +12675,11 @@
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeKeyDown(ADISPLAY_ID_NONE);
+    window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeKeyUp(ADISPLAY_ID_NONE);
+    window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
 
     spy->assertNoEvents();
 }
@@ -12217,7 +12698,8 @@
             {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy1->consumeMotionDown();
@@ -12232,7 +12714,7 @@
     // The rest of the gesture should only be sent to the second spy window.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT))
+                                ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     spy2->consumeMotionMove();
     spy1->assertNoEvents();
@@ -12249,19 +12731,21 @@
     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-    spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+    window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+    spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
 
     window->releaseChannel();
 
     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
 
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+              injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                             ui::LogicalDisplayId::DEFAULT))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-    spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
 }
 
 /**
@@ -12276,8 +12760,8 @@
 
     // First finger down on the window and the spy.
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {100, 200}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {100, 200}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     spy->consumeMotionDown();
     window->consumeMotionDown();
@@ -12289,7 +12773,7 @@
     // Second finger down on the window and spy, but the window should not receive the pointer down.
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
@@ -12304,7 +12788,7 @@
     // Third finger goes down outside all windows, so injection should fail.
     const MotionEvent thirdFingerDownEvent =
             MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
@@ -12332,15 +12816,15 @@
 
     // First finger down on the window only
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {150, 150}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {150, 150}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
 
     // Second finger down on the spy and window
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
@@ -12355,7 +12839,7 @@
     // Third finger down on the spy and window
     const MotionEvent thirdFingerDownEvent =
             MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
@@ -12370,8 +12854,10 @@
 
     // Spy window pilfers the pointers.
     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
-    window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
-    window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
+    window->consumeMotionPointerUp(/*idx=*/2, ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_CANCELED);
+    window->consumeMotionPointerUp(/*idx=*/1, ui::LogicalDisplayId::DEFAULT,
+                                   AMOTION_EVENT_FLAG_CANCELED);
 
     spy->assertNoEvents();
     window->assertNoEvents();
@@ -12392,8 +12878,8 @@
 
     // First finger down on both spy and window
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {10, 10}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {10, 10}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy->consumeMotionDown();
@@ -12401,7 +12887,7 @@
     // Second finger down on the spy and window
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
@@ -12435,8 +12921,8 @@
 
     // First finger down on both window and spy
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
-              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               {10, 10}))
+              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
+                               ui::LogicalDisplayId::DEFAULT, {10, 10}))
             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
     window->consumeMotionDown();
     spy->consumeMotionDown();
@@ -12448,7 +12934,7 @@
     // Second finger down on the window only
     const MotionEvent secondFingerDownEvent =
             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-                    .displayId(ADISPLAY_ID_DEFAULT)
+                    .displayId(ui::LogicalDisplayId::DEFAULT)
                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
@@ -12633,9 +13119,9 @@
     std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
         std::shared_ptr<FakeApplicationHandle> overlayApplication =
                 std::make_shared<FakeApplicationHandle>();
-        sp<FakeWindowHandle> overlay =
-                sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
-                                           "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
+        sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
+                                                                  "Stylus interceptor window",
+                                                                  ui::LogicalDisplayId::DEFAULT);
         overlay->setFocusable(false);
         overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
         overlay->setTouchable(false);
@@ -12646,11 +13132,11 @@
                 std::make_shared<FakeApplicationHandle>();
         sp<FakeWindowHandle> window =
                 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
-                                           ADISPLAY_ID_DEFAULT);
+                                           ui::LogicalDisplayId::DEFAULT);
         window->setFocusable(true);
         window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
 
-        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+        mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
         mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
         setFocusedWindow(window);
         window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
@@ -12660,13 +13146,13 @@
     void sendFingerEvent(int32_t action) {
         mDispatcher->notifyMotion(
                 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
-                                   ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
+                                   ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
     }
 
     void sendStylusEvent(int32_t action) {
         NotifyMotionArgs motionArgs =
                 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
-                                   ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
+                                   ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
         motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
         mDispatcher->notifyMotion(motionArgs);
     }
@@ -12770,7 +13256,7 @@
 
     InputEventInjectionResult injectTargetedMotion(int32_t action) const {
         return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
-                                 ADISPLAY_ID_DEFAULT, {100, 200},
+                                 ui::LogicalDisplayId::DEFAULT, {100, 200},
                                  {AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                   AMOTION_EVENT_INVALID_CURSOR_POSITION},
                                  INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
@@ -12778,7 +13264,8 @@
     }
 
     InputEventInjectionResult injectTargetedKey(int32_t action) const {
-        return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
+        return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
+                                          ui::LogicalDisplayId::INVALID,
                                           InputEventInjectionSync::WAIT_FOR_RESULT,
                                           INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
                                           mPolicyFlags);
@@ -12787,8 +13274,9 @@
     sp<FakeWindowHandle> createWindow(const char* name) const {
         std::shared_ptr<FakeApplicationHandle> overlayApplication =
                 std::make_shared<FakeApplicationHandle>();
-        sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
-                                                                 name, ADISPLAY_ID_DEFAULT);
+        sp<FakeWindowHandle> window =
+                sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
+                                           ui::LogicalDisplayId::DEFAULT);
         window->setOwnerInfo(mPid, mUid);
         return window;
     }
@@ -12810,7 +13298,7 @@
 
     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
               owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
-    window->consumeKeyDown(ADISPLAY_ID_NONE);
+    window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
 }
 
 TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
@@ -12875,7 +13363,7 @@
     // A user that has injection permission can inject into any window.
     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
-                                ADISPLAY_ID_DEFAULT));
+                                ui::LogicalDisplayId::DEFAULT));
     randosSpy->consumeMotionDown();
     window->consumeMotionDown();
 
@@ -12883,7 +13371,7 @@
     randosSpy->consumeFocusEvent(true);
 
     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
-    randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
+    randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
     window->assertNoEvents();
 }
 
@@ -12910,13 +13398,14 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                                           ADISPLAY_ID_DEFAULT);
+                                                           ui::LogicalDisplayId::DEFAULT);
     left->setFrame(Rect(0, 0, 100, 100));
-    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                            "Right Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> right =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     right->setFrame(Rect(100, 0, 200, 100));
-    sp<FakeWindowHandle> spy =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
+                                                          ui::LogicalDisplayId::DEFAULT);
     spy->setFrame(Rect(0, 0, 200, 100));
     spy->setTrustedOverlay(true);
     spy->setSpy(true);
@@ -12933,11 +13422,14 @@
     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 
     // Hover move to the right window.
@@ -12950,11 +13442,14 @@
     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
 
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
 
     // Stop hovering.
@@ -12966,11 +13461,14 @@
     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
 
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 }
 
@@ -12978,13 +13476,14 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                                           ADISPLAY_ID_DEFAULT);
+                                                           ui::LogicalDisplayId::DEFAULT);
     left->setFrame(Rect(0, 0, 100, 100));
-    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                            "Right Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> right =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     right->setFrame(Rect(100, 0, 200, 100));
-    sp<FakeWindowHandle> spy =
-            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
+                                                          ui::LogicalDisplayId::DEFAULT);
     spy->setFrame(Rect(0, 0, 200, 100));
     spy->setTrustedOverlay(true);
     spy->setSpy(true);
@@ -13001,11 +13500,14 @@
     left->consumeMotionDown();
     spy->consumeMotionDown();
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 
     // Second pointer down on right window.
@@ -13019,17 +13521,23 @@
     right->consumeMotionDown();
     spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/1));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/1));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/1));
 
     // Second pointer up.
@@ -13043,17 +13551,23 @@
     right->consumeMotionUp();
     spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/1));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/1));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/1));
 
     // First pointer up.
@@ -13065,11 +13579,14 @@
     left->consumeMotionUp();
     spy->consumeMotionUp();
 
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 }
 
@@ -13078,17 +13595,20 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                                           ADISPLAY_ID_DEFAULT);
+                                                           ui::LogicalDisplayId::DEFAULT);
     left->setFrame(Rect(0, 0, 100, 100));
-    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                            "Right Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> right =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     right->setFrame(Rect(100, 0, 200, 100));
 
     mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
 
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 
     // Hover move into the window.
@@ -13102,7 +13622,8 @@
 
     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
 
     // Move the mouse with another device. This cancels the hovering pointer from the first device.
@@ -13119,9 +13640,10 @@
 
     // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
     // a HOVER_EXIT from the first device.
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
                                                SECOND_DEVICE_ID,
                                                /*pointerId=*/0));
 
@@ -13137,9 +13659,10 @@
 
     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
                                                 SECOND_DEVICE_ID,
                                                 /*pointerId=*/0));
 }
@@ -13153,17 +13676,20 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
 
     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
-                                                           ADISPLAY_ID_DEFAULT);
+                                                           ui::LogicalDisplayId::DEFAULT);
     left->setFrame(Rect(0, 0, 100, 100));
-    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
-                                                            "Right Window", ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> right =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
+                                       ui::LogicalDisplayId::DEFAULT);
     right->setFrame(Rect(100, 0, 200, 100));
 
     mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
 
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                                DEVICE_ID,
                                                 /*pointerId=*/0));
 
     // Hover move into the window.
@@ -13177,7 +13703,8 @@
 
     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
 
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
 
     // Move the mouse with another device
@@ -13192,9 +13719,10 @@
 
     // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
     // a HOVER_EXIT from the first device.
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
                                                SECOND_DEVICE_ID,
                                                /*pointerId=*/0));
 
@@ -13209,9 +13737,10 @@
                     .build());
 
     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
-    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
+    ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
+                                               DEVICE_ID,
                                                /*pointerId=*/0));
-    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
+    ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
                                                 SECOND_DEVICE_ID,
                                                 /*pointerId=*/0));
 }
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index 2aecab9..fea1349 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -29,14 +29,8 @@
 using testing::Return;
 
 void InputMapperUnitTest::SetUpWithBus(int bus) {
-    mFakePointerController = std::make_shared<FakePointerController>();
-    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
-    mFakePointerController->setPosition(INITIAL_CURSOR_X, INITIAL_CURSOR_Y);
     mFakePolicy = sp<FakeInputReaderPolicy>::make();
 
-    EXPECT_CALL(mMockInputReaderContext, getPointerController(DEVICE_ID))
-            .WillRepeatedly(Return(mFakePointerController));
-
     EXPECT_CALL(mMockInputReaderContext, getPolicy()).WillRepeatedly(Return(mFakePolicy.get()));
 
     EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub));
@@ -178,8 +172,8 @@
     return device;
 }
 
-void InputMapperTest::setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
-                                                   ui::Rotation orientation,
+void InputMapperTest::setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width,
+                                                   int32_t height, ui::Rotation orientation,
                                                    const std::string& uniqueId,
                                                    std::optional<uint8_t> physicalPort,
                                                    ViewportType viewportType) {
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index e176a65..5bd8cda 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -40,8 +40,6 @@
 protected:
     static constexpr int32_t EVENTHUB_ID = 1;
     static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
-    static constexpr float INITIAL_CURSOR_X = 400;
-    static constexpr float INITIAL_CURSOR_Y = 240;
     virtual void SetUp() override { SetUpWithBus(0); }
     virtual void SetUpWithBus(int bus);
 
@@ -66,7 +64,6 @@
     InputDeviceIdentifier mIdentifier;
     MockEventHubInterface mMockEventHub;
     sp<FakeInputReaderPolicy> mFakePolicy;
-    std::shared_ptr<FakePointerController> mFakePointerController;
     MockInputReaderContext mMockInputReaderContext;
     std::unique_ptr<InputDevice> mDevice;
 
@@ -131,7 +128,7 @@
                                                  args...);
     }
 
-    void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+    void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
                                       ui::Rotation orientation, const std::string& uniqueId,
                                       std::optional<uint8_t> physicalPort,
                                       ViewportType viewportType);
diff --git a/services/inputflinger/tests/InputProcessorConverter_test.cpp b/services/inputflinger/tests/InputProcessorConverter_test.cpp
index 4b42f4b..bdf156c 100644
--- a/services/inputflinger/tests/InputProcessorConverter_test.cpp
+++ b/services/inputflinger/tests/InputProcessorConverter_test.cpp
@@ -17,7 +17,6 @@
 #include "../InputCommonConverter.h"
 
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <utils/BitSet.h>
 
 using namespace aidl::android::hardware::input;
@@ -39,7 +38,7 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.5);
     static constexpr nsecs_t downTime = 2;
     NotifyMotionArgs motionArgs(/*sequenceNum=*/1, /*eventTime=*/downTime, /*readTime=*/2,
-                                /*deviceId=*/3, AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT,
+                                /*deviceId=*/3, AINPUT_SOURCE_ANY, ui::LogicalDisplayId::DEFAULT,
                                 /*policyFlags=*/4, AMOTION_EVENT_ACTION_DOWN, /*actionButton=*/0,
                                 /*flags=*/0, AMETA_NONE, /*buttonState=*/0,
                                 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
diff --git a/services/inputflinger/tests/InputProcessor_test.cpp b/services/inputflinger/tests/InputProcessor_test.cpp
index 3b7cbfa..f7e5e67 100644
--- a/services/inputflinger/tests/InputProcessor_test.cpp
+++ b/services/inputflinger/tests/InputProcessor_test.cpp
@@ -16,7 +16,6 @@
 
 #include "../InputProcessor.h"
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 
 #include "TestInputListener.h"
 
@@ -45,7 +44,7 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
     static constexpr nsecs_t downTime = 2;
     NotifyMotionArgs motionArgs(/*sequenceNum=*/1, /*eventTime=*/downTime, /*readTime=*/2,
-                                /*deviceId=*/3, AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT,
+                                /*deviceId=*/3, AINPUT_SOURCE_ANY, ui::LogicalDisplayId::DEFAULT,
                                 /*policyFlags=*/4, AMOTION_EVENT_ACTION_DOWN, /*actionButton=*/0,
                                 /*flags=*/0, AMETA_NONE, /*buttonState=*/0,
                                 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
@@ -81,7 +80,7 @@
 TEST_F(InputProcessorTest, SendToNextStage_NotifyKeyArgs) {
     // Create a basic key event and send to processor
     NotifyKeyArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*readTime=*/21, /*deviceId=*/3,
-                       AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, /*policyFlags=*/0,
+                       AINPUT_SOURCE_KEYBOARD, ui::LogicalDisplayId::DEFAULT, /*policyFlags=*/0,
                        AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5,
                        AMETA_NONE, /*downTime=*/6);
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index e5d929d..8536ff0 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -27,6 +27,7 @@
 #include <JoystickInputMapper.h>
 #include <KeyboardInputMapper.h>
 #include <MultiTouchInputMapper.h>
+#include <NotifyArgsBuilders.h>
 #include <PeripheralController.h>
 #include <SensorInputMapper.h>
 #include <SingleTouchInputMapper.h>
@@ -40,13 +41,11 @@
 #include <com_android_input_flags.h>
 #include <ftl/enum.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <ui/Rotation.h>
 
 #include <thread>
 #include "FakeEventHub.h"
 #include "FakeInputReaderPolicy.h"
-#include "FakePointerController.h"
 #include "InputMapperTest.h"
 #include "InstrumentedInputReader.h"
 #include "TestConstants.h"
@@ -61,13 +60,13 @@
 using std::chrono_literals::operator""s;
 
 // Arbitrary display properties.
-static constexpr int32_t DISPLAY_ID = 0;
+static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 static const std::string DISPLAY_UNIQUE_ID = "local:1";
-static constexpr int32_t SECONDARY_DISPLAY_ID = DISPLAY_ID + 1;
-static const std::string SECONDARY_DISPLAY_UNIQUE_ID = "local:2";
+static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
+        ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
 static constexpr int32_t DISPLAY_WIDTH = 480;
 static constexpr int32_t DISPLAY_HEIGHT = 800;
-static constexpr int32_t VIRTUAL_DISPLAY_ID = 1;
+static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
 static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
 static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
 static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
@@ -359,7 +358,7 @@
     virtual void fadePointer() {
     }
 
-    virtual std::optional<int32_t> getAssociatedDisplay() {
+    virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
         if (mViewport) {
             return std::make_optional(mViewport->displayId);
         }
@@ -418,8 +417,8 @@
     const std::string externalUniqueId = "local:1";
     const std::string virtualUniqueId1 = "virtual:2";
     const std::string virtualUniqueId2 = "virtual:3";
-    constexpr int32_t virtualDisplayId1 = 2;
-    constexpr int32_t virtualDisplayId2 = 3;
+    constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
+    constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
 
     // Add an internal viewport
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
@@ -476,8 +475,8 @@
 TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
     const std::string uniqueId1 = "uniqueId1";
     const std::string uniqueId2 = "uniqueId2";
-    constexpr int32_t displayId1 = 2;
-    constexpr int32_t displayId2 = 3;
+    constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
+    constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
 
     std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
                                        ViewportType::VIRTUAL};
@@ -521,13 +520,13 @@
 TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
     const std::string uniqueId1 = "uniqueId1";
     const std::string uniqueId2 = "uniqueId2";
-    constexpr int32_t nonDefaultDisplayId = 2;
-    static_assert(nonDefaultDisplayId != ADISPLAY_ID_DEFAULT,
-                  "Test display ID should not be ADISPLAY_ID_DEFAULT");
+    constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
+    ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
+            << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
 
     // Add the default display first and ensure it gets returned.
     mFakePolicy->clearViewports();
-    mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+    mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
                                     ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
                                     ViewportType::INTERNAL);
     mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
@@ -537,7 +536,7 @@
     std::optional<DisplayViewport> viewport =
             mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
     ASSERT_TRUE(viewport);
-    ASSERT_EQ(ADISPLAY_ID_DEFAULT, viewport->displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
     ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
 
     // Add the default display second to make sure order doesn't matter.
@@ -545,13 +544,13 @@
     mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
                                     ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
                                     ViewportType::INTERNAL);
-    mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+    mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
                                     ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
                                     ViewportType::INTERNAL);
 
     viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
     ASSERT_TRUE(viewport);
-    ASSERT_EQ(ADISPLAY_ID_DEFAULT, viewport->displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
     ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
 }
 
@@ -562,8 +561,8 @@
     constexpr ViewportType type = ViewportType::EXTERNAL;
     const std::string uniqueId1 = "uniqueId1";
     const std::string uniqueId2 = "uniqueId2";
-    constexpr int32_t displayId1 = 1;
-    constexpr int32_t displayId2 = 2;
+    constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
+    constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
     const uint8_t hdmi1 = 0;
     const uint8_t hdmi2 = 1;
     const uint8_t hdmi3 = 2;
@@ -1185,6 +1184,82 @@
     mFakeListener->assertNotifyCaptureWasNotCalled();
 }
 
+TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
+    constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
+    constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
+    FakeInputMapper& firstMapper =
+            addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
+                                         InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
+                                         /*configuration=*/nullptr);
+    FakeInputMapper& secondMapper =
+            addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
+                                         InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
+                                         /*configuration=*/nullptr);
+
+    ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+    // Start a new key gesture from the first device
+    firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
+                                          .deviceId(FIRST_DEVICE_ID)
+                                          .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
+
+    // Start a new touch gesture from the second device
+    secondMapper.setProcessResult(
+            {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
+                     .deviceId(SECOND_DEVICE_ID)
+                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
+                     .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+    // Releasing the key is not a new gesture, so it does not update the last used device
+    firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
+                                          .deviceId(FIRST_DEVICE_ID)
+                                          .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+    // But pressing a new key does start a new gesture
+    firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
+                                          .deviceId(FIRST_DEVICE_ID)
+                                          .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+    // Moving or ending a touch gesture does not update the last used device
+    secondMapper.setProcessResult(
+            {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
+                     .deviceId(SECOND_DEVICE_ID)
+                     .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+                     .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+    secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
+                                           .deviceId(SECOND_DEVICE_ID)
+                                           .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+                                           .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+    // Starting a new hover gesture updates the last used device
+    secondMapper.setProcessResult(
+            {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+                     .deviceId(SECOND_DEVICE_ID)
+                     .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+                     .build()});
+    mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+    mReader->loopOnce();
+    ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+}
+
 class FakeVibratorInputMapper : public FakeInputMapper {
 public:
     FakeVibratorInputMapper(InputDeviceContext& deviceContext,
@@ -1349,8 +1424,6 @@
     sp<FakeInputReaderPolicy> mFakePolicy;
     std::unique_ptr<InputReaderInterface> mReader;
 
-    std::shared_ptr<FakePointerController> mFakePointerController;
-
     constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
     constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
 
@@ -1359,8 +1432,6 @@
         GTEST_SKIP();
 #endif
         mFakePolicy = sp<FakeInputReaderPolicy>::make();
-        mFakePointerController = std::make_shared<FakePointerController>();
-        mFakePolicy->setPointerController(mFakePointerController);
 
         setupInputReader();
     }
@@ -1603,7 +1674,7 @@
         mDeviceInfo = *info;
     }
 
-    void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+    void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
                                       ui::Rotation orientation, const std::string& uniqueId,
                                       std::optional<uint8_t> physicalPort,
                                       ViewportType viewportType) {
@@ -1654,8 +1725,6 @@
         } else {
             mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
         }
-        mFakePointerController = std::make_shared<FakePointerController>();
-        mFakePolicy->setPointerController(mFakePointerController);
 
         InputReaderIntegrationTest::setupInputReader();
 
@@ -3251,7 +3320,7 @@
 
     void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
                              int32_t originalKeyCode, int32_t rotatedKeyCode,
-                             int32_t displayId = ADISPLAY_ID_NONE);
+                             ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
 };
 
 /* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
@@ -3264,7 +3333,8 @@
 
 void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
                                                   int32_t originalScanCode, int32_t originalKeyCode,
-                                                  int32_t rotatedKeyCode, int32_t displayId) {
+                                                  int32_t rotatedKeyCode,
+                                                  ui::LogicalDisplayId displayId) {
     NotifyKeyArgs args;
 
     process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
@@ -3585,19 +3655,19 @@
                                                        AINPUT_KEYBOARD_TYPE_ALPHABETIC);
     NotifyKeyArgs args;
 
-    // Display id should be ADISPLAY_ID_NONE without any display configuration.
+    // Display id should be LogicalDisplayId::INVALID without any display configuration.
     process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
 
     prepareDisplay(ui::ROTATION_0);
     process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
 }
 
 TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
@@ -3611,7 +3681,7 @@
                                                        AINPUT_KEYBOARD_TYPE_ALPHABETIC);
     NotifyKeyArgs args;
 
-    // Display id should be ADISPLAY_ID_NONE without any display configuration.
+    // Display id should be LogicalDisplayId::INVALID without any display configuration.
     // ^--- already checked by the previous test
 
     setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
@@ -3622,7 +3692,7 @@
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DISPLAY_ID, args.displayId);
 
-    constexpr int32_t newDisplayId = 2;
+    constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
     clearViewports();
     setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
                                  UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
@@ -3837,7 +3907,7 @@
     ASSERT_FALSE(device2->isEnabled());
 
     // Prepare second display.
-    constexpr int32_t newDisplayId = 2;
+    constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
     setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
                                  UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
     setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
@@ -5344,10 +5414,6 @@
 }
 
 TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    mFakePolicy->setPointerController(fakePointerController);
-
     addConfigurationProperty("touch.deviceType", "pointer");
     prepareAxes(POSITION);
     prepareDisplay(ui::ROTATION_0);
@@ -6192,52 +6258,6 @@
     ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
 }
 
-TEST_F(SingleTouchInputMapperTest, Process_WhenConfigEnabled_ShouldShowDirectStylusPointer) {
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(ui::ROTATION_0);
-    prepareButtons();
-    prepareAxes(POSITION);
-    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
-    mFakePolicy->setPointerController(fakePointerController);
-    mFakePolicy->setStylusPointerIconEnabled(true);
-    SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
-
-    processKey(mapper, BTN_TOOL_PEN, 1);
-    processMove(mapper, 100, 200);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
-            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                  WithToolType(ToolType::STYLUS),
-                  WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
-    ASSERT_TRUE(fakePointerController->isPointerShown());
-    ASSERT_NO_FATAL_FAILURE(
-            fakePointerController->assertPosition(toDisplayX(100), toDisplayY(200)));
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenConfigDisabled_ShouldNotShowDirectStylusPointer) {
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(ui::ROTATION_0);
-    prepareButtons();
-    prepareAxes(POSITION);
-    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
-    mFakePolicy->setPointerController(fakePointerController);
-    mFakePolicy->setStylusPointerIconEnabled(false);
-    SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
-
-    processKey(mapper, BTN_TOOL_PEN, 1);
-    processMove(mapper, 100, 200);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
-            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                  WithToolType(ToolType::STYLUS),
-                  WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
-    ASSERT_FALSE(fakePointerController->isPointerShown());
-}
-
 TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
     // Initialize the device without setting device source to touch navigation.
     addConfigurationProperty("touch.deviceType", "touchScreen");
@@ -8717,21 +8737,12 @@
 }
 
 TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
-    // Setup for second display.
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
-    fakePointerController->setPosition(100, 200);
-    mFakePolicy->setPointerController(fakePointerController);
-
-    mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
     prepareSecondaryDisplay(ViewportType::EXTERNAL);
 
     prepareDisplay(ui::ROTATION_0);
     prepareAxes(POSITION);
     MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
 
-    // Check source is mouse that would obtain the PointerController.
     ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
 
     NotifyMotionArgs motionArgs;
@@ -8740,7 +8751,7 @@
 
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
-    ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
 }
 
 /**
@@ -8920,97 +8931,6 @@
             WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
 }
 
-TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
-    // Setup the first touch screen device.
-    prepareAxes(POSITION | ID | SLOT);
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
-
-    // Create the second touch screen device, and enable multi fingers.
-    const std::string USB2 = "USB2";
-    const std::string DEVICE_NAME2 = "TOUCHSCREEN2";
-    constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
-    constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
-    std::shared_ptr<InputDevice> device2 =
-            newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
-                      ftl::Flags<InputDeviceClass>(0));
-
-    mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
-                                   /*flat=*/0, /*fuzz=*/0);
-    mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
-                                   /*flat=*/0, /*fuzz=*/0);
-    mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX,
-                                   /*flat=*/0, /*fuzz=*/0);
-    mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX,
-                                   /*flat=*/0, /*fuzz=*/0);
-    mFakeEventHub->setAbsoluteAxisValue(SECOND_EVENTHUB_ID, ABS_MT_SLOT, /*value=*/0);
-    mFakeEventHub->addConfigurationProperty(SECOND_EVENTHUB_ID, String8("touch.deviceType"),
-                                            String8("touchScreen"));
-
-    // Setup the second touch screen device.
-    device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
-    MultiTouchInputMapper& mapper2 = device2->constructAndAddMapper<
-            MultiTouchInputMapper>(SECOND_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
-    std::list<NotifyArgs> unused =
-            device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
-                               /*changes=*/{});
-    unused += device2->reset(ARBITRARY_TIME);
-
-    // Setup PointerController.
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    mFakePolicy->setPointerController(fakePointerController);
-
-    // Setup policy for associated displays and show touches.
-    const uint8_t hdmi1 = 0;
-    const uint8_t hdmi2 = 1;
-    mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
-    mFakePolicy->addInputPortAssociation(USB2, hdmi2);
-    mFakePolicy->setShowTouches(true);
-
-    // Create displays.
-    prepareDisplay(ui::ROTATION_0, hdmi1);
-    prepareSecondaryDisplay(ViewportType::EXTERNAL, hdmi2);
-
-    // Default device will reconfigure above, need additional reconfiguration for another device.
-    unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
-                                 InputReaderConfiguration::Change::DISPLAY_INFO |
-                                         InputReaderConfiguration::Change::SHOW_TOUCHES);
-
-    // Two fingers down at default display.
-    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
-    processPosition(mapper, x1, y1);
-    processId(mapper, 1);
-    processSlot(mapper, 1);
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processSync(mapper);
-
-    std::map<int32_t, std::vector<int32_t>>::const_iterator iter =
-            fakePointerController->getSpots().find(DISPLAY_ID);
-    ASSERT_TRUE(iter != fakePointerController->getSpots().end());
-    ASSERT_EQ(size_t(2), iter->second.size());
-
-    // Two fingers down at second display.
-    processPosition(mapper2, x1, y1);
-    processId(mapper2, 1);
-    processSlot(mapper2, 1);
-    processPosition(mapper2, x2, y2);
-    processId(mapper2, 2);
-    processSync(mapper2);
-
-    iter = fakePointerController->getSpots().find(SECONDARY_DISPLAY_ID);
-    ASSERT_TRUE(iter != fakePointerController->getSpots().end());
-    ASSERT_EQ(size_t(2), iter->second.size());
-
-    // Disable the show touches configuration and ensure the spots are cleared.
-    mFakePolicy->setShowTouches(false);
-    unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
-                                 InputReaderConfiguration::Change::SHOW_TOUCHES);
-
-    ASSERT_TRUE(fakePointerController->getSpots().empty());
-}
-
 TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
     prepareAxes(POSITION);
     addConfigurationProperty("touch.deviceType", "touchScreen");
@@ -9703,58 +9623,6 @@
                   WithToolType(ToolType::STYLUS))));
 }
 
-TEST_F(MultiTouchInputMapperTest, Process_WhenConfigEnabled_ShouldShowDirectStylusPointer) {
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(ui::ROTATION_0);
-    prepareAxes(POSITION | ID | SLOT | TOOL_TYPE | PRESSURE);
-    // Add BTN_TOOL_PEN to statically show stylus support, since using ABS_MT_TOOL_TYPE can only
-    // indicate stylus presence dynamically.
-    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    mFakePolicy->setPointerController(fakePointerController);
-    mFakePolicy->setStylusPointerIconEnabled(true);
-    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
-
-    processId(mapper, FIRST_TRACKING_ID);
-    processPressure(mapper, RAW_PRESSURE_MIN);
-    processPosition(mapper, 100, 200);
-    processToolType(mapper, MT_TOOL_PEN);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
-            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                  WithToolType(ToolType::STYLUS),
-                  WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
-    ASSERT_TRUE(fakePointerController->isPointerShown());
-    ASSERT_NO_FATAL_FAILURE(
-            fakePointerController->assertPosition(toDisplayX(100), toDisplayY(200)));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_WhenConfigDisabled_ShouldNotShowDirectStylusPointer) {
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(ui::ROTATION_0);
-    prepareAxes(POSITION | ID | SLOT | TOOL_TYPE | PRESSURE);
-    // Add BTN_TOOL_PEN to statically show stylus support, since using ABS_MT_TOOL_TYPE can only
-    // indicate stylus presence dynamically.
-    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    mFakePolicy->setPointerController(fakePointerController);
-    mFakePolicy->setStylusPointerIconEnabled(false);
-    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
-
-    processId(mapper, FIRST_TRACKING_ID);
-    processPressure(mapper, RAW_PRESSURE_MIN);
-    processPosition(mapper, 100, 200);
-    processToolType(mapper, MT_TOOL_PEN);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
-            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
-                  WithToolType(ToolType::STYLUS),
-                  WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
-    ASSERT_FALSE(fakePointerController->isPointerShown());
-}
-
 // --- MultiTouchInputMapperTest_ExternalDevice ---
 
 class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
@@ -9780,7 +9648,7 @@
     processPosition(mapper, 100, 100);
     processSync(mapper);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ADISPLAY_ID_DEFAULT, motionArgs.displayId);
+    ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
 
     // Expect the event to be sent to the external viewport if it is present.
     prepareSecondaryDisplay(ViewportType::EXTERNAL);
@@ -9790,18 +9658,15 @@
     ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
 }
 
-TEST_F(MultiTouchInputMapperTest, Process_TouchpadPointer) {
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-    fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
-    fakePointerController->setPosition(0, 0);
-
+// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
+//  unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
+//  PointerChoreographer refactor.
+TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
     // prepare device
     prepareDisplay(ui::ROTATION_0);
     prepareAxes(POSITION | ID | SLOT);
     mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
     mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
-    mFakePolicy->setPointerController(fakePointerController);
     MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
     // run uncaptured pointer tests - pushes out generic events
     // FINGER 0 DOWN
@@ -9855,13 +9720,9 @@
 }
 
 TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
-    std::shared_ptr<FakePointerController> fakePointerController =
-            std::make_shared<FakePointerController>();
-
     prepareDisplay(ui::ROTATION_0);
     prepareAxes(POSITION | ID | SLOT);
     mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
-    mFakePolicy->setPointerController(fakePointerController);
     mFakePolicy->setPointerCapture(/*window=*/nullptr);
     MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
 
@@ -9925,10 +9786,6 @@
     float mPointerXZoomScale;
     void preparePointerMode(int xAxisResolution, int yAxisResolution) {
         addConfigurationProperty("touch.deviceType", "pointer");
-        std::shared_ptr<FakePointerController> fakePointerController =
-                std::make_shared<FakePointerController>();
-        fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
-        fakePointerController->setPosition(0, 0);
         prepareDisplay(ui::ROTATION_0);
 
         prepareAxes(POSITION);
@@ -9937,7 +9794,6 @@
         // needs to be disabled, and the pointer gesture needs to be enabled.
         mFakePolicy->setPointerCapture(/*window=*/nullptr);
         mFakePolicy->setPointerGestureEnabled(true);
-        mFakePolicy->setPointerController(fakePointerController);
 
         float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
         float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
diff --git a/services/inputflinger/tests/InputTracingTest.cpp b/services/inputflinger/tests/InputTracingTest.cpp
index 0404d6d..617d67f 100644
--- a/services/inputflinger/tests/InputTracingTest.cpp
+++ b/services/inputflinger/tests/InputTracingTest.cpp
@@ -41,7 +41,7 @@
 
 namespace {
 
-constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 
 // Ensure common actions are interchangeable between keys and motions for convenience.
 static_assert(static_cast<int32_t>(AMOTION_EVENT_ACTION_DOWN) ==
@@ -127,7 +127,7 @@
         request.token = window->getToken();
         request.windowName = window->getName();
         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-        request.displayId = window->getInfo()->displayId;
+        request.displayId = window->getInfo()->displayId.val();
         mDispatcher->setFocusedWindow(request);
     }
 
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index db89168..6389cdc 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -28,7 +28,6 @@
 #include <EventHub.h>
 #include <InputReaderBase.h>
 #include <NotifyArgs.h>
-#include <PointerControllerInterface.h>
 #include <StylusState.h>
 #include <VibrationElement.h>
 #include <android-base/logging.h>
@@ -54,10 +53,6 @@
     MOCK_METHOD(bool, shouldDropVirtualKey, (nsecs_t now, int32_t keyCode, int32_t scanCode),
                 (override));
 
-    MOCK_METHOD(void, fadePointer, (), (override));
-    MOCK_METHOD(std::shared_ptr<PointerControllerInterface>, getPointerController,
-                (int32_t deviceId), (override));
-
     MOCK_METHOD(void, requestTimeoutAtTime, (nsecs_t when), (override));
     int32_t bumpGeneration() override { return ++mGeneration; }
 
diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
index b44529b..031b77d 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -72,8 +72,6 @@
     }
 
     void testPointerVisibilityForKeys(const std::vector<int32_t>& keyCodes, bool expectVisible) {
-        EXPECT_CALL(mMockInputReaderContext, fadePointer)
-                .Times(expectVisible ? 0 : keyCodes.size());
         for (int32_t keyCode : keyCodes) {
             process(EV_KEY, keyCode, 1);
             process(EV_SYN, SYN_REPORT, 0);
@@ -84,7 +82,6 @@
 
     void testTouchpadTapStateForKeys(const std::vector<int32_t>& keyCodes,
                                      const bool expectPrevent) {
-        EXPECT_CALL(mMockInputReaderContext, isPreventingTouchpadTaps).Times(keyCodes.size());
         if (expectPrevent) {
             EXPECT_CALL(mMockInputReaderContext, setPreventingTouchpadTaps(true))
                     .Times(keyCodes.size());
diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp
index 6606de8..4fcffdd 100644
--- a/services/inputflinger/tests/LatencyTracker_test.cpp
+++ b/services/inputflinger/tests/LatencyTracker_test.cpp
@@ -20,7 +20,6 @@
 #include <android-base/properties.h>
 #include <binder/Binder.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <inttypes.h>
 #include <linux/input.h>
 #include <log/log.h>
@@ -44,7 +43,7 @@
     identifier.product = productId;
     auto info = InputDeviceInfo();
     info.initialize(deviceId, /*generation=*/1, /*controllerNumber=*/1, identifier, "Test Device",
-                    /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE);
+                    /*isExternal=*/false, /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
     return info;
 }
 
diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
index d726385..b5f8971 100644
--- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
+++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
@@ -35,7 +35,7 @@
 using testing::SetArgPointee;
 using testing::VariantWith;
 
-static constexpr int32_t DISPLAY_ID = 0;
+static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 static constexpr int32_t DISPLAY_WIDTH = 480;
 static constexpr int32_t DISPLAY_HEIGHT = 800;
 static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
diff --git a/services/inputflinger/tests/NotifyArgs_test.cpp b/services/inputflinger/tests/NotifyArgs_test.cpp
index 1536756..2e5ecc3 100644
--- a/services/inputflinger/tests/NotifyArgs_test.cpp
+++ b/services/inputflinger/tests/NotifyArgs_test.cpp
@@ -36,7 +36,7 @@
     nsecs_t readTime = downTime++;
     int32_t deviceId = 7;
     uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
-    int32_t displayId = 42;
+    ui::LogicalDisplayId displayId = ui::LogicalDisplayId{42};
     uint32_t policyFlags = POLICY_FLAG_GESTURE;
     int32_t action = AMOTION_EVENT_ACTION_HOVER_MOVE;
     int32_t actionButton = AMOTION_EVENT_BUTTON_PRIMARY;
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 11c6b7e..1689b33 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -15,7 +15,8 @@
  */
 
 #include "../PointerChoreographer.h"
-
+#include <com_android_input_flags.h>
+#include <flag_macros.h>
 #include <gtest/gtest.h>
 #include <deque>
 #include <vector>
@@ -27,6 +28,8 @@
 
 namespace android {
 
+namespace input_flags = com::android::input::flags;
+
 using ControllerType = PointerControllerInterface::ControllerType;
 using testing::AllOf;
 
@@ -43,8 +46,8 @@
 constexpr int32_t DEVICE_ID = 3;
 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
 constexpr int32_t THIRD_DEVICE_ID = SECOND_DEVICE_ID + 1;
-constexpr int32_t DISPLAY_ID = 5;
-constexpr int32_t ANOTHER_DISPLAY_ID = 10;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId{5};
+constexpr ui::LogicalDisplayId ANOTHER_DISPLAY_ID = ui::LogicalDisplayId{10};
 constexpr int32_t DISPLAY_WIDTH = 480;
 constexpr int32_t DISPLAY_HEIGHT = 800;
 constexpr auto DRAWING_TABLET_SOURCE = AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS;
@@ -60,7 +63,7 @@
                                       .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, 20);
 
 static InputDeviceInfo generateTestDeviceInfo(int32_t deviceId, uint32_t source,
-                                              int32_t associatedDisplayId) {
+                                              ui::LogicalDisplayId associatedDisplayId) {
     InputDeviceIdentifier identifier;
 
     auto info = InputDeviceInfo();
@@ -70,7 +73,7 @@
     return info;
 }
 
-static std::vector<DisplayViewport> createViewports(std::vector<int32_t> displayIds) {
+static std::vector<DisplayViewport> createViewports(std::vector<ui::LogicalDisplayId> displayIds) {
     std::vector<DisplayViewport> viewports;
     for (auto displayId : displayIds) {
         DisplayViewport viewport;
@@ -121,7 +124,7 @@
                                         "reference to this PointerController";
     }
 
-    void assertPointerDisplayIdNotified(int32_t displayId) {
+    void assertPointerDisplayIdNotified(ui::LogicalDisplayId displayId) {
         ASSERT_EQ(displayId, mPointerDisplayIdNotified);
         mPointerDisplayIdNotified.reset();
     }
@@ -131,7 +134,7 @@
 private:
     std::deque<std::pair<ControllerType, std::shared_ptr<FakePointerController>>>
             mCreatedControllers;
-    std::optional<int32_t> mPointerDisplayIdNotified;
+    std::optional<ui::LogicalDisplayId> mPointerDisplayIdNotified;
 
     std::shared_ptr<PointerControllerInterface> createPointerController(
             ControllerType type) override {
@@ -141,7 +144,8 @@
         return pc;
     }
 
-    void notifyPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) override {
+    void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
+                                       const FloatPoint& position) override {
         mPointerDisplayIdNotified = displayId;
     }
 };
@@ -198,13 +202,17 @@
 
 TEST_F(PointerChoreographerTest, WhenMouseIsAddedCreatesPointerController) {
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
 }
 
 TEST_F(PointerChoreographerTest, WhenMouseIsRemovedRemovesPointerController) {
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
 
     // Remove the mouse.
@@ -215,7 +223,8 @@
 TEST_F(PointerChoreographerTest, WhenKeyboardIsAddedDoesNotCreatePointerController) {
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerNotCreated();
 }
 
@@ -249,7 +258,9 @@
     // For a mouse event without a target display, default viewport should be set for
     // the PointerController.
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertViewportSet(DISPLAY_ID);
     ASSERT_TRUE(pc->isPointerShown());
@@ -261,7 +272,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto firstDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
     firstDisplayPc->assertViewportSet(DISPLAY_ID);
     ASSERT_TRUE(firstDisplayPc->isPointerShown());
@@ -280,7 +293,9 @@
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
 
     assertPointerDisplayIdNotified(DISPLAY_ID);
@@ -289,7 +304,9 @@
 TEST_F(PointerChoreographerTest, WhenViewportIsSetLaterCallsNotifyPointerDisplayIdChanged) {
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotNotified();
 
@@ -301,12 +318,14 @@
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotified(DISPLAY_ID);
 
     mChoreographer.notifyInputDevicesChanged({/*id=*/1, {}});
-    assertPointerDisplayIdNotified(ADISPLAY_ID_NONE);
+    assertPointerDisplayIdNotified(ui::LogicalDisplayId::INVALID);
     assertPointerControllerRemoved(pc);
 }
 
@@ -317,7 +336,9 @@
     // Set one viewport as a default mouse display ID.
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto firstDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotified(DISPLAY_ID);
 
@@ -333,7 +354,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -345,7 +368,7 @@
             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
                     .pointer(MOUSE_POINTER)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
 
     // Check that the PointerController updated the position and the pointer is shown.
@@ -361,7 +384,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -376,7 +401,7 @@
             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
                     .pointer(absoluteMousePointer)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
 
     // Check that the PointerController updated the position and the pointer is shown.
@@ -398,7 +423,7 @@
     // Add two devices, one unassociated and the other associated with non-default mouse display.
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ANOTHER_DISPLAY_ID)}});
     auto unassociatedMousePc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, unassociatedMousePc->getDisplayId());
@@ -434,7 +459,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -444,7 +471,8 @@
     // Assume that pointer capture is enabled.
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/1,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE_RELATIVE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE_RELATIVE,
+                                     ui::LogicalDisplayId::INVALID)}});
     mChoreographer.notifyPointerCaptureChanged(
             NotifyPointerCaptureChangedArgs(/*id=*/2, systemTime(SYSTEM_TIME_MONOTONIC),
                                             PointerCaptureRequest(/*window=*/sp<BBinder>::make(),
@@ -459,7 +487,7 @@
                                      .axis(AMOTION_EVENT_AXIS_RELATIVE_X, 10)
                                      .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, 20))
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
 
     // Check that there's no update on the PointerController.
@@ -468,7 +496,8 @@
 
     // Check x-y coordinates, displayId and cursor position are not changed.
     mTestListener.assertNotifyMotionWasCalled(
-            AllOf(WithCoords(10, 20), WithRelativeMotion(10, 20), WithDisplayId(ADISPLAY_ID_NONE),
+            AllOf(WithCoords(10, 20), WithRelativeMotion(10, 20),
+                  WithDisplayId(ui::LogicalDisplayId::INVALID),
                   WithCursorPosition(AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                      AMOTION_EVENT_INVALID_CURSOR_POSITION)));
 }
@@ -477,7 +506,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
     ASSERT_TRUE(pc->isPointerShown());
@@ -496,7 +527,9 @@
 
     // A mouse is connected, and the pointer is shown.
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
 
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_TRUE(pc->isPointerShown());
@@ -506,15 +539,17 @@
     // Add a second mouse is added, the pointer is shown again.
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
-              generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
+              generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     ASSERT_TRUE(pc->isPointerShown());
 
     // One of the mice is removed, and it does not cause the mouse pointer to fade, because
     // we have one more mouse connected.
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerNotRemoved(pc);
     ASSERT_TRUE(pc->isPointerShown());
 
@@ -527,7 +562,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
 
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_TRUE(pc->isPointerShown());
@@ -537,7 +574,7 @@
     // Adding a touchscreen device does not unfade the mouse pointer.
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID,
                                      AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
                                      DISPLAY_ID)}});
@@ -554,7 +591,7 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     InputDeviceInfo mouseDeviceInfo =
-            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE);
+            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
     // Disable this mouse device.
     mouseDeviceInfo.setEnabled(false);
     mChoreographer.notifyInputDevicesChanged({/*id=*/0, {mouseDeviceInfo}});
@@ -567,7 +604,7 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     InputDeviceInfo mouseDeviceInfo =
-            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE);
+            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
 
     mChoreographer.notifyInputDevicesChanged({/*id=*/0, {mouseDeviceInfo}});
 
@@ -586,14 +623,16 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     InputDeviceInfo disabledMouseDeviceInfo =
-            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE);
+            generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
     disabledMouseDeviceInfo.setEnabled(false);
 
     InputDeviceInfo enabledMouseDeviceInfo =
-            generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE);
+            generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                   ui::LogicalDisplayId::INVALID);
 
     InputDeviceInfo anotherEnabledMouseDeviceInfo =
-            generateTestDeviceInfo(THIRD_DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE);
+            generateTestDeviceInfo(THIRD_DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                   ui::LogicalDisplayId::INVALID);
 
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
@@ -1155,7 +1194,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
 }
 
@@ -1163,7 +1202,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
 
     // Remove the touchpad.
@@ -1204,7 +1243,9 @@
     // For a touchpad event without a target display, default viewport should be set for
     // the PointerController.
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertViewportSet(DISPLAY_ID);
 }
@@ -1217,7 +1258,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto firstDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
     firstDisplayPc->assertViewportSet(DISPLAY_ID);
 
@@ -1235,7 +1276,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
 
     assertPointerDisplayIdNotified(DISPLAY_ID);
@@ -1246,7 +1287,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotNotified();
 
@@ -1260,12 +1301,12 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotified(DISPLAY_ID);
 
     mChoreographer.notifyInputDevicesChanged({/*id=*/1, {}});
-    assertPointerDisplayIdNotified(ADISPLAY_ID_NONE);
+    assertPointerDisplayIdNotified(ui::LogicalDisplayId::INVALID);
     assertPointerControllerRemoved(pc);
 }
 
@@ -1279,12 +1320,12 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto firstDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
     assertPointerDisplayIdNotified(DISPLAY_ID);
 
-    // Set another viewport as a default mouse display ID. ADISPLAY_ID_NONE will be notified
-    // before a touchpad event.
+    // Set another viewport as a default mouse display ID. ui::LogicalDisplayId::INVALID will be
+    // notified before a touchpad event.
     mChoreographer.setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
     assertPointerControllerRemoved(firstDisplayPc);
 
@@ -1298,7 +1339,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -1310,7 +1351,7 @@
             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
                     .pointer(TOUCHPAD_POINTER)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
 
     // Check that the PointerController updated the position and the pointer is shown.
@@ -1328,7 +1369,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -1342,7 +1383,7 @@
                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(-100).y(0))
                     .classification(MotionClassification::MULTI_FINGER_SWIPE)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
     mTestListener.assertNotifyMotionWasCalled(
             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
@@ -1356,7 +1397,7 @@
                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(0).y(0))
                     .classification(MotionClassification::MULTI_FINGER_SWIPE)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
     mTestListener.assertNotifyMotionWasCalled(
             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
@@ -1373,7 +1414,7 @@
                     .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(100).y(0))
                     .classification(MotionClassification::MULTI_FINGER_SWIPE)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
     mTestListener.assertNotifyMotionWasCalled(
             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
@@ -1388,7 +1429,7 @@
                     .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(110).y(10))
                     .classification(MotionClassification::MULTI_FINGER_SWIPE)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
     mTestListener.assertNotifyMotionWasCalled(
             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
@@ -1407,7 +1448,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE),
+                                     ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
                                      ANOTHER_DISPLAY_ID)}});
     auto unassociatedMousePc = assertPointerControllerCreated(ControllerType::MOUSE);
@@ -1446,7 +1487,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
 
@@ -1463,7 +1504,7 @@
     mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHPAD)
                                         .pointer(FIRST_TOUCH_POINTER)
                                         .deviceId(DEVICE_ID)
-                                        .displayId(ADISPLAY_ID_NONE)
+                                        .displayId(ui::LogicalDisplayId::INVALID)
                                         .build());
 
     // Check that there's no update on the PointerController.
@@ -1472,7 +1513,7 @@
 
     // Check x-y coordinates, displayId and cursor position are not changed.
     mTestListener.assertNotifyMotionWasCalled(
-            AllOf(WithCoords(100, 200), WithDisplayId(ADISPLAY_ID_NONE),
+            AllOf(WithCoords(100, 200), WithDisplayId(ui::LogicalDisplayId::INVALID),
                   WithCursorPosition(AMOTION_EVENT_INVALID_CURSOR_POSITION,
                                      AMOTION_EVENT_INVALID_CURSOR_POSITION)));
 }
@@ -1483,7 +1524,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
     ASSERT_TRUE(pc->isPointerShown());
@@ -1501,7 +1542,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertPointerIconNotSet();
 
@@ -1515,7 +1558,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertPointerIconNotSet();
 
@@ -1530,7 +1575,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertPointerIconNotSet();
 
@@ -1545,7 +1592,9 @@
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     pc->assertCustomPointerIconNotSet();
 
@@ -1568,7 +1617,7 @@
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ANOTHER_DISPLAY_ID)}});
     auto firstMousePc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, firstMousePc->getDisplayId());
@@ -1587,6 +1636,76 @@
     firstMousePc->assertPointerIconNotSet();
 }
 
+TEST_F_WITH_FLAGS(PointerChoreographerTest, HidesTouchSpotsOnMirroredDisplaysForSecureWindow,
+                  REQUIRES_FLAGS_ENABLED(
+                          ACONFIG_FLAG(input_flags, hide_pointer_indicators_for_secure_windows))) {
+    // Add a touch device and enable show touches.
+    mChoreographer.notifyInputDevicesChanged(
+            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
+    mChoreographer.setShowTouchesEnabled(true);
+
+    // Emit touch events to create PointerController
+    mChoreographer.notifyMotion(
+            MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                    .pointer(FIRST_TOUCH_POINTER)
+                    .deviceId(DEVICE_ID)
+                    .displayId(DISPLAY_ID)
+                    .build());
+
+    // By default touch indicators should not be hidden
+    auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
+    pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
+    pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+
+    // adding secure window on display should set flag to hide pointer indicators on corresponding
+    // mirrored display
+    gui::WindowInfo windowInfo;
+    windowInfo.displayId = DISPLAY_ID;
+    windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+    mChoreographer.onWindowInfosChanged({windowInfo});
+    pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/true);
+    pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+
+    // removing the secure window should reset the state
+    windowInfo.inputConfig.clear(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY);
+    mChoreographer.onWindowInfosChanged({windowInfo});
+    pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
+    pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+}
+
+TEST_F_WITH_FLAGS(PointerChoreographerTest,
+                  DoesNotHidesTouchSpotsOnMirroredDisplaysForInvisibleWindow,
+                  REQUIRES_FLAGS_ENABLED(
+                          ACONFIG_FLAG(input_flags, hide_pointer_indicators_for_secure_windows))) {
+    // Add a touch device and enable show touches.
+    mChoreographer.notifyInputDevicesChanged(
+            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
+    mChoreographer.setShowTouchesEnabled(true);
+
+    // Emit touch events to create PointerController
+    mChoreographer.notifyMotion(
+            MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                    .pointer(FIRST_TOUCH_POINTER)
+                    .deviceId(DEVICE_ID)
+                    .displayId(DISPLAY_ID)
+                    .build());
+
+    // By default touch indicators should not be hidden
+    auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
+    pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
+    pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+
+    // adding secure but hidden window on display should still not set flag to hide pointer
+    // indicators
+    gui::WindowInfo windowInfo;
+    windowInfo.displayId = DISPLAY_ID;
+    windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+    windowInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_VISIBLE;
+    mChoreographer.onWindowInfosChanged({windowInfo});
+    pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
+    pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+}
+
 TEST_P(StylusTestFixture, SetsPointerIconForStylus) {
     const auto& [name, source, controllerType] = GetParam();
 
@@ -1693,14 +1812,14 @@
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID, source, DISPLAY_ID)}});
     mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
     mChoreographer.notifyMotion(
             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
                     .pointer(MOUSE_POINTER)
                     .deviceId(DEVICE_ID)
-                    .displayId(ADISPLAY_ID_NONE)
+                    .displayId(ui::LogicalDisplayId::INVALID)
                     .build());
     auto mousePc = assertPointerControllerCreated(ControllerType::MOUSE);
     mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, source)
@@ -1728,7 +1847,7 @@
     mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE),
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
               generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ANOTHER_DISPLAY_ID)}});
     auto firstMousePc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, firstMousePc->getDisplayId());
@@ -1784,7 +1903,9 @@
     // Hide the pointer on the display, and then connect the mouse.
     mChoreographer.setPointerIconVisibility(DISPLAY_ID, false);
     mChoreographer.notifyInputDevicesChanged(
-            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+            {/*id=*/0,
+             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto mousePc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, mousePc->getDisplayId());
 
@@ -1802,7 +1923,7 @@
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
              {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
-                                     ADISPLAY_ID_NONE)}});
+                                     ui::LogicalDisplayId::INVALID)}});
     auto touchpadPc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_EQ(DISPLAY_ID, touchpadPc->getDisplayId());
 
@@ -1847,7 +1968,8 @@
 
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID)}});
     // There should be no controller created when a drawing tablet is connected
     assertPointerControllerNotCreated();
 
@@ -1874,7 +1996,8 @@
     // First drawing tablet is added
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerNotCreated();
 
     mChoreographer.notifyMotion(
@@ -1889,8 +2012,10 @@
     // Second drawing tablet is added
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE),
-              generateTestDeviceInfo(SECOND_DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID),
+              generateTestDeviceInfo(SECOND_DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerNotRemoved(pc);
 
     mChoreographer.notifyMotion(
@@ -1903,7 +2028,8 @@
     // First drawing tablet is removed
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID)}});
     assertPointerControllerNotRemoved(pc);
 
     // Second drawing tablet is removed
@@ -1918,8 +2044,10 @@
     // Mouse and drawing tablet connected
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE),
-              generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID),
+              generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE,
+                                     ui::LogicalDisplayId::INVALID)}});
     auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
     ASSERT_TRUE(pc->isPointerShown());
 
@@ -1934,7 +2062,8 @@
     // Remove the mouse device
     mChoreographer.notifyInputDevicesChanged(
             {/*id=*/0,
-             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE, ADISPLAY_ID_NONE)}});
+             {generateTestDeviceInfo(DEVICE_ID, DRAWING_TABLET_SOURCE,
+                                     ui::LogicalDisplayId::INVALID)}});
 
     // The mouse controller should not be removed, because the drawing tablet has produced a
     // mouse event, so we are treating it as a mouse too.
diff --git a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
index 9818176..a36d526 100644
--- a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
+++ b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include "../PreferStylusOverTouchBlocker.h"
 
 namespace android {
@@ -64,8 +63,9 @@
     }
 
     // Define a valid motion event.
-    NotifyMotionArgs args(/*id=*/0, eventTime, /*readTime=*/0, deviceId, source, /*displayId=*/0,
-                          POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0,
+    NotifyMotionArgs args(/*id=*/0, eventTime, /*readTime=*/0, deviceId, source,
+                          ui::LogicalDisplayId::DEFAULT, POLICY_FLAG_PASS_TO_USER, action,
+                          /* actionButton */ 0,
                           /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
                           AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
                           pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
@@ -439,7 +439,7 @@
     InputDeviceInfo stylusDevice;
     stylusDevice.initialize(STYLUS_DEVICE_ID, /*generation=*/1, /*controllerNumber=*/1,
                             /*identifier=*/{}, "stylus device", /*external=*/false,
-                            /*hasMic=*/false, ADISPLAY_ID_NONE);
+                            /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
     notifyInputDevicesChanged({stylusDevice});
     // The touchscreen device was removed, so we no longer remember anything about it. We should
     // again start blocking touch events from it.
diff --git a/services/inputflinger/tests/TestEventMatchers.h b/services/inputflinger/tests/TestEventMatchers.h
index a3e8eaf..65fb9c6 100644
--- a/services/inputflinger/tests/TestEventMatchers.h
+++ b/services/inputflinger/tests/TestEventMatchers.h
@@ -145,7 +145,7 @@
 class WithDisplayIdMatcher {
 public:
     using is_gtest_matcher = void;
-    explicit WithDisplayIdMatcher(int32_t displayId) : mDisplayId(displayId) {}
+    explicit WithDisplayIdMatcher(ui::LogicalDisplayId displayId) : mDisplayId(displayId) {}
 
     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
         return mDisplayId == args.displayId;
@@ -164,10 +164,10 @@
     void DescribeNegationTo(std::ostream* os) const { *os << "wrong display id"; }
 
 private:
-    const int32_t mDisplayId;
+    const ui::LogicalDisplayId mDisplayId;
 };
 
-inline WithDisplayIdMatcher WithDisplayId(int32_t displayId) {
+inline WithDisplayIdMatcher WithDisplayId(ui::LogicalDisplayId displayId) {
     return WithDisplayIdMatcher(displayId);
 }
 
diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
index a92dce5..2b62dd1 100644
--- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp
+++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
@@ -19,9 +19,7 @@
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
 
-#include <com_android_input_flags.h>
 #include <thread>
-#include "FakePointerController.h"
 #include "InputMapperTest.h"
 #include "InterfaceMocks.h"
 #include "TestEventMatchers.h"
@@ -39,17 +37,15 @@
 constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
 constexpr auto HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
 constexpr auto HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
-constexpr int32_t DISPLAY_ID = 0;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
 constexpr int32_t DISPLAY_WIDTH = 480;
 constexpr int32_t DISPLAY_HEIGHT = 800;
 constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
 
-namespace input_flags = com::android::input::flags;
-
 /**
  * Unit tests for TouchpadInputMapper.
  */
-class TouchpadInputMapperTestBase : public InputMapperUnitTest {
+class TouchpadInputMapperTest : public InputMapperUnitTest {
 protected:
     void SetUp() override {
         InputMapperUnitTest::SetUp();
@@ -117,18 +113,7 @@
                     return base::ResultError("Axis not supported", NAME_NOT_FOUND);
                 });
         createDevice();
-        mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration,
-                                                         isPointerChoreographerEnabled());
-    }
-
-    virtual bool isPointerChoreographerEnabled() { return false; }
-};
-
-class TouchpadInputMapperTest : public TouchpadInputMapperTestBase {
-protected:
-    void SetUp() override {
-        input_flags::enable_pointer_choreographer(false);
-        TouchpadInputMapperTestBase::SetUp();
+        mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration);
     }
 };
 
@@ -139,66 +124,6 @@
  * but only after the button is released.
  */
 TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) {
-    std::list<NotifyArgs> args;
-
-    args += process(EV_ABS, ABS_MT_TRACKING_ID, 1);
-    args += process(EV_KEY, BTN_TOUCH, 1);
-    setScanCodeState(KeyState::DOWN, {BTN_TOOL_FINGER});
-    args += process(EV_KEY, BTN_TOOL_FINGER, 1);
-    args += process(EV_ABS, ABS_MT_POSITION_X, 50);
-    args += process(EV_ABS, ABS_MT_POSITION_Y, 50);
-    args += process(EV_ABS, ABS_MT_PRESSURE, 1);
-    args += process(EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args, testing::IsEmpty());
-
-    // Without this sleep, the test fails.
-    // TODO(b/284133337): Figure out whether this can be removed
-    std::this_thread::sleep_for(std::chrono::milliseconds(20));
-
-    args += process(EV_KEY, BTN_LEFT, 1);
-    setScanCodeState(KeyState::DOWN, {BTN_LEFT});
-    args += process(EV_SYN, SYN_REPORT, 0);
-
-    args += process(EV_KEY, BTN_LEFT, 0);
-    setScanCodeState(KeyState::UP, {BTN_LEFT});
-    args += process(EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args,
-                ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_EXIT)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER))));
-
-    // Liftoff
-    args.clear();
-    args += process(EV_ABS, ABS_MT_PRESSURE, 0);
-    args += process(EV_ABS, ABS_MT_TRACKING_ID, -1);
-    args += process(EV_KEY, BTN_TOUCH, 0);
-    setScanCodeState(KeyState::UP, {BTN_TOOL_FINGER});
-    args += process(EV_KEY, BTN_TOOL_FINGER, 0);
-    args += process(EV_SYN, SYN_REPORT, 0);
-    ASSERT_THAT(args, testing::IsEmpty());
-}
-
-class TouchpadInputMapperTestWithChoreographer : public TouchpadInputMapperTestBase {
-protected:
-    void SetUp() override { TouchpadInputMapperTestBase::SetUp(); }
-
-    bool isPointerChoreographerEnabled() override { return true; }
-};
-
-// TODO(b/311416205): De-duplicate the test cases after the refactoring is complete and the flagging
-//   logic can be removed.
-/**
- * Start moving the finger and then click the left touchpad button. Check whether HOVER_EXIT is
- * generated when hovering stops. Currently, it is not.
- * In the current implementation, HOVER_MOVE and ACTION_DOWN events are not sent out right away,
- * but only after the button is released.
- */
-TEST_F(TouchpadInputMapperTestWithChoreographer, HoverAndLeftButtonPress) {
     mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
                                     /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index 78f7291..853f628 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -18,7 +18,6 @@
 #include <android-base/silent_death_test.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <gui/constants.h>
 #include <linux/input.h>
 #include <thread>
 #include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h"
@@ -89,7 +88,8 @@
 
     // Define a valid motion event.
     NotifyMotionArgs args(/*id=*/0, eventTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-                          /*displayId=*/0, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
+                          ui::LogicalDisplayId::DEFAULT, POLICY_FLAG_PASS_TO_USER, action,
+                          /*actionButton=*/0,
                           /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
                           AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
                           pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
@@ -104,7 +104,7 @@
 
     auto info = InputDeviceInfo();
     info.initialize(DEVICE_ID, /*generation=*/1, /*controllerNumber=*/1, identifier, "alias",
-                    /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE);
+                    /*isExternal=*/false, /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
     info.addSource(AINPUT_SOURCE_TOUCHSCREEN);
     info.addMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN, 0, 1599, /*flat=*/0,
                         /*fuzz=*/0, X_RESOLUTION);
@@ -434,7 +434,7 @@
 TEST_F(UnwantedInteractionBlockerTest, KeyIsPassedToNextListener) {
     // Create a basic key event and send to blocker
     NotifyKeyArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*readTime=*/21, /*deviceId=*/3,
-                       AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, /*policyFlags=*/0,
+                       AINPUT_SOURCE_KEYBOARD, ui::LogicalDisplayId::DEFAULT, /*policyFlags=*/0,
                        AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5,
                        AMETA_NONE, /*downTime=*/6);
 
diff --git a/services/inputflinger/tests/fuzzers/FuzzedInputStream.h b/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
index 885820f..812969b 100644
--- a/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
+++ b/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
@@ -178,7 +178,7 @@
         pointerCoords.push_back(coords);
     }
 
-    const int32_t displayId = fdp.ConsumeIntegralInRange<int32_t>(0, maxDisplays - 1);
+    const ui::LogicalDisplayId displayId{fdp.ConsumeIntegralInRange<int32_t>(0, maxDisplays - 1)};
     const int32_t deviceId = fdp.ConsumeIntegralInRange<int32_t>(0, MAX_RANDOM_DEVICES - 1);
 
     // Current time +- 5 seconds
diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
index deb811d..0b4ac1f 100644
--- a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
@@ -54,7 +54,7 @@
                     mClassifier->notifyKey({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
                                             eventTime, readTime,
                                             /*deviceId=*/fdp.ConsumeIntegral<int32_t>(),
-                                            AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT,
+                                            AINPUT_SOURCE_KEYBOARD, ui::LogicalDisplayId::DEFAULT,
                                             /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(),
                                             AKEY_EVENT_ACTION_DOWN,
                                             /*flags=*/fdp.ConsumeIntegral<int32_t>(), AKEYCODE_HOME,
diff --git a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
index 7335fb7..79a5ff6 100644
--- a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
@@ -90,7 +90,7 @@
 
 sp<FakeWindowHandle> generateFuzzedWindow(FuzzedDataProvider& fdp,
                                           std::unique_ptr<InputDispatcher>& dispatcher,
-                                          int32_t displayId) {
+                                          ui::LogicalDisplayId displayId) {
     static size_t windowNumber = 0;
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     std::string windowName = android::base::StringPrintf("Win") + std::to_string(windowNumber++);
@@ -101,10 +101,11 @@
     return window;
 }
 
-void randomizeWindows(
-        std::unordered_map<int32_t, std::vector<sp<FakeWindowHandle>>>& windowsPerDisplay,
-        FuzzedDataProvider& fdp, std::unique_ptr<InputDispatcher>& dispatcher) {
-    const int32_t displayId = fdp.ConsumeIntegralInRange<int32_t>(0, MAX_RANDOM_DISPLAYS - 1);
+void randomizeWindows(std::unordered_map<ui::LogicalDisplayId, std::vector<sp<FakeWindowHandle>>>&
+                              windowsPerDisplay,
+                      FuzzedDataProvider& fdp, std::unique_ptr<InputDispatcher>& dispatcher) {
+    const ui::LogicalDisplayId displayId{
+            fdp.ConsumeIntegralInRange<int32_t>(0, MAX_RANDOM_DISPLAYS - 1)};
     std::vector<sp<FakeWindowHandle>>& windows = windowsPerDisplay[displayId];
 
     fdp.PickValueInArray<std::function<void()>>({
@@ -148,7 +149,7 @@
     // Start InputDispatcher thread
     dispatcher->start();
 
-    std::unordered_map<int32_t, std::vector<sp<FakeWindowHandle>>> windowsPerDisplay;
+    std::unordered_map<ui::LogicalDisplayId, std::vector<sp<FakeWindowHandle>>> windowsPerDisplay;
 
     // Randomly invoke InputDispatcher api's until randomness is exhausted.
     while (fdp.remaining_bytes() > 0) {
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index 9223287..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(); }
@@ -119,7 +117,7 @@
         return reader->getSensors(deviceId);
     }
 
-    bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
+    bool canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) {
         return reader->canDispatchToDisplay(deviceId, displayId);
     }
 
@@ -169,6 +167,8 @@
         reader->sysfsNodeChanged(sysfsNodePath);
     }
 
+    DeviceId getLastUsedInputDeviceId() override { return reader->getLastUsedInputDeviceId(); }
+
 private:
     std::unique_ptr<InputReaderInterface> reader;
 };
@@ -204,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>(),
@@ -241,7 +240,8 @@
                 },
                 [&]() -> void {
                     reader->canDispatchToDisplay(fdp->ConsumeIntegral<int32_t>(),
-                                                 fdp->ConsumeIntegral<int32_t>());
+                                                 ui::LogicalDisplayId{
+                                                         fdp->ConsumeIntegral<int32_t>()});
                 },
                 [&]() -> void {
                     reader->getKeyCodeForKeyLocation(fdp->ConsumeIntegral<int32_t>(),
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 7898126..25f2f2e 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -258,56 +258,16 @@
     void sysfsNodeChanged(const std::string& sysfsNodePath) override {}
 };
 
-class FuzzPointerController : public PointerControllerInterface {
-    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
-
-public:
-    FuzzPointerController(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
-    ~FuzzPointerController() {}
-    std::optional<FloatRect> getBounds() const override {
-        if (mFdp->ConsumeBool()) {
-            return {};
-        } else {
-            return FloatRect{mFdp->ConsumeFloatingPoint<float>(),
-                             mFdp->ConsumeFloatingPoint<float>(),
-                             mFdp->ConsumeFloatingPoint<float>(),
-                             mFdp->ConsumeFloatingPoint<float>()};
-        }
-    }
-    void move(float deltaX, float deltaY) override {}
-    void setPosition(float x, float y) override {}
-    FloatPoint getPosition() const override {
-        return {mFdp->ConsumeFloatingPoint<float>(), mFdp->ConsumeFloatingPoint<float>()};
-    }
-    void fade(Transition transition) override {}
-    void unfade(Transition transition) override {}
-    void setPresentation(Presentation presentation) override {}
-    void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
-                  BitSet32 spotIdBits, int32_t displayId) override {}
-    void clearSpots() override {}
-    int32_t getDisplayId() const override { return mFdp->ConsumeIntegral<int32_t>(); }
-    void setDisplayViewport(const DisplayViewport& displayViewport) override {}
-    void updatePointerIcon(PointerIconStyle iconId) override {}
-    void setCustomPointerIcon(const SpriteIcon& icon) override {}
-    std::string dump() override { return ""; }
-};
-
 class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
     TouchAffineTransformation mTransform;
-    std::shared_ptr<FuzzPointerController> mPointerController;
     std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 protected:
     ~FuzzInputReaderPolicy() {}
 
 public:
-    FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {
-        mPointerController = std::make_shared<FuzzPointerController>(mFdp);
-    }
+    FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
     void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
-    std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
-        return mPointerController;
-    }
     void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
     std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
             const InputDeviceIdentifier& identifier,
@@ -325,7 +285,7 @@
     void notifyStylusGestureStarted(int32_t, nsecs_t) {}
     bool isInputMethodConnectionActive() override { return mFdp->ConsumeBool(); }
     std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
-            int32_t associatedDisplayId) override {
+            ui::LogicalDisplayId associatedDisplayId) override {
         return {};
     }
 };
@@ -359,10 +319,6 @@
     bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override {
         return mFdp->ConsumeBool();
     }
-    void fadePointer() override {}
-    std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override {
-        return mPolicy->obtainPointerController(0);
-    }
     void requestTimeoutAtTime(nsecs_t when) override {}
     int32_t bumpGeneration() override { return mFdp->ConsumeIntegral<int32_t>(); }
     void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {}
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 8d43f79..5b499a8 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/senserservice_flags.aconfig
@@ -13,4 +13,18 @@
   namespace: "sensors"
   description: "This flag controls if the callback onDynamicSensorsDisconnected is implemented or not."
   bug: "316958439"
+}
+
+flag {
+  name: "sensor_event_connection_send_event_require_nonnull_scratch"
+  namespace: "sensors"
+  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/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index c18be7a..83b1b68 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -79,7 +79,7 @@
 }
 
 bool Display::isVirtual() const {
-    return VirtualDisplayId::tryCast(mId).has_value();
+    return mId.isVirtual();
 }
 
 std::optional<DisplayId> Display::getDisplayId() const {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 45ab7dd..3bf0eaa 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -137,7 +137,7 @@
 
 auto DisplayDevice::getFrontEndInfo() const -> frontend::DisplayInfo {
     gui::DisplayInfo info;
-    info.displayId = getLayerStack().id;
+    info.displayId = ui::LogicalDisplayId{static_cast<int32_t>(getLayerStack().id)};
 
     // The physical orientation is set when the orientation of the display panel is
     // different than the default orientation of the device. Other services like
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index fc5089b..ef3e77d 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -89,7 +89,7 @@
         return mCompositionDisplay;
     }
 
-    bool isVirtual() const { return VirtualDisplayId::tryCast(getId()).has_value(); }
+    bool isVirtual() const { return getId().isVirtual(); }
     bool isPrimary() const { return mIsPrimary; }
 
     // isSecure indicates whether this display can be trusted to display
@@ -329,6 +329,7 @@
     uint32_t width = 0;
     uint32_t height = 0;
     std::string displayName;
+    std::string uniqueId;
     bool isSecure = false;
     bool isProtected = false;
     // Refer to DisplayDevice::mRequestedRefreshRate, for virtual display only
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 96d5ca6..6c1a813 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -46,10 +46,21 @@
 namespace impl {
 
 using aidl::android::hardware::power::Boost;
+using aidl::android::hardware::power::ChannelConfig;
 using aidl::android::hardware::power::Mode;
 using aidl::android::hardware::power::SessionHint;
 using aidl::android::hardware::power::SessionTag;
 using aidl::android::hardware::power::WorkDuration;
+using aidl::android::hardware::power::WorkDurationFixedV1;
+
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::hardware::power::ChannelMessage;
+using android::hardware::EventFlag;
+
+using ChannelMessageContents = ChannelMessage::ChannelMessageContents;
+using MsgQueue = android::AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>;
+using FlagQueue = android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
 
 PowerAdvisor::~PowerAdvisor() = default;
 
@@ -140,15 +151,7 @@
     if (!mBootFinished.load()) {
         return;
     }
-    if (usePowerHintSession()) {
-        std::lock_guard lock(mHintSessionMutex);
-        if (ensurePowerHintSessionRunning()) {
-            auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
-            if (!ret.isOk()) {
-                mHintSession = nullptr;
-            }
-        }
-    }
+    sendHintSessionHint(SessionHint::CPU_LOAD_UP);
 }
 
 void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
@@ -160,15 +163,7 @@
 
     if (mSendUpdateImminent.exchange(false)) {
         ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
-        if (usePowerHintSession()) {
-            std::lock_guard lock(mHintSessionMutex);
-            if (ensurePowerHintSessionRunning()) {
-                auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
-                if (!ret.isOk()) {
-                    mHintSession = nullptr;
-                }
-            }
-        }
+        sendHintSessionHint(SessionHint::CPU_LOAD_RESET);
 
         if (!mHasDisplayUpdateImminent) {
             ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
@@ -210,6 +205,30 @@
             FlagManager::getInstance().adpf_use_fmq_channel();
 }
 
+void PowerAdvisor::sendHintSessionHint(SessionHint hint) {
+    if (!mBootFinished || !usePowerHintSession()) {
+        ALOGV("Power hint session is not enabled, skip sending session hint");
+        return;
+    }
+    ATRACE_CALL();
+    if (sTraceHintSessionData) ATRACE_INT("Session hint", static_cast<int>(hint));
+    {
+        std::scoped_lock lock(mHintSessionMutex);
+        if (!ensurePowerHintSessionRunning()) {
+            ALOGV("Hint session not running and could not be started, skip sending session hint");
+            return;
+        }
+        ALOGV("Sending session hint: %d", static_cast<int>(hint));
+        if (!writeHintSessionMessage<ChannelMessageContents::Tag::hint>(&hint, 1)) {
+            auto ret = mHintSession->sendHint(hint);
+            if (!ret.isOk()) {
+                ALOGW("Failed to send session hint with error: %s", ret.errorMessage());
+                mHintSession = nullptr;
+            }
+        }
+    }
+}
+
 bool PowerAdvisor::ensurePowerHintSessionRunning() {
     if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
         if (shouldCreateSessionWithConfig()) {
@@ -221,6 +240,9 @@
                                                                  &mSessionConfig);
             if (ret.isOk()) {
                 mHintSession = ret.value();
+                if (FlagManager::getInstance().adpf_use_fmq_channel_fixed()) {
+                    setUpFmq();
+                }
             }
             // If it fails the first time we try, or ever returns unsupported, assume unsupported
             else if (mFirstConfigSupportCheck || ret.isUnsupported()) {
@@ -241,9 +263,36 @@
     return mHintSession != nullptr;
 }
 
+void PowerAdvisor::setUpFmq() {
+    auto&& channelRet = getPowerHal().getSessionChannel(getpid(), static_cast<int32_t>(getuid()));
+    if (!channelRet.isOk()) {
+        ALOGE("Failed to get session channel with error: %s", channelRet.errorMessage());
+        return;
+    }
+    auto& channelConfig = channelRet.value();
+    mMsgQueue = std::make_unique<MsgQueue>(std::move(channelConfig.channelDescriptor), true);
+    LOG_ALWAYS_FATAL_IF(!mMsgQueue->isValid(), "Failed to set up hint session msg queue");
+    LOG_ALWAYS_FATAL_IF(channelConfig.writeFlagBitmask <= 0,
+                        "Invalid flag bit masks found in channel config: writeBitMask(%d)",
+                        channelConfig.writeFlagBitmask);
+    mFmqWriteMask = static_cast<uint32_t>(channelConfig.writeFlagBitmask);
+    if (!channelConfig.eventFlagDescriptor.has_value()) {
+        // For FMQ v1 in Android 15 we will force using shared event flag since the default
+        // no-op FMQ impl in Power HAL v5 will always return a valid channel config with
+        // non-zero masks but no shared flag.
+        mMsgQueue = nullptr;
+        ALOGE("No event flag descriptor found in channel config");
+        return;
+    }
+    mFlagQueue = std::make_unique<FlagQueue>(std::move(*channelConfig.eventFlagDescriptor), true);
+    LOG_ALWAYS_FATAL_IF(!mFlagQueue->isValid(), "Failed to set up hint session flag queue");
+    auto status = EventFlag::createEventFlag(mFlagQueue->getEventFlagWord(), &mEventFlag);
+    LOG_ALWAYS_FATAL_IF(status != OK, "Failed to set up hint session event flag");
+}
+
 void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
     if (!mBootFinished || !usePowerHintSession()) {
-        ALOGV("Power hint session target duration cannot be set, skipping");
+        ALOGV("Power hint session is not enabled, skipping target update");
         return;
     }
     ATRACE_CALL();
@@ -251,10 +300,15 @@
         mTargetDuration = targetDuration;
         if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
         if (targetDuration == mLastTargetDurationSent) return;
-        std::lock_guard lock(mHintSessionMutex);
-        if (ensurePowerHintSessionRunning()) {
-            ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
-            mLastTargetDurationSent = targetDuration;
+        std::scoped_lock lock(mHintSessionMutex);
+        if (!ensurePowerHintSessionRunning()) {
+            ALOGV("Hint session not running and could not be started, skip updating target");
+            return;
+        }
+        ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
+        mLastTargetDurationSent = targetDuration;
+        auto target = targetDuration.ns();
+        if (!writeHintSessionMessage<ChannelMessageContents::Tag::targetDuration>(&target, 1)) {
             auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
             if (!ret.isOk()) {
                 ALOGW("Failed to set power hint target work duration with error: %s",
@@ -302,23 +356,73 @@
     }
 
     {
-        std::lock_guard lock(mHintSessionMutex);
+        std::scoped_lock lock(mHintSessionMutex);
         if (!ensurePowerHintSessionRunning()) {
-            ALOGV("Hint session not running and could not be started, skipping");
+            ALOGV("Hint session not running and could not be started, skip reporting durations");
             return;
         }
         mHintSessionQueue.push_back(*actualDuration);
-
-        auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
-        if (!ret.isOk()) {
-            ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
-            mHintSession = nullptr;
-            return;
+        if (!writeHintSessionMessage<
+                    ChannelMessageContents::Tag::workDuration>(mHintSessionQueue.data(),
+                                                               mHintSessionQueue.size())) {
+            auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
+            if (!ret.isOk()) {
+                ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
+                mHintSession = nullptr;
+                return;
+            }
         }
     }
     mHintSessionQueue.clear();
 }
 
+template <ChannelMessage::ChannelMessageContents::Tag T, class In>
+bool PowerAdvisor::writeHintSessionMessage(In* contents, size_t count) {
+    if (!mMsgQueue) {
+        ALOGV("Skip using FMQ with message tag %hhd as it's not supported", T);
+        return false;
+    }
+    auto availableSize = mMsgQueue->availableToWrite();
+    if (availableSize < count) {
+        ALOGW("Skip using FMQ with message tag %hhd as there isn't enough space", T);
+        return false;
+    }
+    MsgQueue::MemTransaction tx;
+    if (!mMsgQueue->beginWrite(count, &tx)) {
+        ALOGW("Failed to begin writing message with tag %hhd", T);
+        return false;
+    }
+    for (size_t i = 0; i < count; ++i) {
+        if constexpr (T == ChannelMessageContents::Tag::workDuration) {
+            const WorkDuration& duration = contents[i];
+            new (tx.getSlot(i)) ChannelMessage{
+                    .sessionID = static_cast<int32_t>(mSessionConfig.id),
+                    .timeStampNanos =
+                            (i == count - 1) ? ::android::uptimeNanos() : duration.timeStampNanos,
+                    .data = ChannelMessageContents::make<ChannelMessageContents::Tag::workDuration,
+                                                         WorkDurationFixedV1>({
+                            .durationNanos = duration.durationNanos,
+                            .workPeriodStartTimestampNanos = duration.workPeriodStartTimestampNanos,
+                            .cpuDurationNanos = duration.cpuDurationNanos,
+                            .gpuDurationNanos = duration.gpuDurationNanos,
+                    }),
+            };
+        } else {
+            new (tx.getSlot(i)) ChannelMessage{
+                    .sessionID = static_cast<int32_t>(mSessionConfig.id),
+                    .timeStampNanos = ::android::uptimeNanos(),
+                    .data = ChannelMessageContents::make<T, In>(std::move(contents[i])),
+            };
+        }
+    }
+    if (!mMsgQueue->commitWrite(count)) {
+        ALOGW("Failed to send message with tag %hhd, fall back to binder call", T);
+        return false;
+    }
+    mEventFlag->wake(mFmqWriteMask);
+    return true;
+}
+
 void PowerAdvisor::enablePowerHintSession(bool enabled) {
     mHintSessionEnabled = enabled;
 }
@@ -334,12 +438,14 @@
     }
     LOG_ALWAYS_FATAL_IF(mHintSessionThreadIds.empty(),
                         "No thread IDs provided to power hint session!");
-    std::lock_guard lock(mHintSessionMutex);
-    if (mHintSession != nullptr) {
-        ALOGE("Cannot start power hint session: already running");
-        return false;
+    {
+        std::scoped_lock lock(mHintSessionMutex);
+        if (mHintSession != nullptr) {
+            ALOGE("Cannot start power hint session: already running");
+            return false;
+        }
+        return ensurePowerHintSessionRunning();
     }
-    return ensurePowerHintSessionRunning();
 }
 
 bool PowerAdvisor::supportsGpuReporting() {
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 161ca63..bc4a41b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -29,6 +29,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 #include <aidl/android/hardware/power/IPower.h>
+#include <fmq/AidlMessageQueue.h>
 #include <powermanager/PowerHalController.h>
 #pragma clang diagnostic pop
 
@@ -237,6 +238,7 @@
     bool shouldCreateSessionWithConfig() REQUIRES(mHintSessionMutex);
 
     bool ensurePowerHintSessionRunning() REQUIRES(mHintSessionMutex);
+    void setUpFmq() REQUIRES(mHintSessionMutex);
     std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData;
     // Current frame's delay
     Duration mFrameDelayDuration{0ns};
@@ -272,6 +274,15 @@
     bool mHasDisplayUpdateImminent = true;
     // Queue of actual durations saved to report
     std::vector<aidl::android::hardware::power::WorkDuration> mHintSessionQueue;
+    std::unique_ptr<::android::AidlMessageQueue<
+            aidl::android::hardware::power::ChannelMessage,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>>
+            mMsgQueue GUARDED_BY(mHintSessionMutex);
+    std::unique_ptr<::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>>
+            mFlagQueue GUARDED_BY(mHintSessionMutex);
+    android::hardware::EventFlag* mEventFlag;
+    uint32_t mFmqWriteMask;
     // The latest values we have received for target and actual
     Duration mTargetDuration = kDefaultTargetDuration;
     // The list of thread ids, stored so we can restart the session from this class if needed
@@ -306,6 +317,12 @@
     // How long we expect hwc to run after the present call until it waits for the fence
     static constexpr const Duration kFenceWaitStartDelayValidated{150us};
     static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
+
+    void sendHintSessionHint(aidl::android::hardware::power::SessionHint hint);
+
+    template <aidl::android::hardware::power::ChannelMessage::ChannelMessageContents::Tag T,
+              class In>
+    bool writeHintSessionMessage(In* elements, size_t count) REQUIRES(mHintSessionMutex);
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 4b5a68c..d69bfaf 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -316,7 +316,7 @@
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
         PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
-    LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
+    LOG_ALWAYS_FATAL_IF(mDisplayId.isVirtual());
 
     status_t result =
             mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
@@ -616,7 +616,7 @@
 }
 
 status_t VirtualDisplaySurface::refreshOutputBuffer() {
-    LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
+    LOG_ALWAYS_FATAL_IF(mDisplayId.isVirtual());
 
     if (mOutputProducerSlot >= 0) {
         mSource[SOURCE_SINK]->cancelBuffer(
diff --git a/services/surfaceflinger/Effects/Daltonizer.cpp b/services/surfaceflinger/Effects/Daltonizer.cpp
index a7090c5..65f2605 100644
--- a/services/surfaceflinger/Effects/Daltonizer.cpp
+++ b/services/surfaceflinger/Effects/Daltonizer.cpp
@@ -37,6 +37,18 @@
     }
 }
 
+void Daltonizer::setLevel(int32_t level) {
+    if (level < 0 || level > 10) {
+        return;
+    }
+
+    float newLevel = level / 10.0f;
+    if (std::fabs(mLevel - newLevel) > 0.09f) {
+        mDirty = true;
+    }
+    mLevel = newLevel;
+}
+
 const mat4& Daltonizer::operator()() {
     if (mDirty) {
         mDirty = false;
@@ -117,25 +129,24 @@
     // a color blind user and "spread" this error onto the healthy cones.
     // The matrices below perform this last step and have been chosen arbitrarily.
 
-    // The amount of correction can be adjusted here.
-
+    // Scale 0 represents no change (mColorTransform is identical matrix).
     // error spread for protanopia
-    const mat4 errp(    1.0, 0.7, 0.7, 0,
-                        0.0, 1.0, 0.0, 0,
-                        0.0, 0.0, 1.0, 0,
-                          0,   0,   0, 1);
+    const mat4 errp(1.0, mLevel, mLevel, 0.0,
+                    0.0,    1.0,    0.0, 0.0,
+                    0.0,    0.0,    1.0, 0.0,
+                    0.0,    0.0,    0.0, 1.0);
 
     // error spread for deuteranopia
-    const mat4 errd(    1.0, 0.0, 0.0, 0,
-                        0.7, 1.0, 0.7, 0,
-                        0.0, 0.0, 1.0, 0,
-                          0,   0,   0, 1);
+    const mat4 errd(   1.0, 0.0,    0.0, 0.0,
+                    mLevel, 1.0, mLevel, 0.0,
+                       0.0, 0.0,    1.0, 0.0,
+                       0.0, 0.0,    0.0, 1.0);
 
     // error spread for tritanopia
-    const mat4 errt(    1.0, 0.0, 0.0, 0,
-                        0.0, 1.0, 0.0, 0,
-                        0.7, 0.7, 1.0, 0,
-                          0,   0,   0, 1);
+    const mat4 errt(   1.0,    0.0, 0.0, 0.0,
+                       0.0,    1.0, 0.0, 0.0,
+                    mLevel, mLevel, 1.0, 0.0,
+                       0.0,    0.0, 0.0, 1.0);
 
     // And the magic happens here...
     // We construct the matrix that will perform the whole correction.
diff --git a/services/surfaceflinger/Effects/Daltonizer.h b/services/surfaceflinger/Effects/Daltonizer.h
index 2fb60e9..f5eaae7 100644
--- a/services/surfaceflinger/Effects/Daltonizer.h
+++ b/services/surfaceflinger/Effects/Daltonizer.h
@@ -21,6 +21,9 @@
 
 namespace android {
 
+// Forward declare test class
+class DaltonizerTest;
+
 enum class ColorBlindnessType {
     None,               // Disables the Daltonizer
     Protanomaly,        // L (red) cone deficient
@@ -37,10 +40,15 @@
 public:
     void setType(ColorBlindnessType type);
     void setMode(ColorBlindnessMode mode);
+    // sets level for correction saturation, [0-10].
+    void setLevel(int32_t level);
 
     // returns the color transform to apply in the shader
     const mat4& operator()();
 
+    // For testing.
+    friend class DaltonizerTest;
+
 private:
     void update();
 
@@ -48,6 +56,8 @@
     ColorBlindnessMode mMode = ColorBlindnessMode::Simulation;
     bool mDirty = true;
     mat4 mColorTransform;
+    // level of error spreading, [0.0-1.0].
+    float mLevel = 0.7f;
 };
 
 } /* namespace android */
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index d0e2d7a..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
@@ -681,6 +688,14 @@
     }
 }
 
+void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
+    std::scoped_lock lock(mMutex);
+
+    mDisplayFrameRenderRate = displayFrameRenderRate;
+    mActuals.presentTime = mPredictions.presentTime;
+    classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
+}
+
 void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
     int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
 
@@ -912,6 +927,15 @@
     finalizeCurrentDisplayFrame();
 }
 
+void FrameTimeline::onCommitNotComposited() {
+    ATRACE_CALL();
+    std::scoped_lock lock(mMutex);
+    mCurrentDisplayFrame->onCommitNotComposited();
+    mCurrentDisplayFrame.reset();
+    mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
+                                                          &mTraceCookieCounter);
+}
+
 void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
     mSurfaceFrames.push_back(surfaceFrame);
 }
@@ -1094,6 +1118,12 @@
     }
 }
 
+void FrameTimeline::DisplayFrame::onCommitNotComposited() {
+    for (auto& surfaceFrame : mSurfaceFrames) {
+        surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
+    }
+}
+
 void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
                                                    nsecs_t monoBootOffset) const {
     int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
@@ -1142,7 +1172,7 @@
                     (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
                      kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
             static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
-                    (static_cast<float>(previousPredictionPresentTime) -
+                    (static_cast<float>(previousPredictionPresentTime) +
                      kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
             // sf skipped frame is not considered if app is self janked
             !surfaceFrame->isSelfJanky()) {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index a76f7d4..94cfcb4 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -204,6 +204,8 @@
     void onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
                    Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
                    nsecs_t displayPresentDelta);
+    // Sets the frame as none janky as there was no real display frame.
+    void onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate);
     // All the timestamps are dumped relative to the baseTime
     void dump(std::string& result, const std::string& indent, nsecs_t baseTime) const;
     // Dumps only the layer, token, is buffer, jank metadata, prediction and present states.
@@ -235,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;
@@ -318,6 +320,10 @@
     virtual void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
                               const std::shared_ptr<FenceTime>& gpuFence) = 0;
 
+    // Tells FrameTimeline that a frame was committed but not composited. This is used to flush
+    // all the associated surface frames.
+    virtual void onCommitNotComposited() = 0;
+
     // Args:
     // -jank : Dumps only the Display Frames that are either janky themselves
     //         or contain janky Surface Frames.
@@ -390,6 +396,8 @@
                         std::optional<TimelineItem> predictions, nsecs_t wakeUpTime);
         // Sets the appropriate metadata and classifies the jank.
         void onPresent(nsecs_t signalTime, nsecs_t previousPresentTime);
+        // Flushes all the surface frames as those were not generating any actual display frames.
+        void onCommitNotComposited();
         // Adds the provided SurfaceFrame to the current display frame.
         void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame);
 
@@ -475,6 +483,7 @@
     void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate, Fps renderRate) override;
     void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
                       const std::shared_ptr<FenceTime>& gpuFence = FenceTime::NO_FENCE) override;
+    void onCommitNotComposited() override;
     void parseArgs(const Vector<String16>& args, std::string& result) override;
     void setMaxDisplayFrames(uint32_t size) override;
     float computeFps(const std::unordered_set<int32_t>& layerIds) override;
diff --git a/services/surfaceflinger/FrontEnd/DisplayInfo.h b/services/surfaceflinger/FrontEnd/DisplayInfo.h
index 6502f36..ea51e92 100644
--- a/services/surfaceflinger/FrontEnd/DisplayInfo.h
+++ b/services/surfaceflinger/FrontEnd/DisplayInfo.h
@@ -21,6 +21,7 @@
 #include <gui/DisplayInfo.h>
 #include <ui/DisplayMap.h>
 #include <ui/LayerStack.h>
+#include <ui/LogicalDisplayId.h>
 #include <ui/Transform.h>
 
 namespace android::surfaceflinger::frontend {
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index a2b5329..f2497d4 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -362,6 +362,7 @@
     snapshot.gameMode = gui::GameMode::Unsupported;
     snapshot.frameRate = {};
     snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
+    snapshot.ignoreLocalTransform = false;
     return snapshot;
 }
 
@@ -1044,7 +1045,8 @@
     snapshot.touchCropId = requested.touchCropId;
 
     snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
-    snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
+    snapshot.inputInfo.displayId =
+            ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)};
     snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
             ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
             : parentSnapshot.inputInfo.touchOcclusionMode;
@@ -1061,8 +1063,8 @@
     }
 
     if (snapshot.isSecure ||
-        parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_TRACING)) {
-        snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_TRACING;
+        parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_PRIVACY)) {
+        snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_PRIVACY;
     }
 
     updateVisibility(snapshot, snapshot.isVisible);
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 09f33de..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
@@ -58,6 +59,13 @@
         GameMode = 1u << 19,
         BufferUsageFlags = 1u << 20,
     };
+
+    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/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0137a7b..363b35c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -90,6 +90,10 @@
 
 const ui::Transform kIdentityTransform;
 
+ui::LogicalDisplayId toLogicalDisplayId(const ui::LayerStack& layerStack) {
+    return ui::LogicalDisplayId{static_cast<int32_t>(layerStack.id)};
+}
+
 bool assignTransform(ui::Transform* dst, ui::Transform& from) {
     if (*dst == from) {
         return false;
@@ -2465,7 +2469,7 @@
         mDrawingState.inputInfo.ownerUid = gui::Uid{mOwnerUid};
         mDrawingState.inputInfo.ownerPid = gui::Pid{mOwnerPid};
         mDrawingState.inputInfo.inputConfig |= WindowInfo::InputConfig::NO_INPUT_CHANNEL;
-        mDrawingState.inputInfo.displayId = getLayerStack().id;
+        mDrawingState.inputInfo.displayId = toLogicalDisplayId(getLayerStack());
     }
 
     const ui::Transform& displayTransform =
@@ -2473,7 +2477,7 @@
 
     WindowInfo info = mDrawingState.inputInfo;
     info.id = sequence;
-    info.displayId = getLayerStack().id;
+    info.displayId = toLogicalDisplayId(getLayerStack());
 
     fillInputFrameInfo(info, displayTransform);
 
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 513c943..753886a 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -465,7 +465,7 @@
     displays.Reserve(displayInfos.size());
     for (const auto& [layerStack, displayInfo] : displayInfos) {
         auto displayProto = displays.Add();
-        displayProto->set_id(displayInfo.info.displayId);
+        displayProto->set_id(displayInfo.info.displayId.val());
         displayProto->set_layer_stack(layerStack.id);
         displayProto->mutable_size()->set_w(displayInfo.info.logicalWidth);
         displayProto->mutable_size()->set_h(displayInfo.info.logicalHeight);
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index c25ddb6..f323ce7 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -25,13 +25,14 @@
 
 namespace android {
 
-LayerRenderArea::LayerRenderArea(sp<Layer> layer, const Rect& crop, ui::Size reqSize,
-                                 ui::Dataspace reqDataSpace, bool allowSecureLayers,
-                                 const ui::Transform& layerTransform, const Rect& layerBufferSize,
-                                 bool hintForSeamlessTransition)
+LayerRenderArea::LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot,
+                                 const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
+                                 bool allowSecureLayers, const ui::Transform& layerTransform,
+                                 const Rect& layerBufferSize, bool hintForSeamlessTransition)
       : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, hintForSeamlessTransition,
                    allowSecureLayers),
         mLayer(std::move(layer)),
+        mLayerSnapshot(std::move(layerSnapshot)),
         mLayerBufferSize(layerBufferSize),
         mCrop(crop),
         mTransform(layerTransform) {}
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
index b12afe8..a12bfca 100644
--- a/services/surfaceflinger/LayerRenderArea.h
+++ b/services/surfaceflinger/LayerRenderArea.h
@@ -32,19 +32,22 @@
 
 class LayerRenderArea : public RenderArea {
 public:
-    LayerRenderArea(sp<Layer> layer, const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
-                    bool allowSecureLayers, const ui::Transform& layerTransform,
-                    const Rect& layerBufferSize, bool hintForSeamlessTransition);
+    LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop,
+                    ui::Size reqSize, ui::Dataspace reqDataSpace, bool allowSecureLayers,
+                    const ui::Transform& layerTransform, const Rect& layerBufferSize,
+                    bool hintForSeamlessTransition);
 
     const ui::Transform& getTransform() const override;
     bool isSecure() const override;
     sp<const DisplayDevice> getDisplayDevice() const override;
     Rect getSourceCrop() const override;
 
-    virtual sp<Layer> getParentLayer() const { return mLayer; }
+    sp<Layer> getParentLayer() const override { return mLayer; }
+    const frontend::LayerSnapshot* getLayerSnapshot() const override { return &mLayerSnapshot; }
 
 private:
     const sp<Layer> mLayer;
+    const frontend::LayerSnapshot mLayerSnapshot;
     const Rect mLayerBufferSize;
     const Rect mCrop;
 
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 77e045d..2b4e234 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -42,6 +42,7 @@
 #include "DisplayRenderArea.h"
 #include "FrontEnd/LayerCreationArgs.h"
 #include "Layer.h"
+#include "RenderAreaBuilder.h"
 #include "Scheduler/VsyncController.h"
 #include "SurfaceFlinger.h"
 
@@ -278,11 +279,6 @@
     const Rect sampledBounds = sampleRegion.bounds();
     constexpr bool kHintForSeamlessTransition = false;
 
-    SurfaceFlinger::RenderAreaFuture renderAreaFuture = ftl::defer([=] {
-        return DisplayRenderArea::create(displayWeak, sampledBounds, sampledBounds.getSize(),
-                                         ui::Dataspace::V0_SRGB, kHintForSeamlessTransition);
-    });
-
     std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
 
     auto layerFilterFn = [&](const char* layerName, uint32_t layerId, const Rect& bounds,
@@ -377,8 +373,14 @@
     constexpr bool kIsProtected = false;
 
     if (const auto fenceResult =
-                mFlinger.captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, buffer,
-                                           kRegionSampling, kGrayscale, kIsProtected, nullptr)
+                mFlinger.captureScreenshot(SurfaceFlinger::RenderAreaBuilderVariant(
+                                                   std::in_place_type<DisplayRenderAreaBuilder>,
+                                                   sampledBounds, sampledBounds.getSize(),
+                                                   ui::Dataspace::V0_SRGB,
+                                                   kHintForSeamlessTransition,
+                                                   true /* captureSecureLayers */, displayWeak),
+                                           getLayerSnapshots, buffer, kRegionSampling, kGrayscale,
+                                           kIsProtected, nullptr)
                         .get();
         fenceResult.ok()) {
         fenceResult.value()->waitForever(LOG_TAG);
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 18a5304..e8d20af 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -4,6 +4,8 @@
 #include <ui/Transform.h>
 
 #include <functional>
+
+#include "FrontEnd/LayerSnapshot.h"
 #include "Layer.h"
 
 namespace android {
@@ -82,6 +84,10 @@
     // capture operation.
     virtual sp<Layer> getParentLayer() const { return nullptr; }
 
+    // If this is a LayerRenderArea, return the layer snapshot
+    // of the root layer of the capture operation
+    virtual const frontend::LayerSnapshot* getLayerSnapshot() const { return nullptr; }
+
     // Returns whether the render result may be used for system animations that
     // must preserve the exact colors of the display.
     bool getHintForSeamlessTransition() const { return mHintForSeamlessTransition; }
diff --git a/services/surfaceflinger/RenderAreaBuilder.h b/services/surfaceflinger/RenderAreaBuilder.h
new file mode 100644
index 0000000..a25c6e0
--- /dev/null
+++ b/services/surfaceflinger/RenderAreaBuilder.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "DisplayDevice.h"
+#include "DisplayRenderArea.h"
+#include "LayerRenderArea.h"
+#include "ui/Size.h"
+#include "ui/Transform.h"
+
+namespace android {
+/**
+ * A parameter object for creating a render area
+ */
+struct RenderAreaBuilder {
+    // Source crop of the render area
+    Rect crop;
+
+    // Size of the physical render area
+    ui::Size reqSize;
+
+    // Composition data space of the render area
+    ui::Dataspace reqDataSpace;
+
+    // If true, the secure layer would be blacked out or skipped
+    // when rendered to an insecure render area
+    bool allowSecureLayers;
+
+    // If true, the render result may be used for system animations
+    // that must preserve the exact colors of the display
+    bool hintForSeamlessTransition;
+
+    virtual std::unique_ptr<RenderArea> build() const = 0;
+
+    RenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
+                      bool allowSecureLayers, bool hintForSeamlessTransition)
+          : crop(crop),
+            reqSize(reqSize),
+            reqDataSpace(reqDataSpace),
+            allowSecureLayers(allowSecureLayers),
+            hintForSeamlessTransition(hintForSeamlessTransition) {}
+
+    virtual ~RenderAreaBuilder() = default;
+};
+
+struct DisplayRenderAreaBuilder : RenderAreaBuilder {
+    DisplayRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
+                             bool allowSecureLayers, bool hintForSeamlessTransition,
+                             wp<const DisplayDevice> displayWeak)
+          : RenderAreaBuilder(crop, reqSize, reqDataSpace, allowSecureLayers,
+                              hintForSeamlessTransition),
+            displayWeak(displayWeak) {}
+
+    // Display that render area will be on
+    wp<const DisplayDevice> displayWeak;
+
+    std::unique_ptr<RenderArea> build() const override {
+        return DisplayRenderArea::create(displayWeak, crop, reqSize, reqDataSpace,
+                                         hintForSeamlessTransition, allowSecureLayers);
+    }
+};
+
+struct LayerRenderAreaBuilder : RenderAreaBuilder {
+    LayerRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
+                           bool allowSecureLayers, bool hintForSeamlessTransition, sp<Layer> layer,
+                           bool childrenOnly)
+          : RenderAreaBuilder(crop, reqSize, reqDataSpace, allowSecureLayers,
+                              hintForSeamlessTransition),
+            layer(layer),
+            childrenOnly(childrenOnly) {}
+
+    // Root layer of the render area
+    sp<Layer> layer;
+
+    // Layer snapshot of the root layer
+    frontend::LayerSnapshot layerSnapshot;
+
+    // Transform to be applied on the layers to transform them
+    // into the logical render area
+    ui::Transform layerTransform{ui::Transform()};
+
+    // Buffer bounds
+    Rect layerBufferSize{Rect()};
+
+    // If false, transform is inverted from the parent snapshot
+    bool childrenOnly;
+
+    // Uses parent snapshot to determine layer transform and buffer size
+    void setLayerSnapshot(const frontend::LayerSnapshot& parentSnapshot) {
+        layerSnapshot = parentSnapshot;
+        if (!childrenOnly) {
+            layerTransform = parentSnapshot.localTransform.inverse();
+        }
+        layerBufferSize = parentSnapshot.bufferSize;
+    }
+
+    std::unique_ptr<RenderArea> build() const override {
+        return std::make_unique<LayerRenderArea>(layer, std::move(layerSnapshot), crop, reqSize,
+                                                 reqDataSpace, allowSecureLayers, layerTransform,
+                                                 layerBufferSize, hintForSeamlessTransition);
+    }
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/ISchedulerCallback.h b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
index 9f4f5b6..43cdb5e 100644
--- a/services/surfaceflinger/Scheduler/ISchedulerCallback.h
+++ b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
@@ -32,6 +32,7 @@
     virtual void onChoreographerAttached() = 0;
     virtual void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>,
                                              Fps renderRate) = 0;
+    virtual void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) = 0;
 
 protected:
     ~ISchedulerCallback() = default;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index a37fb96..2c66492 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -1590,7 +1590,8 @@
     std::lock_guard lock(mLock);
 
     const auto activeMode = getActiveModeLocked();
-    dumper.dump("activeMode"sv, to_string(activeMode));
+    dumper.dump("renderRate"sv, to_string(activeMode.fps));
+    dumper.dump("activeMode"sv, to_string(*activeMode.modePtr));
 
     dumper.dump("displayModes"sv);
     {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 005ec05..60681a2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -221,6 +221,7 @@
             if (FlagManager::getInstance().vrr_config()) {
                 compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
             }
+            mSchedulerCallback.onCommitNotComposited(pacesetterPtr->displayId);
             return;
         }
     }
@@ -1152,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/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index ccb3aa7..ccaa05f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -346,7 +346,9 @@
     // Used to skip event dispatch before EventThread creation during boot.
     // TODO: b/241285191 - Reorder Scheduler initialization to avoid this.
     bool hasEventThreads() const {
-        return CC_LIKELY(mRenderEventThread && mLastCompositeEventThread);
+        return CC_LIKELY(
+                mRenderEventThread &&
+                (FlagManager::getInstance().deprecate_vsync_sf() || mLastCompositeEventThread));
     }
 
     EventThread& eventThreadFor(Cycle cycle) const {
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 0b47924..85ce713 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -650,29 +650,33 @@
     const auto threshold = model.slope / 2;
     const auto lastFrameMissed =
             lastVsyncOpt && std::abs(*lastVsyncOpt - missedVsync.vsync.ns()) < threshold;
-    if (FlagManager::getInstance().vrr_config() && lastFrameMissed) {
-        // If the last frame missed is the last vsync, we already shifted the timeline. Depends on
-        // whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a different
-        // fixup. There is no need to to shift the vsync timeline again.
-        vsyncTime += missedVsync.fixup.ns();
-        ATRACE_FORMAT_INSTANT("lastFrameMissed");
-    } else if (FlagManager::getInstance().vrr_config() && minFramePeriodOpt && mRenderRateOpt &&
-               lastVsyncOpt) {
-        // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
-        // first before trying to use it.
-        lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
-        const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
-        if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
-            // avoid a duplicate vsync
-            ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f which "
-                                  "is %.2f "
-                                  "from "
-                                  "prev. "
-                                  "adjust by %.2f",
-                                  static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
-                                  static_cast<float>(vsyncDiff) / 1e6f,
-                                  static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
-            vsyncTime += mRenderRateOpt->getPeriodNsecs();
+    const auto mightBackpressure = minFramePeriodOpt && mRenderRateOpt &&
+            mRenderRateOpt->getPeriod() < 2 * (*minFramePeriodOpt);
+    if (FlagManager::getInstance().vrr_config()) {
+        if (lastFrameMissed) {
+            // If the last frame missed is the last vsync, we already shifted the timeline. Depends
+            // on whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a
+            // different fixup. There is no need to to shift the vsync timeline again.
+            vsyncTime += missedVsync.fixup.ns();
+            ATRACE_FORMAT_INSTANT("lastFrameMissed");
+        } else if (mightBackpressure && lastVsyncOpt) {
+            // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
+            // first before trying to use it.
+            lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
+            const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
+            if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
+                // avoid a duplicate vsync
+                ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f "
+                                      "which "
+                                      "is %.2f "
+                                      "from "
+                                      "prev. "
+                                      "adjust by %.2f",
+                                      static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
+                                      static_cast<float>(vsyncDiff) / 1e6f,
+                                      static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
+                vsyncTime += mRenderRateOpt->getPeriodNsecs();
+            }
         }
     }
 
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
index 59a6df2..f2be316 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
@@ -36,8 +36,11 @@
 };
 
 inline std::string to_string(const FrameRateMode& mode) {
-    return to_string(mode.fps) + " (" + to_string(mode.modePtr->getPeakFps()) + "(" +
-            to_string(mode.modePtr->getVsyncRate()) + "))";
+    return base::StringPrintf("{fps=%s, modePtr={id=%d, vsyncRate=%s, peakRefreshRate=%s}}",
+                              to_string(mode.fps).c_str(),
+                              ftl::to_underlying(mode.modePtr->getId()),
+                              to_string(mode.modePtr->getVsyncRate()).c_str(),
+                              to_string(mode.modePtr->getPeakFps()).c_str());
 }
 
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bd5accc..62b0ded 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>
@@ -148,6 +149,7 @@
 #include "MutexUtils.h"
 #include "NativeWindowSurface.h"
 #include "RegionSamplingThread.h"
+#include "RenderAreaBuilder.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/LayerHistory.h"
 #include "Scheduler/Scheduler.h"
@@ -424,7 +426,8 @@
         mInternalDisplayDensity(
                 getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
         mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
-        mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
+        mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()),
+        mSkipPowerOnForQuiescent(base::GetBoolProperty("ro.boot.quiescent"s, false)) {
     ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
 }
 
@@ -571,13 +574,14 @@
     mScheduler->run();
 }
 
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure,
-                                          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.
-    const int uid = IPCThreadState::self()->getCallingUid();
-    if (secure && uid != AID_ROOT && uid != AID_GRAPHICS && uid != AID_SYSTEM) {
+    const uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (isSecure && uid != AID_ROOT && uid != AID_GRAPHICS && uid != AID_SYSTEM) {
         ALOGE("Only privileged processes can create a secure display");
         return nullptr;
     }
@@ -601,32 +605,34 @@
     Mutex::Autolock _l(mStateLock);
     // Display ID is assigned when virtual display is allocated by HWC.
     DisplayDeviceState state;
-    state.isSecure = secure;
+    state.isSecure = isSecure;
     // Set display as protected when marked as secure to ensure no behavior change
     // TODO (b/314820005): separate as a different arg when creating the display.
-    state.isProtected = secure;
+    state.isProtected = isSecure;
     state.displayName = displayName;
+    state.uniqueId = uniqueId;
     state.requestedRefreshRate = Fps::fromValue(requestedRefreshRate);
     mCurrentState.displays.add(token, state);
     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) {
@@ -1447,11 +1453,6 @@
             continue;
         }
 
-        if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
-            dropModeRequest(display);
-            continue;
-        }
-
         const auto desiredModeId = desiredModeOpt->mode.modePtr->getId();
         const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId);
 
@@ -2461,7 +2462,12 @@
         mUpdateAttachedChoreographer = true;
     }
     outTransactionsAreEmpty = mLayerLifecycleManager.getGlobalChanges().get() == 0;
-    mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
+    if (FlagManager::getInstance().vrr_bugfix_24q4()) {
+        mustComposite |= mLayerLifecycleManager.getGlobalChanges().any(
+                frontend::RequestedLayerState::kMustComposite);
+    } else {
+        mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
+    }
 
     bool newDataLatched = false;
     ATRACE_NAME("DisplayCallbackAndStatsUpdates");
@@ -3907,7 +3913,9 @@
 
         if (currentState.physical) {
             const auto display = getDisplayDeviceLocked(displayToken);
-            setPowerModeInternal(display, hal::PowerMode::ON);
+            if (!mSkipPowerOnForQuiescent) {
+                setPowerModeInternal(display, hal::PowerMode::ON);
+            }
 
             // TODO(b/175678251) Call a listener instead.
             if (currentState.physical->hwcDisplayId == getHwComposer().getPrimaryHwcDisplayId()) {
@@ -4248,12 +4256,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 {
@@ -4425,6 +4427,12 @@
     scheduleNotifyExpectedPresentHint(displayId);
 }
 
+void SurfaceFlinger::onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) {
+    if (FlagManager::getInstance().commit_not_composited()) {
+        mFrameTimeline->onCommitNotComposited();
+    }
+}
+
 void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
     using namespace scheduler;
 
@@ -6126,8 +6134,11 @@
         // Power on all displays. The primary display is first, so becomes the active display. Also,
         // the DisplayCapability set of a display is populated on its first powering on. Do this now
         // before responding to any Binder query from DisplayManager about display capabilities.
-        for (const auto& [id, display] : mPhysicalDisplays) {
-            setPowerModeInternal(getDisplayDeviceLocked(id), hal::PowerMode::ON);
+        // Additionally, do not turn on displays if the boot should be quiescent.
+        if (!mSkipPowerOnForQuiescent) {
+            for (const auto& [id, display] : mPhysicalDisplays) {
+                setPowerModeInternal(getDisplayDeviceLocked(id), hal::PowerMode::ON);
+            }
         }
     }
 }
@@ -6286,6 +6297,7 @@
 void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
     auto future = mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(
                                                kMainThreadContext) {
+        mSkipPowerOnForQuiescent = false;
         const auto display = getDisplayDeviceLocked(displayToken);
         if (!display) {
             ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -6547,18 +6559,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");
@@ -7015,8 +7028,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:
@@ -7153,6 +7166,7 @@
                 Mutex::Autolock _l(mStateLock);
                 // daltonize
                 n = data.readInt32();
+                mDaltonizer.setLevel(data.readInt32());
                 switch (n % 10) {
                     case 1:
                         mDaltonizer.setType(ColorBlindnessType::Protanomaly);
@@ -7516,14 +7530,11 @@
                 auto future = mScheduler->schedule(
                         [&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
                             n = data.readInt32();
-                            mHdrSdrRatioOverlay = n != 0;
-                            switch (n) {
-                                case 0:
-                                case 1:
-                                    enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay);
-                                    break;
-                                default:
-                                    reply->writeBool(isHdrSdrRatioOverlayEnabled());
+                            if (n == 0 || n == 1) {
+                                mHdrSdrRatioOverlay = n != 0;
+                                enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay);
+                            } else {
+                                reply->writeBool(isHdrSdrRatioOverlayEnabled());
                             }
                         });
                 future.wait();
@@ -7916,11 +7927,6 @@
         }
     }
 
-    RenderAreaFuture renderAreaFuture = ftl::defer([=] {
-        return DisplayRenderArea::create(displayWeak, args.sourceCrop, reqSize, args.dataspace,
-                                         args.hintForSeamlessTransition, args.captureSecureLayers);
-    });
-
     GetLayerSnapshotsFunction getLayerSnapshots;
     if (mLayerLifecycleManagerEnabled) {
         getLayerSnapshots =
@@ -7933,8 +7939,12 @@
         getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
     }
 
-    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
-                        args.allowProtected, args.grayscale, captureListener);
+    captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
+                                                 args.sourceCrop, reqSize, args.dataspace,
+                                                 args.hintForSeamlessTransition,
+                                                 args.captureSecureLayers, displayWeak),
+                        getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+                        args.grayscale, captureListener);
 }
 
 void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
@@ -7970,12 +7980,6 @@
         return;
     }
 
-    RenderAreaFuture renderAreaFuture = ftl::defer([=] {
-        return DisplayRenderArea::create(displayWeak, Rect(), size, args.dataspace,
-                                         args.hintForSeamlessTransition,
-                                         false /* captureSecureLayers */);
-    });
-
     GetLayerSnapshotsFunction getLayerSnapshots;
     if (mLayerLifecycleManagerEnabled) {
         getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
@@ -7996,8 +8000,12 @@
     constexpr bool kAllowProtected = false;
     constexpr bool kGrayscale = false;
 
-    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, args.pixelFormat,
-                        kAllowProtected, kGrayscale, captureListener);
+    captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
+                                                 Rect(), size, args.dataspace,
+                                                 args.hintForSeamlessTransition,
+                                                 false /* captureSecureLayers */, displayWeak),
+                        getLayerSnapshots, size, args.pixelFormat, kAllowProtected, kGrayscale,
+                        captureListener);
 }
 
 ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) {
@@ -8078,25 +8086,6 @@
         return;
     }
 
-    RenderAreaFuture renderAreaFuture = ftl::defer([=, this]() FTL_FAKE_GUARD(kMainThreadContext)
-                                                           -> std::unique_ptr<RenderArea> {
-        ui::Transform layerTransform;
-        Rect layerBufferSize;
-        frontend::LayerSnapshot* snapshot =
-                mLayerSnapshotBuilder.getSnapshot(parent->getSequence());
-        if (!snapshot) {
-            ALOGW("Couldn't find layer snapshot for %d", parent->getSequence());
-        } else {
-            if (!args.childrenOnly) {
-                layerTransform = snapshot->localTransform.inverse();
-            }
-            layerBufferSize = snapshot->bufferSize;
-        }
-
-        return std::make_unique<LayerRenderArea>(parent, crop, reqSize, dataspace,
-                                                 args.captureSecureLayers, layerTransform,
-                                                 layerBufferSize, args.hintForSeamlessTransition);
-    });
     GetLayerSnapshotsFunction getLayerSnapshots;
     if (mLayerLifecycleManagerEnabled) {
         std::optional<FloatRect> parentCrop = std::nullopt;
@@ -8139,8 +8128,12 @@
         return;
     }
 
-    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
-                        args.allowProtected, args.grayscale, captureListener);
+    captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop,
+                                                 reqSize, dataspace, args.captureSecureLayers,
+                                                 args.hintForSeamlessTransition, parent,
+                                                 args.childrenOnly),
+                        getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+                        args.grayscale, captureListener);
 }
 
 // Creates a Future release fence for a layer and keeps track of it in a list to
@@ -8167,7 +8160,7 @@
     return protectedLayerFound;
 }
 
-void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
+void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder,
                                          GetLayerSnapshotsFunction getLayerSnapshots,
                                          ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
                                          bool allowProtected, bool grayscale,
@@ -8216,21 +8209,35 @@
                                                  renderengine::impl::ExternalTexture::Usage::
                                                          WRITEABLE);
     auto futureFence =
-            captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, texture,
+            captureScreenshot(renderAreaBuilder, getLayerSnapshots, texture,
                               false /* regionSampling */, grayscale, isProtected, captureListener);
     futureFence.get();
 }
 
 ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
-        RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots,
+        RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshots,
         const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
         bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) {
     ATRACE_CALL();
 
-    auto takeScreenshotFn = [=, this, renderAreaFuture = std::move(renderAreaFuture)]() REQUIRES(
+    auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
                                     kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
         // LayerSnapshots must be obtained from the main thread.
         auto layers = getLayerSnapshots();
+
+        if (auto* layerRenderAreaBuilder =
+                    std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) {
+            // LayerSnapshotBuilder should only be accessed from the main thread.
+            frontend::LayerSnapshot* snapshot =
+                    mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence());
+            if (!snapshot) {
+                ALOGW("Couldn't find layer snapshot for %d",
+                      layerRenderAreaBuilder->layer->getSequence());
+            } else {
+                layerRenderAreaBuilder->setLayerSnapshot(*snapshot);
+            }
+        }
+
         if (FlagManager::getInstance().ce_fence_promise()) {
             for (auto& [layer, layerFE] : layers) {
                 attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
@@ -8238,7 +8245,10 @@
         }
 
         ScreenCaptureResults captureResults;
-        std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get();
+        std::unique_ptr<const RenderArea> renderArea =
+                std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
+                           renderAreaBuilder);
+
         if (!renderArea) {
             ALOGW("Skipping screen capture because of invalid render area.");
             if (captureListener) {
@@ -8249,8 +8259,8 @@
         }
 
         ftl::SharedFuture<FenceResult> renderFuture =
-                renderScreenImpl(renderArea, buffer, regionSampling, grayscale, isProtected,
-                                 captureResults, layers);
+                renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale,
+                                 isProtected, captureResults, layers);
 
         if (captureListener) {
             // Defer blocking on renderFuture back to the Binder thread.
@@ -8267,9 +8277,7 @@
     };
 
     // TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number
-    // of calls on the main thread. renderAreaFuture runs on the main thread and should
-    // no longer be a future, so that it does not need to make an additional jump on the
-    // main thread whenever get() is called.
+    // of calls on the main thread.
     auto future =
             mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));
 
@@ -8282,16 +8290,16 @@
 }
 
 ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
-        std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
+        std::unique_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
         const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
         bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) {
     auto layers = getLayerSnapshots();
-    return renderScreenImpl(renderArea, buffer, regionSampling, grayscale, isProtected,
+    return renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected,
                             captureResults, layers);
 }
 
 ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
-        std::shared_ptr<const RenderArea> renderArea,
+        std::unique_ptr<const RenderArea> renderArea,
         const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
         bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
         std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) {
@@ -8321,9 +8329,8 @@
         Mutex::Autolock lock(mStateLock);
         const DisplayDevice* display = nullptr;
         if (parent) {
-            const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
-                    ? mLayerSnapshotBuilder.getSnapshot(parent->sequence)
-                    : parent->getLayerSnapshot();
+            const frontend::LayerSnapshot* snapshot =
+                    mLayerSnapshotBuilder.getSnapshot(parent->sequence);
             if (snapshot) {
                 display = findDisplay([layerStack = snapshot->outputFilter.layerStack](
                                               const auto& display) {
@@ -8347,10 +8354,7 @@
                                       renderArea->getHintForSeamlessTransition());
             sdrWhitePointNits = state.sdrWhitePointNits;
 
-             // TODO(b/298219334): Clean this up once we verify this doesn't break anything
-             static constexpr bool kScreenshotsDontDim = true;
-
-            if (kScreenshotsDontDim && !captureResults.capturedHdrLayers) {
+            if (!captureResults.capturedHdrLayers) {
                 displayBrightnessNits = sdrWhitePointNits;
             } else {
                 displayBrightnessNits = state.displayBrightnessNits;
@@ -8582,35 +8586,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());
 
@@ -8641,7 +8621,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)) {
@@ -8999,13 +8979,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();
@@ -9022,12 +8997,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,
@@ -9572,35 +9546,35 @@
     }
 }
 
-binder::Status SurfaceComposerAIDL::createDisplay(const std::string& displayName, bool secure,
-                                                  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, secure, 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) {
     std::vector<PhysicalDisplayId> physicalDisplayIds = mFlinger->getPhysicalDisplayIds();
     std::vector<int64_t> displayIds;
     displayIds.reserve(physicalDisplayIds.size());
-    for (auto item : physicalDisplayIds) {
-        displayIds.push_back(static_cast<int64_t>(item.value));
+    for (const auto id : physicalDisplayIds) {
+        displayIds.push_back(static_cast<int64_t>(id.value));
     }
-    *outDisplayIds = displayIds;
+    *outDisplayIds = std::move(displayIds);
     return binder::Status::ok();
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fc50fd9..0682e95 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -192,6 +192,9 @@
     Always,
 };
 
+struct DisplayRenderAreaBuilder;
+struct LayerRenderAreaBuilder;
+
 using DisplayColorSetting = compositionengine::OutputColorSetting;
 
 class SurfaceFlinger : public BnSurfaceComposer,
@@ -383,7 +386,7 @@
 
     using TransactionSchedule = scheduler::TransactionSchedule;
     using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>;
-    using RenderAreaFuture = ftl::Future<std::unique_ptr<RenderArea>>;
+    using RenderAreaBuilderVariant = std::variant<DisplayRenderAreaBuilder, LayerRenderAreaBuilder>;
     using DumpArgs = Vector<String16>;
     using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
 
@@ -536,16 +539,18 @@
 
     static const size_t MAX_LAYERS = 4096;
 
-    // Implements IBinder.
-    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
-    status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
-    bool callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache = true)
+    static bool callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache = true)
             EXCLUDES(mStateLock);
 
-    // Implements ISurfaceComposer
-    sp<IBinder> createDisplay(const String8& displayName, bool secure,
-                              float requestedRefreshRate = 0.0f);
-    void destroyDisplay(const sp<IBinder>& displayToken);
+    // IBinder overrides:
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+    status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
+
+    // ISurfaceComposer implementation:
+    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();
@@ -664,7 +669,7 @@
 
     void updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t connectedLevel, int32_t maxLevel);
 
-    // Implements IBinder::DeathRecipient.
+    // IBinder::DeathRecipient overrides:
     void binderDied(const wp<IBinder>& who) override;
 
     // HWC2::ComposerCallback overrides:
@@ -696,6 +701,8 @@
     void onChoreographerAttached() override;
     void onExpectedPresentTimePosted(TimePoint expectedPresentTime, ftl::NonNull<DisplayModePtr>,
                                      Fps renderRate) override;
+    void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) override
+            REQUIRES(kMainThreadContext);
 
     // ICEPowerCallback overrides:
     void notifyCpuLoadUp() override;
@@ -750,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);
@@ -891,12 +894,12 @@
     // Checks if a protected layer exists in a list of layers.
     bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
 
-    void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize,
-                             ui::PixelFormat, bool allowProtected, bool grayscale,
-                             const sp<IScreenCaptureListener>&);
+    void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
+                             ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
+                             bool grayscale, const sp<IScreenCaptureListener>&);
 
     ftl::SharedFuture<FenceResult> captureScreenshot(
-            RenderAreaFuture, GetLayerSnapshotsFunction,
+            RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
             const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
             bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&);
 
@@ -904,13 +907,13 @@
     // not yet been captured, and thus cannot yet be passed in as a parameter.
     // Needed for TestableSurfaceFlinger.
     ftl::SharedFuture<FenceResult> renderScreenImpl(
-            std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction,
+            std::unique_ptr<const RenderArea>, GetLayerSnapshotsFunction,
             const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
             bool grayscale, bool isProtected, ScreenCaptureResults&) EXCLUDES(mStateLock)
             REQUIRES(kMainThreadContext);
 
     ftl::SharedFuture<FenceResult> renderScreenImpl(
-            std::shared_ptr<const RenderArea>,
+            std::unique_ptr<const RenderArea>,
             const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
             bool grayscale, bool isProtected, ScreenCaptureResults&,
             std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) EXCLUDES(mStateLock)
@@ -1491,6 +1494,8 @@
     bool mPowerHintSessionEnabled;
 
     bool mLayerLifecycleManagerEnabled = false;
+    // Whether a display should be turned on when initialized
+    bool mSkipPowerOnForQuiescent;
 
     frontend::LayerLifecycleManager mLayerLifecycleManager GUARDED_BY(kMainThreadContext);
     frontend::LayerHierarchyBuilder mLayerHierarchyBuilder GUARDED_BY(kMainThreadContext);
@@ -1554,7 +1559,7 @@
 
 class SurfaceComposerAIDL : public gui::BnSurfaceComposer {
 public:
-    SurfaceComposerAIDL(sp<SurfaceFlinger> sf) : mFlinger(std::move(sf)) {}
+    explicit SurfaceComposerAIDL(sp<SurfaceFlinger> sf) : mFlinger(std::move(sf)) {}
 
     binder::Status bootFinished() override;
     binder::Status createDisplayEventConnection(
@@ -1562,9 +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 secure,
-                                 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;
@@ -1685,7 +1691,7 @@
                                               gui::DynamicDisplayInfo*& outInfo);
 
 private:
-    sp<SurfaceFlinger> mFlinger;
+    const sp<SurfaceFlinger> mFlinger;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 2dc89b5..b3e9fab 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -566,7 +566,7 @@
         const frontend::DisplayInfo& displayInfo, uint32_t layerStack) {
     perfetto::protos::DisplayInfo proto;
     proto.set_layer_stack(layerStack);
-    proto.set_display_id(displayInfo.info.displayId);
+    proto.set_display_id(displayInfo.info.displayId.val());
     proto.set_logical_width(displayInfo.info.logicalWidth);
     proto.set_logical_height(displayInfo.info.logicalHeight);
     asProto(proto.mutable_transform_inverse(), displayInfo.info.transform);
@@ -588,7 +588,7 @@
 frontend::DisplayInfo TransactionProtoParser::fromProto(
         const perfetto::protos::DisplayInfo& proto) {
     frontend::DisplayInfo displayInfo;
-    displayInfo.info.displayId = proto.display_id();
+    displayInfo.info.displayId = ui::LogicalDisplayId{proto.display_id()};
     displayInfo.info.logicalWidth = proto.logical_width();
     displayInfo.info.logicalHeight = proto.logical_height();
     fromProto2(displayInfo.info.transform, proto.transform_inverse());
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 89a8f92..e5d6481 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -23,6 +23,7 @@
 #include "FrontEnd/LayerCreationArgs.h"
 #include "renderengine/ExternalTexture.h"
 
+#include <common/FlagManager.h>
 #include <gui/LayerState.h>
 #include <system/window.h>
 
@@ -108,9 +109,22 @@
 
         for (const auto& state : states) {
             const bool frameRateChanged = state.state.what & layer_state_t::eFrameRateChanged;
-            if (!frameRateChanged ||
-                state.state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) {
-                return true;
+            if (FlagManager::getInstance().vrr_bugfix_24q4()) {
+                const bool frameRateIsNoVote = frameRateChanged &&
+                        state.state.frameRateCompatibility == ANATIVEWINDOW_FRAME_RATE_NO_VOTE;
+                const bool frameRateCategoryChanged =
+                        state.state.what & layer_state_t::eFrameRateCategoryChanged;
+                const bool frameRateCategoryIsNoPreference = frameRateCategoryChanged &&
+                        state.state.frameRateCategory ==
+                                ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE;
+                if (!frameRateIsNoVote && !frameRateCategoryIsNoPreference) {
+                    return true;
+                }
+            } else {
+                if (!frameRateChanged ||
+                    state.state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) {
+                    return true;
+                }
             }
         }
 
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index f074b7d..121629f 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -134,6 +134,7 @@
     DUMP_READ_ONLY_FLAG(screenshot_fence_preservation);
     DUMP_READ_ONLY_FLAG(vulkan_renderengine);
     DUMP_READ_ONLY_FLAG(renderable_buffer_usage);
+    DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4);
     DUMP_READ_ONLY_FLAG(restore_blur_step);
     DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
     DUMP_READ_ONLY_FLAG(protected_if_client);
@@ -144,6 +145,8 @@
     DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
     DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);
     DUMP_READ_ONLY_FLAG(detached_mirror);
+    DUMP_READ_ONLY_FLAG(commit_not_composited);
+    DUMP_READ_ONLY_FLAG(local_tonemap_screenshots);
 
 #undef DUMP_READ_ONLY_FLAG
 #undef DUMP_SERVER_FLAG
@@ -232,12 +235,15 @@
 FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
 FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
 FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
+FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
 FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
 FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
 FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
 FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
 FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");
 FLAG_MANAGER_READ_ONLY_FLAG(detached_mirror, "");
+FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, "");
+FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
 
 /// Trunk stable server flags ///
 FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
@@ -249,5 +255,6 @@
 /// Trunk stable readonly flags from outside SurfaceFlinger ///
 FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "",
                                      com::android::server::display::feature::flags)
+FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os)
 
 } // namespace android
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 0acf754..4cf4453 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -51,6 +51,7 @@
     bool refresh_rate_overlay_on_external_display() const;
     bool adpf_gpu_sf() const;
     bool adpf_use_fmq_channel() const;
+    bool adpf_use_fmq_channel_fixed() const;
 
     /// Trunk stable readonly flags ///
     bool connected_display() const;
@@ -71,6 +72,7 @@
     bool enable_layer_command_batching() const;
     bool screenshot_fence_preservation() const;
     bool vulkan_renderengine() const;
+    bool vrr_bugfix_24q4() const;
     bool renderable_buffer_usage() const;
     bool restore_blur_step() const;
     bool dont_skip_on_early_ro() const;
@@ -82,6 +84,8 @@
     bool deprecate_vsync_sf() const;
     bool allow_n_vsyncs_in_targeter() const;
     bool detached_mirror() const;
+    bool commit_not_composited() const;
+    bool local_tonemap_screenshots() const;
 
 protected:
     // overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 4d3195d..5b94f07 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -22,6 +22,17 @@
  } # ce_fence_promise
 
  flag {
+   name: "commit_not_composited"
+   namespace: "core_graphics"
+   description: "mark frames as non janky if the transaction resulted in no composition"
+   bug: "340633280"
+   is_fixed_read_only: true
+   metadata {
+     purpose: PURPOSE_BUGFIX
+   }
+  } # commit_not_composited
+
+ flag {
   name: "deprecate_vsync_sf"
   namespace: "core_graphics"
   description: "Depracate eVsyncSourceSurfaceFlinger and use vsync_app everywhere"
@@ -65,4 +76,23 @@
   }
 } # latch_unsignaled_with_auto_refresh_changed
 
+flag {
+    name: "local_tonemap_screenshots"
+    namespace: "core_graphics"
+    description: "Enables local tonemapping when capturing screenshots"
+    bug: "329464641"
+    is_fixed_read_only: true
+} # local_tonemap_screenshots
+
+flag {
+  name: "vrr_bugfix_24q4"
+  namespace: "core_graphics"
+  description: "bug fixes for VRR"
+  bug: "331513837"
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+} # vrr_bugfix_24q4
+
 # IMPORTANT - please keep alphabetize to reduce merge conflicts
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/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index 2b1834d..4b3ad8a 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -154,8 +154,6 @@
 
     switch (layerType) {
         case ISurfaceComposerClient::eFXSurfaceBufferQueue:
-            Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply();
-            break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
             Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply();
             break;
@@ -200,13 +198,6 @@
     // layerR = 0, layerG = layerR + 3, layerB = 2
     switch (layerType) {
         case ISurfaceComposerClient::eFXSurfaceBufferQueue:
-            Transaction()
-                    .setPosition(layerG, 8, 8)
-                    .setRelativeLayer(layerG, layerR, 3)
-                    .setPosition(layerB, 16, 16)
-                    .setLayer(layerB, mLayerZBase + 2)
-                    .apply();
-            break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
             Transaction()
                     .setPosition(layerG, 8, 8)
@@ -413,13 +404,6 @@
 
     switch (layerType) {
         case ISurfaceComposerClient::eFXSurfaceBufferQueue:
-            Transaction()
-                    .setAlpha(layer1, 0.25f)
-                    .setAlpha(layer2, 0.75f)
-                    .setPosition(layer2, 16, 0)
-                    .setLayer(layer2, mLayerZBase + 1)
-                    .apply();
-            break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
             Transaction()
                     .setAlpha(layer1, 0.25f)
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index 0ea0824..d97d433 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -19,6 +19,7 @@
 #pragma clang diagnostic ignored "-Wconversion"
 
 #include <android-base/properties.h>
+#include <common/FlagManager.h>
 #include <private/android_filesystem_config.h>
 #include "LayerTransactionTest.h"
 #include "utils/TransactionUtils.h"
@@ -78,6 +79,10 @@
             .show(mirrorLayer)
             .apply();
 
+    if (FlagManager::getInstance().detached_mirror()) {
+        Transaction().setPosition(mirrorLayer, 550, 550).apply();
+    }
+
     {
         SCOPED_TRACE("Initial Mirror");
         auto shot = screenshot();
@@ -172,6 +177,9 @@
             .show(mirrorLayer)
             .apply();
 
+    if (FlagManager::getInstance().detached_mirror()) {
+        Transaction().setPosition(mirrorLayer, 550, 550).apply();
+    }
     {
         SCOPED_TRACE("Initial Mirror BufferQueueLayer");
         auto shot = screenshot();
@@ -263,6 +271,9 @@
             .setLayer(mirrorLayer, INT32_MAX - 1)
             .apply();
 
+    if (FlagManager::getInstance().detached_mirror()) {
+        Transaction().setPosition(mirrorLayer, 550, 550).apply();
+    }
     {
         SCOPED_TRACE("Offscreen Mirror");
         auto shot = screenshot();
@@ -313,8 +324,15 @@
         ASSERT_NE(mirrorLayer, nullptr);
     }
 
+    sp<SurfaceControl> mirrorParent =
+            createLayer("Grandchild layer", 50, 50, ISurfaceComposerClient::eFXSurfaceBufferState);
+
     // Show the mirror layer, but don't reparent to a layer on screen.
-    Transaction().show(mirrorLayer).apply();
+    Transaction().reparent(mirrorLayer, mirrorParent).show(mirrorLayer).apply();
+
+    if (FlagManager::getInstance().detached_mirror()) {
+        Transaction().setPosition(mirrorLayer, 50, 50).apply();
+    }
 
     {
         SCOPED_TRACE("Offscreen Mirror");
@@ -331,7 +349,7 @@
         SCOPED_TRACE("Capture Mirror");
         // Capture just the mirror layer and child.
         LayerCaptureArgs captureArgs;
-        captureArgs.layerHandle = mirrorLayer->getHandle();
+        captureArgs.layerHandle = mirrorParent->getHandle();
         captureArgs.sourceCrop = childBounds;
         std::unique_ptr<ScreenCapture> shot;
         ScreenCapture::captureLayers(&shot, captureArgs);
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/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0c13db3..5145e11 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -66,6 +66,7 @@
         "BackgroundExecutorTest.cpp",
         "CommitTest.cpp",
         "CompositionTest.cpp",
+        "DaltonizerTest.cpp",
         "DisplayIdGeneratorTest.cpp",
         "DisplayTransactionTest.cpp",
         "DisplayDevice_GetBestColorModeTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DaltonizerTest.cpp b/services/surfaceflinger/tests/unittests/DaltonizerTest.cpp
new file mode 100644
index 0000000..9f632a1
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DaltonizerTest.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <math/mat4.h>
+#include <cmath>
+#include "Effects/Daltonizer.h"
+
+namespace android {
+
+class DaltonizerTest {
+private:
+    Daltonizer& mDaltonizer;
+
+public:
+    DaltonizerTest(Daltonizer& daltonizer) : mDaltonizer(daltonizer) {}
+
+    bool isDirty() const { return mDaltonizer.mDirty; }
+
+    float getLevel() const { return mDaltonizer.mLevel; }
+
+    ColorBlindnessType getType() const { return mDaltonizer.mType; }
+};
+
+constexpr float TOLERANCE = 0.01f;
+
+static bool isIdentityMatrix(mat4& matrix) {
+    for (size_t i = 0; i < 4; ++i) {
+        for (size_t j = 0; j < 4; ++j) {
+            if (i == j) {
+                // Check diagonal elements
+                if (std::fabs(matrix[i][j] - 1.0f) > TOLERANCE) {
+                    return false;
+                }
+            } else {
+                // Check off-diagonal elements
+                if (std::fabs(matrix[i][j]) > TOLERANCE) {
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+// Test Suite Name : DaltonizerTest, Test name: ConstructionDefaultValues
+TEST(DaltonizerTest, ConstructionDefaultValues) {
+    Daltonizer daltonizer;
+    DaltonizerTest test(daltonizer);
+
+    EXPECT_EQ(test.getLevel(), 0.7f);
+    ASSERT_TRUE(test.isDirty());
+    EXPECT_EQ(test.getType(), ColorBlindnessType::None);
+    mat4 matrix = daltonizer();
+    ASSERT_TRUE(isIdentityMatrix(matrix));
+}
+
+TEST(DaltonizerTest, NotDirtyAfterColorMatrixReturned) {
+    Daltonizer daltonizer;
+
+    mat4 matrix = daltonizer();
+    DaltonizerTest test(daltonizer);
+
+    ASSERT_FALSE(test.isDirty());
+    ASSERT_TRUE(isIdentityMatrix(matrix));
+}
+
+TEST(DaltonizerTest, LevelOutOfRangeTooLowIgnored) {
+    Daltonizer daltonizer;
+    // Get matrix to reset isDirty == false.
+    mat4 matrix = daltonizer();
+
+    daltonizer.setLevel(-1);
+    DaltonizerTest test(daltonizer);
+
+    EXPECT_EQ(test.getLevel(), 0.7f);
+    ASSERT_FALSE(test.isDirty());
+}
+
+TEST(DaltonizerTest, LevelOutOfRangeTooHighIgnored) {
+    Daltonizer daltonizer;
+    // Get matrix to reset isDirty == false.
+    mat4 matrix = daltonizer();
+
+    daltonizer.setLevel(11);
+    DaltonizerTest test(daltonizer);
+
+    EXPECT_EQ(test.getLevel(), 0.7f);
+    ASSERT_FALSE(test.isDirty());
+}
+
+TEST(DaltonizerTest, ColorCorrectionMatrixNonIdentical) {
+    Daltonizer daltonizer;
+    daltonizer.setType(ColorBlindnessType::Protanomaly);
+    daltonizer.setMode(ColorBlindnessMode::Correction);
+
+    mat4 matrix = daltonizer();
+
+    ASSERT_FALSE(isIdentityMatrix(matrix));
+}
+
+TEST(DaltonizerTest, LevelZeroColorMatrixEqIdentityMatrix) {
+    Daltonizer daltonizer;
+    daltonizer.setType(ColorBlindnessType::Protanomaly);
+    daltonizer.setMode(ColorBlindnessMode::Correction);
+    daltonizer.setLevel(0);
+
+    mat4 matrix = daltonizer();
+
+    ASSERT_TRUE(isIdentityMatrix(matrix));
+}
+
+} /* namespace android */
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index ddc3967..dac9265 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -341,6 +341,57 @@
     EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt);
 }
 
+TEST_F(FrameTimelineTest, displayFrameSkippedComposition) {
+    // Layer specific increment
+    EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(1);
+    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+    int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
+    FrameTimelineInfo ftInfo;
+    ftInfo.vsyncId = surfaceFrameToken1;
+    ftInfo.inputEventId = sInputEventId;
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+                                                       sLayerNameOne, sLayerNameOne,
+                                                       /*isBuffer*/ true, sGameMode);
+    auto surfaceFrame2 =
+            mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdTwo,
+                                                       sLayerNameTwo, sLayerNameTwo,
+                                                       /*isBuffer*/ true, sGameMode);
+
+    mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11);
+    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+    mFrameTimeline->onCommitNotComposited();
+
+    EXPECT_EQ(surfaceFrame1->getActuals().presentTime, 30);
+    ASSERT_NE(surfaceFrame1->getJankType(), std::nullopt);
+    EXPECT_EQ(*surfaceFrame1->getJankType(), JankType::None);
+    ASSERT_NE(surfaceFrame1->getJankSeverityType(), std::nullopt);
+    EXPECT_EQ(*surfaceFrame1->getJankSeverityType(), JankSeverityType::None);
+
+    mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11);
+    surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
+    mFrameTimeline->addSurfaceFrame(surfaceFrame2);
+    mFrameTimeline->setSfPresent(26, presentFence1);
+
+    auto displayFrame = getDisplayFrame(0);
+    auto& presentedSurfaceFrame2 = getSurfaceFrame(0, 0);
+    presentFence1->signalForTest(42);
+
+    // Fences haven't been flushed yet, so it should be 0
+    EXPECT_EQ(displayFrame->getActuals().presentTime, 0);
+    EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0);
+
+    addEmptyDisplayFrame();
+
+    // Fences have flushed, so the present timestamps should be updated
+    EXPECT_EQ(displayFrame->getActuals().presentTime, 42);
+    EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42);
+    EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt);
+    EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt);
+}
+
 TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
     // Insert kMaxDisplayFrames' count of DisplayFrames to fill the deque
     int frameTimeFactor = 0;
@@ -1081,6 +1132,72 @@
     EXPECT_EQ(received.cookie(), source.cookie());
 }
 
+TEST_F(FrameTimelineTest, traceDisplayFrameNoSkipped) {
+    // setup 2 display frames
+    // DF 1: [22, 30] -> [0, 11]
+    // DF 2: [82, 90] -> SF [5, 16]
+    auto tracingSession = getTracingSessionForTest();
+    tracingSession->StartBlocking();
+    int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 30, 40});
+    int64_t sfToken2 = mTokenManager->generateTokenForPredictions({82, 90, 100});
+    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({0, 11, 25});
+    int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({5, 16, 30});
+    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+
+    int64_t traceCookie = snoopCurrentTraceCookie();
+
+    // set up 1st display frame
+    FrameTimelineInfo ftInfo1;
+    ftInfo1.vsyncId = surfaceFrameToken1;
+    ftInfo1.inputEventId = sInputEventId;
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken(ftInfo1, sPidOne, sUidOne, sLayerIdOne,
+                                                       sLayerNameOne, sLayerNameOne,
+                                                       /*isBuffer*/ true, sGameMode);
+    surfaceFrame1->setAcquireFenceTime(11);
+    mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_30);
+    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+    mFrameTimeline->setSfPresent(30, presentFence1);
+    presentFence1->signalForTest(40);
+
+    // Trigger a flush by finalizing the next DisplayFrame
+    auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    FrameTimelineInfo ftInfo2;
+    ftInfo2.vsyncId = surfaceFrameToken2;
+    ftInfo2.inputEventId = sInputEventId;
+    auto surfaceFrame2 =
+            mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+                                                       sLayerNameOne, sLayerNameOne,
+                                                       /*isBuffer*/ true, sGameMode);
+
+    // set up 2nd display frame
+    surfaceFrame2->setAcquireFenceTime(16);
+    mFrameTimeline->setSfWakeUp(sfToken2, 82, RR_11, RR_30);
+    surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
+    mFrameTimeline->addSurfaceFrame(surfaceFrame2);
+    mFrameTimeline->setSfPresent(90, presentFence2);
+    presentFence2->signalForTest(100);
+
+    // the token of skipped Display Frame
+    auto protoSkippedActualDisplayFrameStart =
+            createProtoActualDisplayFrameStart(traceCookie + 9, 0, kSurfaceFlingerPid,
+                                               FrameTimelineEvent::PRESENT_DROPPED, true, false,
+                                               FrameTimelineEvent::JANK_DROPPED,
+                                               FrameTimelineEvent::SEVERITY_NONE,
+                                               FrameTimelineEvent::PREDICTION_VALID);
+    auto protoSkippedActualDisplayFrameEnd = createProtoFrameEnd(traceCookie + 9);
+
+    // Trigger a flush by finalizing the next DisplayFrame
+    addEmptyDisplayFrame();
+    flushTrace();
+    tracingSession->StopBlocking();
+
+    auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
+    // 8 Valid Display Frames + 8 Valid Surface Frames + no Skipped Display Frames
+    EXPECT_EQ(packets.size(), 16u);
+}
+
 TEST_F(FrameTimelineTest, traceDisplayFrameSkipped) {
     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::add_sf_skipped_frames_to_trace,
                       true);
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index 867ff55..cfc8e99 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -461,8 +461,8 @@
                                                                HAL_PIXEL_FORMAT_RGBA_8888,
                                                                GRALLOC_USAGE_PROTECTED /*usage*/));
     EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
-              ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
-                                                       RequestedLayerState::Changes::Content)
+              ftl::Flags<RequestedLayerState::Changes>(
+                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content)
                       .get());
     mLifecycleManager.commitChanges();
 
@@ -493,10 +493,10 @@
                                                                HAL_PIXEL_FORMAT_RGB_888,
                                                                GRALLOC_USAGE_PROTECTED /*usage*/));
     EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
-              ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
-                                                       RequestedLayerState::Changes::Content |
-                                                       RequestedLayerState::Changes::VisibleRegion |
-                                                       RequestedLayerState::Changes::Visibility)
+              ftl::Flags<RequestedLayerState::Changes>(
+                      RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content |
+                      RequestedLayerState::Changes::VisibleRegion |
+                      RequestedLayerState::Changes::Visibility)
                       .get());
     mLifecycleManager.commitChanges();
 }
@@ -580,8 +580,8 @@
                                                             HAL_PIXEL_FORMAT_RGBA_8888,
                                                             GRALLOC_USAGE_SW_READ_NEVER /*usage*/));
     EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
-              ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
-                                                       RequestedLayerState::Changes::Content)
+              ftl::Flags<RequestedLayerState::Changes>(
+                      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 7c6cff0..6b26459 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -254,7 +254,8 @@
 TEST_F(LayerSnapshotTest, FastPathClearsPreviousChangeStates) {
     setColor(11, {1._hf, 0._hf, 0._hf});
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
-    EXPECT_EQ(getSnapshot(11)->changes, RequestedLayerState::Changes::Content);
+    EXPECT_EQ(getSnapshot(11)->changes,
+              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);
@@ -264,7 +265,8 @@
 TEST_F(LayerSnapshotTest, FastPathSetsChangeFlagToContent) {
     setColor(1, {1._hf, 0._hf, 0._hf});
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
-    EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content);
+    EXPECT_EQ(getSnapshot(1)->changes,
+              RequestedLayerState::Changes::Content);
     EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eColorChanged);
 }
 
@@ -1204,34 +1206,34 @@
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
 
     EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(1)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(12)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(2)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
 }
 
 TEST_F(LayerSnapshotTest, setSensitiveForTracingFromInputWindowHandle) {
     setInputInfo(11, [](auto& inputInfo) {
-        inputInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING;
+        inputInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
     });
 
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
 
     EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(1)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(12)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
     EXPECT_FALSE(getSnapshot(2)->inputInfo.inputConfig.test(
-            gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING));
+            gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY));
 }
 
 // b/314350323
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index 86ad86e..e74f643 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -45,6 +45,7 @@
 class PowerAdvisorTest : public testing::Test {
 public:
     void SetUp() override;
+    void SetUpFmq(bool usesSharedEventFlag, bool isQueueFull);
     void startPowerHintSession(bool returnValidSession = true);
     void fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod);
     void setExpectedTiming(Duration totalFrameTargetDuration, TimePoint expectedPresentTime);
@@ -64,16 +65,26 @@
         Duration postCompDuration = 0ms;
         bool frame1RequiresRenderEngine;
         bool frame2RequiresRenderEngine;
+        bool usesFmq = false;
+        bool usesSharedFmqFlag = true;
+        bool fmqFull = false;
     };
 
-    WorkDuration testGpuScenario(GpuTestConfig& config);
+    void testGpuScenario(GpuTestConfig& config, WorkDuration& ret);
 
 protected:
     TestableSurfaceFlinger mFlinger;
     std::unique_ptr<PowerAdvisor> mPowerAdvisor;
     MockPowerHalController* mMockPowerHalController;
     std::shared_ptr<MockPowerHintSessionWrapper> mMockPowerHintSession;
+    std::shared_ptr<AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>> mBackendFmq;
+    std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mBackendFlagQueue;
+    android::hardware::EventFlag* mEventFlag;
+    uint32_t mWriteFlagBitmask = 2;
+    uint32_t mReadFlagBitmask = 1;
+    int64_t mSessionId = 123;
     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, true);
+    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, false);
 };
 
 bool PowerAdvisorTest::sessionExists() {
@@ -95,12 +106,44 @@
                     ByMove(HalResult<int64_t>::fromStatus(ndk::ScopedAStatus::ok(), 16000))));
 }
 
+void PowerAdvisorTest::SetUpFmq(bool usesSharedEventFlag, bool isQueueFull) {
+    mBackendFmq = std::make_shared<
+            AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>>(2, !usesSharedEventFlag);
+    ChannelConfig config;
+    config.channelDescriptor = mBackendFmq->dupeDesc();
+    if (usesSharedEventFlag) {
+        mBackendFlagQueue =
+                std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(1, true);
+        config.eventFlagDescriptor = mBackendFlagQueue->dupeDesc();
+        ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFlagQueue
+                                                                        ->getEventFlagWord(),
+                                                                &mEventFlag),
+                  android::NO_ERROR);
+    } else {
+        ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFmq->getEventFlagWord(),
+                                                                &mEventFlag),
+                  android::NO_ERROR);
+    }
+    config.writeFlagBitmask = static_cast<int32_t>(mWriteFlagBitmask);
+    config.readFlagBitmask = static_cast<int32_t>(mReadFlagBitmask);
+    ON_CALL(*mMockPowerHalController, getSessionChannel)
+            .WillByDefault(Return(
+                    ByMove(HalResult<ChannelConfig>::fromStatus(Status::ok(), std::move(config)))));
+    startPowerHintSession();
+    if (isQueueFull) {
+        std::vector<ChannelMessage> msgs;
+        msgs.resize(2);
+        mBackendFmq->writeBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
+                                   std::chrono::nanoseconds(1ms).count(), mEventFlag);
+    }
+}
+
 void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) {
     mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
     if (returnValidSession) {
         ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
                 .WillByDefault(DoAll(SetArgPointee<5>(aidl::android::hardware::power::SessionConfig{
-                                             .id = 12}),
+                                             .id = mSessionId}),
                                      Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
                                                     fromStatus(binder::Status::ok(),
                                                                mMockPowerHintSession))));
@@ -137,11 +180,17 @@
     mPowerAdvisor->mDelayReportActualMutexAcquisitonPromise.set_value(true);
 }
 
-WorkDuration PowerAdvisorTest::testGpuScenario(GpuTestConfig& config) {
+void PowerAdvisorTest::testGpuScenario(GpuTestConfig& config, WorkDuration& ret) {
     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_gpu_sf,
                       config.adpfGpuFlagOn);
+    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, config.usesFmq);
     mPowerAdvisor->onBootFinished();
-    startPowerHintSession();
+    bool expectsFmqSuccess = config.usesSharedFmqFlag && !config.fmqFull;
+    if (config.usesFmq) {
+        SetUpFmq(config.usesSharedFmqFlag, config.fmqFull);
+    } else {
+        startPowerHintSession();
+    }
 
     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
                                       GpuVirtualDisplayId(1)};
@@ -150,8 +199,41 @@
     // 60hz
 
     TimePoint startTime = TimePoint::now();
+    int64_t target;
+    SessionHint hint;
+    if (!config.usesFmq || !expectsFmqSuccess) {
+        EXPECT_CALL(*mMockPowerHintSession, updateTargetWorkDuration(_))
+                .Times(1)
+                .WillOnce(DoAll(testing::SaveArg<0>(&target),
+                                testing::Return(testing::ByMove(HalResult<void>::ok()))));
+        EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+                .Times(1)
+                .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+                                testing::Return(testing::ByMove(HalResult<void>::ok()))));
+    }
     // advisor only starts on frame 2 so do an initial frame
     fakeBasicFrameTiming(startTime, config.vsyncPeriod);
+    // send a load hint
+    mPowerAdvisor->notifyCpuLoadUp();
+    if (config.usesFmq && expectsFmqSuccess) {
+        std::vector<ChannelMessage> msgs;
+        ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+        msgs.resize(2);
+        ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
+                                              std::chrono::nanoseconds(1ms).count(), mEventFlag));
+        ASSERT_EQ(msgs[0].sessionID, mSessionId);
+        ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
+        ASSERT_EQ(msgs[0].data.getTag(),
+                  ChannelMessage::ChannelMessageContents::Tag::targetDuration);
+        target = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::targetDuration>();
+        ASSERT_EQ(msgs[1].sessionID, mSessionId);
+        ASSERT_GE(msgs[1].timeStampNanos, startTime.ns());
+        ASSERT_EQ(msgs[1].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
+        hint = msgs[1].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
+    }
+    ASSERT_EQ(target, config.vsyncPeriod.ns());
+    ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+
     setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
 
     // report GPU
@@ -171,6 +253,10 @@
     std::this_thread::sleep_for(config.vsyncPeriod);
     startTime = TimePoint::now();
     fakeBasicFrameTiming(startTime, config.vsyncPeriod);
+    if (config.usesFmq && expectsFmqSuccess) {
+        // same target update will not trigger FMQ write
+        ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
+    }
     setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
 
     // report GPU
@@ -192,14 +278,31 @@
     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime, startTime);
     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime, startTime);
 
-    std::vector<aidl::android::hardware::power::WorkDuration> durationReq;
-    EXPECT_CALL(*mMockPowerHintSession, reportActualWorkDuration(_))
-            .Times(1)
-            .WillOnce(DoAll(testing::SaveArg<0>(&durationReq),
-                            testing::Return(testing::ByMove(HalResult<void>::ok()))));
-    mPowerAdvisor->reportActualWorkDuration();
-    EXPECT_EQ(durationReq.size(), 1u);
-    return durationReq[0];
+    if (config.usesFmq && expectsFmqSuccess) {
+        mPowerAdvisor->reportActualWorkDuration();
+        ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
+        std::vector<ChannelMessage> msgs;
+        msgs.resize(1);
+        ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+                                              std::chrono::nanoseconds(1ms).count(), mEventFlag));
+        ASSERT_EQ(msgs[0].sessionID, mSessionId);
+        ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
+        ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::workDuration);
+        auto actual = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::workDuration>();
+        ret.workPeriodStartTimestampNanos = actual.workPeriodStartTimestampNanos;
+        ret.cpuDurationNanos = actual.cpuDurationNanos;
+        ret.gpuDurationNanos = actual.gpuDurationNanos;
+        ret.durationNanos = actual.durationNanos;
+    } else {
+        std::vector<aidl::android::hardware::power::WorkDuration> durationReq;
+        EXPECT_CALL(*mMockPowerHintSession, reportActualWorkDuration(_))
+                .Times(1)
+                .WillOnce(DoAll(testing::SaveArg<0>(&durationReq),
+                                testing::Return(testing::ByMove(HalResult<void>::ok()))));
+        mPowerAdvisor->reportActualWorkDuration();
+        ASSERT_EQ(durationReq.size(), 1u);
+        ret = std::move(durationReq[0]);
+    }
 }
 
 Duration PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
@@ -375,13 +478,6 @@
     mPowerAdvisor->reportActualWorkDuration();
 }
 
-TEST_F(PowerAdvisorTest, hintSessionOnlyCreatedOnce) {
-    EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
-    mPowerAdvisor->onBootFinished();
-    startPowerHintSession();
-    mPowerAdvisor->startPowerHintSession({1, 2, 3});
-}
-
 TEST_F(PowerAdvisorTest, hintSessionTestNotifyReportRace) {
     // notifyDisplayUpdateImminentAndCpuReset or notifyCpuLoadUp gets called in background
     // reportActual gets called during callback and sees true session, passes ensure
@@ -464,15 +560,21 @@
 }
 
 TEST_F(PowerAdvisorTest, legacyHintSessionCreationStillWorks) {
-    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, false);
     mPowerAdvisor->onBootFinished();
     mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
+    EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig)
+            .Times(1)
+            .WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
+                                     fromStatus(ndk::ScopedAStatus::fromExceptionCode(
+                                                        EX_UNSUPPORTED_OPERATION),
+                                                nullptr)));
+
     EXPECT_CALL(*mMockPowerHalController, createHintSession)
             .Times(1)
             .WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
                                      fromStatus(binder::Status::ok(), mMockPowerHintSession)));
     mPowerAdvisor->enablePowerHintSession(true);
-    mPowerAdvisor->startPowerHintSession({1, 2, 3});
+    ASSERT_TRUE(mPowerAdvisor->startPowerHintSession({1, 2, 3}));
 }
 
 TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames) {
@@ -487,7 +589,8 @@
             .frame1RequiresRenderEngine = false,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, 0L);
     EXPECT_EQ(res.cpuDurationNanos, 0L);
     EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -505,7 +608,8 @@
             .frame1RequiresRenderEngine = false,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
     EXPECT_EQ(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -523,7 +627,8 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = false,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, 0L);
     EXPECT_EQ(res.cpuDurationNanos, 0L);
     EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
@@ -540,7 +645,8 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = false,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, 0L);
     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
     EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
@@ -559,7 +665,8 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, 0L);
     EXPECT_EQ(res.cpuDurationNanos, 0L);
     EXPECT_GE(res.durationNanos, toNanos(50ms + getErrorMargin()));
@@ -577,7 +684,8 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, toNanos(50ms));
     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
     EXPECT_EQ(res.durationNanos, toNanos(50ms + getErrorMargin()));
@@ -594,7 +702,8 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, 0L);
     EXPECT_EQ(res.cpuDurationNanos, 0L);
     EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -612,11 +721,122 @@
             .frame1RequiresRenderEngine = true,
             .frame2RequiresRenderEngine = true,
     };
-    WorkDuration res = testGpuScenario(config);
+    WorkDuration res;
+    testGpuScenario(config, res);
     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
     EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
     EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
 }
 
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration) {
+    GpuTestConfig config{
+            .adpfGpuFlagOn = true,
+            .frame1GpuFenceDuration = 30ms,
+            .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+            .vsyncPeriod = 10ms,
+            .presentDuration = 22ms,
+            .postCompDuration = 88ms,
+            .frame1RequiresRenderEngine = true,
+            .frame2RequiresRenderEngine = true,
+            .usesFmq = true,
+            .usesSharedFmqFlag = true,
+    };
+    WorkDuration res;
+    testGpuScenario(config, res);
+    EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+    EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+    EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_noSharedFlag) {
+    GpuTestConfig config{
+            .adpfGpuFlagOn = true,
+            .frame1GpuFenceDuration = 30ms,
+            .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+            .vsyncPeriod = 10ms,
+            .presentDuration = 22ms,
+            .postCompDuration = 88ms,
+            .frame1RequiresRenderEngine = true,
+            .frame2RequiresRenderEngine = true,
+            .usesFmq = true,
+            .usesSharedFmqFlag = false,
+    };
+    WorkDuration res;
+    testGpuScenario(config, res);
+    EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+    EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+    EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_queueFull) {
+    GpuTestConfig config{.adpfGpuFlagOn = true,
+                         .frame1GpuFenceDuration = 30ms,
+                         .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+                         .vsyncPeriod = 10ms,
+                         .presentDuration = 22ms,
+                         .postCompDuration = 88ms,
+                         .frame1RequiresRenderEngine = true,
+                         .frame2RequiresRenderEngine = true,
+                         .usesFmq = true,
+                         .usesSharedFmqFlag = true,
+                         .fmqFull = true};
+    WorkDuration res;
+    testGpuScenario(config, res);
+    EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+    EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+    EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint) {
+    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+    mPowerAdvisor->onBootFinished();
+    SetUpFmq(true, false);
+    auto startTime = uptimeNanos();
+    mPowerAdvisor->notifyCpuLoadUp();
+    std::vector<ChannelMessage> msgs;
+    ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
+    msgs.resize(1);
+    ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+                                          std::chrono::nanoseconds(1ms).count(), mEventFlag));
+    ASSERT_EQ(msgs[0].sessionID, mSessionId);
+    ASSERT_GE(msgs[0].timeStampNanos, startTime);
+    ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
+    auto hint = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
+    ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint_noSharedFlag) {
+    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+    mPowerAdvisor->onBootFinished();
+    SetUpFmq(false, false);
+    SessionHint hint;
+    EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+            .Times(1)
+            .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+                            testing::Return(testing::ByMove(HalResult<void>::ok()))));
+    mPowerAdvisor->notifyCpuLoadUp();
+    ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
+    ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint_queueFull) {
+    SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+    mPowerAdvisor->onBootFinished();
+    SetUpFmq(true, true);
+    ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+    SessionHint hint;
+    EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+            .Times(1)
+            .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+                            testing::Return(testing::ByMove(HalResult<void>::ok()))));
+    std::vector<ChannelMessage> msgs;
+    msgs.resize(1);
+    mBackendFmq->writeBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+                               std::chrono::nanoseconds(1ms).count(), mEventFlag);
+    mPowerAdvisor->notifyCpuLoadUp();
+    ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+    ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
 } // namespace
 } // namespace android::Hwc2::impl
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 28162f4..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,37 @@
     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
+
+    // Creating the display commits a display transaction.
+    EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
+}
+
+TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForUniqueId) {
+    static const std::string kDisplayName("virtual.test");
+    static const std::string kUniqueId = "virtual:package:id";
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    sp<IBinder> displayToken = mFlinger.createVirtualDisplay(kDisplayName, false, kUniqueId);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display should have been added to the current state
+    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+    const auto& display = getCurrentDisplayState(displayToken);
+    EXPECT_TRUE(display.isVirtual());
+    EXPECT_FALSE(display.isSecure);
+    EXPECT_EQ(display.uniqueId, "virtual:package:id");
+    EXPECT_EQ(kDisplayName.c_str(), display.displayName);
 
     // --------------------------------------------------------------------
     // Cleanup conditions
@@ -134,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 9353467..265f804 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -420,12 +420,21 @@
         commit(kComposite);
     }
 
-    auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) {
-        return mFlinger->createDisplay(displayName, secure, 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 destroyDisplay(const sp<IBinder>& displayToken) {
-        return mFlinger->destroyDisplay(displayToken);
+    auto createVirtualDisplay(const std::string& displayName, bool isSecure,
+                              const std::string& uniqueId, float requestedRefreshRate = 0.0f) {
+        return mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId,
+                                              requestedRefreshRate);
+    }
+
+    auto destroyVirtualDisplay(const sp<IBinder>& displayToken) {
+        return mFlinger->destroyVirtualDisplay(displayToken);
     }
 
     auto getDisplay(const sp<IBinder>& displayToken) {
@@ -448,6 +457,7 @@
     void commitTransactionsLocked(uint32_t transactionFlags) {
         Mutex::Autolock lock(mFlinger->mStateLock);
         ftl::FakeGuard guard(kMainThreadContext);
+        mFlinger->processDisplayChangesLocked();
         mFlinger->commitTransactionsLocked(transactionFlags);
     }
 
@@ -475,7 +485,7 @@
         return mFlinger->setPowerModeInternal(display, mode);
     }
 
-    auto renderScreenImpl(std::shared_ptr<const RenderArea> renderArea,
+    auto renderScreenImpl(std::unique_ptr<const RenderArea> renderArea,
                           SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers,
                           const std::shared_ptr<renderengine::ExternalTexture>& buffer,
                           bool regionSampling) {
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index cbb597a..af02330 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -106,7 +106,7 @@
 
 TEST(TransactionProtoParserTest, parseDisplayInfo) {
     frontend::DisplayInfo d1;
-    d1.info.displayId = 42;
+    d1.info.displayId = ui::LogicalDisplayId{42};
     d1.info.logicalWidth = 43;
     d1.info.logicalHeight = 44;
     d1.info.transform.set(1, 2, 3, 4);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index 4ca0542..dec5fa5 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -30,6 +30,7 @@
     MOCK_METHOD(void, onChoreographerAttached, (), (override));
     MOCK_METHOD(void, onExpectedPresentTimePosted, (TimePoint, ftl::NonNull<DisplayModePtr>, Fps),
                 (override));
+    MOCK_METHOD(void, onCommitNotComposited, (PhysicalDisplayId), (override));
 };
 
 struct NoOpSchedulerCallback final : ISchedulerCallback {
@@ -39,6 +40,7 @@
     void triggerOnFrameRateOverridesChanged() override {}
     void onChoreographerAttached() override {}
     void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>, Fps) override {}
+    void onCommitNotComposited(PhysicalDisplayId) override {}
 };
 
 } // namespace android::scheduler::mock
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 81fd118..7ea98f5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -1372,6 +1372,11 @@
             android::GraphicsEnv::getInstance().setTargetStats(
                 android::GpuStatsInfo::Stats::CREATED_VULKAN_API_VERSION,
                 vulkanApiVersion);
+
+            if (pCreateInfo->pApplicationInfo->pEngineName) {
+                android::GraphicsEnv::getInstance().addVulkanEngineName(
+                    pCreateInfo->pApplicationInfo->pEngineName);
+            }
         }
 
         // Update stats for the extensions requested