Loading core/java/android/app/admin/DevicePolicyManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -217,4 +217,9 @@ public abstract class DevicePolicyManagerInternal { */ public abstract void broadcastIntentToCrossProfileManifestReceiversAsUser(Intent intent, UserHandle parentHandle, boolean requiresPermission); /** * Returns the profile owner component for the given user, or {@code null} if there is not one. */ public abstract ComponentName getProfileOwnerAsUser(int userHandle); } services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +26 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.app.IApplicationThread; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -256,6 +257,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (enabledProfileIds.length < 2) { return false; } if (isProfileOwner(packageName, enabledProfileIds)) { return false; } return hasRequestedAppOpPermission( AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName); } Loading Loading @@ -575,6 +579,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (profileIds.length < 2) { return false; } if (isProfileOwner(packageName, profileIds)) { return false; } return hasRequestedAppOpPermission( AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName) && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds); Loading Loading @@ -698,6 +705,25 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { packageName); } private boolean isProfileOwner(String packageName, int[] userIds) { for (int userId : userIds) { if (isProfileOwner(packageName, userId)) { return true; } } return false; } private boolean isProfileOwner(String packageName, final @UserIdInt int userId) { final ComponentName profileOwner = mInjector.withCleanCallingIdentity(() -> mInjector.getDevicePolicyManagerInternal().getProfileOwnerAsUser(userId)); if (profileOwner == null) { return false; } return profileOwner.getPackageName().equals(packageName); } private static class InjectorImpl implements Injector { private Context mContext; Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -12730,6 +12730,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Binder.restoreCallingIdentity(ident); } } @Override public ComponentName getProfileOwnerAsUser(int userHandle) { return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle); } } private Intent createShowAdminSupportIntent(ComponentName admin, int userId) { services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +38 −0 Original line number Diff line number Diff line Loading @@ -37,7 +37,9 @@ import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; Loading Loading @@ -97,6 +99,7 @@ public class CrossProfileAppsServiceImplRoboTest { private static final int WORK_PROFILE_USER_ID = 10; private static final int WORK_PROFILE_UID = 3333; private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20; private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30; private final ContextWrapper mContext = ApplicationProvider.getApplicationContext(); private final UserManager mUserManager = mContext.getSystemService(UserManager.class); Loading Loading @@ -226,6 +229,7 @@ public class CrossProfileAppsServiceImplRoboTest { PERSONAL_PROFILE_USER_ID, WORK_PROFILE_USER_ID, OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID); shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID); } @Before Loading Loading @@ -503,6 +507,36 @@ public class CrossProfileAppsServiceImplRoboTest { .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerWorkProfile_returnsFalse() { when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(WORK_PROFILE_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOtherProfile_returnsFalse() { // Normally, the DPC would not be a profile owner of the personal profile, but for the // purposes of this test, it is just a profile owner of any profile within the profile // group. when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(PERSONAL_PROFILE_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() { when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isTrue(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() { assertThat(mCrossProfileAppsServiceImpl Loading Loading @@ -607,6 +641,10 @@ public class CrossProfileAppsServiceImplRoboTest { .hideAsParsed()).hideAsFinal()); } private ComponentName buildCrossProfileComponentName() { return new ComponentName(CROSS_PROFILE_APP_PACKAGE_NAME, "testClassName"); } private class TestInjector implements CrossProfileAppsServiceImpl.Injector { @Override Loading Loading
core/java/android/app/admin/DevicePolicyManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -217,4 +217,9 @@ public abstract class DevicePolicyManagerInternal { */ public abstract void broadcastIntentToCrossProfileManifestReceiversAsUser(Intent intent, UserHandle parentHandle, boolean requiresPermission); /** * Returns the profile owner component for the given user, or {@code null} if there is not one. */ public abstract ComponentName getProfileOwnerAsUser(int userHandle); }
services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +26 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.app.IApplicationThread; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -256,6 +257,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (enabledProfileIds.length < 2) { return false; } if (isProfileOwner(packageName, enabledProfileIds)) { return false; } return hasRequestedAppOpPermission( AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName); } Loading Loading @@ -575,6 +579,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (profileIds.length < 2) { return false; } if (isProfileOwner(packageName, profileIds)) { return false; } return hasRequestedAppOpPermission( AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName) && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds); Loading Loading @@ -698,6 +705,25 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { packageName); } private boolean isProfileOwner(String packageName, int[] userIds) { for (int userId : userIds) { if (isProfileOwner(packageName, userId)) { return true; } } return false; } private boolean isProfileOwner(String packageName, final @UserIdInt int userId) { final ComponentName profileOwner = mInjector.withCleanCallingIdentity(() -> mInjector.getDevicePolicyManagerInternal().getProfileOwnerAsUser(userId)); if (profileOwner == null) { return false; } return profileOwner.getPackageName().equals(packageName); } private static class InjectorImpl implements Injector { private Context mContext; Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -12730,6 +12730,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Binder.restoreCallingIdentity(ident); } } @Override public ComponentName getProfileOwnerAsUser(int userHandle) { return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle); } } private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +38 −0 Original line number Diff line number Diff line Loading @@ -37,7 +37,9 @@ import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; Loading Loading @@ -97,6 +99,7 @@ public class CrossProfileAppsServiceImplRoboTest { private static final int WORK_PROFILE_USER_ID = 10; private static final int WORK_PROFILE_UID = 3333; private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20; private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30; private final ContextWrapper mContext = ApplicationProvider.getApplicationContext(); private final UserManager mUserManager = mContext.getSystemService(UserManager.class); Loading Loading @@ -226,6 +229,7 @@ public class CrossProfileAppsServiceImplRoboTest { PERSONAL_PROFILE_USER_ID, WORK_PROFILE_USER_ID, OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID); shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID); } @Before Loading Loading @@ -503,6 +507,36 @@ public class CrossProfileAppsServiceImplRoboTest { .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerWorkProfile_returnsFalse() { when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(WORK_PROFILE_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOtherProfile_returnsFalse() { // Normally, the DPC would not be a profile owner of the personal profile, but for the // purposes of this test, it is just a profile owner of any profile within the profile // group. when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(PERSONAL_PROFILE_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isFalse(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() { when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) .isTrue(); } @Test public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() { assertThat(mCrossProfileAppsServiceImpl Loading Loading @@ -607,6 +641,10 @@ public class CrossProfileAppsServiceImplRoboTest { .hideAsParsed()).hideAsFinal()); } private ComponentName buildCrossProfileComponentName() { return new ComponentName(CROSS_PROFILE_APP_PACKAGE_NAME, "testClassName"); } private class TestInjector implements CrossProfileAppsServiceImpl.Injector { @Override Loading