Merge "Introduce DISALLOW_BLUETOOTH_SHARING." into oc-dev
am: 90357d62e9

Change-Id: I925165817781c3b0f4e37afe8ebcce1ac264d775
diff --git a/api/current.txt b/api/current.txt
index 628194d..5217163 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -31680,6 +31680,7 @@
     field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
     field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill";
     field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
+    field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
     field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
     field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
     field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
diff --git a/api/system-current.txt b/api/system-current.txt
index 2757835..0683327 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -34563,6 +34563,7 @@
     field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
     field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill";
     field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
+    field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
     field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
     field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
     field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
diff --git a/api/test-current.txt b/api/test-current.txt
index f151116bd..b11cc1e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -31813,6 +31813,7 @@
     field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
     field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill";
     field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
+    field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
     field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
     field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
     field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f95a34c..52b2f52 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -64,7 +64,7 @@
  */
 public class UserManager {
 
-    private static String TAG = "UserManager";
+    private static final String TAG = "UserManager";
     private final IUserManager mService;
     private final Context mContext;
 
@@ -218,6 +218,23 @@
     public static final String DISALLOW_BLUETOOTH = "no_bluetooth";
 
     /**
+     * Specifies if outgoing bluetooth sharing is disallowed on the device. Device owner and profile
+     * owner can set this restriction. When it is set by device owner, all users on this device will
+     * be affected.
+     *
+     * <p>Default is <code>true</code> for managed profiles and false for otherwise. When a device
+     * upgrades to {@link android.os.Build.VERSION_CODES#O}, the system sets it for all existing
+     * managed profiles.
+     *
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
+
+    /**
      * Specifies if a user is disallowed from transferring files over
      * USB. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 6c18b26..18b4571 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
+import android.app.AppGlobals;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.IBluetooth;
@@ -37,11 +38,11 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -50,7 +51,6 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -61,15 +61,15 @@
 import android.util.Slog;
 
 import com.android.internal.util.DumpUtils;
-import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.UserRestrictionsUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 
 class BluetoothManagerService extends IBluetoothManager.Stub {
@@ -120,7 +120,6 @@
     private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
     private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
 
-    private static final int MAX_SAVE_RETRIES = 3;
     private static final int MAX_ERROR_RESTART_RETRIES = 6;
 
     // Bluetooth persisted setting is off
@@ -223,22 +222,25 @@
         @Override
         public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
                 Bundle prevRestrictions) {
-            if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)
-                    && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) {
-                // The relevant restriction has not changed - do nothing.
-                return;
+            if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+                    UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) {
+                return; // No relevant changes, nothing to do.
             }
-            final boolean bluetoothDisallowed =
-                    newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
-            if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
+
+            final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
+
+            // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the
+            // system user, so we only look at the system user.
+            if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) {
                 try {
-                    disable(null, true);
+                    disable(null /* packageName */, true /* persist */);
                 } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener",
-                            e);
+                    Slog.w(TAG, "Exception when disabling Bluetooth", e);
                 }
             }
-            updateOppLauncherComponentState(bluetoothDisallowed);
+            final boolean sharingDisallowed = disallowed
+                    || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING);
+            updateOppLauncherComponentState(userId, sharingDisallowed);
         }
     };
 
@@ -994,11 +996,6 @@
                 LocalServices.getService(UserManagerInternal.class);
         userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
         final boolean isBluetoothDisallowed = isBluetoothDisallowed();
-        PackageManagerService packageManagerService =
-                (PackageManagerService) ServiceManager.getService("package");
-        if (packageManagerService != null && !packageManagerService.isOnlyCoreApps()) {
-            updateOppLauncherComponentState(isBluetoothDisallowed);
-        }
         if (isBluetoothDisallowed) {
             return;
         }
@@ -2074,21 +2071,21 @@
 
     /**
      * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
-     * offered to the user if Bluetooth is disallowed. Puts the component to its default state if
-     * Bluetooth is not disallowed.
+     * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
+     * state if Bluetooth is not disallowed.
      *
-     * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user
-     * restriction was set.
+     * @param userId user to disable bluetooth sharing for.
+     * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
      */
