Loading services/core/java/com/android/server/SensitiveContentProtectionManagerService.java +35 −16 Original line number Diff line number Diff line Loading @@ -161,20 +161,20 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } if (DEBUG) Log.d(TAG, "onBootPhase - PHASE_BOOT_COMPLETED"); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); init(getContext().getSystemService(MediaProjectionManager.class), LocalServices.getService(WindowManagerInternal.class), getExemptedPackages()); LocalServices.getService(PackageManagerInternal.class), getExemptedPackages() ); if (sensitiveContentAppProtection()) { publishBinderService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE, new SensitiveContentProtectionManagerServiceBinder(mPackageManagerInternal)); new SensitiveContentProtectionManagerServiceBinder()); } } @VisibleForTesting void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager, ArraySet<String> exemptedPackages) { PackageManagerInternal packageManagerInternal, ArraySet<String> exemptedPackages) { if (DEBUG) Log.d(TAG, "init"); Objects.requireNonNull(projectionManager); Loading @@ -182,6 +182,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic mProjectionManager = projectionManager; mWindowManager = windowManager; mPackageManagerInternal = packageManagerInternal; mExemptedPackages = exemptedPackages; // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary Loading Loading @@ -231,14 +232,16 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } private void onProjectionStart(MediaProjectionInfo projectionInfo) { int uid = mPackageManagerInternal.getPackageUid(projectionInfo.getPackageName(), 0, projectionInfo.getUserHandle().getIdentifier()); boolean isPackageExempted = (mExemptedPackages != null && mExemptedPackages.contains( projectionInfo.getPackageName())) || canRecordSensitiveContent(projectionInfo.getPackageName()); || canRecordSensitiveContent(projectionInfo.getPackageName()) || isAutofillServiceRecorderPackage(projectionInfo.getUserHandle().getIdentifier(), projectionInfo.getPackageName()); // TODO(b/324447419): move GlobalSettings lookup to background thread boolean isFeatureDisabled = Settings.Global.getInt(getContext().getContentResolver(), DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0; int uid = mPackageManagerInternal.getPackageUid(projectionInfo.getPackageName(), 0, projectionInfo.getUserHandle().getIdentifier()); mMediaProjectionSession = new MediaProjectionSession( uid, isPackageExempted || isFeatureDisabled, new Random().nextLong()); Loading Loading @@ -295,9 +298,10 @@ public final class SensitiveContentProtectionManagerService extends SystemServic // notify windowmanager of any currently posted sensitive content notifications ArraySet<PackageInfo> packageInfos = getSensitivePackagesFromNotifications(notifications, rankingMap); if (packageInfos.size() > 0) { mWindowManager.addBlockScreenCaptureForApps(packageInfos); } } private ArraySet<PackageInfo> getSensitivePackagesFromNotifications( @NonNull StatusBarNotification[] notifications, RankingMap rankingMap) { Loading Loading @@ -422,6 +426,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic if (!mProjectionActive) { return; } if (DEBUG) { Log.d(TAG, "setSensitiveContentProtection - current package=" + packageInfo + ", isShowingSensitiveContent=" + isShowingSensitiveContent Loading Loading @@ -452,15 +457,29 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } } private final class SensitiveContentProtectionManagerServiceBinder extends ISensitiveContentProtectionManager.Stub { private final PackageManagerInternal mPackageManagerInternal; // TODO: b/328251279 - Autofill service exemption is temporary and will be removed in future. private boolean isAutofillServiceRecorderPackage(int userId, String projectionPackage) { String autofillServiceName = Settings.Secure.getStringForUser( getContext().getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, userId); if (DEBUG) { Log.d(TAG, "autofill service for user " + userId + " is " + autofillServiceName); } SensitiveContentProtectionManagerServiceBinder( PackageManagerInternal packageManagerInternal) { mPackageManagerInternal = packageManagerInternal; if (autofillServiceName == null) { return false; } ComponentName serviceComponent = ComponentName.unflattenFromString(autofillServiceName); if (serviceComponent == null) { return false; } String autofillServicePackage = serviceComponent.getPackageName(); return autofillServicePackage != null && autofillServicePackage.equals(projectionPackage); } private final class SensitiveContentProtectionManagerServiceBinder extends ISensitiveContentProtectionManager.Stub { public void setSensitiveContentProtection(IBinder windowToken, String packageName, boolean isShowingSensitiveContent) { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, Loading services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java +18 −1 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import static com.google.common.truth.Truth.assertThat; 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; import android.media.projection.MediaProjectionManager; import android.os.Binder; Loading Loading @@ -72,6 +74,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { @Mock private WindowManagerInternal mWindowManager; @Mock private MediaProjectionManager mProjectionManager; @Mock private PackageManagerInternal mPackageManagerInternal; private MediaProjectionInfo mMediaProjectionInfo; @Captor Loading @@ -91,7 +94,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { mSensitiveContentProtectionManagerService = new SensitiveContentProtectionManagerService(mContext); mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage))); mPackageManagerInternal, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage))); verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue(); mMediaProjectionInfo = Loading Loading @@ -145,6 +148,20 @@ public class SensitiveContentProtectionManagerServiceContentTest { verify(mWindowManager).clearBlockedApps(); } @Test public void testAutofillServicePackageExemption() { String testAutofillService = mScreenRecorderPackage + "/com.example.SampleAutofillService"; int userId = Process.myUserHandle().getIdentifier(); Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, testAutofillService , userId); mMediaPorjectionCallback.onStart(mMediaProjectionInfo); mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); verify(mWindowManager, never()) .addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test public void testDeveloperOptionDisableFeature() { mockDisabledViaDeveloperOption(); Loading services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.content.pm.PackageManagerInternal; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.platform.test.annotations.RequiresFlagsEnabled; Loading Loading @@ -103,6 +104,9 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { @Mock private WindowManagerInternal mWindowManager; @Mock private PackageManagerInternal mPackageManagerInternal; @Mock private StatusBarNotification mNotification1; Loading Loading @@ -141,7 +145,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { setupSensitiveNotification(); mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); mPackageManagerInternal, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); // Obtain useful mMediaProjectionCallback verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); Loading Loading
services/core/java/com/android/server/SensitiveContentProtectionManagerService.java +35 −16 Original line number Diff line number Diff line Loading @@ -161,20 +161,20 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } if (DEBUG) Log.d(TAG, "onBootPhase - PHASE_BOOT_COMPLETED"); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); init(getContext().getSystemService(MediaProjectionManager.class), LocalServices.getService(WindowManagerInternal.class), getExemptedPackages()); LocalServices.getService(PackageManagerInternal.class), getExemptedPackages() ); if (sensitiveContentAppProtection()) { publishBinderService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE, new SensitiveContentProtectionManagerServiceBinder(mPackageManagerInternal)); new SensitiveContentProtectionManagerServiceBinder()); } } @VisibleForTesting void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager, ArraySet<String> exemptedPackages) { PackageManagerInternal packageManagerInternal, ArraySet<String> exemptedPackages) { if (DEBUG) Log.d(TAG, "init"); Objects.requireNonNull(projectionManager); Loading @@ -182,6 +182,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic mProjectionManager = projectionManager; mWindowManager = windowManager; mPackageManagerInternal = packageManagerInternal; mExemptedPackages = exemptedPackages; // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary Loading Loading @@ -231,14 +232,16 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } private void onProjectionStart(MediaProjectionInfo projectionInfo) { int uid = mPackageManagerInternal.getPackageUid(projectionInfo.getPackageName(), 0, projectionInfo.getUserHandle().getIdentifier()); boolean isPackageExempted = (mExemptedPackages != null && mExemptedPackages.contains( projectionInfo.getPackageName())) || canRecordSensitiveContent(projectionInfo.getPackageName()); || canRecordSensitiveContent(projectionInfo.getPackageName()) || isAutofillServiceRecorderPackage(projectionInfo.getUserHandle().getIdentifier(), projectionInfo.getPackageName()); // TODO(b/324447419): move GlobalSettings lookup to background thread boolean isFeatureDisabled = Settings.Global.getInt(getContext().getContentResolver(), DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0; int uid = mPackageManagerInternal.getPackageUid(projectionInfo.getPackageName(), 0, projectionInfo.getUserHandle().getIdentifier()); mMediaProjectionSession = new MediaProjectionSession( uid, isPackageExempted || isFeatureDisabled, new Random().nextLong()); Loading Loading @@ -295,9 +298,10 @@ public final class SensitiveContentProtectionManagerService extends SystemServic // notify windowmanager of any currently posted sensitive content notifications ArraySet<PackageInfo> packageInfos = getSensitivePackagesFromNotifications(notifications, rankingMap); if (packageInfos.size() > 0) { mWindowManager.addBlockScreenCaptureForApps(packageInfos); } } private ArraySet<PackageInfo> getSensitivePackagesFromNotifications( @NonNull StatusBarNotification[] notifications, RankingMap rankingMap) { Loading Loading @@ -422,6 +426,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic if (!mProjectionActive) { return; } if (DEBUG) { Log.d(TAG, "setSensitiveContentProtection - current package=" + packageInfo + ", isShowingSensitiveContent=" + isShowingSensitiveContent Loading Loading @@ -452,15 +457,29 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } } private final class SensitiveContentProtectionManagerServiceBinder extends ISensitiveContentProtectionManager.Stub { private final PackageManagerInternal mPackageManagerInternal; // TODO: b/328251279 - Autofill service exemption is temporary and will be removed in future. private boolean isAutofillServiceRecorderPackage(int userId, String projectionPackage) { String autofillServiceName = Settings.Secure.getStringForUser( getContext().getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, userId); if (DEBUG) { Log.d(TAG, "autofill service for user " + userId + " is " + autofillServiceName); } SensitiveContentProtectionManagerServiceBinder( PackageManagerInternal packageManagerInternal) { mPackageManagerInternal = packageManagerInternal; if (autofillServiceName == null) { return false; } ComponentName serviceComponent = ComponentName.unflattenFromString(autofillServiceName); if (serviceComponent == null) { return false; } String autofillServicePackage = serviceComponent.getPackageName(); return autofillServicePackage != null && autofillServicePackage.equals(projectionPackage); } private final class SensitiveContentProtectionManagerServiceBinder extends ISensitiveContentProtectionManager.Stub { public void setSensitiveContentProtection(IBinder windowToken, String packageName, boolean isShowingSensitiveContent) { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, Loading
services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java +18 −1 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import static com.google.common.truth.Truth.assertThat; 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; import android.media.projection.MediaProjectionManager; import android.os.Binder; Loading Loading @@ -72,6 +74,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { @Mock private WindowManagerInternal mWindowManager; @Mock private MediaProjectionManager mProjectionManager; @Mock private PackageManagerInternal mPackageManagerInternal; private MediaProjectionInfo mMediaProjectionInfo; @Captor Loading @@ -91,7 +94,7 @@ public class SensitiveContentProtectionManagerServiceContentTest { mSensitiveContentProtectionManagerService = new SensitiveContentProtectionManagerService(mContext); mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage))); mPackageManagerInternal, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage))); verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue(); mMediaProjectionInfo = Loading Loading @@ -145,6 +148,20 @@ public class SensitiveContentProtectionManagerServiceContentTest { verify(mWindowManager).clearBlockedApps(); } @Test public void testAutofillServicePackageExemption() { String testAutofillService = mScreenRecorderPackage + "/com.example.SampleAutofillService"; int userId = Process.myUserHandle().getIdentifier(); Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, testAutofillService , userId); mMediaPorjectionCallback.onStart(mMediaProjectionInfo); mSensitiveContentProtectionManagerService.setSensitiveContentProtection( mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); verify(mWindowManager, never()) .addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); } @Test public void testDeveloperOptionDisableFeature() { mockDisabledViaDeveloperOption(); Loading
services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.content.pm.PackageManagerInternal; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.platform.test.annotations.RequiresFlagsEnabled; Loading Loading @@ -103,6 +104,9 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { @Mock private WindowManagerInternal mWindowManager; @Mock private PackageManagerInternal mPackageManagerInternal; @Mock private StatusBarNotification mNotification1; Loading Loading @@ -141,7 +145,7 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { setupSensitiveNotification(); mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); mPackageManagerInternal, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); // Obtain useful mMediaProjectionCallback verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); Loading