summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-08-10 17:06:33 -0700
committerAmith Yamasani <yamasani@google.com>2012-08-11 18:24:07 -0700
commit258848d2ae04f447ff1c18023fa76b139fcc0862 (patch)
tree8736421f4007d81206d0f0ea8b32a2013508976a /core/java
parent75f0fac91bd7fa67fa76cfdd4e163b9f35be0432 (diff)
downloadframeworks_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.java16
-rw-r--r--core/java/android/app/ApplicationPackageManager.java76
-rw-r--r--core/java/android/app/ContextImpl.java21
-rw-r--r--core/java/android/content/Context.java25
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/SyncManager.java17
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl8
-rw-r--r--core/java/android/content/pm/PackageManager.java50
-rw-r--r--core/java/android/content/pm/UserInfo.java11
-rw-r--r--core/java/android/os/IUserManager.aidl36
-rw-r--r--core/java/android/os/UserManager.java212
-rw-r--r--core/java/android/server/search/SearchManagerService.java4
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) {