Merge "Represent VelocityTracker Strategy as enum class."
diff --git a/headers/Android.bp b/headers/Android.bp
index 5337235..8f41c2b 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -18,4 +18,11 @@
         "libstagefright_foundation_headers",
     ],
     min_sdk_version: "29",
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 4f2709d..5e4c98f 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -98,15 +98,6 @@
     return PROCESS_STATE_UNKNOWN;
 }
 
-bool ActivityManager::isUidActiveOrForeground(const uid_t uid, const String16& callingPackage)
-{
-    sp<IActivityManager> service = getService();
-    if (service != nullptr) {
-        return service->isUidActiveOrForeground(uid, callingPackage);
-    }
-    return false;
-}
-
 status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
     sp<IActivityManager> service = getService();
     if (service != nullptr) {
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 9e1249b..1eb5363 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -104,18 +104,6 @@
         }
         return reply.readInt32();
     }
-
-    virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage)
-    {
-         Parcel data, reply;
-         data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
-         data.writeInt32(uid);
-         data.writeString16(callingPackage);
-         remote()->transact(IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, data, &reply);
-         // fail on exception
-         if (reply.readExceptionCode() != 0) return false;
-         return reply.readInt32() == 1;
-    }
 };
 
 // ------------------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 0bb6d28..9108e31 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -46,24 +46,25 @@
         PROCESS_STATE_PERSISTENT = 0,
         PROCESS_STATE_PERSISTENT_UI = 1,
         PROCESS_STATE_TOP = 2,
-        PROCESS_STATE_BOUND_TOP = 3,
-        PROCESS_STATE_FOREGROUND_SERVICE = 4,
-        PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5,
-        PROCESS_STATE_IMPORTANT_FOREGROUND = 6,
-        PROCESS_STATE_IMPORTANT_BACKGROUND = 7,
-        PROCESS_STATE_TRANSIENT_BACKGROUND = 8,
-        PROCESS_STATE_BACKUP = 9,
-        PROCESS_STATE_SERVICE = 10,
-        PROCESS_STATE_RECEIVER = 11,
-        PROCESS_STATE_TOP_SLEEPING = 12,
-        PROCESS_STATE_HEAVY_WEIGHT = 13,
-        PROCESS_STATE_HOME = 14,
-        PROCESS_STATE_LAST_ACTIVITY = 15,
-        PROCESS_STATE_CACHED_ACTIVITY = 16,
-        PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17,
-        PROCESS_STATE_CACHED_RECENT = 18,
-        PROCESS_STATE_CACHED_EMPTY = 19,
-        PROCESS_STATE_NONEXISTENT = 20,
+        PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3,
+        PROCESS_STATE_BOUND_TOP = 4,
+        PROCESS_STATE_FOREGROUND_SERVICE = 5,
+        PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6,
+        PROCESS_STATE_IMPORTANT_FOREGROUND = 7,
+        PROCESS_STATE_IMPORTANT_BACKGROUND = 8,
+        PROCESS_STATE_TRANSIENT_BACKGROUND = 9,
+        PROCESS_STATE_BACKUP = 10,
+        PROCESS_STATE_SERVICE = 11,
+        PROCESS_STATE_RECEIVER = 12,
+        PROCESS_STATE_TOP_SLEEPING = 13,
+        PROCESS_STATE_HEAVY_WEIGHT = 14,
+        PROCESS_STATE_HOME = 15,
+        PROCESS_STATE_LAST_ACTIVITY = 16,
+        PROCESS_STATE_CACHED_ACTIVITY = 17,
+        PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18,
+        PROCESS_STATE_CACHED_RECENT = 19,
+        PROCESS_STATE_CACHED_EMPTY = 20,
+        PROCESS_STATE_NONEXISTENT = 21,
     };
 
     ActivityManager();
@@ -76,7 +77,6 @@
     void unregisterUidObserver(const sp<IUidObserver>& observer);
     bool isUidActive(const uid_t uid, const String16& callingPackage);
     int getUidProcessState(const uid_t uid, const String16& callingPackage);
-    bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage);
 
 
   status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index 1815ecc..e0248f6 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -39,15 +39,13 @@
     virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0;
     virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0;
     virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0;
-    virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) = 0;
 
     enum {
         OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         REGISTER_UID_OBSERVER_TRANSACTION,
         UNREGISTER_UID_OBSERVER_TRANSACTION,
         IS_UID_ACTIVE_TRANSACTION,
-        GET_UID_PROCESS_STATE_TRANSACTION,
-        IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION,
+        GET_UID_PROCESS_STATE_TRANSACTION
     };
 };
 
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/tests/Android.bp
similarity index 100%
rename from libs/binder/ndk/test/Android.bp
rename to libs/binder/ndk/tests/Android.bp
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/tests/AndroidTest.xml
similarity index 100%
rename from libs/binder/ndk/test/AndroidTest.xml
rename to libs/binder/ndk/tests/AndroidTest.xml
diff --git a/libs/binder/ndk/test/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
similarity index 100%
rename from libs/binder/ndk/test/IBinderNdkUnitTest.aidl
rename to libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/tests/IBinderVendorDoubleLoadTest.aidl
similarity index 100%
rename from libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
rename to libs/binder/ndk/tests/IBinderVendorDoubleLoadTest.aidl
diff --git a/libs/binder/ndk/test/IEmpty.aidl b/libs/binder/ndk/tests/IEmpty.aidl
similarity index 100%
rename from libs/binder/ndk/test/IEmpty.aidl
rename to libs/binder/ndk/tests/IEmpty.aidl
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
similarity index 100%
rename from libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
rename to libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/tests/iface.cpp
similarity index 100%
rename from libs/binder/ndk/test/iface.cpp
rename to libs/binder/ndk/tests/iface.cpp
diff --git a/libs/binder/ndk/test/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
similarity index 100%
rename from libs/binder/ndk/test/include/iface/iface.h
rename to libs/binder/ndk/tests/include/iface/iface.h
diff --git a/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
similarity index 100%
rename from libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
rename to libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index b77dfda..06a968f 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -9,3 +9,5 @@
 steventhomas@google.com
 stoza@google.com
 vhau@google.com
+
+per-file EndToEndNativeInputTest.cpp = svv@google.com
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index c59afba..5188a09 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -178,7 +178,7 @@
         mInputInfo.name = "Test info";
         mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
         mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
-        mInputInfo.dispatchingTimeout = 100000;
+        mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5);
         mInputInfo.globalScaleFactor = 1.0;
         mInputInfo.canReceiveKeys = true;
         mInputInfo.hasFocus = true;
@@ -196,7 +196,7 @@
         InputApplicationInfo aInfo;
         aInfo.token = new BBinder();
         aInfo.name = "Test app info";
-        aInfo.dispatchingTimeout = 100000;
+        aInfo.dispatchingTimeout = seconds_to_nanoseconds(5);
 
         mInputInfo.applicationInfo = aInfo;
     }
diff --git a/libs/ui/DeviceProductInfo.cpp b/libs/ui/DeviceProductInfo.cpp
index 7bced9b..4d6ce43 100644
--- a/libs/ui/DeviceProductInfo.cpp
+++ b/libs/ui/DeviceProductInfo.cpp
@@ -16,13 +16,17 @@
 
 #include <ui/DeviceProductInfo.h>
 
