Merge "Allow device owners to update LOCATION_MODE." into lmp-dev
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ea041e8..8f1343d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3245,11 +3245,15 @@
      * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
      * that the value of the setting is in the correct form for the setting type should be performed
      * by the caller.
-     * <p>The settings that can be updated with this method are:
+     * <p>The settings that can be updated by a profile or device owner with this method are:
      * <ul>
      * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
      * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
      * </ul>
+     * <p>A device owner can additionally update the following settings:
+     * <ul>
+     * <li>{@link Settings.Secure#LOCATION_MODE}</li>
+     * </ul>
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 01fda47..440b1ec 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3150,6 +3150,11 @@
         /** @hide */
         public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                 int userHandle) {
+            if (LOCATION_MODE.equals(name)) {
+                // HACK ALERT: temporary hack to work around b/10491283.
+                // TODO: once b/10491283 fixed, remove this hack
+                return setLocationModeForUser(resolver, Integer.parseInt(value), userHandle);
+            }
             if (MOVED_TO_GLOBAL.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                         + " to android.provider.Settings.Global");
@@ -3265,11 +3270,6 @@
         /** @hide */
         public static boolean putIntForUser(ContentResolver cr, String name, int value,
                 int userHandle) {
-            if (LOCATION_MODE.equals(name)) {
-                // HACK ALERT: temporary hack to work around b/10491283.
-                // TODO: once b/10491283 fixed, remove this hack
-                return setLocationModeForUser(cr, value, userHandle);
-            }
             return putStringForUser(cr, name, Integer.toString(value), userHandle);
         }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 09584f4..5ad9825 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -166,12 +166,17 @@
     }
 
     private static final Set<String> SECURE_SETTINGS_WHITELIST;
+    private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST;
     private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
     static {
         SECURE_SETTINGS_WHITELIST = new HashSet();
         SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
         SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
 
+        SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new HashSet();
+        SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST);
+        SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE);
+
         GLOBAL_SETTINGS_WHITELIST = new HashSet();
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
@@ -5109,11 +5114,17 @@
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
             }
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            ActiveAdmin activeAdmin =
+                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
+            if (isDeviceOwner(activeAdmin.info.getPackageName())) {
+                if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) {
+                    throw new SecurityException(String.format(
+                            "Permission denial: Device owners cannot update %1$s", setting));
+                }
+            } else if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
                 throw new SecurityException(String.format(
-                        "Permission denial: profile/device owners cannot update %1$s", setting));
+                        "Permission denial: Profile owners cannot update %1$s", setting));
             }
 
             long id = Binder.clearCallingIdentity();