Merge "Fix captureDisplay when the display is rotated" into udc-qpr-dev
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 80ac2a9..732ca36 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -120,6 +120,16 @@
     return base::Join(soNames, ':');
 }
 
+static sp<IGpuService> getGpuService() {
+    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+    if (!binder) {
+        ALOGE("Failed to get gpu service");
+        return nullptr;
+    }
+
+    return interface_cast<IGpuService>(binder);
+}
+
 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
     static GraphicsEnv env;
     return env;
@@ -142,6 +152,10 @@
     return appDebuggable || platformDebuggable;
 }
 
+/**
+ * APIs for updatable graphics drivers
+ */
+
 void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string& path,
                                                  const std::string& sphalLibraries) {
     if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
@@ -156,6 +170,108 @@
     mSphalLibraries = sphalLibraries;
 }
 
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+                                            android_namespace_t* vndkNamespace,
+                                            const std::string& sharedSphalLibraries) {
+    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+    if (llndkLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
+        ALOGE("Failed to link default namespace[%s]", dlerror());
+        return false;
+    }
+
+    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+    if (vndkspLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+        ALOGE("Failed to link vndk namespace[%s]", dlerror());
+        return false;
+    }
+
+    if (sharedSphalLibraries.empty()) {
+        return true;
+    }
+
+    // Make additional libraries in sphal to be accessible
+    auto sphalNamespace = android_get_exported_namespace("sphal");
+    if (!sphalNamespace) {
+        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+              sharedSphalLibraries.c_str());
+        return false;
+    }
+
+    if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
+        ALOGE("Failed to link sphal namespace[%s]", dlerror());
+        return false;
+    }
+
+    return true;
+}
+
+android_namespace_t* GraphicsEnv::getDriverNamespace() {
+    std::lock_guard<std::mutex> lock(mNamespaceMutex);
+
+    if (mDriverNamespace) {
+        return mDriverNamespace;
+    }
+
+    if (mDriverPath.empty()) {
+        // For an application process, driver path is empty means this application is not opted in
+        // to use updatable driver. Application process doesn't have the ability to set up
+        // environment variables and hence before `getenv` call will return.
+        // For a process that is not an application process, if it's run from an environment,
+        // for example shell, where environment variables can be set, then it can opt into using
+        // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
+        // driver will be used currently.
+        // TODO(b/159240322) Support the production updatable driver.
+        const char* id = getenv("UPDATABLE_GFX_DRIVER");
+        if (id == nullptr || std::strcmp(id, "1") != 0) {
+            return nullptr;
+        }
+        const sp<IGpuService> gpuService = getGpuService();
+        if (!gpuService) {
+            return nullptr;
+        }
+        mDriverPath = gpuService->getUpdatableDriverPath();
+        if (mDriverPath.empty()) {
+            return nullptr;
+        }
+        mDriverPath.append(UPDATABLE_DRIVER_ABI);
+        ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
+    }
+
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
+
+    mDriverNamespace = android_create_namespace("updatable gfx driver",
+                                                mDriverPath.c_str(), // ld_library_path
+                                                mDriverPath.c_str(), // default_library_path
+                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                nullptr, // permitted_when_isolated_path
+                                                nullptr);
+
+    if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
+        mDriverNamespace = nullptr;
+    }
+
+    return mDriverNamespace;
+}
+
+std::string GraphicsEnv::getDriverPath() const {
+    return mDriverPath;
+}
+
+/**
+ * APIs for GpuStats
+ */
+
 void GraphicsEnv::hintActivityLaunch() {
     ATRACE_CALL();
 
@@ -310,16 +426,6 @@
                         extensionHashes, numStats);
 }
 
-static sp<IGpuService> getGpuService() {
-    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
-    if (!binder) {
-        ALOGE("Failed to get gpu service");
-        return nullptr;
-    }
-
-    return interface_cast<IGpuService>(binder);
-}
-
 bool GraphicsEnv::readyToSendGpuStatsLocked() {
     // Only send stats for processes having at least one activity launched and that process doesn't
     // skip the GraphicsEnvironment setup.
@@ -392,6 +498,10 @@
     return true;
 }
 
+/**
+ * APIs for ANGLE
+ */
+
 bool GraphicsEnv::shouldUseAngle() {
     // Make sure we are init'ed
     if (mPackageName.empty()) {
@@ -423,30 +533,15 @@
     mAnglePath = std::move(path);
     ALOGV("setting app package name to '%s'", packageName.c_str());
     mPackageName = std::move(packageName);
-    if (path == "system") {
+    if (mAnglePath == "system") {
         mShouldUseSystemAngle = true;
     }
-    if (!path.empty()) {
+    if (!mAnglePath.empty()) {
         mShouldUseAngle = true;
     }
     mShouldUseNativeDriver = shouldUseNativeDriver;
 }
 
-void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
-                                const std::string& layerPaths) {
-    if (mLayerPaths.empty()) {
-        mLayerPaths = layerPaths;
-        mAppNamespace = appNamespace;
-    } else {
-        ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
-              layerPaths.c_str(), appNamespace);
-    }
-}
-
-NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
-    return mAppNamespace;
-}
-
 std::string& GraphicsEnv::getPackageName() {
     return mPackageName;
 }
