Merge "SF: Bundle ftl::Flags for CompositionCoverage"
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 7617136..7e7bba3 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -215,8 +215,6 @@
 
 cc_defaults {
     name: "trusty_mock_defaults",
-    vendor_available: true,
-    host_supported: true,
 
     header_libs: [
         "trusty_mock_headers",
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 458dff3..7006f87 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -371,30 +371,6 @@
 }
 
 cc_test {
-    name: "binderRpcTest_on_trusty_mock",
-    defaults: [
-        "trusty_mock_defaults",
-    ],
-
-    srcs: [
-        "binderRpcUniversalTests.cpp",
-        "binderRpcTestCommon.cpp",
-        "binderRpcTestTrusty.cpp",
-    ],
-
-    shared_libs: [
-        "libbinder_on_trusty_mock",
-        "libbase",
-        "libutils",
-        "libcutils",
-    ],
-
-    static_libs: [
-        "binderRpcTestIface-cpp",
-    ],
-}
-
-cc_test {
     name: "binderRpcTest",
     defaults: [
         "binderRpcTest_defaults",
@@ -406,7 +382,6 @@
     required: [
         "libbinder_on_trusty_mock",
         "binderRpcTestService_on_trusty_mock",
-        "binderRpcTest_on_trusty_mock",
     ],
 }
 
diff --git a/libs/binder/tests/binderRpcTestTrusty.cpp b/libs/binder/tests/binderRpcTestTrusty.cpp
deleted file mode 100644
index b3bb5eb..0000000
--- a/libs/binder/tests/binderRpcTestTrusty.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "binderRpcTest"
-
-#include <android-base/stringprintf.h>
-#include <binder/RpcTransportTipcTrusty.h>
-#include <trusty-gtest.h>
-#include <trusty_ipc.h>
-
-#include "binderRpcTestFixture.h"
-
-namespace android {
-
-// Destructors need to be defined, even if pure virtual
-ProcessSession::~ProcessSession() {}
-
-class TrustyProcessSession : public ProcessSession {
-public:
-    ~TrustyProcessSession() override {}
-
-    void setCustomExitStatusCheck(std::function<void(int wstatus)> /*f*/) override {
-        LOG_ALWAYS_FATAL("setCustomExitStatusCheck() not supported");
-    }
-
-    void terminate() override { LOG_ALWAYS_FATAL("terminate() not supported"); }
-};
-
-std::string BinderRpc::PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
-    auto [type, security, clientVersion, serverVersion, singleThreaded, noKernel] = info.param;
-    auto ret = PrintToString(type) + "_clientV" + std::to_string(clientVersion) + "_serverV" +
-            std::to_string(serverVersion);
-    if (singleThreaded) {
-        ret += "_single_threaded";
-    }
-    if (noKernel) {
-        ret += "_no_kernel";
-    }
-    return ret;
-}
-
-// This creates a new process serving an interface on a certain number of
-// threads.
-std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
-        const BinderRpcOptions& options) {
-    LOG_ALWAYS_FATAL_IF(options.numIncomingConnections != 0,
-                        "Non-zero incoming connections %zu on Trusty",
-                        options.numIncomingConnections);
-
-    uint32_t clientVersion = std::get<2>(GetParam());
-    uint32_t serverVersion = std::get<3>(GetParam());
-
-    auto ret = std::make_unique<TrustyProcessSession>();
-
-    status_t status;
-    for (size_t i = 0; i < options.numSessions; i++) {
-        auto factory = android::RpcTransportCtxFactoryTipcTrusty::make();
-        auto session = android::RpcSession::make(std::move(factory));
-
-        EXPECT_TRUE(session->setProtocolVersion(clientVersion));
-        session->setMaxOutgoingThreads(options.numOutgoingConnections);
-        session->setFileDescriptorTransportMode(options.clientFileDescriptorTransportMode);
-
-        status = session->setupPreconnectedClient({}, [&]() {
-            auto port = trustyIpcPort(serverVersion);
-            int rc = connect(port.c_str(), IPC_CONNECT_WAIT_FOR_PORT);
-            LOG_ALWAYS_FATAL_IF(rc < 0, "Failed to connect to service: %d", rc);
-            return base::unique_fd(rc);
-        });
-        if (options.allowConnectFailure && status != OK) {
-            ret->sessions.clear();
-            break;
-        }
-        LOG_ALWAYS_FATAL_IF(status != OK, "Failed to connect to service: %s",
-                            statusToString(status).c_str());
-        ret->sessions.push_back({session, session->getRootObject()});
-    }
-
-    return ret;
-}
-
-INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
-                        ::testing::Combine(::testing::Values(SocketType::TIPC),
-                                           ::testing::Values(RpcSecurity::RAW),
-                                           ::testing::ValuesIn(testVersions()),
-                                           ::testing::ValuesIn(testVersions()),
-                                           ::testing::Values(false), ::testing::Values(true)),
-                        BinderRpc::PrintParamInfo);
-
-} // namespace android
-
-PORT_GTEST(BinderRpcTest, "com.android.trusty.binderRpcTest");
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index 11a22b0..2249e5c 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -386,11 +386,11 @@
     EXPECT_EQ(b, weak.promote());
 }
 
