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

Commit def8ff1b authored by Arpit Singh's avatar Arpit Singh
Browse files

Remove temporary DisplayTopology types

This CL removes and replaces temporary DisplayTopology related struct
and enums.

Test: atest inputflinger_tests
Bug: 367659738
Bug: 367660694
Flag: com.android.input.flags.connected_displays_cursor
Change-Id: I5ca250b762832b35167ea9991a5ce4b00177ae84
parent a2562b0f
Loading
Loading
Loading
Loading
+40 −92
Original line number Diff line number Diff line
@@ -98,6 +98,22 @@ std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowIn
    return privacySensitiveDisplays;
}

vec2 calculatePositionOnDestinationViewport(const DisplayViewport& destinationViewport,
                                            float pointerOffset,
                                            DisplayTopologyPosition sourceBoundary) {
    // destination is opposite of the source boundary
    switch (sourceBoundary) {
        case DisplayTopologyPosition::RIGHT:
            return {0, pointerOffset}; // left edge
        case DisplayTopologyPosition::TOP:
            return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
        case DisplayTopologyPosition::LEFT:
            return {destinationViewport.logicalRight, pointerOffset}; // right edge
        case DisplayTopologyPosition::BOTTOM:
            return {pointerOffset, 0}; // top edge
    }
}

} // namespace

// --- PointerChoreographer ---
@@ -327,19 +343,19 @@ void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterfac
    // except sometimes near the corners.
    // In these cases this behaviour is not noticeable. We also do not apply unconsumed delta on
    // the destination display for the same reason.
    DisplayPosition sourceBoundary;
    DisplayTopologyPosition sourceBoundary;
    float cursorOffset = 0.0f;
    if (rotatedUnconsumedDelta.x > 0) {
        sourceBoundary = DisplayPosition::RIGHT;
        sourceBoundary = DisplayTopologyPosition::RIGHT;
        cursorOffset = rotatedCursorPosition.y;
    } else if (rotatedUnconsumedDelta.x < 0) {
        sourceBoundary = DisplayPosition::LEFT;
        sourceBoundary = DisplayTopologyPosition::LEFT;
        cursorOffset = rotatedCursorPosition.y;
    } else if (rotatedUnconsumedDelta.y > 0) {
        sourceBoundary = DisplayPosition::BOTTOM;
        sourceBoundary = DisplayTopologyPosition::BOTTOM;
        cursorOffset = rotatedCursorPosition.x;
    } else {
        sourceBoundary = DisplayPosition::TOP;
        sourceBoundary = DisplayTopologyPosition::TOP;
        cursorOffset = rotatedCursorPosition.x;
    }

@@ -369,7 +385,8 @@ void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterfac
    pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
    pc.setDisplayViewport(destinationViewport);
    vec2 destinationPosition =
            calculateDestinationPosition(destinationViewport, cursorOffset - destinationOffset,
            calculatePositionOnDestinationViewport(destinationViewport,
                                                   cursorOffset - destinationOffset,
                                                   sourceBoundary);

    // Transform position back to un-rotated coordinate space before sending it to controller
@@ -379,22 +396,6 @@ void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterfac
    pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
}

vec2 PointerChoreographer::calculateDestinationPosition(const DisplayViewport& destinationViewport,
                                                        float pointerOffset,
                                                        DisplayPosition sourceBoundary) {
    // destination is opposite of the source boundary
    switch (sourceBoundary) {
        case DisplayPosition::RIGHT:
            return {0, pointerOffset}; // left edge
        case DisplayPosition::TOP:
            return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
        case DisplayPosition::LEFT:
            return {destinationViewport.logicalRight, pointerOffset}; // right edge
        case DisplayPosition::BOTTOM:
            return {pointerOffset, 0}; // top edge
    }
}

void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
    if (args.displayId == ui::LogicalDisplayId::INVALID) {
        return;
@@ -540,8 +541,7 @@ void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args)
}

void PointerChoreographer::onControllerAddedOrRemovedLocked() {
    if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows() &&
        !com::android::input::flags::connected_displays_cursor()) {
    if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows()) {
        return;
    }
    bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
@@ -607,11 +607,16 @@ void PointerChoreographer::notifyPointerCaptureChanged(
    mNextListener.notify(args);
}

