diff options
author | Amith Yamasani <yamasani@google.com> | 2012-08-10 17:06:33 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2012-08-11 18:24:07 -0700 |
commit | 258848d2ae04f447ff1c18023fa76b139fcc0862 (patch) | |
tree | 8736421f4007d81206d0f0ea8b32a2013508976a /core/java | |
parent | 75f0fac91bd7fa67fa76cfdd4e163b9f35be0432 (diff) | |
download | frameworks_base-258848d2ae04f447ff1c18023fa76b139fcc0862.zip frameworks_base-258848d2ae04f447ff1c18023fa76b139fcc0862.tar.gz frameworks_base-258848d2ae04f447ff1c18023fa76b139fcc0862.tar.bz2 |
User Manager service to manage users and query user details
Moved a bunch of methods from PackageManager to UserManager.
Fix launching of activities from recents to correct user.
Guest creation APIs
Change-Id: I0733405e6eb2829675665e225c759d6baa2b708f
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/accounts/AccountManagerService.java | 16 | ||||
-rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 76 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 21 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 25 | ||||
-rw-r--r-- | core/java/android/content/ContextWrapper.java | 6 | ||||
-rw-r--r-- | core/java/android/content/SyncManager.java | 17 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 8 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageManager.java | 50 | ||||
-rw-r--r-- | core/java/android/content/pm/UserInfo.java | 11 | ||||
-rw-r--r-- | core/java/android/os/IUserManager.aidl | 36 | ||||
-rw-r--r-- | core/java/android/os/UserManager.java | 212 | ||||
-rw-r--r-- | core/java/android/server/search/SearchManagerService.java | 4 |
12 files changed, 336 insertions, 146 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index ba05ee7..935d647 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -51,6 +51,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserId; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -92,6 +93,7 @@ public class AccountManagerService private final Context mContext; private final PackageManager mPackageManager; + private UserManager mUserManager; private HandlerThread mMessageThread; private final MessageHandler mMessageHandler; @@ -245,6 +247,13 @@ public class AccountManagerService initUser(0); } + private UserManager getUserManager() { + if (mUserManager == null) { + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + } + return mUserManager; + } + private UserAccounts initUser(int userId) { synchronized (mUsers) { UserAccounts accounts = mUsers.get(userId); @@ -382,12 +391,7 @@ public class AccountManagerService } private List<UserInfo> getAllUsers() { - try { - return AppGlobals.getPackageManager().getUsers(); - } catch (RemoteException re) { - // Local to system process, shouldn't happen - } - return null; + return getUserManager().getUsers(); } public void onServiceChanged(AuthenticatorDescription desc, boolean removed) { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 9a50a41..2face4c 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -41,8 +41,8 @@ import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.pm.UserInfo; import android.content.pm.ManifestDigest; +import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -1182,80 +1182,6 @@ final class ApplicationPackageManager extends PackageManager { return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; } - // Multi-user support - - /** - * @hide - */ - @Override - public UserInfo createUser(String name, int flags) { - try { - return mPM.createUser(name, flags); - } catch (RemoteException e) { - // Should never happen! - } - return null; - } - - /** - * @hide - */ - @Override - public List<UserInfo> getUsers() { - try { - return mPM.getUsers(); - } catch (RemoteException re) { - ArrayList<UserInfo> users = new ArrayList<UserInfo>(); - UserInfo primary = new UserInfo(0, "Root!", null, - UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY); - users.add(primary); - return users; - } - } - - /** - * @hide - */ - @Override - public UserInfo getUser(int userId) { - try { - return mPM.getUser(userId); - } catch (RemoteException re) { - return null; - } - } - - /** - * @hide - */ - @Override - public boolean removeUser(int id) { - try { - return mPM.removeUser(id); - } catch (RemoteException e) { - return false; - } - } - - /** - * @hide - */ - @Override - public void setUserName(int id, String name) { - try { - mPM.setUserName(id, name); - } catch (RemoteException re) { - } - } - - /** - * @hide - */ - @Override - public void updateUserFlags(int id, int flags) { - // TODO: - } - /** * @hide */ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d886278..4496ce8 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -80,6 +80,7 @@ import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.IPowerManager; +import android.os.IUserManager; import android.os.Looper; import android.os.PowerManager; import android.os.Process; @@ -87,6 +88,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserId; import android.os.SystemVibrator; +import android.os.UserManager; import android.os.storage.StorageManager; import android.telephony.TelephonyManager; import android.content.ClipboardManager; @@ -498,6 +500,13 @@ class ContextImpl extends Context { return WindowManagerImpl.getDefault().makeCompatible( ctx.mPackageInfo.mCompatibilityInfo); }}); + + registerService(USER_SERVICE, new ServiceFetcher() { + public Object getService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(USER_SERVICE); + IUserManager service = IUserManager.Stub.asInterface(b); + return new UserManager(ctx, service); + }}); } static ContextImpl getImpl(Context context) { @@ -918,6 +927,18 @@ class ContextImpl extends Context { (Activity)null, intent, -1, options); } + /** @hide */ + @Override + public void startActivityAsUser(Intent intent, Bundle options, int userId) { + try { + ActivityManagerNative.getDefault().startActivityAsUser( + mMainThread.getApplicationThread(), intent, + intent.resolveTypeIfNeeded(getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options, userId); + } catch (RemoteException re) { + } + } + @Override public void startActivities(Intent[] intents) { startActivities(intents, null); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 5a7a989..bf60a96 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -890,6 +890,22 @@ public abstract class Context { public abstract void startActivity(Intent intent, Bundle options); /** + * Same as {@link #startActivity(Intent, Bundle)}, but for a specific user. It requires holding + * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. + * @param intent The description of the activity to start. + * @param options Additional options for how the Activity should be started. + * May be null if there are no options. See {@link android.app.ActivityOptions} + * for how to build the Bundle supplied here; there are no supported definitions + * for building it manually. + * @param userId The user id of the user to start this activity for. + * @throws ActivityNotFoundException + * @hide + */ + public void startActivityAsUser(Intent intent, Bundle options, int userId) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * Same as {@link #startActivities(Intent[], Bundle)} with no options * specified. * @@ -2018,6 +2034,15 @@ public abstract class Context { public static final String SCHEDULING_POLICY_SERVICE = "scheduling_policy"; /** + * Use with {@link #getSystemService} to retrieve a + * {@link android.os.UserManager} for managing users on devices that support multiple users. + * + * @see #getSystemService + * @see android.os.UserManager + */ + public static final String USER_SERVICE = "user"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index f007720..ff4c9a1 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -287,6 +287,12 @@ public class ContextWrapper extends Context { mBase.startActivity(intent, options); } + /** @hide */ + @Override + public void startActivityAsUser(Intent intent, Bundle options, int userId) { + mBase.startActivityAsUser(intent, options, userId); + } + @Override public void startActivities(Intent[] intents) { mBase.startActivities(intents); diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index badcb03..e6303b9 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -53,6 +53,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserId; +import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; import android.text.format.DateUtils; @@ -206,16 +207,20 @@ public class SyncManager implements OnAccountsUpdateListener { // Use this as a random offset to seed all periodic syncs private int mSyncRandomOffsetMillis; + private UserManager mUserManager; + private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours - private List<UserInfo> getAllUsers() { - try { - return AppGlobals.getPackageManager().getUsers(); - } catch (RemoteException re) { - // Local to system process, shouldn't happen + private UserManager getUserManager() { + if (mUserManager == null) { + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); } - return null; + return mUserManager; + } + + private List<UserInfo> getAllUsers() { + return getUserManager().getUsers(); } private boolean containsAccountAndUser(AccountAndUser[] accounts, Account account, int userId) { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0d87df5..22807a4 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -358,11 +358,6 @@ interface IPackageManager { boolean setInstallLocation(int loc); int getInstallLocation(); - UserInfo createUser(in String name, int flags); - boolean removeUser(int userId); - void setUserName(int userId, String name); - ParcelFileDescriptor setUserIcon(int userId); - void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer, int flags, in String installerPackageName, in Uri verificationURI, in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams); @@ -373,9 +368,6 @@ interface IPackageManager { boolean isFirstBoot(); - List<UserInfo> getUsers(); - UserInfo getUser(int userId); - void setPermissionEnforced(String permission, boolean enforced); boolean isPermissionEnforced(String permission); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index cd7ef0e..f287ca5 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2616,56 +2616,6 @@ public abstract class PackageManager { String packageName, IPackageMoveObserver observer, int flags); /** - * Creates a user with the specified name and options. - * - * @param name the user's name - * @param flags flags that identify the type of user and other properties. - * @see UserInfo - * - * @return the UserInfo object for the created user, or null if the user could not be created. - * @hide - */ - public abstract UserInfo createUser(String name, int flags); - - /** - * @return the list of users that were created - * @hide - */ - public abstract List<UserInfo> getUsers(); - - /** - * @param id the ID of the user, where 0 is the primary user. - * @hide - */ - public abstract boolean removeUser(int id); - - /** - * Updates the user's name. - * - * @param id the user's id - * @param name the new name for the user - * @hide - */ - public abstract void setUserName(int id, String name); - - /** - * Changes the user's properties specified by the flags. - * - * @param id the user's id - * @param flags the new flags for the user - * @hide - */ - public abstract void updateUserFlags(int id, int flags); - - /** - * Returns the details for the user specified by userId. - * @param userId the user id of the user - * @return UserInfo for the specified user, or null if no such user exists. - * @hide - */ - public abstract UserInfo getUser(int userId); - - /** * Returns the device identity that verifiers can use to associate their scheme to a particular * device. This should not be used by anything other than a package verifier. * diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index 68a7257..638e273 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -18,12 +18,17 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; +import android.os.Parcelable.Creator; /** * Per-user information. * @hide */ public class UserInfo implements Parcelable { + + /** 6 bits for user type */ + public static final int FLAG_MASK_USER_TYPE = 0x0000003F; + /** * Primary user. Only one user can have this flag set. Meaning of this * flag TBD. @@ -41,6 +46,12 @@ public class UserInfo implements Parcelable { */ public static final int FLAG_GUEST = 0x00000004; + /** + * Indicates the user has restrictions in privileges, in addition to those for normal users. + * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts. + */ + public static final int FLAG_RESTRICTED = 0x00000008; + public int id; public String name; public String iconPath; diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl new file mode 100644 index 0000000..cb1b962 --- /dev/null +++ b/core/java/android/os/IUserManager.aidl @@ -0,0 +1,36 @@ +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.os; + +import android.os.ParcelFileDescriptor; +import android.content.pm.UserInfo; + +/** + * {@hide} + */ +interface IUserManager { + UserInfo createUser(in String name, int flags); + boolean removeUser(int userHandle); + void setUserName(int userHandle, String name); + ParcelFileDescriptor setUserIcon(int userHandle); + List<UserInfo> getUsers(); + UserInfo getUserInfo(int userHandle); + void setGuestEnabled(boolean enable); + boolean isGuestEnabled(); + void wipeUser(int userHandle); +} diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java new file mode 100644 index 0000000..9c73392 --- /dev/null +++ b/core/java/android/os/UserManager.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.os; + +import com.android.internal.R; +import android.content.Context; +import android.content.pm.UserInfo; +import android.util.Log; + +import java.util.List; + +/** + * Manages users and user details on a multi-user system. + */ +public class UserManager { + + private static String TAG = "UserManager"; + private final IUserManager mService; + private final Context mContext; + + /** @hide */ + public UserManager(Context context, IUserManager service) { + mService = service; + mContext = context; + } + + /** + * Returns whether the system supports multiple users. + * @return true if multiple users can be created, false if it is a single user device. + */ + public boolean supportsMultipleUsers() { + return getMaxSupportedUsers() > 1; + } + + /** + * Returns the user handle for the user that this application is running for. + * @return the user handle of the user making this call. + * @hide + * */ + public int getUserHandle() { + return Process.myUserHandle(); + } + + /** + * Returns the user name of the user making this call. + * @return the user name + */ + public String getUserName() { + try { + return mService.getUserInfo(getUserHandle()).name; + } catch (RemoteException re) { + Log.w(TAG, "Could not get user name", re); + return ""; + } + } + + /** + * Returns the UserInfo object describing a specific user. + * @param userHandle the user handle of the user whose information is being requested. + * @return the UserInfo object for a specific user. + * @hide + * */ + public UserInfo getUserInfo(int userHandle) { + try { + return mService.getUserInfo(userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not get user info", re); + return null; + } + } + + /** + * Creates a user with the specified name and options. + * + * @param name the user's name + * @param flags flags that identify the type of user and other properties. + * @see UserInfo + * + * @return the UserInfo object for the created user, or null if the user could not be created. + * @hide + */ + public UserInfo createUser(String name, int flags) { + try { + return mService.createUser(name, flags); + } catch (RemoteException re) { + Log.w(TAG, "Could not create a user", re); + return null; + } + } + + /** + * Returns information for all users on this device. + * @return the list of users that were created. + * @hide + */ + public List<UserInfo> getUsers() { + try { + return mService.getUsers(); + } catch (RemoteException re) { + Log.w(TAG, "Could not get user list", re); + return null; + } + } + + /** + * Removes a user and all associated data. + * @param userHandle the integer handle of the user, where 0 is the primary user. + * @hide + */ + public boolean removeUser(int userHandle) { + try { + return mService.removeUser(userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not remove user ", re); + return false; + } + } + + /** + * Updates the user's name. + * + * @param userHandle the user's integer handle + * @param name the new name for the user + * @hide + */ + public void setUserName(int userHandle, String name) { + try { + mService.setUserName(userHandle, name); + } catch (RemoteException re) { + Log.w(TAG, "Could not set the user name ", re); + } + } + + /** + * Returns a file descriptor for the user's photo. PNG data can be written into this file. + * @param userHandle the user for whom to change the photo. + * @return a {@link ParcelFileDescriptor} to which to write the photo. + * @hide + */ + public ParcelFileDescriptor setUserIcon(int userHandle) { + try { + return mService.setUserIcon(userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not set the user icon ", re); + return null; + } + } + + /** + * Enable or disable the use of a guest account. If disabled, the existing guest account + * will be wiped. + * @param enable whether to enable a guest account. + * @hide + */ + public void setGuestEnabled(boolean enable) { + try { + mService.setGuestEnabled(enable); + } catch (RemoteException re) { + Log.w(TAG, "Could not change guest account availability to " + enable); + } + } + + /** + * Checks if a guest user is enabled for this device. + * @return whether a guest user is enabled + * @hide + */ + public boolean isGuestEnabled() { + try { + return mService.isGuestEnabled(); + } catch (RemoteException re) { + Log.w(TAG, "Could not retrieve guest enabled state"); + return false; + } + } + + /** + * Wipes all the data for a user, but doesn't remove the user. + * @param userHandle + * @hide + */ + public void wipeUser(int userHandle) { + try { + mService.wipeUser(userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not wipe user " + userHandle); + } + } + + /** + * Returns the maximum number of users that can be created on this device. A return value + * of 1 means that it is a single user device. + * @hide + * @return a value greater than or equal to 1 + */ + public int getMaxSupportedUsers() { + return mContext.getResources().getInteger(R.integer.config_multiuserMaximumUsers); + } +} diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index 2411cec..a1f6735 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -32,6 +32,7 @@ import android.database.ContentObserver; import android.os.Binder; import android.os.Process; import android.os.UserId; +import android.os.UserManager; import android.provider.Settings; import android.util.Log; import android.util.SparseArray; @@ -77,7 +78,8 @@ public class SearchManagerService extends ISearchManager.Stub { Searchables searchables = mSearchables.get(userId); long origId = Binder.clearCallingIdentity(); - boolean userExists = mContext.getPackageManager().getUser(userId) != null; + boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)) + .getUserInfo(userId) != null; Binder.restoreCallingIdentity(origId); if (searchables == null && userExists) { |