@@ -455,124 +550,6 @@
     return mAngleEglFeatures;
 }
 
-const std::string& GraphicsEnv::getLayerPaths() {
-    return mLayerPaths;
-}
-
-const std::string& GraphicsEnv::getDebugLayers() {
-    return mDebugLayers;
-}
-
-const std::string& GraphicsEnv::getDebugLayersGLES() {
-    return mDebugLayersGLES;
-}
-
-void GraphicsEnv::setDebugLayers(const std::string& layers) {
-    mDebugLayers = layers;
-}
-
-void GraphicsEnv::setDebugLayersGLES(const std::string& layers) {
-    mDebugLayersGLES = layers;
-}
-
-// Return true if all the required libraries from vndk and sphal namespace are
-// linked to the driver namespace correctly.
-bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
-                                            android_namespace_t* vndkNamespace,
-                                            const std::string& sharedSphalLibraries) {
-    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
-    if (llndkLibraries.empty()) {
-        return false;
-    }
-    if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
-        ALOGE("Failed to link default namespace[%s]", dlerror());
-        return false;
-    }
-
-    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
-    if (vndkspLibraries.empty()) {
-        return false;
-    }
-    if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
-        ALOGE("Failed to link vndk namespace[%s]", dlerror());
-        return false;
-    }
-
-    if (sharedSphalLibraries.empty()) {
-        return true;
-    }
-
-    // Make additional libraries in sphal to be accessible
-    auto sphalNamespace = android_get_exported_namespace("sphal");
-    if (!sphalNamespace) {
-        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
-              sharedSphalLibraries.c_str());
-        return false;
-    }
-
-    if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
-        ALOGE("Failed to link sphal namespace[%s]", dlerror());
-        return false;
-    }
-
-    return true;
-}
-
-android_namespace_t* GraphicsEnv::getDriverNamespace() {
-    std::lock_guard<std::mutex> lock(mNamespaceMutex);
-
-    if (mDriverNamespace) {
-        return mDriverNamespace;
-    }
-
-    if (mDriverPath.empty()) {
-        // For an application process, driver path is empty means this application is not opted in
-        // to use updatable driver. Application process doesn't have the ability to set up
-        // environment variables and hence before `getenv` call will return.
-        // For a process that is not an application process, if it's run from an environment,
-        // for example shell, where environment variables can be set, then it can opt into using
-        // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
-        // driver will be used currently.
-        // TODO(b/159240322) Support the production updatable driver.
-        const char* id = getenv("UPDATABLE_GFX_DRIVER");
-        if (id == nullptr || std::strcmp(id, "1")) {
-            return nullptr;
-        }
-        const sp<IGpuService> gpuService = getGpuService();
-        if (!gpuService) {
-            return nullptr;
-        }
-        mDriverPath = gpuService->getUpdatableDriverPath();
-        if (mDriverPath.empty()) {
-            return nullptr;
-        }
-        mDriverPath.append(UPDATABLE_DRIVER_ABI);
-        ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
-    }
-
-    auto vndkNamespace = android_get_exported_namespace("vndk");
-    if (!vndkNamespace) {
-        return nullptr;
-    }
-
-    mDriverNamespace = android_create_namespace("updatable gfx driver",
-                                                mDriverPath.c_str(), // ld_library_path
-                                                mDriverPath.c_str(), // default_library_path
-                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
-                                                nullptr, // permitted_when_isolated_path
-                                                nullptr);
-
-    if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
-        mDriverNamespace = nullptr;
-    }
-
-    return mDriverNamespace;
-}
-
-std::string GraphicsEnv::getDriverPath() const {
-    return mDriverPath;
-}
-
 android_namespace_t* GraphicsEnv::getAngleNamespace() {
     std::lock_guard<std::mutex> lock(mNamespaceMutex);
 
@@ -643,4 +620,43 @@
     return mShouldUseNativeDriver;
 }
 