void PointerChoreographer::setDisplayTopology(
        const std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>>&
                displayTopology) {
void PointerChoreographer::setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) {
    std::scoped_lock _l(getLock());
    mTopology = displayTopology;
    mTopology = displayTopologyGraph;

    // make primary display default mouse display, if it was not set
    // or the existing display was removed
    if (mDefaultMouseDisplayId == ui::LogicalDisplayId::INVALID ||
        mTopology.graph.find(mDefaultMouseDisplayId) != mTopology.graph.end()) {
        mDefaultMouseDisplayId = mTopology.primaryDisplayId;
    }
}

void PointerChoreographer::dump(std::string& dump) {
@@ -985,73 +990,17 @@ PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusContr
    return ConstructorDelegate(std::move(ctor));
}

void PointerChoreographer::populateFakeDisplayTopologyLocked(
        const std::vector<gui::DisplayInfo>& displayInfos) {
    if (!com::android::input::flags::connected_displays_cursor()) {
        return;
    }

    if (displayInfos.size() == mTopology.size()) {
        bool displaysChanged = false;
        for (const auto& displayInfo : displayInfos) {
            if (mTopology.find(displayInfo.displayId) == mTopology.end()) {
                displaysChanged = true;
                break;
            }
        }

        if (!displaysChanged) {
            return;
        }
    }

    // create a fake topology assuming following order
    // default-display (top-edge) -> next-display (right-edge) -> next-display (right-edge) ...
    // This also adds a 100px offset on corresponding edge for better manual testing
    //   ┌────────┐
    //   │ next   ├─────────┐
    // ┌─└───────┐┤ next 2  │ ...
    // │ default │└─────────┘
    // └─────────┘
    mTopology.clear();

    // treat default display as base, in real topology it should be the primary-display
    ui::LogicalDisplayId previousDisplay = ui::LogicalDisplayId::DEFAULT;
    for (const auto& displayInfo : displayInfos) {
        if (displayInfo.displayId == ui::LogicalDisplayId::DEFAULT) {
            continue;
        }
        if (previousDisplay == ui::LogicalDisplayId::DEFAULT) {
            mTopology[previousDisplay].push_back(
                    {displayInfo.displayId, DisplayPosition::TOP, 100});
            mTopology[displayInfo.displayId].push_back(
                    {previousDisplay, DisplayPosition::BOTTOM, -100});
        } else {
            mTopology[previousDisplay].push_back(
                    {displayInfo.displayId, DisplayPosition::RIGHT, 100});
            mTopology[displayInfo.displayId].push_back(
                    {previousDisplay, DisplayPosition::LEFT, -100});
        }
        previousDisplay = displayInfo.displayId;
    }

    // update default pointer display. In real topology it should be the primary-display
    if (mTopology.find(mDefaultMouseDisplayId) == mTopology.end()) {
        mDefaultMouseDisplayId = ui::LogicalDisplayId::DEFAULT;
    }
}

std::optional<std::pair<const DisplayViewport*, float /*offset*/>>
PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
                                                   const DisplayPosition sourceBoundary,
                                                   const DisplayTopologyPosition sourceBoundary,
                                                   float cursorOffset) const {
    const auto& sourceNode = mTopology.find(sourceDisplayId);
    if (sourceNode == mTopology.end()) {
    const auto& sourceNode = mTopology.graph.find(sourceDisplayId);
    if (sourceNode == mTopology.graph.end()) {
        // Topology is likely out of sync with viewport info, wait for it to be updated
        LOG(WARNING) << "Source display missing from topology " << sourceDisplayId;
        return std::nullopt;
    }
    for (const AdjacentDisplay& adjacentDisplay : sourceNode->second) {
    for (const DisplayTopologyAdjacentDisplay& adjacentDisplay : sourceNode->second) {
        if (adjacentDisplay.position != sourceBoundary) {
            continue;
        }
@@ -1064,8 +1013,8 @@ PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId so
            continue;
        }
        // target position must be within target display boundary
        const int32_t edgeSize =
                sourceBoundary == DisplayPosition::TOP || sourceBoundary == DisplayPosition::BOTTOM
        const int32_t edgeSize = sourceBoundary == DisplayTopologyPosition::TOP ||
                        sourceBoundary == DisplayTopologyPosition::BOTTOM
                ? (destinationViewport->logicalRight - destinationViewport->logicalLeft)
                : (destinationViewport->logicalBottom - destinationViewport->logicalTop);
        if (cursorOffset >= adjacentDisplay.offsetPx &&
@@ -1093,7 +1042,6 @@ void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfo
        mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
        mPointerChoreographer->onPrivacySensitiveDisplaysChangedLocked(mPrivacySensitiveDisplays);
    }
    mPointerChoreographer->populateFakeDisplayTopologyLocked(windowInfosUpdate.displayInfos);
}

void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfosLocked(
+15 −28
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <android-base/thread_annotations.h>
#include <gui/WindowInfosListener.h>
#include <input/DisplayTopologyGraph.h>
#include <type_traits>
#include <unordered_set>

@@ -80,6 +81,11 @@ public:
     */
    virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;

    /*
     * Used by InputManager to notify changes in the DisplayTopology
     */
    virtual void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) = 0;

    /**
     * This method may be called on any thread (usually by the input manager on a binder thread).
     */
@@ -103,6 +109,7 @@ public:
                        ui::LogicalDisplayId displayId, DeviceId deviceId) override;
    void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
    void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
    void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph);

    void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
    void notifyKey(const NotifyKeyArgs& args) override;
