Merge "Disallow data clearing of DeviceOwner."
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 7f062d9..b11c509 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2513,6 +2513,14 @@
             return true;
         }
 
+        case UPDATE_DEVICE_OWNER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            String packageName = data.readString();
+            updateDeviceOwner(packageName);
+            reply.writeNoException();
+            return true;
+        }
+
         case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
@@ -5801,6 +5809,18 @@
     }
 
     @Override
+    public void updateDeviceOwner(String packageName) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeString(packageName);
+        mRemote.transact(UPDATE_DEVICE_OWNER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    @Override
     public int getPackageProcessState(String packageName) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 7e03faa..00558fe 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -495,6 +495,7 @@
     public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
             throws RemoteException;
     public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
+    public void updateDeviceOwner(String packageName) throws RemoteException;
 
     public int getPackageProcessState(String packageName) throws RemoteException;
 
@@ -837,4 +838,5 @@
     int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292;
     int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
     int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
+    int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9d5ae8e..a48a4d9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -437,6 +437,11 @@
      */
     SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
 
+    /**
+     * The package name of the DeviceOwner. This package is not permitted to have its data cleared.
+     */
+    String mDeviceOwnerName;
+
     public class PendingAssistExtras extends Binder implements Runnable {
         public final ActivityRecord activity;
         public final Bundle extras;
@@ -4831,6 +4836,9 @@
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) {
         enforceNotIsolatedCaller("clearApplicationUserData");
+        if (packageName != null && packageName.equals(mDeviceOwnerName)) {
+            throw new SecurityException("Clearing DeviceOwner data is forbidden.");
+        }
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
         userId = handleIncomingUser(pid, uid,
@@ -8563,6 +8571,17 @@
     }
 
     @Override
+    public void updateDeviceOwner(String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException("updateDeviceOwner called from non-system process");
+        }
+        synchronized (this) {
+            mDeviceOwnerName = packageName;
+        }
+    }
+
+    @Override
     public void updateLockTaskPackages(int userId, String[] packages) {
         final int callingUid = Binder.getCallingUid();
         if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9bb97f7..44b3f69 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1106,6 +1106,7 @@
     void loadDeviceOwner() {
         synchronized (this) {
             mDeviceOwner = DeviceOwner.load();
+            updateDeviceOwnerLocked();
         }
     }
 
@@ -1667,6 +1668,18 @@
         }
     }
 
+    private void updateDeviceOwnerLocked() {
+        IActivityManager am = ActivityManagerNative.getDefault();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            am.updateDeviceOwner(mDeviceOwner.getDeviceOwnerPackageName());
+        } catch (RemoteException e) {
+            // Not gonna happen.
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     static void validateQualityConstant(int quality) {
         switch (quality) {
             case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
@@ -3990,14 +4003,13 @@
             if (mDeviceOwner == null) {
                 // Device owner is not set and does not exist, set it.
                 mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName);
-                mDeviceOwner.writeOwnerFile();
-                return true;
             } else {
                 // Device owner is not set but a profile owner exists, update Device owner state.
                 mDeviceOwner.setDeviceOwner(packageName, ownerName);
-                mDeviceOwner.writeOwnerFile();
-                return true;
             }
+            mDeviceOwner.writeOwnerFile();
+            updateDeviceOwnerLocked();
+            return true;
         }
     }
 
@@ -4079,6 +4091,7 @@
                 if (mDeviceOwner != null) {
                     mDeviceOwner.clearDeviceOwner();
                     mDeviceOwner.writeOwnerFile();
+                    updateDeviceOwnerLocked();
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -4107,15 +4120,13 @@
 
             if (mDeviceOwner == null) {
                 // Device owner state does not exist, create it.
-                mDeviceOwner = DeviceOwner.createWithDeviceInitializer(
-                        initializer, ownerName);
+                mDeviceOwner = DeviceOwner.createWithDeviceInitializer(initializer, ownerName);
             } else {
                 // Device owner already exists, update it.
                 mDeviceOwner.setDeviceInitializer(initializer, ownerName);
             }
 
             addDeviceInitializerToLockTaskPackagesLocked(UserHandle.USER_OWNER);
-
             mDeviceOwner.writeOwnerFile();
             return true;
         }