-    private void updateOppLauncherComponentState(boolean bluetoothDisallowed) {
+    private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
         final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
                 "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
-        final int newState = bluetoothDisallowed
+        final int newState = bluetoothSharingDisallowed
                 ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
         try {
-            mContext.getPackageManager()
-                    .setComponentEnabledSetting(oppLauncherComponent, newState, 0);
+            final IPackageManager imp = AppGlobals.getPackageManager();
+            imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId);
         } catch (Exception e) {
             // The component was not found, do nothing.
         }
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 84381fe..c6667a7 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -74,6 +74,7 @@
             UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
             UserManager.DISALLOW_CONFIG_BLUETOOTH,
             UserManager.DISALLOW_BLUETOOTH,
+            UserManager.DISALLOW_BLUETOOTH_SHARING,
             UserManager.DISALLOW_USB_FILE_TRANSFER,
             UserManager.DISALLOW_CONFIG_CREDENTIALS,
             UserManager.DISALLOW_REMOVE_USER,
@@ -155,6 +156,7 @@
      */
     private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
             UserManager.DISALLOW_ADJUST_VOLUME,
+            UserManager.DISALLOW_BLUETOOTH_SHARING,
             UserManager.DISALLOW_RUN_IN_BACKGROUND,
             UserManager.DISALLOW_UNMUTE_MICROPHONE,
             UserManager.DISALLOW_UNMUTE_DEVICE
@@ -167,6 +169,17 @@
             UserManager.DISALLOW_ADD_MANAGED_PROFILE
     );
 
+    /**
+     * User restrictions that default to {@code true} for managed profile owners.
+     *
+     * NB: {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is also set by default but it is
+     * not set to existing profile owners unless they used to have INSTALL_NON_MARKET_APPS disabled
+     * in settings. So it is handled separately.
+     */
+    private static final Set<String> DEFAULT_ENABLED_FOR_MANAGED_PROFILES = Sets.newArraySet(
+            UserManager.DISALLOW_BLUETOOTH_SHARING
+    );
+
     /*
      * Special user restrictions that are always applied to all users no matter who sets them.
      */
@@ -308,6 +321,13 @@
     }
 
     /**
+     * Returns the user restrictions that default to {@code true} for managed profile owners.
+     */
+    public static @NonNull Set<String> getDefaultEnabledForManagedProfiles() {
+        return DEFAULT_ENABLED_FOR_MANAGED_PROFILES;
+    }
+
+    /**
      * Takes restrictions that can be set by device owner, and sort them into what should be applied
      * globally and what should be applied only on the current user.
      */
@@ -544,8 +564,8 @@
     public static void moveRestriction(String restrictionKey, SparseArray<Bundle> srcRestrictions,
             SparseArray<Bundle> destRestrictions) {
         for (int i = 0; i < srcRestrictions.size(); i++) {
-            int key = srcRestrictions.keyAt(i);
-            Bundle from = srcRestrictions.valueAt(i);
+            final int key = srcRestrictions.keyAt(i);
+            final Bundle from = srcRestrictions.valueAt(i);
             if (contains(from, restrictionKey)) {
                 from.remove(restrictionKey);
                 Bundle to = destRestrictions.get(key);
@@ -562,4 +582,24 @@
             }
         }
     }
