Merge "Keep track of user_setup_complete in DPMS" into lmp-dev
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 92d3d95..9e4d90d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -55,7 +55,9 @@
 import android.media.AudioManager;
 import android.media.IAudioService;
 import android.net.ConnectivityManager;
+import android.net.Uri;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
 import android.net.ProxyInfo;
 import android.os.Binder;
 import android.os.Bundle;
@@ -136,6 +138,7 @@
     private static final boolean DBG = false;
 
     private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
+    private static final String ATTR_SETUP_COMPLETE = "setup-complete";
 
     final Context mContext;
     final UserManager mUserManager;
@@ -174,6 +177,7 @@
             }
         }
     }
+
     public static class DevicePolicyData {
         int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
         int mActivePasswordLength = 0;
@@ -188,6 +192,7 @@
         int mUserHandle;
         int mPasswordOwner = -1;
         long mLastMaximumTimeToLock = -1;
+        boolean mUserSetupComplete = false;
 
         final HashMap<ComponentName, ActiveAdmin> mAdminMap
                 = new HashMap<ComponentName, ActiveAdmin>();
@@ -973,6 +978,10 @@
                 out.attribute(null, ATTR_PERMISSION_PROVIDER,
                         policy.mRestrictionsProvider.flattenToString());
             }
+            if (policy.mUserSetupComplete) {
+                out.attribute(null, ATTR_SETUP_COMPLETE,
+                        Boolean.toString(true));
+            }
 
             final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
@@ -1074,6 +1083,10 @@
             if (permissionProvider != null) {
                 policy.mRestrictionsProvider = ComponentName.unflattenFromString(permissionProvider);
             }
+            String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
+            if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
+                policy.mUserSetupComplete = true;
+            }
 
             type = parser.next();
             int outerDepth = parser.getDepth();
@@ -1266,6 +1279,10 @@
                 }
             }
         }
+        // Register an observer for watching for user setup complete.
+        new SetupContentObserver(mHandler).register(mContext.getContentResolver());
+        // Initialize the user setup state, to handle the upgrade case.
+        updateUserSetupComplete();
     }
 
     private void cleanUpOldUsers() {
@@ -4102,4 +4119,50 @@
             return audioManager.isMasterMute();
         }
     }
+
+    /**
+     * We need to update the internal state of whether a user has completed setup once. After
+     * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes
+     * as we don't trust any apps that might try to reset it.
+     * <p>
+     * Unfortunately, we don't know which user's setup state was changed, so we write all of
+     * them.
+     */
+    void updateUserSetupComplete() {
+        List<UserInfo> users = mUserManager.getUsers(true);
+        ContentResolver resolver = mContext.getContentResolver();
+        final int N = users.size();
+        for (int i = 0; i < N; i++) {
+            int userHandle = users.get(i).id;
+            if (Settings.Secure.getIntForUser(resolver, Settings.Secure.USER_SETUP_COMPLETE, 0,
+                    userHandle) != 0) {
+                DevicePolicyData policy = getUserData(userHandle);
+                policy.mUserSetupComplete = true;
+                synchronized (this) {
+                    saveSettingsLocked(userHandle);
+                }
+            }
+        }
+    }
+
+    private class SetupContentObserver extends ContentObserver {
+
+        private final Uri mUserSetupComplete = Settings.Secure.getUriFor(
+                Settings.Secure.USER_SETUP_COMPLETE);
+
+        public SetupContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        void register(ContentResolver resolver) {
+            resolver.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (mUserSetupComplete.equals(uri)) {
+                updateUserSetupComplete();
+            }
+        }
+    }
 }