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
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 811692f..5bf6ebb 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -98,6 +98,22 @@
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 @@
// 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,8 +385,9 @@
pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
pc.setDisplayViewport(destinationViewport);
vec2 destinationPosition =
- calculateDestinationPosition(destinationViewport, cursorOffset - destinationOffset,
- sourceBoundary);
+ calculatePositionOnDestinationViewport(destinationViewport,
+ cursorOffset - destinationOffset,
+ sourceBoundary);
// Transform position back to un-rotated coordinate space before sending it to controller
destinationPosition = pc.getDisplayTransform().inverse().transform(destinationPosition.x,
@@ -379,22 +396,6 @@
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::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 @@
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 @@
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 @@
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 @@
mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
mPointerChoreographer->onPrivacySensitiveDisplaysChangedLocked(mPrivacySensitiveDisplays);
}
- mPointerChoreographer->populateFakeDisplayTopologyLocked(windowInfosUpdate.displayInfos);
}
void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfosLocked(
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 939529f..c2f5ec0 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -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 @@
*/
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 @@
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 @@
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 @@
void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
REQUIRES(getLock());
- void populateFakeDisplayTopologyLocked(const std::vector<gui::DisplayInfo>& displayInfos)
+ std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
+ const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayTopologyPosition sourceBoundary, float cursorOffset) const
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);
-
- 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.
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 27da3d3..1ca2998 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -2633,16 +2633,14 @@
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 @@
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 */,