-#define EXPECT_SESSIONS(expected, iface)                  \
+#define expectSessions(expected, iface)                   \
     do {                                                  \
         int session;                                      \
         EXPECT_OK((iface)->getNumOpenSessions(&session)); \
-        EXPECT_EQ(static_cast<int>(expected), session);   \
+        EXPECT_EQ(expected, session);                     \
     } while (false)
 
 TEST_P(BinderRpc, SingleSession) {
@@ -402,9 +402,9 @@
     EXPECT_OK(session->getName(&out));
     EXPECT_EQ("aoeu", out);
 
-    EXPECT_SESSIONS(1, proc.rootIface);
+    expectSessions(1, proc.rootIface);
     session = nullptr;
-    EXPECT_SESSIONS(0, proc.rootIface);
+    expectSessions(0, proc.rootIface);
 }
 
 TEST_P(BinderRpc, ManySessions) {
@@ -413,24 +413,24 @@
     std::vector<sp<IBinderRpcSession>> sessions;
 
     for (size_t i = 0; i < 15; i++) {
-        EXPECT_SESSIONS(i, proc.rootIface);
+        expectSessions(i, proc.rootIface);
         sp<IBinderRpcSession> session;
         EXPECT_OK(proc.rootIface->openSession(std::to_string(i), &session));
         sessions.push_back(session);
     }
-    EXPECT_SESSIONS(sessions.size(), proc.rootIface);
+    expectSessions(sessions.size(), proc.rootIface);
     for (size_t i = 0; i < sessions.size(); i++) {
         std::string out;
         EXPECT_OK(sessions.at(i)->getName(&out));
         EXPECT_EQ(std::to_string(i), out);
     }
-    EXPECT_SESSIONS(sessions.size(), proc.rootIface);
+    expectSessions(sessions.size(), proc.rootIface);
 
     while (!sessions.empty()) {
         sessions.pop_back();
-        EXPECT_SESSIONS(sessions.size(), proc.rootIface);
+        expectSessions(sessions.size(), proc.rootIface);
     }
-    EXPECT_SESSIONS(0, proc.rootIface);
+    expectSessions(0, proc.rootIface);
 }
 
 TEST_P(BinderRpc, OnewayCallDoesNotWait) {
@@ -483,7 +483,7 @@
                     cb->mCv.wait_for(_l, 1s, [&] { return !cb->mValues.empty(); });
                 }
 
-                EXPECT_EQ(cb->mValues.size(), 1UL)
+                EXPECT_EQ(cb->mValues.size(), 1)
                         << "callIsOneway: " << callIsOneway
                         << " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed;
                 if (cb->mValues.empty()) continue;
