diff options
| -rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 22 | ||||
| -rw-r--r-- | core/java/android/accounts/AccountManager.java | 24 | ||||
| -rw-r--r-- | core/java/android/accounts/IAccountManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/os/Binder.java | 2 | ||||
| -rw-r--r-- | core/java/android/os/IUserManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/Process.java | 4 | ||||
| -rw-r--r-- | core/java/android/os/UserHandle.java | 14 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 17 | ||||
| -rw-r--r-- | services/core/java/com/android/server/accounts/AccountManagerService.java | 29 | ||||
| -rw-r--r-- | services/core/java/com/android/server/notification/NotificationManagerService.java | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 21 |
11 files changed, 99 insertions, 39 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 3f0a4445fdce..ebf508514b3c 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -22,11 +22,13 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; +import android.accounts.IAccountManager; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.PackageInstallObserver; import android.content.ComponentName; +import android.content.Context; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.Intent; @@ -92,6 +94,7 @@ public final class Pm { IPackageManager mPm; IPackageInstaller mInstaller; IUserManager mUm; + IAccountManager mAm; private WeakHashMap<String, Resources> mResourceCache = new WeakHashMap<String, Resources>(); @@ -122,9 +125,10 @@ public final class Pm { if (args.length < 1) { return showUsage(); } - - mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user")); + mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE)); + mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE)); mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); + if (mPm == null) { System.err.println(PM_NOT_RUNNING_ERR); return 1; @@ -1381,6 +1385,8 @@ public final class Pm { } } else if ("--managed".equals(opt)) { flags |= UserInfo.FLAG_MANAGED_PROFILE; + } else if ("--restricted".equals(opt)) { + flags |= UserInfo.FLAG_RESTRICTED; } else { System.err.println("Error: unknown option " + opt); showUsage(); @@ -1394,12 +1400,18 @@ public final class Pm { } name = arg; try { - UserInfo info = null; - if (userId < 0) { + UserInfo info; + if ((flags & UserInfo.FLAG_RESTRICTED) != 0) { + // In non-split user mode, userId can only be SYSTEM + int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM; + info = mUm.createRestrictedProfile(name, parentUserId); + mAm.addSharedAccountsFromParentUser(userId, parentUserId); + } else if (userId < 0) { info = mUm.createUser(name, flags); } else { info = mUm.createProfileForUser(name, flags, userId); } + if (info != null) { System.out.println("Success: created user id " + info.id); return 1; @@ -2122,7 +2134,7 @@ public final class Pm { System.err.println(" pm get-install-location"); System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); System.err.println(" pm trim-caches DESIRED_FREE_SPACE [internal|UUID]"); - System.err.println(" pm create-user [--profileOf USER_ID] [--managed] USER_NAME"); + System.err.println(" pm create-user [--profileOf USER_ID] [--managed] [--restricted] USER_NAME"); System.err.println(" pm remove-user USER_ID"); System.err.println(" pm get-max-users"); System.err.println(""); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index d751f96f65f6..0a7568a8c876 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -16,6 +16,7 @@ package android.accounts; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.Size; import android.app.Activity; @@ -423,6 +424,7 @@ public class AccountManager { * @return An array of {@link Account}, one for each account. Empty * (never null) if no accounts have been added. */ + @NonNull @RequiresPermission(GET_ACCOUNTS) public Account[] getAccounts() { try { @@ -448,6 +450,7 @@ public class AccountManager { * @return An array of {@link Account}, one for each account. Empty * (never null) if no accounts have been added. */ + @NonNull @RequiresPermission(GET_ACCOUNTS) public Account[] getAccountsAsUser(int userId) { try { @@ -466,6 +469,7 @@ public class AccountManager { * @param uid the uid of the calling app. * @return the accounts that are available to this package and user. */ + @NonNull public Account[] getAccountsForPackage(String packageName, int uid) { try { return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName()); @@ -483,6 +487,7 @@ public class AccountManager { * @return An array of {@link Account}, one per matching account. Empty * (never null) if no accounts of the specified type have been added. */ + @NonNull public Account[] getAccountsByTypeForPackage(String type, String packageName) { try { return mService.getAccountsByTypeForPackage(type, packageName, @@ -515,12 +520,14 @@ public class AccountManager { * @return An array of {@link Account}, one per matching account. Empty * (never null) if no accounts of the specified type have been added. */ + @NonNull @RequiresPermission(GET_ACCOUNTS) public Account[] getAccountsByType(String type) { return getAccountsByTypeAsUser(type, Process.myUserHandle()); } /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */ + @NonNull public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) { try { return mService.getAccountsAsUser(type, userHandle.getIdentifier(), @@ -1537,23 +1544,22 @@ public class AccountManager { }.start(); } + /** - * Adds a shared account from the primary user to a secondary user. Adding the shared account + * Adds shared accounts from a parent user to a secondary user. Adding the shared account * doesn't take effect immediately. When the target user starts up, any pending shared accounts * are attempted to be copied to the target user from the primary via calls to the * authenticator. - * @param account the account to share - * @param user the target user - * @return + * @param parentUser parent user + * @param user target user * @hide */ - public boolean addSharedAccount(final Account account, UserHandle user) { + public void addSharedAccountsFromParentUser(UserHandle parentUser, UserHandle user) { try { - boolean val = mService.addSharedAccountAsUser(account, user.getIdentifier()); - return val; + mService.addSharedAccountsFromParentUser(parentUser.getIdentifier(), + user.getIdentifier()); } catch (RemoteException re) { - // won't ever happen - throw new RuntimeException(re); + throw new IllegalStateException(re); } } diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 4378df408d10..0d95db1d8302 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -74,9 +74,9 @@ interface IAccountManager { String authTokenType); /* Shared accounts */ - boolean addSharedAccountAsUser(in Account account, int userId); Account[] getSharedAccountsAsUser(int userId); boolean removeSharedAccountAsUser(in Account account, int userId); + void addSharedAccountsFromParentUser(int parentUserId, int userId); /* Account renaming. */ void renameAccount(in IAccountManagerResponse response, in Account accountToRename, String newName); diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index cfa6164b0454..c4501bade098 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -157,7 +157,7 @@ public class Binder implements IBinder { * incoming transaction, then its own UserHandle is returned. */ public static final UserHandle getCallingUserHandle() { - return new UserHandle(UserHandle.getUserId(getCallingUid())); + return UserHandle.of(UserHandle.getUserId(getCallingUid())); } /** diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index aeb5d4517e6c..7c091575df38 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -35,6 +35,7 @@ interface IUserManager { UserInfo createUser(in String name, int flags); UserInfo createProfileForUser(in String name, int flags, int userHandle); + UserInfo createRestrictedProfile(String name, int parentUserId); void setUserEnabled(int userHandle); boolean removeUser(int userHandle); void setUserName(int userHandle, String name); diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 7234e985757a..4ac361d00682 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -797,8 +797,8 @@ public class Process { * {@link #myUid()} in that a particular user will have multiple * distinct apps running under it each with their own uid. */ - public static final UserHandle myUserHandle() { - return new UserHandle(UserHandle.getUserId(myUid())); + public static UserHandle myUserHandle() { + return UserHandle.of(UserHandle.getUserId(myUid())); } /** diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 213e0831c0f2..796addc4c3bc 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -17,7 +17,6 @@ package android.os; import android.annotation.SystemApi; -import android.util.SparseArray; import java.io.PrintWriter; @@ -83,8 +82,6 @@ public final class UserHandle implements Parcelable { final int mHandle; - private static final SparseArray<UserHandle> userHandles = new SparseArray<UserHandle>(); - /** * Checks to see if the user id is the same for the two uids, i.e., they belong to the same * user. @@ -144,15 +141,8 @@ public final class UserHandle implements Parcelable { } /** @hide */ - public static UserHandle getCallingUserHandle() { - int userId = getUserId(Binder.getCallingUid()); - UserHandle userHandle = userHandles.get(userId); - // Intentionally not synchronized to save time - if (userHandle == null) { - userHandle = new UserHandle(userId); - userHandles.put(userId, userHandle); - } - return userHandle; + public static UserHandle of(int userId) { + return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId); } /** diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 64e2505b5006..f58933a82186 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -15,6 +15,7 @@ */ package android.os; +import android.accounts.AccountManager; import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.ActivityManager; @@ -927,7 +928,8 @@ public class UserManager { } /** - * Creates a restricted profile with the specified name. + * Creates a restricted profile with the specified name. This method also sets necessary + * restrictions and adds shared accounts. * * @param name profile's name * @return UserInfo object for the created user, or null if the user could not be created. @@ -935,13 +937,14 @@ public class UserManager { */ public UserInfo createRestrictedProfile(String name) { try { - if (isSplitSystemUser()) { - return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, - UserHandle.getCallingUserId()); - } else { - return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, - UserHandle.USER_SYSTEM); + UserHandle parentUserHandle = Process.myUserHandle(); + UserInfo user = mService.createRestrictedProfile(name, + parentUserHandle.getIdentifier()); + if (user != null) { + AccountManager.get(mContext).addSharedAccountsFromParentUser(parentUserHandle, + UserHandle.of(user.id)); } + return user; } catch (RemoteException e) { Log.w(TAG, "Could not create a restricted profile", e); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index dbf128840c59..6b346123e94a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -29,6 +29,7 @@ import android.accounts.IAccountAuthenticator; import android.accounts.IAccountAuthenticatorResponse; import android.accounts.IAccountManager; import android.accounts.IAccountManagerResponse; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -2526,6 +2527,7 @@ public class AccountManagerService * Returns the accounts visible to the client within the context of a specific user * @hide */ + @NonNull public Account[] getAccounts(int userId, String opPackageName) { int callingUid = Binder.getCallingUid(); List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId, @@ -2551,6 +2553,7 @@ public class AccountManagerService * * @hide */ + @NonNull public AccountAndUser[] getRunningAccounts() { final int[] runningUserIds; try { @@ -2563,6 +2566,7 @@ public class AccountManagerService } /** {@hide} */ + @NonNull public AccountAndUser[] getAllAccounts() { final List<UserInfo> users = getUserManager().getUsers(); final int[] userIds = new int[users.size()]; @@ -2572,6 +2576,7 @@ public class AccountManagerService return getAccounts(userIds); } + @NonNull private AccountAndUser[] getAccounts(int[] userIds) { final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList(); for (int userId : userIds) { @@ -2591,10 +2596,12 @@ public class AccountManagerService } @Override + @NonNull public Account[] getAccountsAsUser(String type, int userId, String opPackageName) { return getAccountsAsUser(type, userId, null, -1, opPackageName); } + @NonNull private Account[] getAccountsAsUser( String type, int userId, @@ -2649,6 +2656,7 @@ public class AccountManagerService } } + @NonNull private Account[] getAccountsInternal( UserAccounts userAccounts, int callingUid, @@ -2672,7 +2680,15 @@ public class AccountManagerService } @Override - public boolean addSharedAccountAsUser(Account account, int userId) { + public void addSharedAccountsFromParentUser(int parentUserId, int userId) { + checkManageUsersPermission("addSharedAccountsFromParentUser"); + Account[] accounts = getAccountsAsUser(null, parentUserId, mContext.getOpPackageName()); + for (Account account : accounts) { + addSharedAccountAsUser(account, userId); + } + } + + private boolean addSharedAccountAsUser(Account account, int userId) { userId = handleIncomingUser(userId); UserAccounts accounts = getUserAccounts(userId); SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); @@ -2764,11 +2780,13 @@ public class AccountManagerService } @Override + @NonNull public Account[] getAccounts(String type, String opPackageName) { return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName); } @Override + @NonNull public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) { int callingUid = Binder.getCallingUid(); if (!UserHandle.isSameApp(callingUid, Process.myUid())) { @@ -2780,6 +2798,7 @@ public class AccountManagerService } @Override + @NonNull public Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName) { int packageUid = -1; @@ -3844,6 +3863,14 @@ public class AccountManagerService return false; } + private static void checkManageUsersPermission(String message) { + if (ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, Binder.getCallingUid(), -1, true) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("You need MANAGE_USERS permission to: " + message); + } + } + private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType, int callerUid) { if (callerUid == Process.SYSTEM_UID) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 0c884f1558fa..14a2cbc0e591 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1684,7 +1684,7 @@ public class NotificationManagerService extends SystemService { public boolean matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); return mZenModeHelper.matchesCallFilter( - UserHandle.getCallingUserHandle(), + Binder.getCallingUserHandle(), extras, mRankingHelper.findExtractor(ValidateNotificationPeople.class), MATCHES_CALL_FILTER_CONTACTS_TIMEOUT_MS, diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 1924bab6fac6..0577d5905085 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import android.accounts.Account; import android.annotation.NonNull; import android.app.Activity; import android.app.ActivityManager; @@ -63,6 +64,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsService; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; +import com.android.server.accounts.AccountManagerService; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -1386,6 +1388,25 @@ public class UserManagerService extends IUserManager.Stub { } /** + * @hide + */ + public UserInfo createRestrictedProfile(String name, int parentUserId) { + checkManageUsersPermission("setupRestrictedProfile"); + final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId); + if (user == null) { + return null; + } + setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id); + // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise + // the putIntForUser() will fail. + android.provider.Settings.Secure.putIntForUser(mContext.getContentResolver(), + android.provider.Settings.Secure.LOCATION_MODE, + android.provider.Settings.Secure.LOCATION_MODE_OFF, user.id); + setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user.id); + return user; + } + + /** * Find the current guest user. If the Guest user is partial, * then do not include it in the results as it is about to die. */ |