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

Commit 7fa3483d authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge changes I111361f7,Ic4979b91,Ic289d772 into tm-qpr-dev

* changes:
  Reset the touch state when the active viewport is disabled
  Fix issues with InputMapper tests
  Fix spot not disappear when display id changed
parents ed1fc29d f670dad1
Loading
Loading
Loading
Loading
+24 −22
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);

// --- Static Definitions ---

static const DisplayViewport kUninitializedViewport;

template <typename T>
inline static void swap(T& a, T& b) {
    T temp = a;
@@ -390,6 +392,10 @@ void TouchInputMapper::configure(nsecs_t when, const InputReaderConfiguration* c
    }

    if (changes && resetNeeded) {
        // If the device needs to be reset, cancel any ongoing gestures and reset the state.
        cancelTouch(when, when);
        reset(when);

        // Send reset, unless this is the first time the device has been configured,
        // in which case the reader will call reset itself after all mappers are ready.
        NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
@@ -877,7 +883,7 @@ void TouchInputMapper::initializeOrientedRanges() {
}

void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) {
    DeviceMode oldDeviceMode = mDeviceMode;
    const DeviceMode oldDeviceMode = mDeviceMode;

    resolveExternalStylusPresence();

@@ -906,42 +912,37 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
        mDeviceMode = DeviceMode::UNSCALED;
    }

    // Ensure we have valid X and Y axes.
    const std::optional<DisplayViewport> newViewportOpt = findViewport();

    // Ensure the device is valid and can be used.
    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
              "The device will be inoperable.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    // Get associated display dimensions.
    std::optional<DisplayViewport> newViewport = findViewport();
    if (!newViewport) {
    } else if (!newViewportOpt) {
        ALOGI("Touch device '%s' could not query the properties of its associated "
              "display.  The device will be inoperable until the display size "
              "becomes available.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    if (!newViewport->isActive) {
    } else if (!newViewportOpt->isActive) {
        ALOGI("Disabling %s (device %i) because the associated viewport is not active",
              getDeviceName().c_str(), getDeviceId());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    // Raw width and height in the natural orientation.
    const int32_t rawWidth = mRawPointerAxes.getRawWidth();
    const int32_t rawHeight = mRawPointerAxes.getRawHeight();

    const bool viewportChanged = mViewport != *newViewport;
    const DisplayViewport& newViewport = newViewportOpt.value_or(kUninitializedViewport);
    const bool viewportChanged = mViewport != newViewport;
    bool skipViewportUpdate = false;
    if (viewportChanged) {
        const bool viewportOrientationChanged = mViewport.orientation != newViewport->orientation;
        mViewport = *newViewport;
        const bool viewportOrientationChanged = mViewport.orientation != newViewport.orientation;
        const bool viewportDisplayIdChanged = mViewport.displayId != newViewport.displayId;
        mViewport = newViewport;

        if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) {
            // Convert rotated viewport to the natural orientation.
@@ -1016,8 +1017,9 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
                    : getInverseRotation(mViewport.orientation);
            // For orientation-aware devices that work in the un-rotated coordinate space, the
            // viewport update should be skipped if it is only a change in the orientation.
            skipViewportUpdate = mParameters.orientationAware && mDisplayWidth == oldDisplayWidth &&
                    mDisplayHeight == oldDisplayHeight && viewportOrientationChanged;
            skipViewportUpdate = !viewportDisplayIdChanged && mParameters.orientationAware &&
                    mDisplayWidth == oldDisplayWidth && mDisplayHeight == oldDisplayHeight &&
                    viewportOrientationChanged;

            // Apply the input device orientation for the device.
            mInputDeviceOrientation =
@@ -1094,10 +1096,6 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
            // of the diagonal axis of the touch pad.  Touches that are wider than this are
            // translated into freeform gestures.
            mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;

            // Abort current pointer usages because the state has changed.
            const nsecs_t readTime = when; // synthetic event
            abortPointerUsage(when, readTime, 0 /*policyFlags*/);
        }

        // Inform the dispatcher about the changes.
@@ -1926,6 +1924,10 @@ void TouchInputMapper::dispatchVirtualKey(nsecs_t when, nsecs_t readTime, uint32
}

void TouchInputMapper::abortTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) {
    if (mCurrentMotionAborted) {
        // Current motion event was already aborted.
        return;
    }
    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
    if (!currentIdBits.isEmpty()) {
        int32_t metaState = getContext()->getGlobalMetaState();
+103 −10
Original line number Diff line number Diff line
@@ -2938,6 +2938,8 @@ protected:
        mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
                                                            *mFakeListener);
        mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
        // Consume the device reset notification generated when adding a new device.
        mFakeListener->assertNotifyDeviceResetWasCalled();
    }

    void SetUp() override {
@@ -2962,6 +2964,8 @@ protected:
            mReader->loopOnce();
        }
        mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
        // Loop the reader to flush the input listener queue.
        mReader->loopOnce();
    }

    std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
@@ -2985,6 +2989,8 @@ protected:
        configureDevice(0);
        mDevice->reset(ARBITRARY_TIME);
        mapper.reset(ARBITRARY_TIME);
        // Loop the reader to flush the input listener queue.
        mReader->loopOnce();
        return mapper;
    }

