Hide Mouse and stylus pointers on mirrored displays
Hide the Mouse and Stylus pointers on mirrored displays if a privacy
sensitive window is present on the source display.
Test: atest PointerChoreographerTest
Bug: 325252005
Change-Id: Idc7a73508e360dfc6fc0bd66c4eb21f497e5bf6b
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 8a1eed6..02453ef 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -89,6 +89,19 @@
}
}
+// filters and returns a set of privacy sensitive displays that are currently visible.
+std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowInfos(
+ const std::vector<gui::WindowInfo>& windowInfos) {
+ std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
+ for (const auto& windowInfo : windowInfos) {
+ if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
+ windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
+ privacySensitiveDisplays.insert(windowInfo.displayId);
+ }
+ }
+ return privacySensitiveDisplays;
+}
+
} // namespace
// --- PointerChoreographer ---
@@ -246,10 +259,13 @@
}
// Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
- auto [it, _] = mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
- getMouseControllerConstructor(
- args.displayId));
- // TODO (b/325252005): Add handing for drawing tablets mouse pointer controller
+ auto [it, controllerAdded] =
+ mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
+ getMouseControllerConstructor(
+ args.displayId));
+ if (controllerAdded) {
+ onControllerAddedOrRemovedLocked();
+ }
PointerControllerInterface& pc = *it->second;
@@ -290,7 +306,7 @@
auto [it, controllerAdded] =
mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
if (controllerAdded) {
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
}
PointerControllerInterface& pc = *it->second;
@@ -326,10 +342,12 @@
}
// Get the stylus pointer controller for the device, or create one if it doesn't exist.
- auto [it, _] =
+ auto [it, controllerAdded] =
mStylusPointersByDevice.try_emplace(args.deviceId,
getStylusControllerConstructor(args.displayId));
- // TODO (b/325252005): Add handing for stylus pointer controller
+ if (controllerAdded) {
+ onControllerAddedOrRemovedLocked();
+ }
PointerControllerInterface& pc = *it->second;
@@ -369,15 +387,15 @@
mTouchPointersByDevice.erase(args.deviceId);
mStylusPointersByDevice.erase(args.deviceId);
mDrawingTabletPointersByDevice.erase(args.deviceId);
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
}
-void PointerChoreographer::onControllerAddedOrRemoved() {
+void PointerChoreographer::onControllerAddedOrRemovedLocked() {
if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
return;
}
- bool requireListener = !mTouchPointersByDevice.empty();
- // TODO (b/325252005): Update for other types of pointer controllers
+ bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
+ !mDrawingTabletPointersByDevice.empty() || !mStylusPointersByDevice.empty();
if (requireListener && mWindowInfoListener == nullptr) {
mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
@@ -387,12 +405,47 @@
SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
&initialInfo);
#endif
- onWindowInfosChangedLocked(initialInfo.first);
+ mWindowInfoListener->setInitialDisplayInfos(initialInfo.first);
+ onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
} else if (!requireListener && mWindowInfoListener != nullptr) {
#if defined(__ANDROID__)
SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
#endif
mWindowInfoListener = nullptr;
+ } else if (requireListener && mWindowInfoListener != nullptr) {
+ // controller may have been added to an existing privacy sensitive display, we need to
+ // update all controllers again
+ onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
+ }
+}
+
+void PointerChoreographer::onPrivacySensitiveDisplaysChangedLocked(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
+ for (auto& [_, pc] : mTouchPointersByDevice) {
+ pc->clearSkipScreenshotFlags();
+ for (auto displayId : privacySensitiveDisplays) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ }
+ }
+
+ for (auto& [displayId, pc] : mMousePointersByDisplay) {
+ if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ } else {
+ pc->clearSkipScreenshotFlags();
+ }
+ }
+
+ for (auto* pointerControllerByDevice :
+ {&mDrawingTabletPointersByDevice, &mStylusPointersByDevice}) {
+ for (auto& [_, pc] : *pointerControllerByDevice) {
+ auto displayId = pc->getDisplayId();
+ if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ } else {
+ pc->clearSkipScreenshotFlags();
+ }
+ }
}
}
@@ -407,10 +460,10 @@
mNextListener.notify(args);
}
-void PointerChoreographer::onWindowInfosChanged(
- const std::vector<android::gui::WindowInfo>& windowInfos) {
+void PointerChoreographer::onPrivacySensitiveDisplaysChanged(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
std::scoped_lock _l(mLock);
- onWindowInfosChangedLocked(windowInfos);
+ onPrivacySensitiveDisplaysChangedLocked(privacySensitiveDisplays);
}
void PointerChoreographer::dump(std::string& dump) {
@@ -467,7 +520,7 @@
if (it == mMousePointersByDisplay.end()) {
it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
.first;
- // TODO (b/325252005): Add handing for mouse pointer controller
+ onControllerAddedOrRemovedLocked();
}
return {displayId, *it->second};
@@ -509,7 +562,9 @@
auto [mousePointerIt, isNewMousePointer] =
mMousePointersByDisplay.try_emplace(displayId,
getMouseControllerConstructor(displayId));
- // TODO (b/325252005): Add handing for mouse pointer controller
+ if (isNewMousePointer) {
+ onControllerAddedOrRemovedLocked();
+ }
mMouseDevices.emplace(info.getId());
if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
@@ -549,7 +604,7 @@
mInputDeviceInfos.end();
});
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
// Check if we need to notify the policy if there's a change on the pointer display ID.
return calculatePointerDisplayChangeToNotify();
@@ -715,31 +770,6 @@
return false;
}
-void PointerChoreographer::onWindowInfosChangedLocked(
- const std::vector<android::gui::WindowInfo>& windowInfos) {
- // Mark all spot controllers secure on displays containing secure windows and
- // remove secure flag from others if required
- std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
- std::unordered_set<ui::LogicalDisplayId> allDisplayIds;
- for (const auto& windowInfo : windowInfos) {
- allDisplayIds.insert(windowInfo.displayId);
- if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
- windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
- privacySensitiveDisplays.insert(windowInfo.displayId);
- }
- }
-
- for (auto& it : mTouchPointersByDevice) {
- auto& pc = it.second;
- for (ui::LogicalDisplayId displayId : allDisplayIds) {
- pc->setSkipScreenshot(displayId,
- privacySensitiveDisplays.find(displayId) !=
- privacySensitiveDisplays.end());
- }
- }
- // TODO (b/325252005): update skip screenshot flag for other types of pointer controllers
-}
-
void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
std::scoped_lock lock(mLock);
if (visible) {
@@ -793,9 +823,27 @@
void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
const gui::WindowInfosUpdate& windowInfosUpdate) {
std::scoped_lock _l(mListenerLock);
- if (mPointerChoreographer != nullptr) {
- mPointerChoreographer->onWindowInfosChanged(windowInfosUpdate.windowInfos);
+ if (mPointerChoreographer == nullptr) {
+ return;
}
+ auto newPrivacySensitiveDisplays =
+ getPrivacySensitiveDisplaysFromWindowInfos(windowInfosUpdate.windowInfos);
+ if (newPrivacySensitiveDisplays != mPrivacySensitiveDisplays) {
+ mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
+ mPointerChoreographer->onPrivacySensitiveDisplaysChanged(mPrivacySensitiveDisplays);
+ }
+}
+
+void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfos(
+ const std::vector<gui::WindowInfo>& windowInfos) {
+ std::scoped_lock _l(mListenerLock);
+ mPrivacySensitiveDisplays = getPrivacySensitiveDisplaysFromWindowInfos(windowInfos);
+}
+
+std::unordered_set<ui::LogicalDisplayId /*displayId*/>
+PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplays() {
+ std::scoped_lock _l(mListenerLock);
+ return mPrivacySensitiveDisplays;
}
void PointerChoreographer::PointerChoreographerDisplayInfoListener::