+#include <android-base/stringprintf.h>
 #include <ui/FlattenableHelpers.h>
+#include <utils/Log.h>
 
 #define RETURN_IF_ERROR(op) \
     if (const status_t status = (op); status != OK) return status;
 
 namespace android {
 
+using base::StringAppendF;
+
 size_t DeviceProductInfo::getFlattenedSize() const {
     return FlattenableHelpers::getFlattenedSize(name) +
             FlattenableHelpers::getFlattenedSize(manufacturerPnpId) +
@@ -52,4 +56,32 @@
     return OK;
 }
 
+void DeviceProductInfo::dump(std::string& result) const {
+    StringAppendF(&result, "{name=%s, ", name.c_str());
+    StringAppendF(&result, "manufacturerPnpId=%s, ", manufacturerPnpId.data());
+    StringAppendF(&result, "productId=%s, ", productId.c_str());
+
+    if (const auto* model = std::get_if<ModelYear>(&manufactureOrModelDate)) {
+        StringAppendF(&result, "modelYear=%u, ", model->year);
+    } else if (const auto* manufactureWeekAndYear =
+                       std::get_if<ManufactureWeekAndYear>(&manufactureOrModelDate)) {
+        StringAppendF(&result, "manufactureWeek=%u, ", manufactureWeekAndYear->week);
+        StringAppendF(&result, "manufactureYear=%d, ", manufactureWeekAndYear->year);
+    } else if (const auto* manufactureYear =
+                       std::get_if<ManufactureYear>(&manufactureOrModelDate)) {
+        StringAppendF(&result, "manufactureYear=%d, ", manufactureYear->year);
+    } else {
+        ALOGE("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
+    }
+
+    result.append("relativeAddress=[");
+    for (size_t i = 0; i < relativeAddress.size(); i++) {
+        if (i != 0) {
+            result.append(", ");
+        }
+        StringAppendF(&result, "%u", relativeAddress[i]);
+    }
+    result.append("]}");
+}
+
 } // namespace android
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 82ce757..e01309b 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -224,6 +224,11 @@
     validate(*this, "this->operator=");
     validate(rhs, "rhs.operator=");
 #endif
+    if (this == &rhs) {
+        // Already equal to itself
+        return *this;
+    }
+
     mStorage.clear();
     mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
     return *this;
diff --git a/libs/ui/include/ui/DeviceProductInfo.h b/libs/ui/include/ui/DeviceProductInfo.h
index 0bc1e5c..807a5d9 100644
--- a/libs/ui/include/ui/DeviceProductInfo.h
+++ b/libs/ui/include/ui/DeviceProductInfo.h
@@ -68,6 +68,8 @@
     size_t getFlattenedSize() const;
     status_t flatten(void* buffer, size_t size) const;
     status_t unflatten(void const* buffer, size_t size);
+
+    void dump(std::string& result) const;
 };
 
 } // namespace android
diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp
index b104a46..c6b826d 100644
--- a/libs/ui/tests/Region_test.cpp
+++ b/libs/ui/tests/Region_test.cpp
@@ -152,5 +152,20 @@
     }
 }
 
+TEST_F(RegionTest, EqualsToSelf) {
+    Region touchableRegion;
+    touchableRegion.orSelf(Rect(0, 0, 100, 100));
+
+    ASSERT_TRUE(touchableRegion.contains(50, 50));
+
+    // Compiler prevents us from directly calling 'touchableRegion = touchableRegion'
+    Region& referenceTouchableRegion = touchableRegion;
+    touchableRegion = referenceTouchableRegion;
+
+    ASSERT_FALSE(touchableRegion.isEmpty());
+
+    ASSERT_TRUE(touchableRegion.contains(50, 50));
+}
+
 }; // namespace android
 
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 7c5c9c5..5a14133 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -28,8 +28,8 @@
 static const int32_t INJECTOR_PID = 999;
 static const int32_t INJECTOR_UID = 1001;
 
-static const int32_t INJECT_EVENT_TIMEOUT = 5000;
-static const int32_t DISPATCHING_TIMEOUT = 100000;
+static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
+static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms;
 
 static nsecs_t now() {
     return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -47,7 +47,7 @@
 private:
     virtual void notifyConfigurationChanged(nsecs_t) override {}
 
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&, const sp<IBinder>&,
+    virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
                               const std::string& name) override {
         ALOGE("The window is not responding : %s", name.c_str());
         return 0;
@@ -98,7 +98,7 @@
     virtual ~FakeApplicationHandle() {}
 
     virtual bool updateInfo() {
-        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
         return true;
     }
 };
@@ -163,7 +163,7 @@
         mInfo.name = "FakeWindowHandle";
         mInfo.layoutParamsFlags = 0;
         mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
-        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
         mInfo.frameLeft = mFrame.left;
         mInfo.frameTop = mFrame.top;
         mInfo.frameRight = mFrame.right;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index dda04f2..92f1750 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -543,7 +543,7 @@
         }
 
         // Get ready to dispatch the event.
-        resetANRTimeoutsLocked();
+        resetAnrTimeoutsLocked();
     }
 
     // Now we have an event to dispatch.
@@ -893,7 +893,7 @@
 
 void InputDispatcher::releasePendingEventLocked() {
     if (mPendingEvent) {
-        resetANRTimeoutsLocked();
+        resetAnrTimeoutsLocked();
         releaseInboundEventLocked(mPendingEvent);
         mPendingEvent = nullptr;
     }
@@ -1303,7 +1303,7 @@
     }
 
     if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, applicationHandle, windowHandle, entry.eventTime,
+        onAnrLocked(currentTime, applicationHandle, windowHandle, entry.eventTime,
                     mInputTargetWaitStartTime, reason);
 
         // Force poll loop to wake up immediately on next iteration once we get the
@@ -1356,7 +1356,7 @@
     return 0;
 }
 
-void InputDispatcher::resetANRTimeoutsLocked() {
+void InputDispatcher::resetAnrTimeoutsLocked() {
     if (DEBUG_FOCUS) {
         ALOGD("Resetting ANR timeouts.");
     }
@@ -3265,14 +3265,14 @@
 
 int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid,
                                           int32_t injectorUid, int32_t syncMode,
-                                          int32_t timeoutMillis, uint32_t policyFlags) {
+                                          std::chrono::milliseconds timeout, uint32_t policyFlags) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-          "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
-          event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+          "syncMode=%d, timeout=%lld, policyFlags=0x%08x",
+          event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags);
 #endif
 
-    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
+    nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
 
     policyFlags |= POLICY_FLAG_INJECTED;
     if (hasInjectionPermission(injectorPid, injectorUid)) {
@@ -3459,8 +3459,7 @@
     } // release lock
 
 #if DEBUG_INJECTION
-    ALOGD("injectInputEvent - Finished with result %d.  "
-          "injectorPid=%d, injectorUid=%d",
+    ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d",
           injectionResult, injectorPid, injectorUid);
 #endif
 