diff --git a/libs/binder/trusty/binderRpcTest/manifest.json b/libs/binder/trusty/binderRpcTest/manifest.json
deleted file mode 100644
index d8b080f..0000000
--- a/libs/binder/trusty/binderRpcTest/manifest.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "uuid": "9dbe9fb8-60fd-4bdd-af86-03e95d7ad78b",
-    "app_name": "binderRpcTest",
-    "min_heap": 163840,
-    "min_stack": 16384
-}
diff --git a/libs/binder/trusty/binderRpcTest/rules.mk b/libs/binder/trusty/binderRpcTest/rules.mk
deleted file mode 100644
index ae39492..0000000
--- a/libs/binder/trusty/binderRpcTest/rules.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_DIR := $(GET_LOCAL_DIR)
-LIBBINDER_TESTS_DIR := frameworks/native/libs/binder/tests
-
-MODULE := $(LOCAL_DIR)
-
-MANIFEST := $(LOCAL_DIR)/manifest.json
-
-MODULE_SRCS += \
-	$(LIBBINDER_TESTS_DIR)/binderRpcUniversalTests.cpp \
-	$(LIBBINDER_TESTS_DIR)/binderRpcTestCommon.cpp \
-	$(LIBBINDER_TESTS_DIR)/binderRpcTestTrusty.cpp \
-
-MODULE_LIBRARY_DEPS += \
-	$(LOCAL_DIR)/aidl \
-	frameworks/native/libs/binder/trusty \
-	frameworks/native/libs/binder/trusty/ndk \
-	trusty/user/base/lib/googletest \
-	trusty/user/base/lib/libstdc++-trusty \
-
-include make/trusted_app.mk
diff --git a/libs/binder/trusty/build-config-usertests b/libs/binder/trusty/build-config-usertests
deleted file mode 100644
index d0a1fbc..0000000
--- a/libs/binder/trusty/build-config-usertests
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file lists userspace tests
-
-[
-    porttest("com.android.trusty.binderRpcTest"),
-]
diff --git a/libs/binder/trusty/include_mock/trusty-gtest.h b/libs/binder/trusty/include_mock/trusty-gtest.h
deleted file mode 100644
index 046b403..0000000
--- a/libs/binder/trusty/include_mock/trusty-gtest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#define PORT_GTEST(suite, port) \
-    int main(void) {            \
-        return 0;               \
-    }
diff --git a/libs/binder/trusty/include_mock/trusty_ipc.h b/libs/binder/trusty/include_mock/trusty_ipc.h
index db044c2..43ab84a 100644
--- a/libs/binder/trusty/include_mock/trusty_ipc.h
+++ b/libs/binder/trusty/include_mock/trusty_ipc.h
@@ -27,8 +27,6 @@
 #define IPC_PORT_ALLOW_TA_CONNECT 0x1
 #define IPC_PORT_ALLOW_NS_CONNECT 0x2
 
-#define IPC_CONNECT_WAIT_FOR_PORT 0x1
-
 #define IPC_HANDLE_POLL_HUP 0x1
 #define IPC_HANDLE_POLL_MSG 0x2
 #define IPC_HANDLE_POLL_SEND_UNBLOCKED 0x4
diff --git a/libs/binder/trusty/usertests-inc.mk b/libs/binder/trusty/usertests-inc.mk
index 1300121..2f5a7f4 100644
--- a/libs/binder/trusty/usertests-inc.mk
+++ b/libs/binder/trusty/usertests-inc.mk
@@ -14,6 +14,4 @@
 #
 
 TRUSTY_USER_TESTS += \
-	frameworks/native/libs/binder/trusty/binderRpcTest \
 	frameworks/native/libs/binder/trusty/binderRpcTest/service \
-
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index dc9f02a..5d9ee5f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3165,6 +3165,9 @@
             }
 
             dispatchEntry->resolvedFlags = motionEntry.flags;
