diff options
| author | 2024-05-01 15:52:41 -0700 | |
|---|---|---|
| committer | 2024-05-03 18:51:10 -0700 | |
| commit | 721631a93e2da5e80f5c61d60c61849c9ff6dc9d (patch) | |
| tree | 857b822a15e6d9a6b1df05f07176176b3045b54e | |
| parent | e2e250069489ce27c5e2fe44e12ade0ebf984957 (diff) | |
Add window remove listener in SensitiveContentProtectionManagerService
SCPMS tracks sensitive windows, and in some cases the window
may stay lingering when an app fails to call remove protection.
The callback would help cleaning up the windows in SCPMS.
Bug: 336626172
Test: atest ViewSensitiveContentTest
Change-Id: Id7b5d1e929b1229c4d392f4a5b57ead5375c089e
5 files changed, 116 insertions, 33 deletions
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java index 64bca33569cc..04edb5756599 100644 --- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java +++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java @@ -27,6 +27,7 @@ import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDI import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START; import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP; import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_SESSION; +import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListener; import android.annotation.NonNull; import android.annotation.Nullable; @@ -210,6 +211,12 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } }; + private final OnWindowRemovedListener mOnWindowRemovedListener = token -> { + synchronized (mSensitiveContentProtectionLock) { + mPackagesShowingSensitiveContent.removeIf(pkgInfo -> pkgInfo.getWindowToken() == token); + } + }; + public SensitiveContentProtectionManagerService(@NonNull Context context) { super(context); if (sensitiveNotificationAppProtection()) { @@ -265,6 +272,10 @@ public final class SensitiveContentProtectionManagerService extends SystemServic // Intra-process call, should never happen. } } + + if (sensitiveContentAppProtection()) { + mWindowManager.registerOnWindowRemovedListener(mOnWindowRemovedListener); + } } /** Cleanup any callbacks and listeners */ diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index eeedec398be4..19053f70e7e6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -306,6 +306,18 @@ public abstract class WindowManagerInternal { } /** + * An interface to be notified on window removal. + */ + public interface OnWindowRemovedListener { + /** + * Called when a window is removed. + * + * @param token the client token + */ + void onWindowRemoved(IBinder token); + } + + /** * An interface to be notified when keyguard exit animation should start. */ public interface KeyguardExitAnimationStartListener { @@ -1076,6 +1088,20 @@ public abstract class WindowManagerInternal { public abstract void clearBlockedApps(); /** + * Register a listener to receive a callback on window removal. + * + * @param listener the listener to be registered. + */ + public abstract void registerOnWindowRemovedListener(OnWindowRemovedListener listener); + + /** + * Removes the listener. + * + * @param listener the listener to be removed. + */ + public abstract void unregisterOnWindowRemovedListener(OnWindowRemovedListener listener); + + /** * Moves the current focus to the adjacent activity if it has the latest created window. */ public abstract boolean moveFocusToAdjacentEmbeddedActivityIfNeeded(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index feede01bdf41..5d4c2011376e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -53,6 +53,7 @@ import static android.service.dreams.Flags.dreamHandlesConfirmKeys; import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; @@ -147,6 +148,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListener; import static com.android.server.wm.WindowManagerServiceDumpProto.BACK_NAVIGATION; import static com.android.server.wm.WindowManagerServiceDumpProto.DISPLAY_FROZEN; import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP; @@ -489,6 +491,9 @@ public class WindowManagerService extends IWindowManager.Stub private final RemoteCallbackList<IKeyguardLockedStateListener> mKeyguardLockedStateListeners = new RemoteCallbackList<>(); + + private final List<OnWindowRemovedListener> mOnWindowRemovedListeners = new ArrayList<>(); + private boolean mDispatchedKeyguardLockedState = false; // VR Vr2d Display Id. @@ -2073,7 +2078,11 @@ public class WindowManagerService extends IWindowManager.Stub */ void postWindowRemoveCleanupLocked(WindowState win) { ProtoLog.v(WM_DEBUG_ADD_REMOVE, "postWindowRemoveCleanupLocked: %s", win); - mWindowMap.remove(win.mClient.asBinder()); + final IBinder client = win.mClient.asBinder(); + mWindowMap.remove(client); + if (sensitiveContentAppProtection()) { + notifyWindowRemovedListeners(client); + } final DisplayContent dc = win.getDisplayContent(); dc.getDisplayRotation().markForSeamlessRotation(win, false /* seamlesslyRotated */); @@ -5335,6 +5344,23 @@ public class WindowManagerService extends IWindowManager.Stub } } + private void notifyWindowRemovedListeners(IBinder client) { + OnWindowRemovedListener[] windowRemovedListeners; + synchronized (mGlobalLock) { + if (mOnWindowRemovedListeners.isEmpty()) { + return; + } + windowRemovedListeners = new OnWindowRemovedListener[mOnWindowRemovedListeners.size()]; + mOnWindowRemovedListeners.toArray(windowRemovedListeners); + } + mH.post(() -> { + int size = windowRemovedListeners.length; + for (int i = 0; i < size; i++) { + windowRemovedListeners[i].onWindowRemoved(client); + } + }); + } + private void notifyWindowsChanged() { WindowChangeListener[] windowChangeListeners; synchronized (mGlobalLock) { @@ -8868,6 +8894,20 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public void registerOnWindowRemovedListener(OnWindowRemovedListener listener) { + synchronized (mGlobalLock) { + mOnWindowRemovedListeners.add(listener); + } + } + + @Override + public void unregisterOnWindowRemovedListener(OnWindowRemovedListener listener) { + synchronized (mGlobalLock) { + mOnWindowRemovedListeners.remove(listener); + } + } + + @Override public boolean moveFocusToAdjacentEmbeddedActivityIfNeeded() { synchronized (mGlobalLock) { final WindowState focusedWindow = getFocusedWindow(); diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java index 7aafa8e92690..5ddd8a50135b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java @@ -26,7 +26,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; import android.content.pm.PackageManagerInternal; import android.media.projection.MediaProjectionInfo; @@ -108,7 +107,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { mMediaPorjectionCallback.onStart(exemptedRecorderPackage); mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -135,7 +134,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { // when screen sharing is not active, no app window should be blocked. mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -158,8 +157,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { mMediaPorjectionCallback.onStart(mMediaProjectionInfo); mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); - verify(mWindowManager, never()) - .addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -168,7 +166,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { mMediaProjectionCallbackCaptor.getValue().onStart(mMediaProjectionInfo); mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } private void mockDisabledViaDeveloperOption() { diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java index a20d935c50aa..8b653378664e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.content.pm.PackageManagerInternal; @@ -102,6 +101,8 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { @Captor ArgumentCaptor<MediaProjectionManager.Callback> mMediaProjectionCallbackCaptor; + @Captor + private ArgumentCaptor<ArraySet<PackageInfo>> mPackageInfoCaptor; @Mock private MediaProjectionManager mProjectionManager; @@ -309,7 +310,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -469,7 +470,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -480,7 +481,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -495,7 +496,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -519,7 +520,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -530,7 +531,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -541,7 +542,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -557,7 +558,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -574,7 +575,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -586,7 +587,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -598,7 +599,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verifyNoBlockOrClearInteractionWithWindowManager(); } @Test @@ -614,7 +615,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verifyNoBlockOrClearInteractionWithWindowManager(); } @Test @@ -640,7 +641,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -652,7 +653,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -666,7 +667,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(null); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -684,7 +685,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -702,7 +703,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -715,7 +716,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationRankingUpdate(mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -727,7 +728,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification1, mRankingMap); - verifyZeroInteractions(mWindowManager); + verifyNoBlockOrClearInteractionWithWindowManager(); } @Test @@ -743,7 +744,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification1, mRankingMap); - verifyZeroInteractions(mWindowManager); + verifyNoBlockOrClearInteractionWithWindowManager(); } @Test @@ -773,7 +774,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification2, mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -787,7 +788,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(null, mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -801,7 +802,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification1, null); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -816,7 +817,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification1, mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test @@ -829,7 +830,14 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener .onNotificationPosted(mNotification1, mRankingMap); - verifyZeroInteractions(mWindowManager); + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); + } + + private void verifyNoBlockOrClearInteractionWithWindowManager() { + verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); + verify(mWindowManager, never()).clearBlockedApps(); + verify(mWindowManager, never()) + .removeBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } private void mockDisabledViaDevelopOption() { |