@@ -3793,12 +3792,12 @@
         if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
             if (oldFocusedApplicationHandle != inputApplicationHandle) {
                 if (oldFocusedApplicationHandle != nullptr) {
-                    resetANRTimeoutsLocked();
+                    resetAnrTimeoutsLocked();
                 }
                 mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
             }
         } else if (oldFocusedApplicationHandle != nullptr) {
-            resetANRTimeoutsLocked();
+            resetAnrTimeoutsLocked();
             oldFocusedApplicationHandle.clear();
             mFocusedApplicationHandlesByDisplay.erase(displayId);
         }
@@ -3879,7 +3878,7 @@
 
         if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
             if (mDispatchFrozen && !frozen) {
-                resetANRTimeoutsLocked();
+                resetAnrTimeoutsLocked();
             }
 
             if (mDispatchEnabled && !enabled) {
@@ -4019,7 +4018,7 @@
     resetKeyRepeatLocked();
     releasePendingEventLocked();
     drainInboundQueueLocked();
-    resetANRTimeoutsLocked();
+    resetAnrTimeoutsLocked();
 
     mTouchStatesByDisplay.clear();
     mLastHoverWindowHandle.clear();
@@ -4523,7 +4522,7 @@
     postCommandLocked(std::move(commandEntry));
 }
 
-void InputDispatcher::onANRLocked(nsecs_t currentTime,
+void InputDispatcher::onAnrLocked(nsecs_t currentTime,
                                   const sp<InputApplicationHandle>& applicationHandle,
                                   const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
                                   nsecs_t waitStartTime, const char* reason) {
@@ -4540,19 +4539,19 @@
     localtime_r(&t, &tm);
     char timestr[64];
     strftime(timestr, sizeof(timestr), "%F %T", &tm);
-    mLastANRState.clear();
-    mLastANRState += INDENT "ANR:\n";
-    mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
-    mLastANRState +=
+    mLastAnrState.clear();
+    mLastAnrState += INDENT "ANR:\n";
+    mLastAnrState += StringPrintf(INDENT2 "Time: %s\n", timestr);
+    mLastAnrState +=
             StringPrintf(INDENT2 "Window: %s\n",
                          getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
-    mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
-    mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
-    mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
-    dumpDispatchStateLocked(mLastANRState);
+    mLastAnrState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
+    mLastAnrState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
+    mLastAnrState += StringPrintf(INDENT2 "Reason: %s\n", reason);
+    dumpDispatchStateLocked(mLastAnrState);
 
     std::unique_ptr<CommandEntry> commandEntry =
-            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyANRLockedInterruptible);
+            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
     commandEntry->inputApplicationHandle = applicationHandle;
     commandEntry->inputChannel =
             windowHandle != nullptr ? getInputChannelLocked(windowHandle->getToken()) : nullptr;
@@ -4588,13 +4587,13 @@
     mLock.lock();
 }
 
-void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
     sp<IBinder> token =
             commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr;
     mLock.unlock();
 
     nsecs_t newTimeout =
-            mPolicy->notifyANR(commandEntry->inputApplicationHandle, token, commandEntry->reason);
+            mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);
 
     mLock.lock();
 
@@ -4955,9 +4954,9 @@
     dump += "Input Dispatcher State:\n";
     dumpDispatchStateLocked(dump);
 
-    if (!mLastANRState.empty()) {
+    if (!mLastAnrState.empty()) {
         dump += "\nInput Dispatcher State at time of last ANR:\n";
-        dump += mLastANRState;
+        dump += mLastAnrState;
     }
 }
 
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index a3afe1e..4f950a2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -103,7 +103,8 @@
     virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
 
     virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
-                                     int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+                                     int32_t injectorUid, int32_t syncMode,
+                                     std::chrono::milliseconds timeout,
                                      uint32_t policyFlags) override;
 
     virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
@@ -316,7 +317,7 @@
     int32_t mFocusedDisplayId GUARDED_BY(mLock);
 
     // Dispatcher state at time of last ANR.
-    std::string mLastANRState GUARDED_BY(mLock);
+    std::string mLastAnrState GUARDED_BY(mLock);
 
     // Dispatch inbound events.
     bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry)
@@ -362,7 +363,7 @@
                                                  const sp<IBinder>& inputConnectionToken)
             REQUIRES(mLock);
     nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
-    void resetANRTimeoutsLocked() REQUIRES(mLock);
+    void resetAnrTimeoutsLocked() REQUIRES(mLock);
 
     int32_t getTargetDisplayId(const EventEntry& entry);
     int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry,
@@ -467,7 +468,7 @@
             REQUIRES(mLock);
     void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
                               const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
-    void onANRLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+    void onAnrLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
                      const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
                      nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
 
@@ -476,7 +477,7 @@
             REQUIRES(mLock);
     void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
     void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
     void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
             REQUIRES(mLock);
     void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 09dc92c..9b002f4 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -90,8 +90,8 @@
      * This method may be called on any thread (usually by the input manager).
      */
     virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
-                                     int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
-                                     uint32_t policyFlags) = 0;
+                                     int32_t injectorUid, int32_t syncMode,
+                                     std::chrono::milliseconds timeout, uint32_t policyFlags) = 0;
 
     /*
      * Check whether InputEvent actually happened by checking the signature of the event.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 4214488..667af9b 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -47,7 +47,7 @@
 
     /* Notifies the system that an application is not responding.
      * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+    virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle,
                               const sp<IBinder>& token, const std::string& reason) = 0;
 
     /* Notifies the system that an input channel is unrecoverably broken. */
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e0d32a0..eeff757 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -127,19 +127,16 @@
         mConfigurationChangedTime = when;
     }
 
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
-            const sp<IBinder>&,
-            const std::string&) {
+    virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
+                              const std::string&) override {
         return 0;
     }
 
-    virtual void notifyInputChannelBroken(const sp<IBinder>&) {
-    }
+    virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
 
-    virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
-    }
+    virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
 
-    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
+    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
         *outConfig = mConfig;
     }
 
@@ -160,19 +157,17 @@
         return true;
     }
 
-    virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
-    }
+    virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
 
-    virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
-    }
+    virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
 
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
-            const KeyEvent*, uint32_t) {
+    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
+                                                  uint32_t) override {
         return 0;
     }
 
-    virtual bool dispatchUnhandledKey(const sp<IBinder>&,
-            const KeyEvent*, uint32_t, KeyEvent*) {
+    virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
+                                      KeyEvent*) override {
         return false;
     }
 
@@ -184,14 +179,13 @@
         mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
     }
 
-    virtual void pokeUserActivity(nsecs_t, int32_t) {
-    }
+    virtual void pokeUserActivity(nsecs_t, int32_t) override {}
 
-    virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
+    virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
         return false;
     }
 
-    virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
+    virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
         mOnPointerDownToken = newToken;
     }
 
@@ -313,18 +307,18 @@
                      INVALID_HMAC,
                      /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
                      ARBITRARY_TIME);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "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);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject key events with ACTION_MULTIPLE.";
 }
 
@@ -350,9 +344,9 @@
                      1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with undefined action.";
 
     // Rejects pointer down with invalid index.