+
+    /**
+     * Returns whether restrictions differ between two bundles.
+     * @param oldRestrictions old bundle of restrictions.
+     * @param newRestrictions new bundle of restrictions
+     * @param restrictions restrictions of interest, if empty, all restrictions are checked.
+     */
+    public static boolean restrictionsChanged(Bundle oldRestrictions, Bundle newRestrictions,
+            String... restrictions) {
+        if (restrictions.length == 0) {
+            return areEqual(oldRestrictions, newRestrictions);
+        }
+        for (final String restriction : restrictions) {
+            if (oldRestrictions.getBoolean(restriction, false) !=
+                    newRestrictions.getBoolean(restriction, false)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2f26f43..2ddce16 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1903,7 +1903,7 @@
             setDeviceOwnerSystemPropertyLocked();
             findOwnerComponentIfNecessaryLocked();
             migrateUserRestrictionsIfNecessaryLocked();
-            setDefaultEnabledUserRestrictionsIfNecessaryLocked();
+            maybeSetDefaultDeviceOwnerUserRestrictionsLocked();
 
             // TODO PO may not have a class name either due to b/17652534.  Address that too.
 
@@ -1911,36 +1911,80 @@
         }
     }
 
-    private void setDefaultEnabledUserRestrictionsIfNecessaryLocked() {
+    /** Apply default restrictions that haven't been applied to device owners yet. */
+    private void maybeSetDefaultDeviceOwnerUserRestrictionsLocked() {
         final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-        if (deviceOwner != null
-                && !UserRestrictionsUtils.getDefaultEnabledForDeviceOwner().equals(
-                        deviceOwner.defaultEnabledRestrictionsAlreadySet)) {
-            Slog.i(LOG_TAG,"New user restrictions need to be set by default for the device owner");
+        if (deviceOwner != null) {
+            maybeSetDefaultRestrictionsForAdminLocked(mOwners.getDeviceOwnerUserId(),
+                    deviceOwner, UserRestrictionsUtils.getDefaultEnabledForDeviceOwner());
+        }
+    }
 
-            if (VERBOSE_LOG) {
-                Slog.d(LOG_TAG,"Default enabled restrictions for DO: "
-                        + UserRestrictionsUtils.getDefaultEnabledForDeviceOwner()
-                        + ". Restrictions already enabled: "
-                        + deviceOwner.defaultEnabledRestrictionsAlreadySet);
-            }
-
-            Set<String> restrictionsToSet = new ArraySet<>(
-                    UserRestrictionsUtils.getDefaultEnabledForDeviceOwner());
-            restrictionsToSet.removeAll(deviceOwner.defaultEnabledRestrictionsAlreadySet);
-            if (!restrictionsToSet.isEmpty()) {
-                for (String restriction : restrictionsToSet) {
-                    deviceOwner.ensureUserRestrictions().putBoolean(restriction, true);
+    /** Apply default restrictions that haven't been applied to profile owners yet. */
+    private void maybeSetDefaultProfileOwnerUserRestrictions() {
+        synchronized (this) {
+            for (final int userId : mOwners.getProfileOwnerKeys()) {
+                final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+                // The following restrictions used to be applied to managed profiles by different
+                // means (via Settings or by disabling components). Now they are proper user
+                // restrictions so we apply them to managed profile owners. Non-managed secondary
+                // users didn't have those restrictions so we skip them to keep existing behavior.
+                if (profileOwner == null || !mUserManager.isManagedProfile(userId)) {
+                    continue;
                 }
-                deviceOwner.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet);
-                Slog.i(LOG_TAG,
-                        "Enabled the following restrictions by default: " + restrictionsToSet);
-
-                saveUserRestrictionsLocked(mOwners.getDeviceOwnerUserId());
+                maybeSetDefaultRestrictionsForAdminLocked(userId, profileOwner,
+                        UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
+                ensureUnknownSourcesRestrictionForProfileOwnerLocked(
+                        userId, profileOwner, false /* newOwner */);
             }
         }
     }
 
+    /**
+     * Checks whether {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} should be added to the
+     * set of restrictions for this profile owner.
+     */
+    private void ensureUnknownSourcesRestrictionForProfileOwnerLocked(int userId,
+            ActiveAdmin profileOwner, boolean newOwner) {
+        if (newOwner || mInjector.settingsSecureGetIntForUser(
+                Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) != 0) {
+            profileOwner.ensureUserRestrictions().putBoolean(
+                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+            saveUserRestrictionsLocked(userId);
+            mInjector.settingsSecurePutIntForUser(
+                    Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId);
+        }
+    }
+
+    /**
+     * Apply default restrictions that haven't been applied to a given admin yet.
+     */
+    private void maybeSetDefaultRestrictionsForAdminLocked(
+            int userId, ActiveAdmin admin, Set<String> defaultRestrictions) {
+        if (defaultRestrictions.equals(admin.defaultEnabledRestrictionsAlreadySet)) {
+            return; // The same set of default restrictions has been already applied.
+        }
+        Slog.i(LOG_TAG, "New user restrictions need to be set by default for user " + userId);
+
+        if (VERBOSE_LOG) {
+            Slog.d(LOG_TAG,"Default enabled restrictions: "
+                    + defaultRestrictions
+                    + ". Restrictions already enabled: "
+                    + admin.defaultEnabledRestrictionsAlreadySet);
+        }
+
+        final Set<String> restrictionsToSet = new ArraySet<>(defaultRestrictions);
+        restrictionsToSet.removeAll(admin.defaultEnabledRestrictionsAlreadySet);
+        if (!restrictionsToSet.isEmpty()) {
+            for (final String restriction : restrictionsToSet) {
+                admin.ensureUserRestrictions().putBoolean(restriction, true);
+            }
+            admin.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet);
+            Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictionsToSet);
+            saveUserRestrictionsLocked(userId);
+        }
+    }
+
     private void setDeviceOwnerSystemPropertyLocked() {
         final boolean deviceProvisioned =
                 mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
@@ -2927,41 +2971,11 @@
         }
     }
 
-    private void ensureUnknownSourcesRestrictionForProfileOwners() {
-        synchronized (this) {
-            for (int userId : mOwners.getProfileOwnerKeys()) {
-                if (!mUserManager.isManagedProfile(userId) ||
-                        mInjector.settingsSecureGetIntForUser(
-                        Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) == 0) {
-                    continue;
-                }
-                setUserRestrictionOnBehalfOfProfileOwnerLocked(
-                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId);
-                mInjector.settingsSecurePutIntForUser(
-                        Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId);
-            }
-        }
-    }
-
-    private void setUserRestrictionOnBehalfOfProfileOwnerLocked(String userRestrictionKey,
-            int userId) {
-        if (UserRestrictionsUtils.isValidRestriction(userRestrictionKey) &&
-                UserRestrictionsUtils.canProfileOwnerChange(userRestrictionKey, userId)) {
-            ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
-            if (profileOwner == null) {
-                return;
-            }
-            Bundle restrictions = profileOwner.ensureUserRestrictions();
-            restrictions.putBoolean(userRestrictionKey, true);
-            saveUserRestrictionsLocked(userId);
-        }
-    }
-
     private void onLockSettingsReady() {
         getUserData(UserHandle.USER_SYSTEM);
         loadOwners();
         cleanUpOldUsers();
-        ensureUnknownSourcesRestrictionForProfileOwners();
+        maybeSetDefaultProfileOwnerUserRestrictions();
         handleStartUser(UserHandle.USER_SYSTEM);
 
         // Register an observer for watching for user setup complete and settings changes.
@@ -6713,8 +6727,8 @@
         synchronized (this) {
             enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb);
 
-            if (getActiveAdminUncheckedLocked(who, userHandle) == null
-                    || getUserData(userHandle).mRemovingAdmins.contains(who)) {
+            final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+            if (admin == null || getUserData(userHandle).mRemovingAdmins.contains(who)) {
                 throw new IllegalArgumentException("Not active admin: " + who);
             }
 
@@ -6730,10 +6744,10 @@
             final long id = mInjector.binderClearCallingIdentity();
             try {
                 if (mUserManager.isManagedProfile(userHandle)) {
-                    setUserRestrictionOnBehalfOfProfileOwnerLocked(
-                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle);
-                    mInjector.settingsSecurePutIntForUser(
-                            Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userHandle);
+                    maybeSetDefaultRestrictionsForAdminLocked(userHandle, admin,
+                            UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
+                    ensureUnknownSourcesRestrictionForProfileOwnerLocked(userHandle, admin,
+                            true /* newOwner */);
                 }
             } finally {
                 mInjector.binderRestoreCallingIdentity(id);
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml
new file mode 100644
index 0000000..b162785
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+<admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
+    <policies flags="991" />
+    <strong-auth-unlock-timeout value="0" />
+    <organization-color value="-16738680" />
+</admin>
+</policies>
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml
new file mode 100644
index 0000000..7440424
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<root>
+    <profile-owner
+        package="com.android.frameworks.servicestests"
+        name="com.android.frameworks.servicestests"
+        component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+        userRestrictionsMigrated="true" />
+</root>
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml
new file mode 100644
index 0000000..5f9a871
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml
@@ -0,0 +1,3 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+</policies>
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index b440095..be1d07b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -15,31 +15,28 @@
  */
 package com.android.server.devicepolicy;
 
-import com.android.server.LocalServices;
-import com.android.server.SystemService;
-import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
 
-import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.util.Pair;
+import android.provider.Settings;
 
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
 
 import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
+import java.util.Set;
 
 public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
     private DpmMockContext mContext;
@@ -57,7 +54,7 @@
     public void testMigration() throws Exception {
         final File user10dir = mMockContext.addUser(10, 0);
         final File user11dir = mMockContext.addUser(11, UserInfo.FLAG_MANAGED_PROFILE);
-        final File user12dir = mMockContext.addUser(12, 0);
+        mMockContext.addUser(12, 0);
 
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123));
@@ -109,16 +106,13 @@
 
         final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>();
 
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Integer userId = (Integer) invocation.getArguments()[0];
-                Bundle bundle = (Bundle) invocation.getArguments()[1];
+        doAnswer(invocation -> {
+            Integer userId = (Integer) invocation.getArguments()[0];
+            Bundle bundle = (Bundle) invocation.getArguments()[1];
 
-                newBaseRestrictions.put(userId, bundle);
+            newBaseRestrictions.put(userId, bundle);
 
-                return null;
-            }
+            return null;
         }).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration(
                 anyInt(), any(Bundle.class));
 
@@ -225,16 +219,13 @@
 
         final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>();
 
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Integer userId = (Integer) invocation.getArguments()[0];
-                Bundle bundle = (Bundle) invocation.getArguments()[1];
+        doAnswer(invocation -> {
+            Integer userId = (Integer) invocation.getArguments()[0];
+            Bundle bundle = (Bundle) invocation.getArguments()[1];
 
-                newBaseRestrictions.put(userId, bundle);
+            newBaseRestrictions.put(userId, bundle);
 
-                return null;
-            }
+            return null;
         }).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration(
                 anyInt(), any(Bundle.class));
 
@@ -278,4 +269,63 @@
                 ),
                 dpms.getProfileOwnerAdminLocked(UserHandle.USER_SYSTEM).ensureUserRestrictions());
     }
+
+    // Test setting default restrictions for managed profile.
+    public void testMigration3_managedProfileOwner() throws Exception {
+        // Create a managed profile user.
+        final File user10dir = mMockContext.addUser(10, UserInfo.FLAG_MANAGED_PROFILE);
+        // Profile owner package for managed profile user.
+        setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123));
+        // Set up fake UserManager to make it look like a managed profile.
+        when(mMockContext.userManager.isManagedProfile(eq(10))).thenReturn(true);
+        // Set up fake Settings to make it look like INSTALL_NON_MARKET_APPS was reversed.
+        when(mMockContext.settings.settingsSecureGetIntForUser(
+                eq(Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED),
+                eq(0), eq(10))).thenReturn(1);
+        // Write policy and owners files.
+        DpmTestUtils.writeToFile(
+                (new File(mContext.systemUserDataDir, "device_policies.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml"));
+        DpmTestUtils.writeToFile(
+                (new File(user10dir, "device_policies.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml"));
+        DpmTestUtils.writeToFile(
+                (new File(user10dir, "profile_owner.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest3/profile_owner.xml"));
+
+        final DevicePolicyManagerServiceTestable dpms;
+
+        // Initialize DPM/DPMS and let it migrate the persisted information.
+        // (Need clearCallingIdentity() to pass permission checks.)
+        final long ident = mContext.binder.clearCallingIdentity();
+        try {
+            LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+
+            dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
+
+            dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY);
+            dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED);
+        } finally {
+            mContext.binder.restoreCallingIdentity(ident);
+        }
+
+        assertFalse(dpms.mOwners.hasDeviceOwner());
+        assertTrue(dpms.mOwners.hasProfileOwner(10));
+
+        // Check that default restrictions were applied.
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                        UserManager.DISALLOW_BLUETOOTH_SHARING
+                ),
+                dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions());
+
+        final Set<String> alreadySet =
+                dpms.getProfileOwnerAdminLocked(10).defaultEnabledRestrictionsAlreadySet;
+        assertEquals(alreadySet.size(), 1);
+        assertTrue(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index a6ce1d5..46da3de 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -21,7 +21,6 @@
 import android.app.backup.IBackupManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
@@ -56,17 +55,17 @@
     public static class OwnersTestable extends Owners {
         public static final String LEGACY_FILE = "legacy.xml";
         public static final String DEVICE_OWNER_FILE = "device_owner2.xml";
-        public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
+        public static final String PROFILE_OWNER_FILE = "profile_owner.xml";
 
         private final File mLegacyFile;
         private final File mDeviceOwnerFile;
-        private final File mProfileOwnerBase;
+        private final File mUsersDataDir;
 
         public OwnersTestable(DpmMockContext context) {
             super(context.userManager, context.userManagerInternal, context.packageManagerInternal);
             mLegacyFile = new File(context.dataDir, LEGACY_FILE);
             mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE);
-            mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE);
+            mUsersDataDir = new File(context.dataDir, "users");
         }
 
         @Override
@@ -81,7 +80,8 @@
 
         @Override
         File getProfileOwnerFileWithTestOverride(int userId) {
-            return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
+            final File userDir = new File(mUsersDataDir, String.valueOf(userId));
+            return new File(userDir, PROFILE_OWNER_FILE);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 1ea12d8..23fada4 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -468,7 +468,7 @@
         when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
 
         // Create a data directory.
-        final File dir = new File(dataDir, "user" + userId);
+        final File dir = new File(dataDir, "users/" + userId);
         DpmTestUtils.clearDir(dir);
 
         when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);