Add method to set SkipScreenshot flag on cursorcontroller sprites
Add a methods to be able to set ISurfaceComposerClient::eSkipScreenshot
flag on MouseCursorController. This will be used to hide mouse and
stylus pointers on mirrored displays when a privacy sensitive window is
present on source display.
Test: manual test & atest PointerControllerTest
Bug: 325252005
Change-Id: Ide428e8daf96a1d919adb9d6374a9ea738f87cc5
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index f1ee325..eecc741 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -165,6 +165,15 @@
}
}
+void MouseCursorController::setSkipScreenshot(bool skip) {
+ std::scoped_lock lock(mLock);
+ if (mLocked.skipScreenshot == skip) {
+ return;
+ }
+ mLocked.skipScreenshot = skip;
+ updatePointerLocked();
+}
+
void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
std::scoped_lock lock(mLock);
@@ -352,6 +361,7 @@
mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
+ mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
if (mLocked.pointerAlpha > 0) {
mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index dc7e8ca..78f6413 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -53,6 +53,9 @@
void setDisplayViewport(const DisplayViewport& viewport, bool getAdditionalMouseResources);
void setStylusHoverMode(bool stylusHoverMode);
+ // Set/Unset flag to hide the mouse cursor on the mirrored display
+ void setSkipScreenshot(bool skip);
+
void updatePointerIcon(PointerIconStyle iconId);
void setCustomPointerIcon(const SpriteIcon& icon);
void reloadPointerResources(bool getAdditionalMouseResources);
@@ -94,6 +97,7 @@
PointerIconStyle requestedPointerType;
PointerIconStyle resolvedPointerType;
+ bool skipScreenshot{false};
bool animating{false};
} mLocked GUARDED_BY(mLock);
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index cca1b07..11b27a2 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -286,13 +286,16 @@
mCursorController.setCustomPointerIcon(icon);
}
-void PointerController::setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) {
+void PointerController::setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) {
std::scoped_lock lock(getLock());
- if (skip) {
- mLocked.displaysToSkipScreenshot.insert(displayId);
- } else {
- mLocked.displaysToSkipScreenshot.erase(displayId);
- }
+ mLocked.displaysToSkipScreenshot.insert(displayId);
+ mCursorController.setSkipScreenshot(true);
+}
+
+void PointerController::clearSkipScreenshotFlags() {
+ std::scoped_lock lock(getLock());
+ mLocked.displaysToSkipScreenshot.clear();
+ mCursorController.setSkipScreenshot(false);
}
void PointerController::doInactivityTimeout() {
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index c6430f7..4d1e1d7 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -66,7 +66,8 @@
void clearSpots() override;
void updatePointerIcon(PointerIconStyle iconId) override;
void setCustomPointerIcon(const SpriteIcon& icon) override;
- void setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) override;
+ void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) override;
+ void clearSkipScreenshotFlags() override;
virtual void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void doInactivityTimeout();
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 2dcb1f1..cbef68e 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -183,12 +183,16 @@
MyLooper() : Looper(false) {}
~MyLooper() = default;
};
- sp<MyLooper> mLooper;
std::thread mThread;
+
+protected:
+ sp<MyLooper> mLooper;
};
-PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
- mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
+PointerControllerTest::PointerControllerTest()
+ : mPointerSprite(new NiceMock<MockSprite>),
+ mThread(&PointerControllerTest::loopThread, this),
+ mLooper(new MyLooper) {
mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
mPolicy = new MockPointerControllerPolicyInterface();
@@ -339,7 +343,7 @@
testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
// Marking the display to skip screenshot should update sprite as well
- mPointerController->setSkipScreenshot(ui::LogicalDisplayId::DEFAULT, true);
+ mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(true));
// Update spots to sync state with sprite
@@ -348,13 +352,53 @@
testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
// Reset flag and verify again
- mPointerController->setSkipScreenshot(ui::LogicalDisplayId::DEFAULT, false);
+ mPointerController->clearSkipScreenshotFlags();
EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
ui::LogicalDisplayId::DEFAULT);
testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
}
+class PointerControllerSkipScreenshotFlagTest
+ : public PointerControllerTest,
+ public testing::WithParamInterface<PointerControllerInterface::ControllerType> {};
+
+TEST_P(PointerControllerSkipScreenshotFlagTest, updatesSkipScreenshotFlag) {
+ sp<MockSprite> testPointerSprite(new NiceMock<MockSprite>);
+ EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite));
+
+ // Create a pointer controller
+ mPointerController =
+ PointerController::create(mPolicy, mLooper, *mSpriteController, GetParam());
+ ensureDisplayViewportIsSet(ui::LogicalDisplayId::DEFAULT);
+
+ // By default skip screenshot flag is not set for the sprite
+ EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
+
+ // Update pointer to sync state with sprite
+ mPointerController->setPosition(100, 100);
+ testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
+
+ // Marking the controller to skip screenshot should update pointer sprite
+ mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
+ EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(true));
+
+ // Update pointer to sync state with sprite
+ mPointerController->move(10, 10);
+ testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
+
+ // Reset flag and verify again
+ mPointerController->clearSkipScreenshotFlags();
+ EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
+ mPointerController->move(10, 10);
+ testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
+}
+
+INSTANTIATE_TEST_SUITE_P(PointerControllerSkipScreenshotFlagTest,
+ PointerControllerSkipScreenshotFlagTest,
+ testing::Values(PointerControllerInterface::ControllerType::MOUSE,
+ PointerControllerInterface::ControllerType::STYLUS));
+
class PointerControllerWindowInfoListenerTest : public Test {};
TEST_F(PointerControllerWindowInfoListenerTest,