@@ -363,9 +357,9 @@
                      0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer down index too large.";
 
     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -375,9 +369,9 @@
                      0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer down index too small.";
 
     // Rejects pointer up with invalid index.
@@ -388,9 +382,9 @@
                      0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer up index too large.";
 
     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -400,9 +394,9 @@
                      0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer up index too small.";
 
     // Rejects motion events with invalid number of pointers.
@@ -412,9 +406,9 @@
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 0, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with 0 pointers.";
 
     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -423,9 +417,9 @@
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with more than MAX_POINTERS pointers.";
 
     // Rejects motion events with invalid pointer ids.
@@ -436,9 +430,9 @@
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer ids less than 0.";
 
     pointerProperties[0].id = MAX_POINTER_ID + 1;
@@ -448,9 +442,9 @@
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 1, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
 
     // Rejects motion events with duplicate pointer ids.
@@ -462,9 +456,9 @@
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      ARBITRARY_TIME, ARBITRARY_TIME,
                      /*pointerCount*/ 2, pointerProperties, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
-            &event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+              mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+                                            INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
             << "Should reject motion events with duplicate pointer ids.";
 }
 
@@ -490,16 +484,16 @@
 }
 
 // --- InputDispatcherTest SetInputWindowTest ---
-static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
-static constexpr nsecs_t DISPATCHING_TIMEOUT = seconds_to_nanoseconds(5);
+static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
+static constexpr std::chrono::duration DISPATCHING_TIMEOUT = 5s;
 
 class FakeApplicationHandle : public InputApplicationHandle {
 public:
     FakeApplicationHandle() {}
     virtual ~FakeApplicationHandle() {}
 
-    virtual bool updateInfo() {
-        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+    virtual bool updateInfo() override {
+        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
         return true;
     }
 };
@@ -634,11 +628,11 @@
         mInfo.applicationInfo = *inputApplicationHandle->getInfo();
 
         mInfo.token = token;
-        mInfo.id = 0;
+        mInfo.id = sId++;
         mInfo.name = name;
         mInfo.layoutParamsFlags = 0;
         mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
-        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
         mInfo.frameLeft = 0;
         mInfo.frameTop = 0;
         mInfo.frameRight = WIDTH;
@@ -672,8 +666,6 @@
 
     void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
 
-    void setId(int32_t id) { mInfo.id = id; }
-
     void setWindowScale(float xScale, float yScale) {
         mInfo.windowXScale = xScale;
         mInfo.windowYScale = yScale;
@@ -755,8 +747,11 @@
 private:
     const std::string mName;
     std::unique_ptr<FakeInputReceiver> mInputReceiver;
+    static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
 };
 
+std::atomic<int32_t> FakeWindowHandle::sId{1};
+
 static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
         int32_t displayId = ADISPLAY_ID_NONE) {
     KeyEvent event;
@@ -810,13 +805,15 @@
 }
 
 static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
-                                int32_t displayId, int32_t x = 100, int32_t y = 200) {
-    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
+                                int32_t displayId, const PointF& location = {100, 200}) {
+    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x,
+                             location.y);
 }
 
 static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
-                              int32_t displayId, int32_t x = 100, int32_t y = 200) {
-    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
+                              int32_t displayId, const PointF& location = {100, 200}) {
+    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x,
+                             location.y);
 }
 
 static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
@@ -880,6 +877,55 @@
     window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
 }
 
+/**
+ * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
+ * To ensure that window receives only events that were directly inside of it, add
+ * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
+ * when finding touched windows.
+ * This test serves as a sanity check for the next test, where setInputWindows is
+ * called twice.
+ */
+TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+    sp<FakeWindowHandle> window =
+            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+    window->setFrame(Rect(0, 0, 100, 100));
+    window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                               {50, 50}))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+    // Window should receive motion event.
+    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+}
+
+/**
+ * Calling setInputWindows twice, with the same info, should not cause any issues.
+ * To ensure that window receives only events that were directly inside of it, add
+ * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
+ * when finding touched windows.
+ */
+TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+    sp<FakeWindowHandle> window =
+            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+    window->setFrame(Rect(0, 0, 100, 100));
+    window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                               {50, 50}))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+    // Window should receive motion event.
+    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+}
+
 // The foreground window should receive the first touch down event.
 TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
     sp<FakeApplicationHandle> application = new FakeApplicationHandle();
@@ -1821,7 +1867,6 @@
                 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
         mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
         mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
-        mFocusedWindowTouchPoint = 60;
 
         // Set focused application.
         mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1842,15 +1887,16 @@
 protected:
     sp<FakeWindowHandle> mUnfocusedWindow;
     sp<FakeWindowHandle> mFocusedWindow;
-    int32_t mFocusedWindowTouchPoint;
+    static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
 };
 
 // Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
 // DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
 // the onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
-            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                               {20, 20}))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     mUnfocusedWindow->consumeMotionDown();
 
@@ -1862,8 +1908,8 @@
 // DOWN on the window that doesn't have focus. Ensure no window received the
 // onPointerDownOutsideFocus callback.
 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
-            AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     mFocusedWindow->consumeMotionDown();
 
@@ -1889,7 +1935,7 @@
         OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
     ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
               injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
-                               mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
+                               FOCUSED_WINDOW_TOUCH_POINT))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     mFocusedWindow->consumeMotionDown();
 
@@ -1910,14 +1956,12 @@
         // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
         mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
                                       InputWindowInfo::FLAG_SPLIT_TOUCH);
-        mWindow1->setId(0);
         mWindow1->setFrame(Rect(0, 0, 100, 100));
 
         mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
                                         ADISPLAY_ID_DEFAULT, mWindow1->getToken());
         mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
                                       InputWindowInfo::FLAG_SPLIT_TOUCH);
-        mWindow2->setId(1);
         mWindow2->setFrame(Rect(100, 100, 200, 200));
 
         mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index d3712d9..a0606b4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -24,6 +24,7 @@
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/OutputColorSetting.h>
 #include <math/mat4.h>
+#include <ui/Transform.h>
 
 namespace android::compositionengine {
 
@@ -57,6 +58,9 @@
     // Forces a color mode on the outputs being refreshed
     ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE};
 
+    // Used to correctly apply an inverse-display buffer transform if applicable
+    ui::Transform::RotationFlags internalDisplayRotationFlags{ui::Transform::ROT_0};
+
     // If true, GPU clocks will be increased when rendering blurs
     bool blursAreExpensive{false};
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index cf77738..aa70ef8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -19,6 +19,7 @@
 #include <optional>
 #include <string>
 
+#include <ui/Transform.h>
 #include <utils/StrongPointer.h>
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -77,7 +78,12 @@
 
     // Recalculates the state of the output layer from the output-independent
     // layer. If includeGeometry is false, the geometry state can be skipped.
-    virtual void updateCompositionState(bool includeGeometry, bool forceClientComposition) = 0;
+    // internalDisplayRotationFlags must be set to the rotation flags for the
+    // internal display, and is used to properly compute the inverse-display
+    // transform, if needed.
+    virtual void updateCompositionState(
+            bool includeGeometry, bool forceClientComposition,
+            ui::Transform::RotationFlags internalDisplayRotationFlags) = 0;
 
     // Writes the geometry state to the HWC, or does nothing if this layer does
     // not use the HWC. If includeGeometry is false, the geometry state can be
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 79df9b2..8cb5ae8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -39,7 +39,8 @@
 
     void setHwcLayer(std::shared_ptr<HWC2::Layer>) override;
 