@@ -3010,6 +3016,7 @@ protected:
        event.code = code;
        event.value = value;
        mapper.process(&event);
        // Loop the reader to flush the input listener queue.
        mReader->loopOnce();
    }

@@ -4907,7 +4914,6 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) {
    ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
    ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);

    process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10);
@@ -6690,6 +6696,89 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsV
            toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}

TEST_F(SingleTouchInputMapperTest,
       Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    prepareButtons();
    prepareAxes(POSITION);
    SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
    NotifyMotionArgs motionArgs;

    // Down.
    processDown(mapper, 100, 200);
    processSync(mapper);

    // We should receive a down event
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);

    // Change display id
    clearViewports();
    prepareSecondaryDisplay(ViewportType::INTERNAL);

    // We should receive a cancel event
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
    // Then receive reset called
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
}

TEST_F(SingleTouchInputMapperTest,
       Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    prepareButtons();
    prepareAxes(POSITION);
    SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
    NotifyMotionArgs motionArgs;

    // Start a new gesture.
    processDown(mapper, 100, 200);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);

    // Make the viewport inactive. This will put the device in disabled mode.
    auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
    viewport->isActive = false;
    mFakePolicy->updateViewport(*viewport);
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);

    // We should receive a cancel event for the ongoing gesture.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
    // Then we should be notified that the device was reset.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());

    // No events are generated while the viewport is inactive.
    processMove(mapper, 101, 201);
    processSync(mapper);
    processDown(mapper, 102, 202);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // Make the viewport active again. The device should resume processing events.
    viewport->isActive = true;
    mFakePolicy->updateViewport(*viewport);
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);

    // The device is reset because it changes back to direct mode, without generating any events.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // Start a new gesture.
    processDown(mapper, 100, 200);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);

    // No more events.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
}

// --- TouchDisplayProjectionTest ---

class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
@@ -8547,27 +8636,27 @@ TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
    ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);

    // Finger move
    // The ongoing touch should be canceled immediately
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);

    // Finger move is ignored
    x += 10, y += 10;
    processPosition(mapper, x, y);
    processSync(mapper);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // Reactivate display viewport
    displayViewport.isActive = true;
    ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);

    // Finger move again
    // Finger move again starts new gesture
    x += 10, y += 10;
    processPosition(mapper, x, y);
    processSync(mapper);

    // Gesture is aborted, so events after display is activated won't be dispatched until there is
    // no pointer on the touch device.
    mFakeListener->assertNotifyMotionWasNotCalled();
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
}

TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
@@ -8725,6 +8814,10 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated
        // window's coordinate space.
        frames[0].rotate(getInverseRotation(orientation));
        ASSERT_EQ(frames, motionArgs.videoFrames);

        // Release finger.
        processSync(mapper);
        ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    }
}