Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3087211d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Reland "Set down time when event slips into Wallpaper" - try 2" into main

parents 0335b360 fe34698f
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -2683,7 +2683,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio


                // Check if the wallpaper window should deliver the corresponding event.
                // Check if the wallpaper window should deliver the corresponding event.
                slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
                slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
                                   tempTouchState, entry.deviceId, pointer, targets);
                                   tempTouchState, entry, targets);
                tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
                tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
                                                               oldTouchedWindowHandle);
                                                               oldTouchedWindowHandle);
            }
            }
@@ -7100,9 +7100,11 @@ void InputDispatcher::setMonitorDispatchingTimeoutForTest(std::chrono::nanosecon
void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                                         const sp<WindowInfoHandle>& oldWindowHandle,
                                         const sp<WindowInfoHandle>& oldWindowHandle,
                                         const sp<WindowInfoHandle>& newWindowHandle,
                                         const sp<WindowInfoHandle>& newWindowHandle,
                                         TouchState& state, DeviceId deviceId,
                                         TouchState& state, const MotionEntry& entry,
                                         const PointerProperties& pointerProperties,
                                         std::vector<InputTarget>& targets) const {
                                         std::vector<InputTarget>& targets) const {
    LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry;
    const DeviceId deviceId = entry.deviceId;
    const PointerProperties& pointerProperties = entry.pointerProperties[0];
    std::vector<PointerProperties> pointers{pointerProperties};
    std::vector<PointerProperties> pointers{pointerProperties};
    const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
    const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -7129,7 +7131,7 @@ void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFl
        state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
        state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
                                InputTarget::Flags::WINDOW_IS_OBSCURED |
                                InputTarget::Flags::WINDOW_IS_OBSCURED |
                                        InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
                                        InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
                                deviceId, pointers);
                                deviceId, pointers, entry.eventTime);
    }
    }
}
}


+14 −2
Original line number Original line Diff line number Diff line
@@ -709,11 +709,23 @@ private:


    sp<InputReporterInterface> mReporter;
    sp<InputReporterInterface> mReporter;


    /**
     * Slip the wallpaper touch if necessary.
     *
     * @param targetFlags the target flags
     * @param oldWindowHandle the old window that the touch slipped out of
     * @param newWindowHandle the new window that the touch is slipping into
     * @param state the current touch state. This will be updated if necessary to reflect the new
     *        windows that are receiving touch.
     * @param deviceId the device id of the current motion being processed
     * @param pointerProperties the pointer properties of the current motion being processed
     * @param targets the current targets to add the walpaper ones to
     * @param eventTime the new downTime for the wallpaper target
     */
    void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
    void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                            const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                            const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                            const sp<android::gui::WindowInfoHandle>& newWindowHandle,
                            const sp<android::gui::WindowInfoHandle>& newWindowHandle,
                            TouchState& state, DeviceId deviceId,
                            TouchState& state, const MotionEntry& entry,
                            const PointerProperties& pointerProperties,
                            std::vector<InputTarget>& targets) const REQUIRES(mLock);
                            std::vector<InputTarget>& targets) const REQUIRES(mLock);
    void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
    void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
                                ftl::Flags<InputTarget::Flags> newTargetFlags,
                                ftl::Flags<InputTarget::Flags> newTargetFlags,
+1 −1
Original line number Original line Diff line number Diff line
@@ -47,7 +47,7 @@ struct TouchState {
            const sp<android::gui::WindowInfoHandle>& windowHandle,
            const sp<android::gui::WindowInfoHandle>& windowHandle,
            InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
            InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
            DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers,
            DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers,
            std::optional<nsecs_t> firstDownTimeInTarget = std::nullopt);
            std::optional<nsecs_t> firstDownTimeInTarget);
    void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
    void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
                                    DeviceId deviceId, const PointerProperties& pointer);
                                    DeviceId deviceId, const PointerProperties& pointer);
    void removeHoveringPointer(DeviceId deviceId, int32_t pointerId);
    void removeHoveringPointer(DeviceId deviceId, int32_t pointerId);
+267 −0
Original line number Original line Diff line number Diff line
@@ -5710,6 +5710,273 @@ TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
    rightWindow->assertNoEvents();
    rightWindow->assertNoEvents();
}
}
/**
 * Three windows:
 * 1) A window on the left, with flag dup_to_wallpaper
 * 2) A window on the right, with flag slippery
 * 3) A wallpaper window  under the left window
 * When touch slips from right window to left, the wallpaper should receive a similar slippery
 * enter event. Later on, when another device becomes active, the wallpaper should receive
 * consistent streams from the new device, and also from the old device.
 * This test attempts to reproduce a crash in the dispatcher where the wallpaper target's downTime
 * was not getting set during slippery entrance.
 */
TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch) {
    SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
    std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
    std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
    std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> wallpaper =
            sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
                                       ui::LogicalDisplayId::DEFAULT);
    wallpaper->setIsWallpaper(true);
    wallpaper->setPreventSplitting(true);
    wallpaper->setTouchable(false);
    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
                                                                 ui::LogicalDisplayId::DEFAULT);
    leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
    leftWindow->setDupTouchToWallpaper(true);
    sp<FakeWindowHandle> rightWindow =
            sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
                                       ui::LogicalDisplayId::DEFAULT);
    rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
    rightWindow->setSlippery(true);
    rightWindow->setWatchOutsideTouch(true);
    rightWindow->setTrustedOverlay(true);
    mDispatcher->onWindowInfosChanged(
            {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
    const DeviceId deviceA = 3;
    const DeviceId deviceB = 9;
    // First finger from device A into right window
    NotifyMotionArgs deviceADownArgs =
            MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
                    .deviceId(deviceA)
                    .build();
    mDispatcher->notifyMotion(deviceADownArgs);
    rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    // Move the finger of device A from right window into left window. It should slip.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
    wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    // Finger from device B down into left window
    NotifyMotionArgs deviceBDownArgs =
            MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
                    .deviceId(deviceB)
                    .build();
    mDispatcher->notifyMotion(deviceBDownArgs);
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
    rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
    // Move finger from device B, still keeping it in the left window
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
                                      .deviceId(deviceB)
                                      .downTime(deviceBDownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
    // Lift the finger from device B
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
                                      .deviceId(deviceB)
                                      .downTime(deviceBDownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
    // Move the finger of device A, keeping it in the left window
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
    // Second finger down from device A, into the right window. It should be split into:
    // MOVE for the left window (due to existing implementation) + a DOWN into the right window
    // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    auto firstFingerMoveFromDeviceA = AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE),
                                            WithPointerCount(1), WithPointerId(0, 0));
    leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
    wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
    rightWindow->consumeMotionEvent(
            AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
    // Lift up the second finger.
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
    leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
    wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
    rightWindow->assertNoEvents();
}
/**
 * Same test as above, but with enable_multi_device_same_window_stream flag set to false.
 */
TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy) {
    SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
    std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
    std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
    std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> wallpaper =
            sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
                                       ui::LogicalDisplayId::DEFAULT);
    wallpaper->setIsWallpaper(true);
    wallpaper->setPreventSplitting(true);
    wallpaper->setTouchable(false);
    sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
                                                                 ui::LogicalDisplayId::DEFAULT);
    leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
    leftWindow->setDupTouchToWallpaper(true);
    sp<FakeWindowHandle> rightWindow =
            sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
                                       ui::LogicalDisplayId::DEFAULT);
    rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
    rightWindow->setSlippery(true);
    rightWindow->setWatchOutsideTouch(true);
    rightWindow->setTrustedOverlay(true);
    mDispatcher->onWindowInfosChanged(
            {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
    const DeviceId deviceA = 3;
    const DeviceId deviceB = 9;
    // First finger from device A into right window
    NotifyMotionArgs deviceADownArgs =
            MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
                    .deviceId(deviceA)
                    .build();
    mDispatcher->notifyMotion(deviceADownArgs);
    rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    // Move the finger of device A from right window into left window. It should slip.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
    wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    // Finger from device B down into left window
    NotifyMotionArgs deviceBDownArgs =
            MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
                    .deviceId(deviceB)
                    .build();
    mDispatcher->notifyMotion(deviceBDownArgs);
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
    rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
    // Move finger from device B, still keeping it in the left window
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
                                      .deviceId(deviceB)
                                      .downTime(deviceBDownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
    // Lift the finger from device B
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
                                      .deviceId(deviceB)
                                      .downTime(deviceBDownArgs.downTime)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
    wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
    // Move the finger of device A, keeping it in the left window
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    // This device was already canceled, so MOVE events will not be arriving to the windows from it.
    // Second finger down from device A, into the right window. It should be split into:
    // MOVE for the left window (due to existing implementation) + a DOWN into the right window
    // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    rightWindow->consumeMotionEvent(
            AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
    // Lift up the second finger.
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
                                      .deviceId(deviceA)
                                      .downTime(deviceADownArgs.downTime)
                                      .build());
    rightWindow->assertNoEvents();
}
/**
/**
 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
 * down event to the right window. Device B sends a down event to the left window, and then a
 * down event to the right window. Device B sends a down event to the left window, and then a