-    void updateCompositionState(bool includeGeometry, bool forceClientComposition) override;
+    void updateCompositionState(bool includeGeometry, bool forceClientComposition,
+                                ui::Transform::RotationFlags) override;
     void writeStateToHWC(bool) override;
     void writeCursorPositionToHWC() const override;
 
@@ -55,7 +56,8 @@
 
     virtual FloatRect calculateOutputSourceCrop() const;
     virtual Rect calculateOutputDisplayFrame() const;
-    virtual uint32_t calculateOutputRelativeBufferTransform() const;
+    virtual uint32_t calculateOutputRelativeBufferTransform(
+            uint32_t internalDisplayRotationFlags) const;
 
 protected:
     // Implemented by the final implementation for the final state it uses.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 2ecbad8..81e1fc7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -38,7 +38,7 @@
     MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
     MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
 
-    MOCK_METHOD2(updateCompositionState, void(bool, bool));
+    MOCK_METHOD3(updateCompositionState, void(bool, bool, ui::Transform::RotationFlags));
     MOCK_METHOD1(writeStateToHWC, void(bool));
     MOCK_CONST_METHOD0(writeCursorPositionToHWC, void());
 
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b7ea089..b07c904 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -588,7 +588,8 @@
     for (auto* layer : getOutputLayersOrderedByZ()) {
         layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
                                       refreshArgs.devOptForceClientComposition ||
-                                              forceClientComposition);
+                                              forceClientComposition,
+                                      refreshArgs.internalDisplayRotationFlags);
 
         if (mLayerRequestingBackgroundBlur == layer) {
             forceClientComposition = false;
@@ -815,6 +816,43 @@
     OutputCompositionState& outputCompositionState = editState();
     const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
                                                       outputState.usesClientComposition};
+
+    auto& renderEngine = getCompositionEngine().getRenderEngine();
+    const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
+
+    // If we the display is secure, protected content support is enabled, and at
+    // least one layer has protected content, we need to use a secure back
+    // buffer.
+    if (outputState.isSecure && supportsProtectedContent) {
+        auto layers = getOutputLayersOrderedByZ();
+        bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
+            return layer->getLayerFE().getCompositionState()->hasProtectedContent;
+        });
+        if (needsProtected != renderEngine.isProtected()) {
+            renderEngine.useProtectedContext(needsProtected);
+        }
+        if (needsProtected != mRenderSurface->isProtected() &&
+            needsProtected == renderEngine.isProtected()) {
+            mRenderSurface->setProtected(needsProtected);
+        }
+    }
+
+    base::unique_fd fd;
+    sp<GraphicBuffer> buf;
+
+    // If we aren't doing client composition on this output, but do have a
+    // flipClientTarget request for this frame on this output, we still need to
+    // dequeue a buffer.
+    if (hasClientComposition || outputState.flipClientTarget) {
+        buf = mRenderSurface->dequeueBuffer(&fd);
+        if (buf == nullptr) {
+            ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
+                  "client composition for this frame",
+                  mName.c_str());
+            return {};
+        }
+    }
+
     base::unique_fd readyFence;
     if (!hasClientComposition) {
         setExpensiveRenderingExpected(false);
@@ -823,9 +861,6 @@
 
     ALOGV("hasClientComposition");
 
-    auto& renderEngine = getCompositionEngine().getRenderEngine();
-    const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
-
     renderengine::DisplaySettings clientCompositionDisplay;
     clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
     clientCompositionDisplay.clip = outputState.sourceClip;
@@ -851,32 +886,6 @@
                                               clientCompositionDisplay.outputDataspace);
     appendRegionFlashRequests(debugRegion, clientCompositionLayers);
 
-    // If we the display is secure, protected content support is enabled, and at
-    // least one layer has protected content, we need to use a secure back
-    // buffer.
-    if (outputState.isSecure && supportsProtectedContent) {
-        auto layers = getOutputLayersOrderedByZ();
-        bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
-            return layer->getLayerFE().getCompositionState()->hasProtectedContent;
-        });
-        if (needsProtected != renderEngine.isProtected()) {
-            renderEngine.useProtectedContext(needsProtected);
-        }
-        if (needsProtected != mRenderSurface->isProtected() &&
-            needsProtected == renderEngine.isProtected()) {
-            mRenderSurface->setProtected(needsProtected);
-        }
-    }
-
-    base::unique_fd fd;
-    sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
-    if (buf == nullptr) {
-        ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
-              "client composition for this frame",
-              mName.c_str());
-        return std::nullopt;
-    }
-
     // Check if the client composition requests were rendered into the provided graphic buffer. If
     // so, we can reuse the buffer and avoid client composition.
     if (mClientCompositionRequestCache) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index c9a070d..81f2dd1 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -223,7 +223,8 @@
     return displayTransform.transform(frame);
 }
 
-uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
+uint32_t OutputLayer::calculateOutputRelativeBufferTransform(
+        uint32_t internalDisplayRotationFlags) const {
     const auto& layerState = *getLayerFE().getCompositionState();
     const auto& outputState = getOutput().getState();
 
@@ -241,10 +242,11 @@
 
     if (layerState.geomBufferUsesDisplayInverseTransform) {
         /*
-         * the code below applies the primary display's inverse transform to the
-         * buffer
+         * We must apply the internal display's inverse transform to the buffer
+         * transform, and not the one for the output this layer is on.
          */
-        uint32_t invTransform = outputState.orientation;
+        uint32_t invTransform = internalDisplayRotationFlags;
+
         // calculate the inverse transform
         if (invTransform & HAL_TRANSFORM_ROT_90) {
             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
@@ -261,9 +263,11 @@
 
     // this gives us only the "orientation" component of the transform
     return transform.getOrientation();
-} // namespace impl
+}
 
-void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition) {
+void OutputLayer::updateCompositionState(
+        bool includeGeometry, bool forceClientComposition,
+        ui::Transform::RotationFlags internalDisplayRotationFlags) {
     const auto* layerFEState = getLayerFE().getCompositionState();
     if (!layerFEState) {
         return;
@@ -283,8 +287,8 @@
 
         state.displayFrame = calculateOutputDisplayFrame();
         state.sourceCrop = calculateOutputSourceCrop();
-        state.bufferTransform =
-                static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
+        state.bufferTransform = static_cast<Hwc2::Transform>(
+                calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));
 
         if ((layerFEState->isSecure && !outputState.isSecure) ||
             (state.bufferTransform & ui::Transform::ROT_INVALID)) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 59889b6..62977a4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -30,6 +30,7 @@
 #include <compositionengine/mock/OutputLayer.h>
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
+#include <renderengine/mock/RenderEngine.h>
 #include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
 
@@ -156,6 +157,8 @@
 
     DisplayTestCommon() {
         EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
+        EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
+        EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
     }
 
     DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
@@ -182,6 +185,7 @@
 
     StrictMock<android::mock::HWComposer> mHwComposer;
     StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
+    StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
 };
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index bdacb22..020f93a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -361,7 +361,7 @@
         mOutputState.orientation = entry.display;
         mOutputState.transform = ui::Transform{entry.display};
 
-        auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+        const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.display);
         EXPECT_EQ(entry.expected, actual) << "entry " << i;
     }
 }
