Merge cherrypicks of ['googleplex-android-review.googlesource.com/26513672', 'googleplex-android-review.googlesource.com/26513673'] into 24Q2-release.
Change-Id: I887087b781dd9d83e6b597eb491e35f046b91aa8
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 3ac4285..9db3574 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -26,6 +26,7 @@
namespace android {
namespace {
+
bool isFromMouse(const NotifyMotionArgs& args) {
return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
args.pointerProperties[0].toolType == ToolType::MOUSE;
@@ -44,13 +45,23 @@
bool isStylusHoverEvent(const NotifyMotionArgs& args) {
return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
}
+
+inline void notifyPointerDisplayChange(std::optional<std::tuple<int32_t, FloatPoint>> change,
+ PointerChoreographerPolicyInterface& policy) {
+ if (!change) {
+ return;
+ }
+ const auto& [displayId, cursorPosition] = *change;
+ policy.notifyPointerDisplayIdChanged(displayId, cursorPosition);
+}
+
} // namespace
// --- PointerChoreographer ---
PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
PointerChoreographerPolicyInterface& policy)
- : mTouchControllerConstructor([this]() REQUIRES(mLock) {
+ : mTouchControllerConstructor([this]() {
return mPolicy.createPointerController(
PointerControllerInterface::ControllerType::TOUCH);
}),
@@ -62,10 +73,16 @@
mStylusPointerIconEnabled(false) {}
void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
- std::scoped_lock _l(mLock);
+ PointerDisplayChange pointerDisplayChange;
- mInputDeviceInfos = args.inputDeviceInfos;
- updatePointerControllersLocked();
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ mInputDeviceInfos = args.inputDeviceInfos;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
mNextListener.notify(args);
}
@@ -104,7 +121,7 @@
<< args.dump();
}
- auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
+ auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
@@ -124,7 +141,7 @@
}
NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
- auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
+ auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
NotifyMotionArgs newArgs(args);
newArgs.displayId = displayId;
@@ -308,17 +325,13 @@
return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
}
-std::pair<int32_t, PointerControllerInterface&>
-PointerChoreographer::getDisplayIdAndMouseControllerLocked(int32_t associatedDisplayId) {
+std::pair<int32_t, PointerControllerInterface&> PointerChoreographer::ensureMouseControllerLocked(
+ int32_t associatedDisplayId) {
const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
- // Get the mouse pointer controller for the display, or create one if it doesn't exist.
- auto [it, emplaced] =
- mMousePointersByDisplay.try_emplace(displayId,
- getMouseControllerConstructor(displayId));
- if (emplaced) {
- notifyPointerDisplayIdChangedLocked();
- }
+ auto it = mMousePointersByDisplay.find(displayId);
+ LOG_ALWAYS_FATAL_IF(it == mMousePointersByDisplay.end(),
+ "There is no mouse controller created for display %d", displayId);
return {displayId, *it->second};
}
@@ -333,7 +346,7 @@
return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
}
-void PointerChoreographer::updatePointerControllersLocked() {
+PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
std::set<DeviceId> touchDevicesToKeep;
std::set<DeviceId> stylusDevicesToKeep;
@@ -382,11 +395,12 @@
mInputDeviceInfos.end();
});
- // Notify the policy if there's a change on the pointer display ID.
- notifyPointerDisplayIdChangedLocked();
+ // Check if we need to notify the policy if there's a change on the pointer display ID.
+ return calculatePointerDisplayChangeToNotify();
}
-void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
+PointerChoreographer::PointerDisplayChange
+PointerChoreographer::calculatePointerDisplayChangeToNotify() {
int32_t displayIdToNotify = ADISPLAY_ID_NONE;
FloatPoint cursorPosition = {0, 0};
if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
@@ -398,38 +412,49 @@
displayIdToNotify = pointerController->getDisplayId();
cursorPosition = pointerController->getPosition();
}
-
if (mNotifiedPointerDisplayId == displayIdToNotify) {
- return;
+ return {};
}
- mPolicy.notifyPointerDisplayIdChanged(displayIdToNotify, cursorPosition);
mNotifiedPointerDisplayId = displayIdToNotify;
+ return {{displayIdToNotify, cursorPosition}};
}
void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
- std::scoped_lock _l(mLock);
+ PointerDisplayChange pointerDisplayChange;
- mDefaultMouseDisplayId = displayId;
- updatePointerControllersLocked();
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ mDefaultMouseDisplayId = displayId;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
- std::scoped_lock _l(mLock);
- for (const auto& viewport : viewports) {
- const int32_t displayId = viewport.displayId;
- if (const auto it = mMousePointersByDisplay.find(displayId);
- it != mMousePointersByDisplay.end()) {
- it->second->setDisplayViewport(viewport);
- }
- for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
- const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
- if (info && info->getAssociatedDisplayId() == displayId) {
- stylusPointerController->setDisplayViewport(viewport);
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ for (const auto& viewport : viewports) {
+ const int32_t displayId = viewport.displayId;
+ if (const auto it = mMousePointersByDisplay.find(displayId);
+ it != mMousePointersByDisplay.end()) {
+ it->second->setDisplayViewport(viewport);
+ }
+ for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
+ const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
+ if (info && info->getAssociatedDisplayId() == displayId) {
+ stylusPointerController->setDisplayViewport(viewport);
+ }
}
}
- }
- mViewports = viewports;
- notifyPointerDisplayIdChangedLocked();
+ mViewports = viewports;
+ pointerDisplayChange = calculatePointerDisplayChangeToNotify();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
@@ -453,21 +478,33 @@
}
void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
- std::scoped_lock _l(mLock);
- if (mShowTouchesEnabled == enabled) {
- return;
- }
- mShowTouchesEnabled = enabled;
- updatePointerControllersLocked();
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ if (mShowTouchesEnabled == enabled) {
+ return;
+ }
+ mShowTouchesEnabled = enabled;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
- std::scoped_lock _l(mLock);
- if (mStylusPointerIconEnabled == enabled) {
- return;
- }
- mStylusPointerIconEnabled = enabled;
- updatePointerControllersLocked();
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ if (mStylusPointerIconEnabled == enabled) {
+ return;
+ }
+ mStylusPointerIconEnabled = enabled;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
bool PointerChoreographer::setPointerIcon(
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 6aab3aa..db1488b 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -109,11 +109,13 @@
void dump(std::string& dump) override;
private:
- void updatePointerControllersLocked() REQUIRES(mLock);
- void notifyPointerDisplayIdChangedLocked() REQUIRES(mLock);
+ using PointerDisplayChange =
+ std::optional<std::tuple<int32_t /*displayId*/, FloatPoint /*cursorPosition*/>>;
+ [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(mLock);
+ [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(mLock);
const DisplayViewport* findViewportByIdLocked(int32_t displayId) const REQUIRES(mLock);
int32_t getTargetMouseDisplayLocked(int32_t associatedDisplayId) const REQUIRES(mLock);
- std::pair<int32_t, PointerControllerInterface&> getDisplayIdAndMouseControllerLocked(
+ std::pair<int32_t /*displayId*/, PointerControllerInterface&> ensureMouseControllerLocked(
int32_t associatedDisplayId) REQUIRES(mLock);
InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(mLock);
bool canUnfadeOnDisplay(int32_t displayId) REQUIRES(mLock);
diff --git a/services/inputflinger/include/PointerChoreographerPolicyInterface.h b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
index 8b47b55..462aedc 100644
--- a/services/inputflinger/include/PointerChoreographerPolicyInterface.h
+++ b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
@@ -25,6 +25,9 @@
*
* This is the interface that PointerChoreographer uses to talk to Window Manager and other
* system components.
+ *
+ * NOTE: In general, the PointerChoreographer must not interact with the policy while
+ * holding any locks.
*/
class PointerChoreographerPolicyInterface {
public:
@@ -37,6 +40,9 @@
* for and runnable on the host, the PointerController implementation must be in a separate
* library, libinputservice, that has the additional dependencies. The PointerController
* will be mocked when testing PointerChoreographer.
+ *
+ * Since this is a factory method used to work around dependencies, it will not interact with
+ * other input components and may be called with the PointerChoreographer lock held.
*/
virtual std::shared_ptr<PointerControllerInterface> createPointerController(
PointerControllerInterface::ControllerType type) = 0;