+            if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
+                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
+            }
             if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
                 dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
             }
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 563868d..93419a1 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -289,13 +289,16 @@
             if (options.pointerIds == std::nullopt) {
                 const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
                                                         : AMOTION_EVENT_ACTION_CANCEL;
+                int32_t flags = memento.flags;
+                if (action == AMOTION_EVENT_ACTION_CANCEL) {
+                    flags |= AMOTION_EVENT_FLAG_CANCELED;
+                }
                 events.push_back(
                         std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
                                                       memento.deviceId, memento.source,
                                                       memento.displayId, memento.policyFlags,
-                                                      action, 0 /*actionButton*/, memento.flags,
-                                                      AMETA_NONE, 0 /*buttonState*/,
-                                                      MotionClassification::NONE,
+                                                      action, 0 /*actionButton*/, flags, AMETA_NONE,
+                                                      0 /*buttonState*/, MotionClassification::NONE,
                                                       AMOTION_EVENT_EDGE_FLAG_NONE,
                                                       memento.xPrecision, memento.yPrecision,
                                                       memento.xCursorPosition,
@@ -388,11 +391,15 @@
     if (canceledPointerIndices.size() == memento.pointerCount) {
         const int32_t action =
                 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
+        int32_t flags = memento.flags;
+        if (action == AMOTION_EVENT_ACTION_CANCEL) {
+            flags |= AMOTION_EVENT_FLAG_CANCELED;
+        }
         events.push_back(
                 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
                                               memento.source, memento.displayId,
                                               memento.policyFlags, action, 0 /*actionButton*/,
-                                              memento.flags, AMETA_NONE, 0 /*buttonState*/,
+                                              flags, AMETA_NONE, 0 /*buttonState*/,
                                               MotionClassification::NONE,
                                               AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
                                               memento.yPrecision, memento.xCursorPosition,
@@ -400,7 +407,7 @@
                                               memento.pointerCount, memento.pointerProperties,
                                               memento.pointerCoords));
     } else {
-        // If we aren't canceling all pointers, we need to generated ACTION_POINTER_UP with
+        // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
         // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
         // previously canceled pointers from PointerProperties and PointerCoords, and update
         // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3abe43a..dfe3d16 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -58,6 +58,7 @@
 static constexpr int32_t SECOND_DISPLAY_ID = 1;
 
 static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
+static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
 static constexpr int32_t POINTER_1_DOWN =
         AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
 static constexpr int32_t POINTER_2_DOWN =
@@ -139,12 +140,20 @@
     return arg.getDownTime() == downTime;
 }
 
+MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
+    return arg.getDisplayId() == displayId;
+}
+
 MATCHER_P(WithSource, source, "InputEvent with specified source") {
     *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
                      << inputEventSourceToString(arg.getSource());
     return arg.getSource() == source;
 }
 
+MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
+    return arg.getFlags() == flags;
+}
+
 MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
     if (arg.getPointerCount() != 1) {
         *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
@@ -944,6 +953,28 @@
         }
     }
 
+    MotionEvent* consumeMotion() {
+        InputEvent* event = consume();
+
+        if (event == nullptr) {
+            ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
+            return nullptr;
+        }
+
+        if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
+            ADD_FAILURE() << mName << " expected a MotionEvent, got "
+                          << inputEventTypeToString(event->getType()) << " event";
+            return nullptr;
+        }
+        return static_cast<MotionEvent*>(event);
+    }
+
+    void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
+        MotionEvent* motionEvent = consumeMotion();
+        ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
+        ASSERT_THAT(*motionEvent, matcher);
+    }
+
     void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
         InputEvent* event = consume();
         ASSERT_NE(nullptr, event) << mName.c_str()
@@ -1196,14 +1227,14 @@
 
     void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
                              int32_t expectedFlags = 0) {
-        consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
-                     expectedFlags);
+        consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
+                                 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
     }
 
     void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
                            int32_t expectedFlags = 0) {
-        consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
-                     expectedFlags);
+        consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+                                 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
     }
 
     void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
@@ -2546,8 +2577,8 @@
     // on the app side.
     NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
     mDispatcher->notifyDeviceReset(&args);
-    window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
-                         0 /*expectedFlags*/);
+    window->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
 }
 
 TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
@@ -3544,8 +3575,10 @@
     }
 
     void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
-        mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
-                                     expectedDisplayId, expectedFlags);
+        mInputReceiver->consumeMotionEvent(
+                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
+                      WithDisplayId(expectedDisplayId),
+                      WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
     }
 
     void consumeMotionPointerDown(int32_t pointerIdx) {
@@ -5109,8 +5142,8 @@
     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
 
     mWindow->finishEvent(*sequenceNum);
-    mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
-                          ADISPLAY_ID_DEFAULT, 0 /*flags*/);
+    mWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
 }
@@ -5277,8 +5310,8 @@
     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
 
     spy->finishEvent(*sequenceNum);
-    spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
-                      0 /*flags*/);
+    spy->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
 }
@@ -5400,8 +5433,8 @@
     mFakePolicy->assertNotifyAnrWasNotCalled();
     // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
     mWindow->consumeMotionDown();