+/**
+ * APIs for debuggable layers
+ */
+
+void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
+                                const std::string& layerPaths) {
+    if (mLayerPaths.empty()) {
+        mLayerPaths = layerPaths;
+        mAppNamespace = appNamespace;
+    } else {
+        ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
+              layerPaths.c_str(), appNamespace);
+    }
+}
+
+NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
+    return mAppNamespace;
+}
+
+const std::string& GraphicsEnv::getLayerPaths() {
+    return mLayerPaths;
+}
+
+const std::string& GraphicsEnv::getDebugLayers() {
+    return mDebugLayers;
+}
+
+const std::string& GraphicsEnv::getDebugLayersGLES() {
+    return mDebugLayersGLES;
+}
+
+void GraphicsEnv::setDebugLayers(const std::string& layers) {
+    mDebugLayers = layers;
+}
+
+void GraphicsEnv::setDebugLayersGLES(const std::string& layers) {
+    mDebugLayersGLES = layers;
+}
+
 } // namespace android
diff --git a/services/inputflinger/InputDeviceMetricsCollector.cpp b/services/inputflinger/InputDeviceMetricsCollector.cpp
index 89e37db..7c99a1c 100644
--- a/services/inputflinger/InputDeviceMetricsCollector.cpp
+++ b/services/inputflinger/InputDeviceMetricsCollector.cpp
@@ -31,7 +31,7 @@
 
 namespace {
 
-constexpr nanoseconds DEFAULT_USAGE_SESSION_TIMEOUT = std::chrono::seconds(5);
+constexpr nanoseconds DEFAULT_USAGE_SESSION_TIMEOUT = std::chrono::minutes(2);
 
 /**
  * Log debug messages about metrics events logged to statsd.
@@ -39,6 +39,8 @@
  */
 const bool DEBUG = __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO);
 
+constexpr size_t INTERACTIONS_QUEUE_CAPACITY = 500;
+
 int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) {
     // When adding cases to this switch, also add them to the copy of this method in
     // TouchpadInputMapper.cpp.
@@ -201,7 +203,10 @@
 InputDeviceMetricsCollector::InputDeviceMetricsCollector(InputListenerInterface& listener,
                                                          InputDeviceMetricsLogger& logger,
                                                          nanoseconds usageSessionTimeout)
-      : mNextListener(listener), mLogger(logger), mUsageSessionTimeout(usageSessionTimeout) {}
+      : mNextListener(listener),
+        mLogger(logger),
+        mUsageSessionTimeout(usageSessionTimeout),
+        mInteractionsQueue(INTERACTIONS_QUEUE_CAPACITY) {}
 
 void InputDeviceMetricsCollector::notifyInputDevicesChanged(
         const NotifyInputDevicesChangedArgs& args) {
@@ -262,6 +267,9 @@
 
 void InputDeviceMetricsCollector::notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                                           const std::set<Uid>& uids) {
+    if (isIgnoredInputDeviceId(deviceId)) {
+        return;
+    }
     mInteractionsQueue.push(DeviceId{deviceId}, timestamp, uids);
 }
 
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 1a9f47d..37b3187 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -34,7 +34,7 @@
 namespace android {
 
 static const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
-        sysprop::InputProperties::enable_input_device_usage_metrics().value_or(false);
+        sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
 
 using gui::FocusRequest;
 
diff --git a/services/inputflinger/SyncQueue.h b/services/inputflinger/SyncQueue.h
index 62efd55..84ccace 100644
--- a/services/inputflinger/SyncQueue.h
+++ b/services/inputflinger/SyncQueue.h
@@ -27,6 +27,10 @@
 template <class T>
 class SyncQueue {
 public:
+    SyncQueue() = default;
+
+    SyncQueue(size_t capacity) : mCapacity(capacity) {}
+
     /** Retrieve and remove the oldest object. Returns std::nullopt if the queue is empty. */
     std::optional<T> pop() {
         std::scoped_lock lock(mLock);
@@ -38,14 +42,23 @@
         return t;
     };
 
-    /** Add a new object to the queue. */
+    /**
+     * Add a new object to the queue.
+     * Return true if an element was successfully added.
+     * Return false if the queue is full.
+     */
     template <class... Args>
-    void push(Args&&... args) {
+    bool push(Args&&... args) {
         std::scoped_lock lock(mLock);
+        if (mCapacity && mQueue.size() == mCapacity) {
+            return false;
+        }
         mQueue.emplace_back(args...);
+        return true;
     };
 
 private:
+    const std::optional<size_t> mCapacity;
     std::mutex mLock;
     std::list<T> mQueue GUARDED_BY(mLock);
 };
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 61a9f82..65bd05b 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2257,7 +2257,6 @@
         const bool anotherDeviceIsActive =
                 oldActiveDevices.count(entry.deviceId) == 0 && !oldActiveDevices.empty();
         switchedDevice |= anotherDeviceIsActive;
-        switchedDevice |= oldState->source != entry.source;
     }
 
     const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
@@ -2287,7 +2286,6 @@
     if (newGesture) {
         // If a new gesture is starting, clear the touch state completely.
         tempTouchState.reset();
-        tempTouchState.source = entry.source;
         isSplit = false;
     } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
         ALOGI("Dropping move event because a pointer for a different device is already active "
@@ -2694,7 +2692,6 @@
         }
         if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
             maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-            tempTouchState.source = entry.source;
         }
     } else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
         // Pointer went up.
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index dcbb366..dadfdc1 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -277,7 +277,6 @@
 
 std::string TouchState::dump() const {
     std::string out;
-    out += StringPrintf("source=%s\n", inputEventSourceToString(source).c_str());
     if (!windows.empty()) {
         out += "  Windows:\n";
         for (size_t i = 0; i < windows.size(); i++) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 1bda0fb..9f29a4a 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -29,9 +29,6 @@
 namespace inputdispatcher {
 
 struct TouchState {
-    // source of the device that is current down, others are rejected
-    uint32_t source = 0;
-
     std::vector<TouchedWindow> windows;
 
     TouchState() = default;
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 1088821..e826341 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -239,6 +239,11 @@
         out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0,
                                      newButtonState, /* pointerCount= */ 1, mFingerProps.data(),
                                      &coords, xCursorPosition, yCursorPosition));
+        // Send a HOVER_MOVE to tell the application that the mouse is hovering again.
+        out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_HOVER_MOVE,
+                                     /*actionButton=*/0, newButtonState, /*pointerCount=*/1,
+                                     mFingerProps.data(), &coords, xCursorPosition,
+                                     yCursorPosition));
     }
     mButtonState = newButtonState;
     return out;
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index a3994f0..482a266 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -169,7 +169,7 @@
                            /* down= */ GESTURES_BUTTON_NONE, /* up= */ GESTURES_BUTTON_RIGHT,
                            /* is_tap= */ false);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, rightUpGesture);
