summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java65
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt66
-rw-r--r--services/core/java/com/android/server/SensitiveContentProtectionManagerService.java21
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java23
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java21
6 files changed, 174 insertions, 27 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
index 799e957656dc..bab5a2d6793d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy
import android.app.IActivityManager
+import android.app.role.RoleManager
import android.content.pm.PackageManager
import android.media.projection.MediaProjectionManager
import android.os.Handler
@@ -48,6 +49,7 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase(
@Mock private lateinit var mediaProjectionManager: MediaProjectionManager
@Mock private lateinit var packageManager: PackageManager
@Mock private lateinit var telephonyManager: TelephonyManager
+ @Mock private lateinit var roleManager: RoleManager
private lateinit var controller: SensitiveNotificationProtectionControllerImpl
@Before
@@ -62,9 +64,10 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase(
activityManager,
packageManager,
telephonyManager,
+ roleManager,
handler,
FakeExecutor(FakeSystemClock()),
- logger
+ logger,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
index 9ab8175e13b8..36513f77f1a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
@@ -24,6 +24,9 @@ import static com.android.systemui.Flags.screenshareNotificationHidingBugFix;
import android.annotation.MainThread;
import android.app.IActivityManager;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ExecutorContentObserver;
@@ -51,6 +54,8 @@ import com.android.systemui.util.Assert;
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.settings.GlobalSettings;
+import java.util.List;
+import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Executor;
@@ -63,12 +68,14 @@ public class SensitiveNotificationProtectionControllerImpl
private static final String LOG_TAG = "SNPC";
private final SensitiveNotificationProtectionControllerLogger mLogger;
private final PackageManager mPackageManager;
+ private final RoleManager mRoleManager;
// Packages exempt from projection session protections (if they start a projection session)
private final ArraySet<String> mSessionProtectionExemptPackages = new ArraySet<>();
// Packages exempt from individual notification protections (if they post a notification)
private final ArraySet<String> mNotificationProtectionExemptPackages = new ArraySet<>();
private final ListenerSet<Runnable> mListeners = new ListenerSet<>();
private volatile MediaProjectionInfo mProjection;
+ private ArraySet<RoleHolder> mNotificationProtectionExemptByRolePackages = new ArraySet<>();
private SensitiveNotificatioMediaProjectionSession mActiveMediaProjectionSession;
boolean mDisableScreenShareProtections = false;
@@ -128,6 +135,27 @@ public class SensitiveNotificationProtectionControllerImpl
}
};
+ @VisibleForTesting
+ final OnRoleHoldersChangedListener mRoleHoldersChangedListener =
+ new OnRoleHoldersChangedListener() {
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName,
+ @NonNull UserHandle user) {
+ if (!roleName.equals(AssociationRequest.DEVICE_PROFILE_APP_STREAMING)) {
+ return;
+ }
+
+ List<String> appStreamingRoleHolders = mRoleManager.getRoleHoldersAsUser(
+ roleName, user);
+ ArraySet<RoleHolder> roleHolders = new ArraySet<>();
+ for (String appStreamingRoleHolder : appStreamingRoleHolders) {
+ RoleHolder roleHolder = new RoleHolder(appStreamingRoleHolder, user);
+ roleHolders.add(roleHolder);
+ }
+ mNotificationProtectionExemptByRolePackages = roleHolders;
+ }
+ };
+
private void logSensitiveContentProtectionSessionStart(
long sessionId, int projectionAppUid, boolean exempt) {
mActiveMediaProjectionSession =
@@ -166,11 +194,13 @@ public class SensitiveNotificationProtectionControllerImpl
IActivityManager activityManager,
PackageManager packageManager,
TelephonyManager telephonyManager,
+ RoleManager roleManager,
@Main Handler mainHandler,
@Background Executor bgExecutor,
SensitiveNotificationProtectionControllerLogger logger) {
mLogger = logger;
mPackageManager = packageManager;
+ mRoleManager = roleManager;
if (!screenshareNotificationHiding()) {
return;
@@ -215,6 +245,8 @@ public class SensitiveNotificationProtectionControllerImpl
});
mediaProjectionManager.addCallback(mMediaProjectionCallback, mainHandler);
+ roleManager.addOnRoleHoldersChangedListenerAsUser(bgExecutor, mRoleHoldersChangedListener,
+ UserHandle.ALL);
}
@NonNull
@@ -314,6 +346,10 @@ public class SensitiveNotificationProtectionControllerImpl
Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName()
+ " via permission");
return null;
+ } else if (info != null && isAppStreamingRoleHolder(info)) {
+ Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName()
+ + " via role(s) held");
+ return null;
} else if (info != null && info.getLaunchCookie() != null) {
// Only enable sensitive content protection if sharing full screen
// Launch cookie only set (non-null) if sharing single app/task
@@ -323,11 +359,16 @@ public class SensitiveNotificationProtectionControllerImpl
return info;
}
+ private boolean isAppStreamingRoleHolder(@NonNull MediaProjectionInfo info) {
+ return mNotificationProtectionExemptByRolePackages.contains(
+ new RoleHolder(info.getPackageName(), info.getUserHandle()));
+ }
+
private boolean canRecordSensitiveContent(@NonNull String packageName) {
// RECORD_SENSITIVE_CONTENT is flagged api on sensitiveNotificationAppProtection
if (sensitiveNotificationAppProtection()) {
return mPackageManager.checkPermission(
- android.Manifest.permission.RECORD_SENSITIVE_CONTENT, packageName)
+ android.Manifest.permission.RECORD_SENSITIVE_CONTENT, packageName)
== PackageManager.PERMISSION_GRANTED;
}
return false;
@@ -382,4 +423,26 @@ public class SensitiveNotificationProtectionControllerImpl
boolean userForcesRedaction = entry.isChannelVisibilityPrivate();
return notificationRequestsRedaction || userForcesRedaction;
}
+
+ private static final class RoleHolder {
+ private final String mPackageName;
+ private final UserHandle mUserHandle;
+
+ RoleHolder(String packageName, UserHandle userHandle) {
+ mPackageName = packageName;
+ mUserHandle = userHandle;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RoleHolder that)) return false;
+ return Objects.equals(mPackageName, that.mPackageName) && Objects.equals(
+ mUserHandle, that.mUserHandle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mUserHandle);
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
index 573927552acc..7e27783a116e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
@@ -25,6 +25,9 @@ import android.app.Notification.VISIBILITY_PUBLIC
import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
+import android.app.role.OnRoleHoldersChangedListener
+import android.app.role.RoleManager
+import android.companion.AssociationRequest
import android.content.pm.PackageManager
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
@@ -89,6 +92,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
@Mock private lateinit var activityManager: IActivityManager
@Mock private lateinit var mediaProjectionManager: MediaProjectionManager
@Mock private lateinit var packageManager: PackageManager
+ @Mock private lateinit var roleManager: RoleManager
@Mock private lateinit var telephonyManager: TelephonyManager
@Mock private lateinit var listener1: Runnable
@Mock private lateinit var listener2: Runnable
@@ -98,6 +102,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
private lateinit var executor: FakeExecutor
private lateinit var globalSettings: FakeGlobalSettings
private lateinit var mediaProjectionCallback: MediaProjectionManager.Callback
+ private lateinit var roleHolderCallback: OnRoleHoldersChangedListener
private lateinit var controller: SensitiveNotificationProtectionControllerImpl
private lateinit var mediaProjectionInfo: MediaProjectionInfo
@@ -117,14 +122,14 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.getPackageUidAsUser(
TEST_PROJECTION_PACKAGE_NAME,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(TEST_PROJECTION_PACKAGE_UID)
whenever(
packageManager.getPackageUidAsUser(
BUGREPORT_PACKAGE_NAME,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(BUGREPORT_PACKAGE_UID)
@@ -134,7 +139,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.getPackageUidAsUser(
mContext.packageName,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(mContext.applicationInfo.uid)
@@ -155,9 +160,10 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
activityManager,
packageManager,
telephonyManager,
+ roleManager,
mockExecutorHandler(executor),
executor,
- logger
+ logger,
)
// Process pending work (getting global setting and list of exemptions)
@@ -167,6 +173,9 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
mediaProjectionCallback = withArgCaptor {
verify(mediaProjectionManager).addCallback(capture(), any())
}
+ roleHolderCallback = withArgCaptor {
+ verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), capture(), any())
+ }
}
@After
@@ -307,7 +316,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -322,7 +331,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -340,6 +349,25 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
}
@Test
+ fun isSensitiveStateActive_projectionActive_appStreamingRoleHolderExempt_false() {
+ setShareFullScreen()
+ whenever(
+ roleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.userHandle,
+ )
+ )
+ .thenReturn(listOf(TEST_PROJECTION_PACKAGE_NAME))
+ roleHolderCallback.onRoleHoldersChanged(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.userHandle,
+ )
+ mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+ assertFalse(controller.isSensitiveStateActive)
+ }
+
+ @Test
fun isSensitiveStateActive_projectionActive_disabledViaDevOption_false() {
setDisabledViaDeveloperOption()
mediaProjectionCallback.onStart(mediaProjectionInfo)
@@ -449,7 +477,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -466,7 +494,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -528,7 +556,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(false),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -541,7 +569,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(false),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -559,7 +587,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -572,7 +600,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -590,7 +618,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -603,7 +631,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -623,7 +651,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(mContext.applicationInfo.uid),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -636,7 +664,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(mContext.applicationInfo.uid),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -654,7 +682,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(BUGREPORT_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -667,7 +695,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
eq(BUGREPORT_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -757,7 +785,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
return setupNotificationEntry(
packageName,
overrideVisibility = true,
- overrideChannelVisibility = true
+ overrideChannelVisibility = true,
)
}
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index 04edb5756599..cd632e638281 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -31,6 +31,8 @@ import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListene
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -81,6 +83,8 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
private PackageManagerInternal mPackageManagerInternal;
+ private RoleManager mRoleManager;
+
@Nullable
private WindowManagerInternal mWindowManager;
@@ -225,7 +229,8 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
}
@Override
- public void onStart() {}
+ public void onStart() {
+ }
@Override
public void onBootPhase(int phase) {
@@ -237,6 +242,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
init(getContext().getSystemService(MediaProjectionManager.class),
LocalServices.getService(WindowManagerInternal.class),
LocalServices.getService(PackageManagerInternal.class),
+ getContext().getSystemService(RoleManager.class),
getExemptedPackages()
);
if (sensitiveContentAppProtection()) {
@@ -247,7 +253,8 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
@VisibleForTesting
void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager,
- PackageManagerInternal packageManagerInternal, ArraySet<String> exemptedPackages) {
+ PackageManagerInternal packageManagerInternal, RoleManager roleManager,
+ ArraySet<String> exemptedPackages) {
if (DEBUG) Log.d(TAG, "init");
Objects.requireNonNull(projectionManager);
@@ -256,6 +263,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
mProjectionManager = projectionManager;
mWindowManager = windowManager;
mPackageManagerInternal = packageManagerInternal;
+ mRoleManager = roleManager;
mExemptedPackages = exemptedPackages;
// TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary
@@ -312,8 +320,10 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
boolean isPackageExempted = (mExemptedPackages != null && mExemptedPackages.contains(
projectionInfo.getPackageName()))
|| canRecordSensitiveContent(projectionInfo.getPackageName())
+ || holdsAppStreamingRole(projectionInfo.getPackageName(),
+ projectionInfo.getUserHandle())
|| isAutofillServiceRecorderPackage(projectionInfo.getUserHandle().getIdentifier(),
- projectionInfo.getPackageName());
+ 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;
@@ -348,6 +358,11 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
}
}
+ private boolean holdsAppStreamingRole(String packageName, UserHandle userHandle) {
+ return mRoleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING, userHandle).contains(packageName);
+ }
+
private void onProjectionEnd() {
synchronized (mSensitiveContentProtectionLock) {
mProjectionActive = false;
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
index 5ddd8a50135b..2e315ecd7b37 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
@@ -26,7 +26,10 @@ 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.when;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.pm.PackageManagerInternal;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
@@ -54,6 +57,7 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -74,6 +78,7 @@ public class SensitiveContentProtectionManagerServiceContentTest {
@Mock private WindowManagerInternal mWindowManager;
@Mock private MediaProjectionManager mProjectionManager;
@Mock private PackageManagerInternal mPackageManagerInternal;
+ @Mock private RoleManager mRoleManager;
private MediaProjectionInfo mMediaProjectionInfo;
@Captor
@@ -93,7 +98,8 @@ public class SensitiveContentProtectionManagerServiceContentTest {
mSensitiveContentProtectionManagerService =
new SensitiveContentProtectionManagerService(mContext);
mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager,
- mPackageManagerInternal, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage)));
+ mPackageManagerInternal, mRoleManager,
+ new ArraySet<>(Set.of(mExemptedScreenRecorderPackage)));
verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any());
mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue();
mMediaProjectionInfo =
@@ -152,7 +158,7 @@ public class SensitiveContentProtectionManagerServiceContentTest {
String testAutofillService = mScreenRecorderPackage + "/com.example.SampleAutofillService";
int userId = Process.myUserHandle().getIdentifier();
Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.AUTOFILL_SERVICE, testAutofillService , userId);
+ Settings.Secure.AUTOFILL_SERVICE, testAutofillService, userId);
mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
@@ -169,6 +175,19 @@ public class SensitiveContentProtectionManagerServiceContentTest {
verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
+ @Test
+ public void testAppStreamingRoleHolderExemption() {
+ when(mRoleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mMediaProjectionInfo.getUserHandle())).thenReturn(
+ List.of(mMediaProjectionInfo.getPackageName()));
+
+ mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
+ mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+ mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ }
+
private void mockDisabledViaDeveloperOption() {
Settings.Global.putInt(
mContext.getContentResolver(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index 32135f1cb7fa..3c6e18f822af 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -33,6 +33,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.pm.PackageManagerInternal;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
@@ -67,6 +69,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -116,6 +119,9 @@ public class SensitiveContentProtectionManagerServiceNotificationTest {
private PackageManagerInternal mPackageManagerInternal;
@Mock
+ private RoleManager mRoleManager;
+
+ @Mock
private StatusBarNotification mNotification1;
@Mock
@@ -161,7 +167,8 @@ public class SensitiveContentProtectionManagerServiceNotificationTest {
setupSensitiveNotification();
mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager,
- mPackageManagerInternal, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE)));
+ mPackageManagerInternal, mRoleManager,
+ new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE)));
// Obtain useful mMediaProjectionCallback
verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any());
@@ -315,6 +322,18 @@ public class SensitiveContentProtectionManagerServiceNotificationTest {
}
@Test
+ public void mediaProjectionOnStart_verifyExemptedAppStreamingPackage() {
+ MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
+ when(mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.getUserHandle())).thenReturn(
+ List.of(mediaProjectionInfo.getPackageName()));
+
+ mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
+
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ }
+
+ @Test
public void mediaProjectionOnStart_verifyExemptedRecorderPackage() {
MediaProjectionInfo mediaProjectionInfo = createExemptMediaProjectionInfo();