diff options
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() { |