Loading services/core/java/com/android/server/SensitiveContentProtectionManagerService.java 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wm.SensitiveContentPackages.PackageInfo; import com.android.server.wm.WindowManagerInternal; import java.util.Collections; import java.util.Set; /** * Service that monitors for notifications with sensitive content and protects content from screen * sharing */ public final class SensitiveContentProtectionManagerService extends SystemService { private static final String TAG = "SensitiveContentProtect"; private static final boolean DEBUG = false; @VisibleForTesting NotificationListener mNotificationListener; private @Nullable MediaProjectionManager mProjectionManager; private @Nullable WindowManagerInternal mWindowManager; private final MediaProjectionManager.Callback mProjectionCallback = new MediaProjectionManager.Callback() { @Override public void onStart(MediaProjectionInfo info) { if (DEBUG) Log.d(TAG, "onStart projection: " + info); onProjectionStart(); } @Override public void onStop(MediaProjectionInfo info) { if (DEBUG) Log.d(TAG, "onStop projection: " + info); onProjectionEnd(); } }; public SensitiveContentProtectionManagerService(@NonNull Context context) { super(context); mNotificationListener = new NotificationListener(); } @Override public void onStart() {} @Override public void onBootPhase(int phase) { if (phase != SystemService.PHASE_BOOT_COMPLETED) { return; } if (DEBUG) Log.d(TAG, "onBootPhase - PHASE_BOOT_COMPLETED"); init(getContext().getSystemService(MediaProjectionManager.class), LocalServices.getService(WindowManagerInternal.class)); } @VisibleForTesting void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager) { if (DEBUG) Log.d(TAG, "init"); checkNotNull(projectionManager, "Failed to get valid MediaProjectionManager"); checkNotNull(windowManager, "Failed to get valid WindowManagerInternal"); mProjectionManager = projectionManager; mWindowManager = windowManager; // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary // handler, delegate, and binder death recipient mProjectionManager.addCallback(mProjectionCallback, new Handler(Looper.getMainLooper())); try { mNotificationListener.registerAsSystemService(getContext(), new ComponentName(getContext(), NotificationListener.class), UserHandle.USER_ALL); } catch (RemoteException e) { // Intra-process call, should never happen. } } /** Cleanup any callbacks and listeners */ @VisibleForTesting void onDestroy() { if (mProjectionManager != null) { mProjectionManager.removeCallback(mProjectionCallback); } try { mNotificationListener.unregisterAsSystemService(); } catch (RemoteException e) { // Intra-process call, should never happen. } if (mWindowManager != null) { onProjectionEnd(); } } private void onProjectionStart() { StatusBarNotification[] notifications; try { notifications = mNotificationListener.getActiveNotifications(); } catch (SecurityException e) { Log.e(TAG, "SensitiveContentProtectionManagerService doesn't have access.", e); notifications = new StatusBarNotification[0]; } RankingMap rankingMap; try { rankingMap = mNotificationListener.getCurrentRanking(); } catch (SecurityException e) { Log.e(TAG, "SensitiveContentProtectionManagerService doesn't have access.", e); rankingMap = null; } // notify windowmanager of any currently posted sensitive content notifications Set<PackageInfo> packageInfos = getSensitivePackagesFromNotifications( notifications, rankingMap); mWindowManager.setShouldBlockScreenCaptureForApp(packageInfos); } private void onProjectionEnd() { // notify windowmanager to clear any sensitive notifications observed during projection // session mWindowManager.setShouldBlockScreenCaptureForApp(Collections.emptySet()); } private Set<PackageInfo> getSensitivePackagesFromNotifications( StatusBarNotification[] notifications, RankingMap rankingMap) { if (rankingMap == null) { Log.w(TAG, "Ranking map not initialized."); return Collections.emptySet(); } Set<PackageInfo> sensitivePackages = new ArraySet<>(); for (StatusBarNotification sbn : notifications) { NotificationListenerService.Ranking ranking = rankingMap.getRawRankingObject(sbn.getKey()); if (ranking != null && ranking.hasSensitiveContent()) { PackageInfo info = new PackageInfo(sbn.getPackageName(), sbn.getUid()); sensitivePackages.add(info); } } return sensitivePackages; } // TODO(b/317251408): add trigger that updates on onNotificationPosted, // onNotificationRankingUpdate and onListenerConnected @VisibleForTesting static class NotificationListener extends NotificationListenerService {} } services/core/java/com/android/server/wm/SensitiveContentPackages.java 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.annotation.NonNull; import android.util.ArraySet; import java.io.PrintWriter; import java.util.Objects; import java.util.Set; /** * Cache of distinct package/uid pairs that require being blocked from screen capture. This class is * not threadsafe and any call site should hold {@link WindowManagerGlobalLock} */ public class SensitiveContentPackages { private final ArraySet<PackageInfo> mProtectedPackages = new ArraySet<>(); /** Returns {@code true} if package/uid pair should be blocked from screen capture */ public boolean shouldBlockScreenCaptureForApp(String pkg, int uid) { for (int i = 0; i < mProtectedPackages.size(); i++) { PackageInfo info = mProtectedPackages.valueAt(i); if (info != null && info.mPkg.equals(pkg) && info.mUid == uid) { return true; } } return false; } /** Replaces the set of package/uid pairs to set that should be blocked from screen capture */ public void setShouldBlockScreenCaptureForApp(@NonNull Set<PackageInfo> packageInfos) { mProtectedPackages.clear(); mProtectedPackages.addAll(packageInfos); } void dump(PrintWriter pw) { final String innerPrefix = " "; pw.println("SensitiveContentPackages:"); pw.println(innerPrefix + "Packages that should block screen capture (" + mProtectedPackages.size() + "):"); for (PackageInfo info : mProtectedPackages) { pw.println(innerPrefix + " package=" + info.mPkg + " uid=" + info.mUid); } } /** Helper class that represents a package/uid pair */ public static class PackageInfo { private String mPkg; private int mUid; public PackageInfo(String pkg, int uid) { this.mPkg = pkg; this.mUid = uid; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PackageInfo)) return false; PackageInfo that = (PackageInfo) o; return mUid == that.mUid && Objects.equals(mPkg, that.mPkg); } @Override public int hashCode() { return Objects.hash(mPkg, mUid); } } } services/core/java/com/android/server/wm/WindowManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.window.ScreenCapture; import com.android.internal.policy.KeyInterceptionInfo; import com.android.server.input.InputManagerService; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.SensitiveContentPackages.PackageInfo; import java.lang.annotation.Retention; import java.util.List; Loading Loading @@ -1012,4 +1013,12 @@ public abstract class WindowManagerInternal { */ public abstract void setOrientationRequestPolicy(boolean respected, int[] fromOrientations, int[] toOrientations); /** * Set whether screen capture should be disabled for all windows of a specific app windows based * on sensitive content protections. * * @param packageInfos set of {@link PackageInfo} whose windows should be blocked from capture */ public abstract void setShouldBlockScreenCaptureForApp(@NonNull Set<PackageInfo> packageInfos); } services/core/java/com/android/server/wm/WindowManagerService.java +18 −2 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; import static com.android.server.wm.SensitiveContentPackages.PackageInfo; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; Loading Loading @@ -312,6 +313,7 @@ import android.window.WindowContainerToken; import android.window.WindowContextInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; Loading Loading @@ -366,6 +368,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; Loading Loading @@ -1053,6 +1056,9 @@ public class WindowManagerService extends IWindowManager.Stub SystemPerformanceHinter mSystemPerformanceHinter; @GuardedBy("mGlobalLock") final SensitiveContentPackages mSensitiveContentPackages = new SensitiveContentPackages(); /** Listener to notify activity manager about app transitions. */ final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier = new WindowManagerInternal.AppTransitionListener() { Loading Loading @@ -1931,12 +1937,13 @@ public class WindowManagerService extends IWindowManager.Stub /** * Set whether screen capture is disabled for all windows of a specific user from * the device policy cache. * the device policy cache, or specific windows based on sensitive content protections. */ @Override public void refreshScreenCaptureDisabled() { int callingUid = Binder.getCallingUid(); if (callingUid != SYSTEM_UID) { // MY_UID (Process.myUid()) should always be SYSTEM_UID here, but using MY_UID for tests if (callingUid != MY_UID) { throw new SecurityException("Only system can call refreshScreenCaptureDisabled."); } Loading Loading @@ -7169,6 +7176,7 @@ public class WindowManagerService extends IWindowManager.Stub } mSystemPerformanceHinter.dump(pw, ""); mTrustedPresentationListenerController.dump(pw); mSensitiveContentPackages.dump(pw); } } Loading Loading @@ -8550,6 +8558,14 @@ public class WindowManagerService extends IWindowManager.Stub InputTarget inputTarget = WindowManagerService.this.getInputTargetFromToken(inputToken); return inputTarget == null ? null : inputTarget.getWindowToken(); } @Override public void setShouldBlockScreenCaptureForApp(Set<PackageInfo> packageInfos) { synchronized (mGlobalLock) { mSensitiveContentPackages.setShouldBlockScreenCaptureForApp(packageInfos); WindowManagerService.this.refreshScreenCaptureDisabled(); } } } private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { Loading services/core/java/com/android/server/wm/WindowState.java +8 −0 Original line number Diff line number Diff line Loading @@ -1896,6 +1896,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { return true; } if (com.android.server.notification.Flags.sensitiveNotificationAppProtection()) { if (mWmService.mSensitiveContentPackages .shouldBlockScreenCaptureForApp(getOwningPackage(), getOwningUid())) { return true; } } return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId); } Loading Loading
services/core/java/com/android/server/SensitiveContentProtectionManagerService.java 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wm.SensitiveContentPackages.PackageInfo; import com.android.server.wm.WindowManagerInternal; import java.util.Collections; import java.util.Set; /** * Service that monitors for notifications with sensitive content and protects content from screen * sharing */ public final class SensitiveContentProtectionManagerService extends SystemService { private static final String TAG = "SensitiveContentProtect"; private static final boolean DEBUG = false; @VisibleForTesting NotificationListener mNotificationListener; private @Nullable MediaProjectionManager mProjectionManager; private @Nullable WindowManagerInternal mWindowManager; private final MediaProjectionManager.Callback mProjectionCallback = new MediaProjectionManager.Callback() { @Override public void onStart(MediaProjectionInfo info) { if (DEBUG) Log.d(TAG, "onStart projection: " + info); onProjectionStart(); } @Override public void onStop(MediaProjectionInfo info) { if (DEBUG) Log.d(TAG, "onStop projection: " + info); onProjectionEnd(); } }; public SensitiveContentProtectionManagerService(@NonNull Context context) { super(context); mNotificationListener = new NotificationListener(); } @Override public void onStart() {} @Override public void onBootPhase(int phase) { if (phase != SystemService.PHASE_BOOT_COMPLETED) { return; } if (DEBUG) Log.d(TAG, "onBootPhase - PHASE_BOOT_COMPLETED"); init(getContext().getSystemService(MediaProjectionManager.class), LocalServices.getService(WindowManagerInternal.class)); } @VisibleForTesting void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager) { if (DEBUG) Log.d(TAG, "init"); checkNotNull(projectionManager, "Failed to get valid MediaProjectionManager"); checkNotNull(windowManager, "Failed to get valid WindowManagerInternal"); mProjectionManager = projectionManager; mWindowManager = windowManager; // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary // handler, delegate, and binder death recipient mProjectionManager.addCallback(mProjectionCallback, new Handler(Looper.getMainLooper())); try { mNotificationListener.registerAsSystemService(getContext(), new ComponentName(getContext(), NotificationListener.class), UserHandle.USER_ALL); } catch (RemoteException e) { // Intra-process call, should never happen. } } /** Cleanup any callbacks and listeners */ @VisibleForTesting void onDestroy() { if (mProjectionManager != null) { mProjectionManager.removeCallback(mProjectionCallback); } try { mNotificationListener.unregisterAsSystemService(); } catch (RemoteException e) { // Intra-process call, should never happen. } if (mWindowManager != null) { onProjectionEnd(); } } private void onProjectionStart() { StatusBarNotification[] notifications; try { notifications = mNotificationListener.getActiveNotifications(); } catch (SecurityException e) { Log.e(TAG, "SensitiveContentProtectionManagerService doesn't have access.", e); notifications = new StatusBarNotification[0]; } RankingMap rankingMap; try { rankingMap = mNotificationListener.getCurrentRanking(); } catch (SecurityException e) { Log.e(TAG, "SensitiveContentProtectionManagerService doesn't have access.", e); rankingMap = null; } // notify windowmanager of any currently posted sensitive content notifications Set<PackageInfo> packageInfos = getSensitivePackagesFromNotifications( notifications, rankingMap); mWindowManager.setShouldBlockScreenCaptureForApp(packageInfos); } private void onProjectionEnd() { // notify windowmanager to clear any sensitive notifications observed during projection // session mWindowManager.setShouldBlockScreenCaptureForApp(Collections.emptySet()); } private Set<PackageInfo> getSensitivePackagesFromNotifications( StatusBarNotification[] notifications, RankingMap rankingMap) { if (rankingMap == null) { Log.w(TAG, "Ranking map not initialized."); return Collections.emptySet(); } Set<PackageInfo> sensitivePackages = new ArraySet<>(); for (StatusBarNotification sbn : notifications) { NotificationListenerService.Ranking ranking = rankingMap.getRawRankingObject(sbn.getKey()); if (ranking != null && ranking.hasSensitiveContent()) { PackageInfo info = new PackageInfo(sbn.getPackageName(), sbn.getUid()); sensitivePackages.add(info); } } return sensitivePackages; } // TODO(b/317251408): add trigger that updates on onNotificationPosted, // onNotificationRankingUpdate and onListenerConnected @VisibleForTesting static class NotificationListener extends NotificationListenerService {} }
services/core/java/com/android/server/wm/SensitiveContentPackages.java 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.annotation.NonNull; import android.util.ArraySet; import java.io.PrintWriter; import java.util.Objects; import java.util.Set; /** * Cache of distinct package/uid pairs that require being blocked from screen capture. This class is * not threadsafe and any call site should hold {@link WindowManagerGlobalLock} */ public class SensitiveContentPackages { private final ArraySet<PackageInfo> mProtectedPackages = new ArraySet<>(); /** Returns {@code true} if package/uid pair should be blocked from screen capture */ public boolean shouldBlockScreenCaptureForApp(String pkg, int uid) { for (int i = 0; i < mProtectedPackages.size(); i++) { PackageInfo info = mProtectedPackages.valueAt(i); if (info != null && info.mPkg.equals(pkg) && info.mUid == uid) { return true; } } return false; } /** Replaces the set of package/uid pairs to set that should be blocked from screen capture */ public void setShouldBlockScreenCaptureForApp(@NonNull Set<PackageInfo> packageInfos) { mProtectedPackages.clear(); mProtectedPackages.addAll(packageInfos); } void dump(PrintWriter pw) { final String innerPrefix = " "; pw.println("SensitiveContentPackages:"); pw.println(innerPrefix + "Packages that should block screen capture (" + mProtectedPackages.size() + "):"); for (PackageInfo info : mProtectedPackages) { pw.println(innerPrefix + " package=" + info.mPkg + " uid=" + info.mUid); } } /** Helper class that represents a package/uid pair */ public static class PackageInfo { private String mPkg; private int mUid; public PackageInfo(String pkg, int uid) { this.mPkg = pkg; this.mUid = uid; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PackageInfo)) return false; PackageInfo that = (PackageInfo) o; return mUid == that.mUid && Objects.equals(mPkg, that.mPkg); } @Override public int hashCode() { return Objects.hash(mPkg, mUid); } } }
services/core/java/com/android/server/wm/WindowManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.window.ScreenCapture; import com.android.internal.policy.KeyInterceptionInfo; import com.android.server.input.InputManagerService; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.SensitiveContentPackages.PackageInfo; import java.lang.annotation.Retention; import java.util.List; Loading Loading @@ -1012,4 +1013,12 @@ public abstract class WindowManagerInternal { */ public abstract void setOrientationRequestPolicy(boolean respected, int[] fromOrientations, int[] toOrientations); /** * Set whether screen capture should be disabled for all windows of a specific app windows based * on sensitive content protections. * * @param packageInfos set of {@link PackageInfo} whose windows should be blocked from capture */ public abstract void setShouldBlockScreenCaptureForApp(@NonNull Set<PackageInfo> packageInfos); }
services/core/java/com/android/server/wm/WindowManagerService.java +18 −2 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; import static com.android.server.wm.SensitiveContentPackages.PackageInfo; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; Loading Loading @@ -312,6 +313,7 @@ import android.window.WindowContainerToken; import android.window.WindowContextInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; Loading Loading @@ -366,6 +368,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; Loading Loading @@ -1053,6 +1056,9 @@ public class WindowManagerService extends IWindowManager.Stub SystemPerformanceHinter mSystemPerformanceHinter; @GuardedBy("mGlobalLock") final SensitiveContentPackages mSensitiveContentPackages = new SensitiveContentPackages(); /** Listener to notify activity manager about app transitions. */ final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier = new WindowManagerInternal.AppTransitionListener() { Loading Loading @@ -1931,12 +1937,13 @@ public class WindowManagerService extends IWindowManager.Stub /** * Set whether screen capture is disabled for all windows of a specific user from * the device policy cache. * the device policy cache, or specific windows based on sensitive content protections. */ @Override public void refreshScreenCaptureDisabled() { int callingUid = Binder.getCallingUid(); if (callingUid != SYSTEM_UID) { // MY_UID (Process.myUid()) should always be SYSTEM_UID here, but using MY_UID for tests if (callingUid != MY_UID) { throw new SecurityException("Only system can call refreshScreenCaptureDisabled."); } Loading Loading @@ -7169,6 +7176,7 @@ public class WindowManagerService extends IWindowManager.Stub } mSystemPerformanceHinter.dump(pw, ""); mTrustedPresentationListenerController.dump(pw); mSensitiveContentPackages.dump(pw); } } Loading Loading @@ -8550,6 +8558,14 @@ public class WindowManagerService extends IWindowManager.Stub InputTarget inputTarget = WindowManagerService.this.getInputTargetFromToken(inputToken); return inputTarget == null ? null : inputTarget.getWindowToken(); } @Override public void setShouldBlockScreenCaptureForApp(Set<PackageInfo> packageInfos) { synchronized (mGlobalLock) { mSensitiveContentPackages.setShouldBlockScreenCaptureForApp(packageInfos); WindowManagerService.this.refreshScreenCaptureDisabled(); } } } private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { Loading
services/core/java/com/android/server/wm/WindowState.java +8 −0 Original line number Diff line number Diff line Loading @@ -1896,6 +1896,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { return true; } if (com.android.server.notification.Flags.sensitiveNotificationAppProtection()) { if (mWmService.mSensitiveContentPackages .shouldBlockScreenCaptureForApp(getOwningPackage(), getOwningUid())) { return true; } } return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId); } Loading