Device Owner, a special kind of device admin

A Device Owner cannot be uninstalled and is available to all users. It must
be registered before the device_provisioned flag is set.

Device admins can be disabled until used, but visible to device policy
manager, so that users wont be bothered with update requests.

Opened up a few related APIs for use by a system-installed Device Owner.

Change-Id: I847b5fe68c0f724863f778a67602b5bddc79d8e5
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c0eba0..8284b2c 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1513,4 +1513,57 @@
             }
         }
     }
+
+    /**
+     * @hide
+     * Sets the given package as the device owner. The package must already be installed and there
+     * shouldn't be an existing device owner registered, for this call to succeed. Also, this
+     * method must be called before the device is provisioned.
+     * @param packageName the package name of the application to be registered as the device owner.
+     * @return whether the package was successfully registered as the device owner.
+     * @throws IllegalArgumentException if the package name is null or invalid
+     * @throws IllegalStateException if a device owner is already registered or the device has
+     *         already been provisioned.
+     */
+    public boolean setDeviceOwner(String packageName) throws IllegalArgumentException,
+            IllegalStateException {
+        if (mService != null) {
+            try {
+                return mService.setDeviceOwner(packageName);
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to set device owner");
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Used to determine if a particular package has been registered as a Device Owner admin.
+     * Device Owner admins cannot be deactivated by the user unless the Device Owner itself allows
+     * it. And Device Owner packages cannot be uninstalled, once registered.
+     * @param packageName the package name to check against the registered device owner.
+     * @return whether or not the package is registered as the Device Owner.
+     */
+    public boolean isDeviceOwner(String packageName) {
+        if (mService != null) {
+            try {
+                return mService.isDeviceOwner(packageName);
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to check device owner");
+            }
+        }
+        return false;
+    }
+
+    /** @hide */
+    public String getDeviceOwner() {
+        if (mService != null) {
+            try {
+                return mService.getDeviceOwner();
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to get device owner");
+            }
+        }
+        return null;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e061ab3..b2a65bf 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -97,4 +97,8 @@
         int numbers, int symbols, int nonletter, int userHandle);
     void reportFailedPasswordAttempt(int userHandle);
     void reportSuccessfulPasswordAttempt(int userHandle);
+
+    boolean setDeviceOwner(String packageName);
+    boolean isDeviceOwner(String packageName);
+    String getDeviceOwner();
 }
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 4c2d7a6..2e8092a 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -34,6 +34,7 @@
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
     UserInfo getUserInfo(int userHandle);
+    boolean isRestricted();
     void setGuestEnabled(boolean enable);
     boolean isGuestEnabled();
     void wipeUser(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7c05528..3f666c1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -37,48 +37,56 @@
     private final Context mContext;
 
     /**
-     * @hide
-     * Key for user restrictions. Specifies if a user is allowed to add or remove accounts.
+     * Key for user restrictions. Specifies if a user is disallowed from adding and removing
+     * accounts.
+     * The default value is <code>false</code>.
+     * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String ALLOW_MODIFY_ACCOUNTS = "modify_accounts";
+    public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
 
     /**
-     * @hide
-     * Key for user restrictions. Specifies if a user is allowed to change Wi-Fi access points.
+     * Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi
+     * access points.
+     * The default value is <code>false</code>.
+     * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String ALLOW_CONFIG_WIFI = "config_wifi";
+    public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
 
     /**
-     * @hide
-     * Key for user restrictions. Specifies if a user is allowed to install applications.
+     * Key for user restrictions. Specifies if a user is disallowed from installing applications.
+     * The default value is <code>false</code>.
+     * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String ALLOW_INSTALL_APPS = "install_apps";
+    public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
 
     /**
-     * @hide
-     * Key for user restrictions. Specifies if a user is allowed to uninstall applications.
+     * Key for user restrictions. Specifies if a user is disallowed from uninstalling applications.
+     * The default value is <code>false</code>.
+     * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String ALLOW_UNINSTALL_APPS = "uninstall_apps";
+    public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
 
-    /** @hide *
-     * Key for user restrictions. Specifies if a user is allowed to toggle location sharing.
+    /**
+     * Key for user restrictions. Specifies if a user is disallowed from toggling location sharing.
+     * The default value is <code>false</code>.
+     * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String ALLOW_CONFIG_LOCATION_ACCESS = "config_location_access";
+    public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
 
     /** @hide */
     public UserManager(Context context, IUserManager service) {
@@ -129,11 +137,14 @@
     }
 
     /**
-     * @hide
+     * Used to check if the user making this call is a restricted user. Restricted users may have
+     * application restrictions imposed on them. All apps should default to the most restrictive
+     * version, unless they have specific restrictions available through a call to
+     * {@link Context#getApplicationRestrictions()}.
      */
     public boolean isUserRestricted() {
         try {
-            return mService.getUserInfo(getUserHandle()).isRestricted();
+            return mService.isRestricted();
         } catch (RemoteException re) {
             Log.w(TAG, "Could not check if user restricted ", re);
             return false;
@@ -189,12 +200,19 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Returns the user-wide restrictions imposed on this user.
+     * @return a Bundle containing all the restrictions.
+     */
     public Bundle getUserRestrictions() {
         return getUserRestrictions(Process.myUserHandle());
     }
 
-    /** @hide */
+    /**
+     * Returns the user-wide restrictions imposed on the user specified by <code>userHandle</code>.
+     * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
+     * @return a Bundle containing all the restrictions.
+     */
     public Bundle getUserRestrictions(UserHandle userHandle) {
         try {
             return mService.getUserRestrictions(userHandle.getIdentifier());
@@ -204,12 +222,21 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Sets all the user-wide restrictions for this user.
+     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param restrictions the Bundle containing all the restrictions.
+     */
     public void setUserRestrictions(Bundle restrictions) {
         setUserRestrictions(restrictions, Process.myUserHandle());
     }
 
-    /** @hide */
+    /**
+     * Sets all the user-wide restrictions for the specified user.
+     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param restrictions the Bundle containing all the restrictions.
+     * @param userHandle the UserHandle of the user for whom to set the restrictions.
+     */
     public void setUserRestrictions(Bundle restrictions, UserHandle userHandle) {
         try {
             mService.setUserRestrictions(restrictions, userHandle.getIdentifier());
@@ -218,7 +245,27 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Sets the value of a specific restriction.
+     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param key the key of the restriction
+     * @param value the value for the restriction
+     * @param userHandle the user whose restriction is to be changed.
+     */
+    public void setUserRestriction(String key, boolean value) {
+        Bundle bundle = getUserRestrictions();
+        bundle.putBoolean(key, value);
+        setUserRestrictions(bundle);
+    }
+
+    /**
+     * @hide
+     * Sets the value of a specific restriction on a specific user.
+     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param key the key of the restriction
+     * @param value the value for the restriction
+     * @param userHandle the user whose restriction is to be changed.
+     */
     public void setUserRestriction(String key, boolean value, UserHandle userHandle) {
         Bundle bundle = getUserRestrictions(userHandle);
         bundle.putBoolean(key, value);
@@ -467,7 +514,7 @@
      * @hide
      */
     public boolean isLocationSharingToggleAllowed() {
-        return getUserRestrictions().getBoolean(ALLOW_CONFIG_LOCATION_ACCESS);
+        return !getUserRestrictions().getBoolean(DISALLOW_SHARE_LOCATION, false);
     }
 
     /**