@@ -371,56 +371,109 @@
     mLayerFEState.geomBufferUsesDisplayInverseTransform = true;
 
     struct Entry {
-        uint32_t layer;
+        uint32_t layer; /* shouldn't affect the result, so we just use arbitrary values */
         uint32_t buffer;
         uint32_t display;
+        uint32_t internal;
         uint32_t expected;
     };
-    // Not an exhaustive list of cases, but hopefully enough.
-    const std::array<Entry, 24> testData = {
+    const std::array<Entry, 64> testData = {
             // clang-format off
-            //             layer       buffer      display     expected
-            /*  0 */ Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT},
-            /*  1 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_IDENT},
-            /*  2 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_180, TR_IDENT},
-            /*  3 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_IDENT},
+            //    layer       buffer      display     internal    expected
+            Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT},
+            Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_ROT_270},
+            Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_ROT_180, TR_ROT_180},
+            Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_ROT_90},
 
-            /*  4 */ Entry{TR_IDENT,   TR_FLP_H,   TR_IDENT,   TR_FLP_H},
-            /*  5 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
-            /*  6 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_180, TR_FLP_H},
-            /*  7 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+            Entry{TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_IDENT,   TR_ROT_90},
+            Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_90,  TR_ROT_90,  TR_IDENT},
+            Entry{TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_ROT_180, TR_ROT_270},
+            Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_90,  TR_ROT_270, TR_ROT_180},
 
-            /*  8 */ Entry{TR_IDENT,   TR_FLP_V,   TR_IDENT,   TR_FLP_V},
-            /*  9 */ Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_90,  TR_ROT_90},
-            /* 10 */ Entry{TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_ROT_180},
-            /* 11 */ Entry{TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_ROT_270},
+            Entry{TR_ROT_180, TR_IDENT,   TR_ROT_180, TR_IDENT,   TR_ROT_180},
+            Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_ROT_90,  TR_ROT_90},
+            Entry{TR_ROT_180, TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_IDENT},
+            Entry{TR_ROT_270, TR_IDENT,   TR_ROT_180, TR_ROT_270, TR_ROT_270},
 
-            /* 12 */ Entry{TR_ROT_90,  TR_IDENT,   TR_IDENT,   TR_IDENT},
-            /* 13 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
-            /* 14 */ Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_IDENT},
-            /* 15 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+            Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT,   TR_ROT_270},
+            Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_ROT_90,  TR_ROT_180},
+            Entry{TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_ROT_180, TR_ROT_90},
+            Entry{TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_IDENT},
 
-            /* 16 */ Entry{TR_ROT_180, TR_FLP_H,   TR_IDENT,   TR_FLP_H},
-            /* 17 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_IDENT},
-            /* 18 */ Entry{TR_ROT_180, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
-            /* 19 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_IDENT},
+            //    layer       buffer      display     internal    expected
+            Entry{TR_IDENT,   TR_ROT_90,  TR_IDENT,   TR_IDENT,   TR_ROT_90},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            Entry{TR_ROT_180, TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_ROT_270},
+            Entry{TR_ROT_270, TR_ROT_90,  TR_IDENT,   TR_ROT_270, TR_ROT_180},
 
-            /* 20 */ Entry{TR_ROT_270, TR_IDENT,   TR_IDENT,   TR_IDENT},
-            /* 21 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
-            /* 22 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
-            /* 23 */ Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_ROT_90,  TR_IDENT,   TR_ROT_180},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_ROT_90,  TR_ROT_90,  TR_ROT_90},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_ROT_90,  TR_ROT_180, TR_IDENT},
+            Entry{TR_ROT_270, TR_ROT_90,  TR_ROT_90,  TR_ROT_270, TR_ROT_270},
+
+            Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_180, TR_IDENT,   TR_ROT_270},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_ROT_180, TR_ROT_90,  TR_ROT_180},
+            Entry{TR_ROT_180, TR_ROT_90,  TR_ROT_180, TR_ROT_180, TR_ROT_90},
+            Entry{TR_ROT_90,  TR_ROT_90,  TR_ROT_180, TR_ROT_270, TR_IDENT},
+
+            Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_270, TR_IDENT,   TR_IDENT},
+            Entry{TR_ROT_270, TR_ROT_90,  TR_ROT_270, TR_ROT_90,  TR_ROT_270},
+            Entry{TR_ROT_180, TR_ROT_90,  TR_ROT_270, TR_ROT_180, TR_ROT_180},
+            Entry{TR_ROT_270, TR_ROT_90,  TR_ROT_270, TR_ROT_270, TR_ROT_90},
+
+            //    layer       buffer      display     internal    expected
+            Entry{TR_IDENT,   TR_ROT_180, TR_IDENT,   TR_IDENT,   TR_ROT_180},
+            Entry{TR_IDENT,   TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_ROT_90},
+            Entry{TR_ROT_180, TR_ROT_180, TR_IDENT,   TR_ROT_180, TR_IDENT},
+            Entry{TR_ROT_270, TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_ROT_270},
+
+            Entry{TR_IDENT,   TR_ROT_180, TR_ROT_90,  TR_IDENT,   TR_ROT_270},
+            Entry{TR_ROT_90,  TR_ROT_180, TR_ROT_90,  TR_ROT_90,  TR_ROT_180},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90,  TR_ROT_180, TR_ROT_90},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90,  TR_ROT_270, TR_IDENT},
+
+            Entry{TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_IDENT,   TR_IDENT},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_90,  TR_ROT_270},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180},
+            Entry{TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90},
+
+            Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_IDENT,   TR_ROT_90},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90,  TR_IDENT},
+            Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_270},
+            Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_270, TR_ROT_180},
+
+            //    layer       buffer      display     internal    expected
+            Entry{TR_IDENT,   TR_ROT_270, TR_IDENT,   TR_IDENT,   TR_ROT_270},
+            Entry{TR_ROT_90,  TR_ROT_270, TR_IDENT,   TR_ROT_90,  TR_ROT_180},
+            Entry{TR_ROT_270, TR_ROT_270, TR_IDENT,   TR_ROT_180, TR_ROT_90},
+            Entry{TR_IDENT,   TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            Entry{TR_ROT_270, TR_ROT_270, TR_ROT_90,  TR_IDENT,   TR_IDENT},
+            Entry{TR_ROT_90,  TR_ROT_270, TR_ROT_90,  TR_ROT_90,  TR_ROT_270},
+            Entry{TR_ROT_180, TR_ROT_270, TR_ROT_90,  TR_ROT_180, TR_ROT_180},
+            Entry{TR_ROT_90,  TR_ROT_270, TR_ROT_90,  TR_ROT_270, TR_ROT_90},
+
+            Entry{TR_IDENT,   TR_ROT_270, TR_ROT_180, TR_IDENT,   TR_ROT_90},
+            Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_90,  TR_IDENT},
+            Entry{TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270},
+            Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_180},
+
+            Entry{TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_IDENT,   TR_ROT_180},
+            Entry{TR_ROT_90,  TR_ROT_270, TR_ROT_270, TR_ROT_90,  TR_ROT_90},
+            Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_IDENT},
+            Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270},
             // clang-format on
     };
 
     for (size_t i = 0; i < testData.size(); i++) {
         const auto& entry = testData[i];
 
-        mLayerFEState.geomLayerTransform = ui::Transform{entry.layer};
+        mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080);
         mLayerFEState.geomBufferTransform = entry.buffer;
         mOutputState.orientation = entry.display;
         mOutputState.transform = ui::Transform{entry.display};
 
