diff options
8 files changed, 115 insertions, 18 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index ace4e3284930..ac8ee8d38c3f 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -981,7 +981,7 @@ public final class Pm { } else if (userId < 0) { info = mUm.createUser(name, flags); } else { - info = mUm.createProfileForUser(name, flags, userId); + info = mUm.createProfileForUser(name, flags, userId, null); } if (info != null) { diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index eeb641d33c20..3324f6fe4589 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -36,7 +36,8 @@ interface IUserManager { int getCredentialOwnerProfile(int userHandle); UserInfo createUser(in String name, int flags); - UserInfo createProfileForUser(in String name, int flags, int userHandle); + UserInfo createProfileForUser(in String name, int flags, int userHandle, + in String[] disallowedPackages); UserInfo createRestrictedProfile(String name, int parentUserHandle); void setUserEnabled(int userHandle); boolean removeUser(int userHandle); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 5dc18fb117ef..c7e5e6308a8a 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1340,15 +1340,34 @@ public class UserManager { * * @param name the user's name * @param flags flags that identify the type of user and other properties. - * @see UserInfo - * @param userHandle new user will be a profile of this use. + * @param userHandle new user will be a profile of this user. * - * @return the UserInfo object for the created user, or null if the user could not be created. + * @return the {@link UserInfo} object for the created user, or null if the user + * could not be created. * @hide */ public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle) { + return createProfileForUser(name, flags, userHandle, null); + } + + /** + * Version of {@link #createProfileForUser(String, int, int)} that allows you to specify + * any packages that should not be installed in the new profile by default, these packages can + * still be installed later by the user if needed. + * + * @param name the user's name + * @param flags flags that identify the type of user and other properties. + * @param userHandle new user will be a profile of this user. + * @param disallowedPackages packages that will not be installed in the profile being created. + * + * @return the {@link UserInfo} object for the created user, or null if the user + * could not be created. + * @hide + */ + public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle, + String[] disallowedPackages) { try { - return mService.createProfileForUser(name, flags, userHandle); + return mService.createProfileForUser(name, flags, userHandle, disallowedPackages); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index df02b86956cc..6e87558324c4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -20618,9 +20618,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } /** Called by UserManagerService */ - void createNewUser(int userId) { + void createNewUser(int userId, String[] disallowedPackages) { synchronized (mInstallLock) { - mSettings.createNewUserLI(this, mInstaller, userId); + mSettings.createNewUserLI(this, mInstaller, userId, disallowedPackages); } synchronized (mPackages) { scheduleWritePackageRestrictionsLocked(userId); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 8cab355dc3bd..ba1dde0d9467 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3956,7 +3956,7 @@ final class Settings { } void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer, - int userHandle) { + int userHandle, String[] disallowedPackages) { String[] volumeUuids; String[] names; int[] appIds; @@ -3977,8 +3977,10 @@ final class Settings { if (ps.pkg == null || ps.pkg.applicationInfo == null) { continue; } + final boolean shouldInstall = ps.isSystem() && + !ArrayUtils.contains(disallowedPackages, ps.name); // Only system apps are initially installed. - ps.setInstalled(ps.isSystem(), userHandle); + ps.setInstalled(shouldInstall, userHandle); // Need to create a data directory for all apps under this user. Accumulate all // required args and call the installer after mPackages lock has been released volumeUuids[i] = ps.volumeUuid; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 533d9b5b6c73..9146bec2af49 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -2182,9 +2182,10 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo createProfileForUser(String name, int flags, int userId) { + public UserInfo createProfileForUser(String name, int flags, int userId, + String[] disallowedPackages) { checkManageOrCreateUsersPermission(flags); - return createUserInternal(name, flags, userId); + return createUserInternal(name, flags, userId, disallowedPackages); } @Override @@ -2194,6 +2195,11 @@ public class UserManagerService extends IUserManager.Stub { } private UserInfo createUserInternal(String name, int flags, int parentId) { + return createUserInternal(name, flags, parentId, null); + } + + private UserInfo createUserInternal(String name, int flags, int parentId, + String[] disallowedPackages) { if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) { Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); return null; @@ -2204,10 +2210,11 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Cannot add user. Not enough space on disk."); return null; } - return createUserInternalUnchecked(name, flags, parentId); + return createUserInternalUnchecked(name, flags, parentId, disallowedPackages); } - private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) { + private UserInfo createUserInternalUnchecked(String name, int flags, int parentId, + String[] disallowedPackages) { if (ActivityManager.isLowRamDeviceStatic()) { return null; } @@ -2321,7 +2328,7 @@ public class UserManagerService extends IUserManager.Stub { storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral()); mPm.prepareUserData(userId, userInfo.serialNumber, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); - mPm.createNewUser(userId); + mPm.createNewUser(userId, disallowedPackages); userInfo.partial = false; synchronized (mPackagesLock) { writeUserLP(userData); @@ -2371,7 +2378,8 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createRestrictedProfile(String name, int parentUserId) { checkManageOrCreateUsersPermission("setupRestrictedProfile"); - final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId); + final UserInfo user = createProfileForUser( + name, UserInfo.FLAG_RESTRICTED, parentUserId, null); if (user == null) { return null; } @@ -3533,7 +3541,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createUserEvenWhenDisallowed(String name, int flags) { - UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL); + UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL, null); // Keep this in sync with UserManager.createUser if (user != null && !user.isAdmin()) { setUserRestriction(UserManager.DISALLOW_SMS, true, user.id); diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 514f095cbd58..3548f28ec52e 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -44,6 +44,7 @@ <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" /> <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> + <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 6a434ca4d3fc..0fb2c9fb28dc 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.app.ActivityManager; import android.os.Bundle; @@ -46,16 +47,24 @@ public class UserManagerTest extends AndroidTestCase { private static final int REMOVE_TIMEOUT_MILLIS = 60 * 1000; // 60 seconds private static final int SWITCH_USER_TIMEOUT_MILLIS = 40 * 1000; // 40 seconds + // Packages which are used during tests. + private static final String[] PACKAGES = new String[] { + "com.android.egg", + "com.android.retaildemo" + }; + private final Object mUserRemoveLock = new Object(); private final Object mUserSwitchLock = new Object(); private UserManager mUserManager = null; + private PackageManager mPackageManager; private List<Integer> usersToRemove; @Override public void setUp() throws Exception { super.setUp(); mUserManager = UserManager.get(getContext()); + mPackageManager = getContext().getPackageManager(); IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_SWITCHED); @@ -185,6 +194,49 @@ public class UserManagerTest extends AndroidTestCase { assertFalse(mUserManager.isManagedProfile()); } + // Verify that disallowed packages are not installed in the managed profile. + @MediumTest + public void testAddManagedProfile_withDisallowedPackages() throws Exception { + final int primaryUserId = mUserManager.getPrimaryUser().id; + UserInfo userInfo1 = createProfileForUser("Managed1", + UserInfo.FLAG_MANAGED_PROFILE, primaryUserId); + // Verify that the packagesToVerify are installed by default. + for (String pkg : PACKAGES) { + assertTrue("Package should be installed in managed profile: " + pkg, + isPackageInstalledForUser(pkg, userInfo1.id)); + } + removeUser(userInfo1.id); + + UserInfo userInfo2 = createProfileForUser("Managed2", + UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES); + // Verify that the packagesToVerify are not installed by default. + for (String pkg : PACKAGES) { + assertFalse("Package should not be installed in managed profile when disallowed: " + + pkg, isPackageInstalledForUser(pkg, userInfo2.id)); + } + } + + // Verify that if any packages are disallowed to install during creation of managed profile can + // still be installed later. + @MediumTest + public void testAddManagedProfile_disallowedPackagesInstalledLater() throws Exception { + final int primaryUserId = mUserManager.getPrimaryUser().id; + UserInfo userInfo = createProfileForUser("Managed", + UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES); + // Verify that the packagesToVerify are not installed by default. + for (String pkg : PACKAGES) { + assertFalse("Package should not be installed in managed profile when disallowed: " + + pkg, isPackageInstalledForUser(pkg, userInfo.id)); + } + + // Verify that the disallowed packages during profile creation can be installed now. + for (String pkg : PACKAGES) { + assertEquals("Package could not be installed: " + pkg, + PackageManager.INSTALL_SUCCEEDED, + mPackageManager.installExistingPackageAsUser(pkg, userInfo.id)); + } + } + @MediumTest public void testAddRestrictedProfile() throws Exception { UserInfo userInfo = createRestrictedProfile("Profile"); @@ -357,6 +409,14 @@ public class UserManagerTest extends AndroidTestCase { switchUser(startUser); } + private boolean isPackageInstalledForUser(String packageName, int userId) { + try { + return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + private void switchUser(int userId) { synchronized (mUserSwitchLock) { ActivityManager am = getContext().getSystemService(ActivityManager.class); @@ -401,7 +461,13 @@ public class UserManagerTest extends AndroidTestCase { } private UserInfo createProfileForUser(String name, int flags, int userHandle) { - UserInfo profile = mUserManager.createProfileForUser(name, flags, userHandle); + return createProfileForUser(name, flags, userHandle, null); + } + + private UserInfo createProfileForUser(String name, int flags, int userHandle, + String[] disallowedPackages) { + UserInfo profile = mUserManager.createProfileForUser( + name, flags, userHandle, disallowedPackages); if (profile != null) { usersToRemove.add(profile.id); } |