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 {