@@ -113,24 +120,6 @@ public:
    void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
    void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;

    // TODO(b/362719483) remove these when real topology is available
    enum class DisplayPosition {
        RIGHT,
        TOP,
        LEFT,
        BOTTOM,
        ftl_last = BOTTOM,
    };

    struct AdjacentDisplay {
        ui::LogicalDisplayId displayId;
        DisplayPosition position;
        float offsetPx;
    };
    void setDisplayTopology(
            const std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>>&
                    displayTopology);

    void dump(std::string& dump) override;

private:
@@ -174,18 +163,16 @@ private:
    void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
            REQUIRES(getLock());

    void populateFakeDisplayTopologyLocked(const std::vector<gui::DisplayInfo>& displayInfos)
            REQUIRES(getLock());

    std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
            const ui::LogicalDisplayId sourceDisplayId, const DisplayPosition sourceBoundary,
            float cursorOffset) const REQUIRES(getLock());

    static vec2 calculateDestinationPosition(const DisplayViewport& destinationViewport,
                                             float pointerOffset, DisplayPosition sourceBoundary);
            const ui::LogicalDisplayId sourceDisplayId,
            const DisplayTopologyPosition sourceBoundary, float cursorOffset) const
            REQUIRES(getLock());

    std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>> mTopology
            GUARDED_BY(getLock());
    /* Topology is initialized with default-constructed value, which is an empty topology. Till we
     * receive setDisplayTopology call.
     * Meanwhile Choreographer will treat every display as independent disconnected display.
     */
    DisplayTopologyGraph mTopology GUARDED_BY(getLock());

    /* This listener keeps tracks of visible privacy sensitive displays and updates the
     * choreographer if there are any changes.
+13 −10
Original line number Diff line number Diff line
@@ -2633,16 +2633,14 @@ protected:
                           ui::ROTATION_0),
    };

    std::unordered_map<ui::LogicalDisplayId, std::vector<PointerChoreographer::AdjacentDisplay>>
            mTopology{
                    {DISPLAY_CENTER_ID,
                     {{DISPLAY_TOP_ID, PointerChoreographer::DisplayPosition::TOP, 10.0f},
                      {DISPLAY_RIGHT_ID, PointerChoreographer::DisplayPosition::RIGHT, 10.0f},
                      {DISPLAY_BOTTOM_ID, PointerChoreographer::DisplayPosition::BOTTOM, 10.0f},
                      {DISPLAY_LEFT_ID, PointerChoreographer::DisplayPosition::LEFT, 10.0f},
                      {DISPLAY_TOP_RIGHT_CORNER_ID, PointerChoreographer::DisplayPosition::RIGHT,
                       -90.0f}}},
            };
    DisplayTopologyGraph mTopology{DISPLAY_CENTER_ID,
                                   {{DISPLAY_CENTER_ID,
                                     {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 10.0f},
                                      {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
                                      {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
                                      {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
                                      {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT,
                                       -90.0f}}}}};

private:
    DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
@@ -2706,6 +2704,11 @@ INSTANTIATE_TEST_SUITE_P(
        testing::Values(
                // Note: Upon viewport transition cursor will be positioned at the boundary of the
                // destination, as we drop any unconsumed delta.
                std::make_tuple("PrimaryDisplayIsDefault", AINPUT_SOURCE_MOUSE,
                                ControllerType::MOUSE, ToolType::MOUSE,
                                vec2(50, 50) /* initial x/y */, vec2(0, 0) /* delta x/y */,
                                PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
                                vec2(50, 50) /* destination x/y */),
                std::make_tuple("UnchangedDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
                                ToolType::MOUSE, vec2(50, 50) /* initial x/y */,
                                vec2(25, 25) /* delta x/y */,