Do not allow DO and PO running on the same user.
Bug 25346603
Change-Id: Ic5fbed82466a538fbf64ef802fc2624dd67313bb
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index aea2ecf..debb41b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4799,10 +4799,14 @@
if (info.isGuest()) {
throw new IllegalStateException("Cannot set a profile owner on a guest");
}
- if (getProfileOwner(userHandle) != null) {
+ if (mOwners.hasProfileOwner(userHandle)) {
throw new IllegalStateException("Trying to set the profile owner, but profile owner "
+ "is already set.");
}
+ if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userHandle) {
+ throw new IllegalStateException("Trying to set the profile owner, but the user "
+ + "already has a device owner.");
+ }
int callingUid = mInjector.binderGetCallingUid();
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
if (hasUserSetupCompleted(userHandle) &&
@@ -4832,6 +4836,10 @@
throw new IllegalStateException("Trying to set the device owner, but device owner "
+ "is already set.");
}
+ if (mOwners.hasProfileOwner(userId)) {
+ throw new IllegalStateException("Trying to set the device owner, but the user already "
+ + "has a profile owner.");
+ }
if (!mUserManager.isUserRunning(new UserHandle(userId))) {
throw new IllegalStateException("User not running: " + userId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 12b3775..ded4422 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -121,17 +121,20 @@
if (!legacy.delete()) {
Slog.e(TAG, "Failed to remove the legacy setting file");
}
- return;
- }
+ } else {
+ // No legacy file, read from the new format files.
+ new DeviceOwnerReadWriter().readFromFileLocked();
- // No legacy file, read from the new format files.
- new DeviceOwnerReadWriter().readFromFileLocked();
-
- final List<UserInfo> users = mUserManager.getUsers();
- for (UserInfo ui : users) {
- new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (UserInfo ui : users) {
+ new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
+ }
}
}
+ if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
+ Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
+ getDeviceOwnerUserId()));
+ }
}
String getDeviceOwnerPackageName() {
@@ -218,6 +221,10 @@
return mDeviceOwner != null;
}
+ boolean hasProfileOwner(int userId) {
+ return getProfileOwnerComponent(userId) != null;
+ }
+
/**
* @return true if user restrictions need to be migrated for DO.
*/
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 727858b..d579f58 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -490,6 +490,17 @@
assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
+ // Try to set a profile owner on the same user, which should fail.
+ setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ dpm.setActiveAdmin(admin2, /* refreshing= */ true, UserHandle.USER_SYSTEM);
+ try {
+ dpm.setProfileOwner(admin2, "owner-name", UserHandle.USER_SYSTEM);
+ fail("IllegalStateException not thrown");
+ } catch (IllegalStateException expected) {
+ assertTrue("Message was: " + expected.getMessage(),
+ expected.getMessage().contains("already has a device owner"));
+ }
+
// TODO Test getDeviceOwnerName() too. To do so, we need to change
// DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
}
@@ -509,6 +520,8 @@
dpm.setDeviceOwner(new ComponentName("a.b.c", ".def"));
fail("Didn't throw IllegalArgumentException");
} catch (IllegalArgumentException expected) {
+ assertTrue("Message was: " + expected.getMessage(),
+ expected.getMessage().contains("Invalid component"));
}
}
@@ -597,6 +610,17 @@
public void testSetProfileOwner() throws Exception {
setAsProfileOwner(admin1);
+
+ // Try setting DO on the same user, which should fail.
+ setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
+ dpm.setActiveAdmin(admin2, /* refreshing= */ true, DpmMockContext.CALLER_USER_HANDLE);
+ try {
+ dpm.setDeviceOwner(admin2, "owner-name", DpmMockContext.CALLER_USER_HANDLE);
+ fail("IllegalStateException not thrown");
+ } catch (IllegalStateException expected) {
+ assertTrue("Message was: " + expected.getMessage(),
+ expected.getMessage().contains("already has a profile owner"));
+ }
}
public void testSetProfileOwner_failures() throws Exception {