-    mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
-                          ADISPLAY_ID_DEFAULT, 0 /*flags*/);
+    mWindow->consumeMotionEvent(
+            AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
     mWindow->assertNoEvents();
     mDispatcher->waitForIdle();
     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
@@ -7768,7 +7801,7 @@
     ASSERT_EQ(InputEventInjectionResult::FAILED,
               injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
                                 InputEventInjectionSync::WAIT_FOR_RESULT))
-            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+            << "Inject motion event should return InputEventInjectionResult::FAILED";
 
     spy->assertNoEvents();
     window->assertNoEvents();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 1d27cfc..c5b3e14 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -929,17 +929,38 @@
                                          RefreshRateOrder refreshRateOrder,
                                          std::optional<DisplayModeId> preferredDisplayModeOpt) const
         -> FrameRateRanking {
+    using fps_approx_ops::operator<;
     const char* const whence = __func__;
+
+    // find the highest frame rate for each display mode
+    ftl::SmallMap<DisplayModeId, Fps, 8> maxRenderRateForMode;
+    const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
+    if (ascending) {
+        // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
+        //  use a lower frame rate when we want Ascending frame rates.
+        for (const auto& frameRateMode : mPrimaryFrameRates) {
+            if (anchorGroupOpt && frameRateMode.modePtr->getGroup() != anchorGroupOpt) {
+                continue;
+            }
+
+            const auto [iter, _] = maxRenderRateForMode.try_emplace(frameRateMode.modePtr->getId(),
+                                                                    frameRateMode.fps);
+            if (iter->second < frameRateMode.fps) {
+                iter->second = frameRateMode.fps;
+            }
+        }
+    }
+
     std::deque<ScoredFrameRate> ranking;
     const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) {
-        using fps_approx_ops::operator<;
         const auto& modePtr = frameRateMode.modePtr;
         if (anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) {
             return;
         }
 
         const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
-        if (ascending && frameRateMode.fps < getMinRefreshRateByPolicyLocked()->getFps()) {
+        const auto id = frameRateMode.modePtr->getId();
+        if (ascending && frameRateMode.fps < *maxRenderRateForMode.get(id)) {
             // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
             //  use a lower frame rate when we want Ascending frame rates.
             return;
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index 5fddda5..f4d052d 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -1165,7 +1165,7 @@
             case Config::FrameRateOverride::AppOverride:
                 return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}};
             case Config::FrameRateOverride::Enabled:
-                return {{30_Hz, kMode30}, {45_Hz, kMode90}, {60_Hz, kMode60}, {90_Hz, kMode90}};
+                return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}};
         }
     }();
     ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
@@ -1197,7 +1197,7 @@
             case Config::FrameRateOverride::AppOverride:
                 return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}};
             case Config::FrameRateOverride::Enabled:
-                return {{30_Hz, kMode30}, {45_Hz, kMode90}, {60_Hz, kMode60}, {90_Hz, kMode90}};
+                return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}};
         }
     }();
     ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
@@ -2983,5 +2983,24 @@
     EXPECT_FRAME_RATE_MODE(kMode60, 60_Hz, selector.getBestScoredFrameRate(layers).frameRateMode);
 }
 
+TEST_P(RefreshRateSelectorTest, frameRateIsCappedByPolicy) {
+    if (GetParam() != Config::FrameRateOverride::Enabled) {
+        return;
+    }
+
+    auto selector = createSelector(kModes_60_90, kModeId60);
+
+    constexpr FpsRanges kCappedAt30 = {{60_Hz, 90_Hz}, {30_Hz, 30_Hz}};
+
+    EXPECT_EQ(SetPolicyResult::Changed,
+              selector.setDisplayManagerPolicy(
+                      {DisplayModeId(kModeId60), kCappedAt30, kCappedAt30}));
+
+    std::vector<LayerRequirement> layers = {{.weight = 1.f}};
+    layers[0].name = "Test layer";
+    layers[0].vote = LayerVoteType::Min;
+    EXPECT_FRAME_RATE_MODE(kMode60, 30_Hz, selector.getBestScoredFrameRate(layers).frameRateMode);
+}
+
 } // namespace
 } // namespace android::scheduler