-        auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+        const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.internal);
         EXPECT_EQ(entry.expected, actual) << "entry " << i;
     }
 }
@@ -436,7 +489,7 @@
     // Mock everything called by updateCompositionState to simplify testing it.
     MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
     MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
-    MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+    MOCK_CONST_METHOD1(calculateOutputRelativeBufferTransform, uint32_t(uint32_t));
 
     // compositionengine::OutputLayer overrides
     const compositionengine::Output& getOutput() const override { return mOutput; }
@@ -463,10 +516,11 @@
 
     ~OutputLayerUpdateCompositionStateTest() = default;
 
-    void setupGeometryChildCallValues() {
+    void setupGeometryChildCallValues(ui::Transform::RotationFlags internalDisplayRotationFlags) {
         EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
         EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
-        EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
+        EXPECT_CALL(mOutputLayer,
+                    calculateOutputRelativeBufferTransform(internalDisplayRotationFlags))
                 .WillOnce(Return(mBufferTransform));
     }
 
@@ -489,7 +543,7 @@
 TEST_F(OutputLayerUpdateCompositionStateTest, doesNothingIfNoFECompositionState) {
     EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
 
-    mOutputLayer.updateCompositionState(true, false);
+    mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90);
 }
 
 TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
@@ -497,9 +551,9 @@
     mOutputState.isSecure = true;
     mOutputLayer.editState().forceClientComposition = true;
 
-    setupGeometryChildCallValues();
+    setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_90);
 
-    mOutputLayer.updateCompositionState(true, false);
+    mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90);
 
     validateComputedGeometryState();
 
@@ -511,9 +565,9 @@
     mLayerFEState.isSecure = true;
     mOutputState.isSecure = false;
 
-    setupGeometryChildCallValues();
+    setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
 
-    mOutputLayer.updateCompositionState(true, false);
+    mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0);
 
     validateComputedGeometryState();
 
@@ -527,9 +581,9 @@
 
     mBufferTransform = ui::Transform::ROT_INVALID;
 
-    setupGeometryChildCallValues();
+    setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
 
-    mOutputLayer.updateCompositionState(true, false);
+    mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0);
 
     validateComputedGeometryState();
 
@@ -544,7 +598,7 @@
     // should use the layers requested colorspace.
     mLayerFEState.isColorspaceAgnostic = false;
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace);
 
@@ -552,7 +606,7 @@
     // should use the colorspace chosen for the whole output.
     mLayerFEState.isColorspaceAgnostic = true;
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace);
 }
@@ -560,7 +614,7 @@
 TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
     mOutputLayer.editState().forceClientComposition = false;
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
 }
@@ -569,7 +623,7 @@
        doesNotClearForceClientCompositionIfNotDoingGeometry) {
     mOutputLayer.editState().forceClientComposition = true;
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
 }
@@ -578,7 +632,7 @@
     mLayerFEState.forceClientComposition = true;
     mOutputLayer.editState().forceClientComposition = false;
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
 }
@@ -588,7 +642,7 @@
     mOutputLayer.editState().forceClientComposition = false;
     EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false));
 
-    mOutputLayer.updateCompositionState(false, false);
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
 }
@@ -597,15 +651,15 @@
     mLayerFEState.forceClientComposition = false;
     mOutputLayer.editState().forceClientComposition = false;
 
-    mOutputLayer.updateCompositionState(false, true);
+    mOutputLayer.updateCompositionState(false, true, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
 
     mOutputLayer.editState().forceClientComposition = false;
 
-    setupGeometryChildCallValues();
+    setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
 
-    mOutputLayer.updateCompositionState(true, true);
+    mOutputLayer.updateCompositionState(true, true, ui::Transform::RotationFlags::ROT_0);
 
     EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
 }
@@ -810,7 +864,7 @@
     // geomBufferTransform is set to the inverse transform.
     mLayerFEState.geomBufferTransform = TR_ROT_270;
 
-    EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform());
+    EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform(ui::Transform::ROT_90));
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 1c9cd9c..59ed72e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -696,11 +696,11 @@
     InjectedLayer layer2;
     InjectedLayer layer3;
 
-    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false));
+    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
     EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false));
+    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
     EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
     EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
 
     injectOutputLayer(layer1);
@@ -712,6 +712,7 @@
     CompositionRefreshArgs args;
     args.updatingGeometryThisFrame = false;
     args.devOptForceClientComposition = false;
+    args.internalDisplayRotationFlags = ui::Transform::ROT_180;
     mOutput->updateAndWriteCompositionState(args);
 }
 
@@ -720,11 +721,11 @@
     InjectedLayer layer2;
     InjectedLayer layer3;
 
-    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false));
+    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
     EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(true));
-    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false));
+    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
     EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(true));
-    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false));
+    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
     EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(true));
 
     injectOutputLayer(layer1);
@@ -744,11 +745,11 @@
     InjectedLayer layer2;
     InjectedLayer layer3;
 
-    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
     EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
     EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true));
+    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
     EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
 
     injectOutputLayer(layer1);
@@ -2797,6 +2798,7 @@
         mOutput.mState.usesClientComposition = true;
         mOutput.mState.usesDeviceComposition = false;
         mOutput.mState.reusedClientComposition = false;
+        mOutput.mState.flipClientTarget = false;
 
         EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
         EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
@@ -2868,19 +2870,40 @@
 TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) {
     mOutput.mState.usesClientComposition = false;
 
+    EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
 
     verify().execute().expectAFenceWasReturned();
 }
 
-TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
-    EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
-    EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
+TEST_F(OutputComposeSurfacesTest,
+       dequeuesABufferIfNoClientCompositionButFlipClientTargetRequested) {
+    mOutput.mState.usesClientComposition = false;
+    mOutput.mState.flipClientTarget = true;
+
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
-    EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
-            .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
-    EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
-            .WillRepeatedly(Return());
+
+    EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
+    EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
+
+    verify().execute().expectAFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) {
+    EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+
+    EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
+
+    verify().execute().expectNoFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest,
+       doesMinimalWorkIfDequeueBufferFailsForNoClientCompositionButFlipClientTargetRequested) {
+    mOutput.mState.usesClientComposition = false;
+    mOutput.mState.flipClientTarget = true;
+
+    EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
 
@@ -3315,7 +3338,7 @@
         mLayer.layerFEState.backgroundBlurRadius = 10;
         mOutput.editState().isEnabled = true;
 
-        EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true));
+        EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
         EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false));
         EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
                 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
@@ -3894,11 +3917,11 @@
     InjectedLayer layer3;
 
     // Layer requesting blur, or below, should request client composition.
