diff --git a/api/current.txt b/api/current.txt index bc74a0afebfa1..fc23b36e32c74 100644 --- a/api/current.txt +++ b/api/current.txt @@ -31680,6 +31680,7 @@ package android.os { 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 1d3299e59a663..1fe7288066079 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -34563,6 +34563,7 @@ package android.os { 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 df4b94a380f7f..68f69ad6af728 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -31813,6 +31813,7 @@ package android.os { 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 f95a34cd7ec85..52b2f52c452e9 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -64,7 +64,7 @@ import java.util.List; */ public class UserManager { - private static String TAG = "UserManager"; + private static final String TAG = "UserManager"; private final IUserManager mService; private final Context mContext; @@ -217,6 +217,23 @@ public class UserManager { */ 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. + * + *

Default is true 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. + * + *

Key for user restrictions. + *

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. diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 6c18b260e18db..18b4571ca3eaf 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; 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.Intent; 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.Message; 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.provider.Settings.SettingNotFoundException; 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 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @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 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * 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 84381fe20acca..c6667a702f677 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 @@ public class UserRestrictionsUtils { 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 @@ public class UserRestrictionsUtils { */ private static final Set 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 @@ public class UserRestrictionsUtils { 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 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. */ @@ -307,6 +320,13 @@ public class UserRestrictionsUtils { return DEFAULT_ENABLED_FOR_DEVICE_OWNERS; } + /** + * Returns the user restrictions that default to {@code true} for managed profile owners. + */ + public static @NonNull Set 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 class UserRestrictionsUtils { public static void moveRestriction(String restrictionKey, SparseArray srcRestrictions, SparseArray 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 @@ public class UserRestrictionsUtils { } } } + + /** + * 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 2f26f43b78a73..2ddce1652b612 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - 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 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 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 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 0000000000000..b162785aefef8 --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml @@ -0,0 +1,8 @@ + + + + + + + + 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 0000000000000..744042413e089 --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml @@ -0,0 +1,8 @@ + + + + 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 0000000000000..5f9a87194bf79 --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml @@ -0,0 +1,3 @@ + + + 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 b440095e60cc4..be1d07bbec0be 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 class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { final Map newBaseRestrictions = new HashMap<>(); - doAnswer(new Answer() { - @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 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { final Map newBaseRestrictions = new HashMap<>(); - doAnswer(new Answer() { - @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 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { ), 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 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 a6ce1d51f80ea..46da3dedc77e4 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.PendingIntent; 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 class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi 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 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi @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 1ea12d8535563..23fada46d16e9 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 @@ public class DpmMockContext extends MockContext { 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);