getDefaultCrossProfilePackages();
+
/**
* Sends the {@code intent} to the packages with cross profile capabilities.
*
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 7578ede2648db..144a07eb4ea34 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -435,6 +435,9 @@ public class CrossProfileApps {
* This differs from {@link #canConfigureInteractAcrossProfiles(String)} since it will
* not return {@code false} if the app is not whitelisted or not installed in the other profile.
*
+ *
Note that platform-signed apps that are automatically granted the permission and are not
+ * whitelisted by the OEM will not be included in this list.
+ *
* @hide
*/
public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 40876754eae85..28c8642d3e608 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -294,6 +294,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
.getAllCrossProfilePackages().contains(packageName));
}
+ private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
+ return mInjector.withCleanCallingIdentity(() ->
+ mInjector.getDevicePolicyManagerInternal()
+ .getDefaultCrossProfilePackages().contains(packageName));
+ }
+
private List getTargetUserProfilesUnchecked(
String packageName, @UserIdInt int userId) {
return mInjector.withCleanCallingIdentity(() -> {
@@ -528,6 +534,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
@Override
public boolean canConfigureInteractAcrossProfiles(String packageName) {
+ if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
+ return false;
+ }
if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
return false;
}
@@ -546,7 +555,35 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
return false;
}
return hasRequestedAppOpPermission(
- AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
+ AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
+ && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
+ }
+
+ private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
+ String packageName, int[] profileIds) {
+ return !isCrossProfilePackageWhitelistedByDefault(packageName)
+ && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
+ }
+
+ /**
+ * Only platform-signed apps can be granted INTERACT_ACROSS_PROFILES automatically without user
+ * consent.
+ *
+ * Returns true if the app is automatically granted the permission in at least one profile.
+ */
+ private boolean isPlatformSignedAppWithAutomaticProfilesPermission(
+ String packageName, int[] profileIds) {
+ for (int userId : profileIds) {
+ final int uid = mInjector.getPackageManagerInternal().getPackageUidInternal(
+ packageName, /* flags= */ 0, userId);
+ if (uid == -1) {
+ continue;
+ }
+ if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
+ return true;
+ }
+ }
+ return false;
}
private boolean hasOtherProfileWithPackageInstalled(String packageName, @UserIdInt int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d1c47d9feed75..67e83bad154f8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12459,6 +12459,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return DevicePolicyManagerService.this.getAllCrossProfilePackages();
}
+ @Override
+ public List getDefaultCrossProfilePackages() {
+ return DevicePolicyManagerService.this.getDefaultCrossProfilePackages();
+ }
+
/**
* Sends the {@code intent} to the packages with cross profile capabilities.
*
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 138f9829c0888..f8d197acf8833 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -199,6 +199,12 @@ public class CrossProfileAppsServiceImplRoboTest {
CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
ShadowApplicationPackageManager.setPackageUidAsUser(
CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
+ when(mPackageManagerInternal.getPackageUidInternal(
+ CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
+ .thenReturn(PERSONAL_PROFILE_UID);
+ when(mPackageManagerInternal.getPackageUidInternal(
+ CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
+ .thenReturn(WORK_PROFILE_UID);
}
@Before
@@ -455,6 +461,19 @@ public class CrossProfileAppsServiceImplRoboTest {
.isTrue();
}
+ @Test
+ public void canUserAttemptToConfigureInteractAcrossProfiles_platformSignedAppWithAutomaticPermission_returnsFalse() {
+ mockCrossProfileAppNotWhitelistedByOem();
+ shadowOf(mContext).grantPermissions(
+ Process.myPid(),
+ PERSONAL_PROFILE_UID,
+ Manifest.permission.INTERACT_ACROSS_PROFILES);
+
+ assertThat(mCrossProfileAppsServiceImpl
+ .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+ .isFalse();
+ }
+
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
assertThat(mCrossProfileAppsServiceImpl
@@ -528,6 +547,11 @@ public class CrossProfileAppsServiceImplRoboTest {
.thenReturn(new ArrayList<>());
}
+ private void mockCrossProfileAppNotWhitelistedByOem() {
+ when(mDevicePolicyManagerInternal.getDefaultCrossProfilePackages())
+ .thenReturn(new ArrayList<>());
+ }
+
private boolean receivedManifestCanInteractAcrossProfilesChangedBroadcast() {
final UserHandle userHandle = UserHandle.of(PERSONAL_PROFILE_USER_ID);
if (!mSentUserBroadcasts.containsKey(userHandle)) {