-    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+    EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
     EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+    EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
     EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
-    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+    EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
     EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
 
     layer2.layerFEState.backgroundBlurRadius = 10;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9af9cad..2cebecb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -116,6 +116,10 @@
     }
 }
 
+void DisplayDevice::setDeviceProductInfo(std::optional<DeviceProductInfo> info) {
+    mDeviceProductInfo = std::move(info);
+}
+
 uint32_t DisplayDevice::getPageFlipCount() const {
     return mCompositionDisplay->getRenderSurface()->getPageFlipCount();
 }
@@ -267,6 +271,12 @@
     StringAppendF(&result, "powerMode=%s (%d), ", to_string(mPowerMode).c_str(),
                   static_cast<int32_t>(mPowerMode));
     StringAppendF(&result, "activeConfig=%d, ", mActiveConfig.value());
+    StringAppendF(&result, "deviceProductInfo=");
+    if (mDeviceProductInfo) {
+        mDeviceProductInfo->dump(result);
+    } else {
+        result.append("{}");
+    }
     getCompositionDisplay()->dump(result);
 }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8c86153..a35cada 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -132,6 +132,11 @@
     void setDisplayName(const std::string& displayName);
     const std::string& getDisplayName() const { return mDisplayName; }
 
+    void setDeviceProductInfo(std::optional<DeviceProductInfo> info);
+    const std::optional<DeviceProductInfo>& getDeviceProductInfo() const {
+        return mDeviceProductInfo;
+    }
+
     /* ------------------------------------------------------------------------
      * Display power mode management.
      */
@@ -178,6 +183,8 @@
 
     // TODO(b/74619554): Remove special cases for primary display.
     const bool mIsPrimary;
+
+    std::optional<DeviceProductInfo> mDeviceProductInfo;
 };
 
 struct DisplayDeviceState {
@@ -185,7 +192,7 @@
         DisplayId id;
         DisplayConnectionType type;
         hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
-
+        std::optional<DeviceProductInfo> deviceProductInfo;
         bool operator==(const Physical& other) const {
             return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
         }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0ea3340..fb82033 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -349,7 +349,7 @@
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
                            std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) {
-    uint32_t intDisplayRequests;
+    uint32_t intDisplayRequests = 0;
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
     auto intError = mComposer.getDisplayRequests(
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 2e7fbc1..436a83b 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -207,7 +207,7 @@
     }
 
     const int32_t left = display->getWidth() / 32;
-    const int32_t top = display->getHeight() / 32;
+    const int32_t top = display->getHeight() / 16;
     const int32_t right = left + display->getWidth() / 8;
     const int32_t buttom = top + display->getHeight() / 32;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index be2c4e4..0c332af 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -836,7 +836,7 @@
     }
 
     info->secure = display->isSecure();
-    info->deviceProductInfo = getDeviceProductInfoLocked(*display);
+    info->deviceProductInfo = display->getDeviceProductInfo();
 
     return NO_ERROR;
 }
@@ -1309,30 +1309,6 @@
     return NO_ERROR;
 }
 
-std::optional<DeviceProductInfo> SurfaceFlinger::getDeviceProductInfoLocked(
-        const DisplayDevice& display) const {
-    // TODO(b/149075047): Populate DeviceProductInfo on hotplug and store it in DisplayDevice to
-    // avoid repetitive HAL IPC and EDID parsing.
-    const auto displayId = display.getId();
-    LOG_FATAL_IF(!displayId);
-
-    const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
-    LOG_FATAL_IF(!hwcDisplayId);
-
-    uint8_t port;
-    DisplayIdentificationData data;
-    if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) {
-        ALOGV("%s: No identification data.", __FUNCTION__);
-        return {};
-    }
-
-    const auto info = parseDisplayIdentificationData(port, data);
-    if (!info) {
-        return {};
-    }
-    return info->deviceProductInfo;
-}
-
 status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
                                                                ui::PixelFormat* outFormat,
                                                                ui::Dataspace* outDataspace,
@@ -2051,6 +2027,7 @@
     refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
     refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty;
     refreshArgs.blursAreExpensive = mBlursAreExpensive;
+    refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();
 
     if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
         refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
@@ -2426,8 +2403,10 @@
                 }
 
                 DisplayDeviceState state;
-                state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId),
-                                  event.hwcDisplayId};
+                state.physical = {.id = displayId,
+                                  .type = getHwComposer().getDisplayConnectionType(displayId),
+                                  .hwcDisplayId = event.hwcDisplayId,
+                                  .deviceProductInfo = info->deviceProductInfo};
                 state.isSecure = true; // All physical displays are currently considered secure.
                 state.displayName = info->name;
 
@@ -2543,6 +2522,7 @@
         LOG_ALWAYS_FATAL_IF(!displayId);
         auto activeConfigId = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(*displayId));
         display->setActiveConfig(activeConfigId);
+        display->setDeviceProductInfo(state.physical->deviceProductInfo);
     }
 
     display->setLayerStack(state.layerStack);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4b5a843..ad0d9d4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -774,7 +774,7 @@
         return nullptr;
     }
 
-    std::optional<DeviceProductInfo> getDeviceProductInfoLocked(const DisplayDevice&) const;
+    std::optional<DeviceProductInfo> getDeviceProductInfoLocked(DisplayId) const;
 
     // mark a region of a layer stack dirty. this updates the dirty
     // region of all screens presenting this layer stack.
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index f41b10e..9130b04 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -1821,7 +1821,7 @@
         ASSERT_TRUE(displayId);
         const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
         ASSERT_TRUE(hwcDisplayId);
-        state.physical = {*displayId, *connectionType, *hwcDisplayId};
+        state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId};
     }
 
     state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -1997,7 +1997,9 @@
         ASSERT_TRUE(displayId);
         const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
         ASSERT_TRUE(hwcDisplayId);
-        expectedPhysical = {*displayId, *connectionType, *hwcDisplayId};
+        expectedPhysical = {.id = *displayId,
+                            .type = *connectionType,
+                            .hwcDisplayId = *hwcDisplayId};
     }
 
     // The display should have been set up in the current display state
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 445f04a..11db91d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -629,7 +629,7 @@
             if (const auto type = mCreationArgs.connectionType) {
                 LOG_ALWAYS_FATAL_IF(!displayId);
                 LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
-                state.physical = {*displayId, *type, *mHwcDisplayId};
+                state.physical = {.id = *displayId, .type = *type, .hwcDisplayId = *mHwcDisplayId};
             }
 
             state.isSecure = mCreationArgs.isSecure;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 22122a5..74ef0e7 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -252,18 +252,6 @@
     result = LoadUpdatedDriver(&module);
     if (result == -ENOENT) {
         result = LoadBuiltinDriver(&module);
-        if (result != 0) {
-            // -ENOENT means the sphal namespace doesn't exist, not that there
-            // is a problem with the driver.
-            ALOGW_IF(
-                result != -ENOENT,
-                "Failed to load Vulkan driver into sphal namespace. This "
-                "usually means the driver has forbidden library dependencies."
-                "Please fix, this will soon stop working.");
-            result =
-                hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
-                              reinterpret_cast<const hw_module_t**>(&module));
-        }
     }
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(