-    ASSERT_EQ(2u, args.size());
+    ASSERT_EQ(3u, args.size());
 
     ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
@@ -181,6 +181,10 @@
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0),
                       WithCoords(POINTER_X, POINTER_Y),
                       WithToolType(ToolType::FINGER)));
+    args.pop_front();
+    ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
+                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithButtonState(0),
+                      WithCoords(POINTER_X, POINTER_Y), WithToolType(ToolType::FINGER)));
 }
 
 TEST_F(GestureConverterTest, DragWithButton) {
@@ -225,7 +229,7 @@
                       /* down= */ GESTURES_BUTTON_NONE, /* up= */ GESTURES_BUTTON_LEFT,
                       /* is_tap= */ false);
     args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, upGesture);
-    ASSERT_EQ(2u, args.size());
+    ASSERT_EQ(3u, args.size());
 
     ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
@@ -237,6 +241,10 @@
                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0),
                       WithCoords(POINTER_X - 5, POINTER_Y + 10),
                       WithToolType(ToolType::FINGER)));
+    args.pop_front();
+    ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
+                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithButtonState(0),
+                      WithCoords(POINTER_X - 5, POINTER_Y + 10), WithToolType(ToolType::FINGER)));
 }
 
 TEST_F(GestureConverterTest, Scroll) {
diff --git a/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp b/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
index 0aa5e23..484e7d6 100644
--- a/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
+++ b/services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp
@@ -421,6 +421,7 @@
         // Device was used.
         mMetricsCollector.notifyMotion(generateMotionArgs(ignoredDeviceId));
         mTestListener.assertNotifyMotionWasCalled();
+        mMetricsCollector.notifyDeviceInteraction(ignoredDeviceId, TIME.count(), uids({0, 1, 2}));
         ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged());
 
         // Device was used again after the usage timeout expired, but we still don't log usage.
diff --git a/services/inputflinger/tests/SyncQueue_test.cpp b/services/inputflinger/tests/SyncQueue_test.cpp
index af2f961..b57ccc2 100644
--- a/services/inputflinger/tests/SyncQueue_test.cpp
+++ b/services/inputflinger/tests/SyncQueue_test.cpp
@@ -50,6 +50,18 @@
     }
 }
 
+// Make sure the queue has strict capacity limits.
+TEST(SyncQueueTest, QueueReachesCapacity) {
+    constexpr size_t capacity = 3;
+    SyncQueue<int> queue(capacity);
+
+    // First 3 elements should be added successfully
+    ASSERT_TRUE(queue.push(1));
+    ASSERT_TRUE(queue.push(2));
+    ASSERT_TRUE(queue.push(3));
+    ASSERT_FALSE(queue.push(4)) << "Queue should reach capacity at size " << capacity;
+}
+
 TEST(SyncQueueTest, AllowsMultipleThreads) {
     SyncQueue<int> queue;
 
diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
index 92cd462..02abf9f 100644
--- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp
+++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
@@ -139,7 +139,8 @@
                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)),
                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
-                            VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
+                            VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
+                            VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
 
     // Liftoff
     args.clear();