summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java26
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java5
-rw-r--r--services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java38
4 files changed, 74 insertions, 0 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 41f04f73aa87..8f5dbc45bf1b 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -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);
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 28c8642d3e60..b9729f02d78b 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -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;
@@ -255,6 +256,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);
}
@@ -554,6 +558,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);
@@ -677,6 +684,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;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7e4c8f3e48e5..34be681d1e47 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12683,6 +12683,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) {
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index f8d197acf883..65183f15b0fd 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -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;
@@ -96,6 +98,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);
@@ -224,6 +227,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
@@ -475,6 +479,36 @@ public class CrossProfileAppsServiceImplRoboTest {
}
@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
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -578,6 +612,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