diff options
| author | 2015-09-25 22:48:05 +0000 | |
|---|---|---|
| committer | 2015-09-25 22:48:05 +0000 | |
| commit | 9265189f774858b47ecde5e961a1058d3c63d38c (patch) | |
| tree | 44129e682e2c19b1cff286ffe163ab2329fa94c0 | |
| parent | e6ac1a68e9da6b07f575bf6cbde644c5e28e3927 (diff) | |
| parent | 737b216b5c28f7d7162f219136d4e8a9eb1a486b (diff) | |
Merge "Added --restricted option for create-user command"
| -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.       */  |