Android User Manager class.
User interface: UserManager.java
Framework implementation: UserManagerService.java
Main methods inUserManager
1995 public static int getMaxSupportedUsers() { 1996 // Don't allow multiple users on certain builds 1997 if (android.os.Build.ID.startsWith("JVP")) return 1; 1998 // Svelte devices don't get multi-user. 1999 if (ActivityManager.isLowRamDeviceStatic()) return 1; 2000 return SystemProperties.getInt("fw.max_users", 2001 Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers)); 2002 }
1280 public UserInfo createUser(String name, int flags) { 1281 UserInfo user = null; 1282 try { 1283 user = mService.createUser(name, flags); 1284 // TODO: Keep this in sync with 1285 // UserManagerService.LocalService.createUserEvenWhenDisallowed 1286 if (user != null && !user.isAdmin()) { 1287 mService.setUserRestriction(DISALLOW_SMS, true, user.id); 1288 mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id); 1289 } 1290 } catch (RemoteException re) { 1291 throw re.rethrowFromSystemServer(); 1292 } 1293 return user; 1294 } 1295 1296 /** 1297 * Creates a guest user and configures it. 1298 * @param context an application context 1299 * @param name the name to set for the user 1300 * @hide 1301 */ 1302 public UserInfo createGuest(Context context, String name) { 1303 UserInfo guest = null; 1304 try { 1305 guest = mService.createUser(name, UserInfo.FLAG_GUEST); 1306 if (guest != null) { 1307 Settings.Secure.putStringForUser(context.getContentResolver(), 1308 Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id); 1309 } 1310 } catch (RemoteException re) { 1311 throw re.rethrowFromSystemServer(); 1312 } 1313 return guest; 1314 } 1315 1316 /** 1317 * Creates a user with the specified name and options as a profile of another user. 1318 * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. 1319 * 1320 * @param name the user's name 1321 * @param flags flags that identify the type of user and other properties. 1322 * @see UserInfo 1323 * @param userHandle new user will be a profile of this use. 1324 * 1325 * @return the UserInfo object for the created user, or null if the user could not be created. 1326 * @hide 1327 */ 1328 public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle) { 1329 try { 1330 return mService.createProfileForUser(name, flags, userHandle); 1331 } catch (RemoteException re) { 1332 throw re.rethrowFromSystemServer(); 1333 } 1334 } 1335 1336 /** 1337 * Creates a restricted profile with the specified name. This method also sets necessary 1338 * restrictions and adds shared accounts. 1339 * 1340 * @param name profile's name 1341 * @return UserInfo object for the created user, or null if the user could not be created. 1342 * @hide 1343 */ 1344 public UserInfo createRestrictedProfile(String name) { 1345 try { 1346 UserHandle parentUserHandle = Process.myUserHandle(); 1347 UserInfo user = mService.createRestrictedProfile(name, 1348 parentUserHandle.getIdentifier()); 1349 if (user != null) { 1350 AccountManager.get(mContext).addSharedAccountsFromParentUser(parentUserHandle, 1351 UserHandle.of(user.id)); 1352 } 1353 return user; 1354 } catch (RemoteException re) { 1355 throw re.rethrowFromSystemServer(); 1356 } 1357 }
1542 public List<UserInfo> getUsers() { 1543 try { 1544 return mService.getUsers(false); 1545 } catch (RemoteException re) { 1546 throw re.rethrowFromSystemServer(); 1547 } 1548 }
1925 public boolean removeUser(@UserIdInt int userHandle) { 1926 try { 1927 return mService.removeUser(userHandle); 1928 } catch (RemoteException re) { 1929 throw re.rethrowFromSystemServer(); 1930 } 1931 }
We can use pm command to add/remove user also.
pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME
pm remove-user USER_ID
pm get-max-users
How to switch user.
It is implemented in ActivityManagerService.switchUser method.
We can use "am switch-user" also.
am switch-user <USER_ID>
am start-user <USER_ID>
am unlock-user <USER_ID> [TOKEN_HEX]
am stop-user [-w] [-f] <USER_ID>
Inframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
21764 public boolean switchUser(final int targetUserId) { 21765 enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId); 21766 UserInfo currentUserInfo; 21767 UserInfo targetUserInfo; 21768 synchronized (this) { 21769 int currentUserId = mUserController.getCurrentUserIdLocked(); 21770 currentUserInfo = mUserController.getUserInfo(currentUserId); 21771 targetUserInfo = mUserController.getUserInfo(targetUserId); 21789 mUserController.setTargetUserIdLocked(targetUserId); 21790 } 21791 Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo); 21792 mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG); 21793 mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_UI_MSG, userNames)); 21794 return true; 21795 }
1753 case START_USER_SWITCH_UI_MSG: { 1754 mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj); 1755 break; 1756 }
Inframeworks/base/services/core/java/com/android/server/am/UserController.java
1021 void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { 1022 // The dialog will show and then initiate the user switch by calling startUserInForeground 1023 Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromToUserPair.first, 1024 fromToUserPair.second, true /* above system */); 1025 d.show(); 1026 }
Inframeworks/base/services/core/java/com/android/server/am/UserSwitchingDialog.java
93 public void show() { 94 // Slog.v(TAG, "show called"); 95 super.show(); 96 final View decorView = getWindow().getDecorView(); 97 if (decorView != null) { 98 decorView.getViewTreeObserver().addOnWindowShownListener(this); 99 } 100 // Add a timeout as a safeguard, in case a race in screen on/off causes the window 101 // callback to never come. 102 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 103 WINDOW_SHOWN_TIMEOUT_MS); 104 } 105 106 @Override 107 public void onWindowShown() { 108 // Slog.v(TAG, "onWindowShown called"); 109 startUser(); 110 } 111 112 void startUser() { 113 synchronized (this) { 114 if (!mStartedUser) { 115 mService.mUserController.startUserInForeground(mUserId, this); 116 mStartedUser = true; 117 final View decorView = getWindow().getDecorView(); 118 if (decorView != null) { 119 decorView.getViewTreeObserver().removeOnWindowShownListener(this); 120 } 121 mHandler.removeMessages(MSG_START_USER); 122 } 123 } 124 }
Inframeworks/base/services/core/java/com/android/server/am/UserController.java
924 boolean startUserInForeground(final int userId, Dialog dlg) { 925 boolean result = startUser(userId, /* foreground */ true); 926 dlg.dismiss(); 927 return result; 928 }
767 boolean startUser(final int userId, final boolean foreground) { 777 778 Slog.i(TAG, "Starting userid:" + userId + " fg:" + foreground); 779 780 final long ident = Binder.clearCallingIdentity(); 781 try { 782 synchronized (mService) { 783 final int oldUserId = mCurrentUserId; 784 if (oldUserId == userId) { 785 return true; 786 } 787 788 mService.mStackSupervisor.setLockTaskModeLocked(null, 789 ActivityManager.LOCK_TASK_MODE_NONE, "startUser", false); 790 791 final UserInfo userInfo = getUserInfo(userId); 792 if (userInfo == null) { 793 Slog.w(TAG, "No user info for user #" + userId); 794 return false; 795 } 796 if (foreground && userInfo.isManagedProfile()) { 797 Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user"); 798 return false; 799 } 800 801 if (foreground) { 802 mService.mWindowManager.startFreezingScreen( 803 R.anim.screen_user_exit, R.anim.screen_user_enter); 804 } 805 806 boolean needStart = false; 807 808 // If the user we are switching to is not currently started, then 809 // we need to start it now. 810 if (mStartedUsers.get(userId) == null) { 811 UserState userState = new UserState(UserHandle.of(userId)); 812 mStartedUsers.put(userId, userState); 813 getUserManagerInternal().setUserState(userId, userState.state); 814 updateStartedUserArrayLocked(); 815 needStart = true; 816 } 817 818 final UserState uss = mStartedUsers.get(userId); 819 final Integer userIdInt = userId; 820 mUserLru.remove(userIdInt); 821 mUserLru.add(userIdInt); 822 823 if (foreground) { 824 mCurrentUserId = userId; 825 mService.updateUserConfigurationLocked(); 826 mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up 827 updateCurrentProfileIdsLocked(); 828 mService.mWindowManager.setCurrentUser(userId, mCurrentProfileIds); 829 // Once the internal notion of the active user has switched, we lock the device 830 // with the option to show the user switcher on the keyguard. 831 mService.mWindowManager.lockNow(null); 832 } else { 833 final Integer currentUserIdInt = mCurrentUserId; 834 updateCurrentProfileIdsLocked(); 835 mService.mWindowManager.setCurrentProfileIds(mCurrentProfileIds); 836 mUserLru.remove(currentUserIdInt); 837 mUserLru.add(currentUserIdInt); 838 } 839 840 // Make sure user is in the started state. If it is currently 841 // stopping, we need to knock that off. 842 if (uss.state == UserState.STATE_STOPPING) { 843 // If we are stopping, we haven't sent ACTION_SHUTDOWN, 844 // so we can just fairly silently bring the user back from 845 // the almost-dead. 846 uss.setState(uss.lastState); 847 getUserManagerInternal().setUserState(userId, uss.state); 848 updateStartedUserArrayLocked(); 849 needStart = true; 850 } else if (uss.state == UserState.STATE_SHUTDOWN) { 851 // This means ACTION_SHUTDOWN has been sent, so we will 852 // need to treat this as a new boot of the user. 853 uss.setState(UserState.STATE_BOOTING); 854 getUserManagerInternal().setUserState(userId, uss.state); 855 updateStartedUserArrayLocked(); 856 needStart = true; 857 } 858 859 if (uss.state == UserState.STATE_BOOTING) { 860 // Give user manager a chance to propagate user restrictions 861 // to other services and prepare app storage 862 getUserManager().onBeforeStartUser(userId); 863 864 // Booting up a new user, need to tell system services about it. 865 // Note that this is on the same handler as scheduling of broadcasts, 866 // which is important because it needs to go first. 867 mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId, 0)); 868 } 869 870 if (foreground) { 871 mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId, 872 oldUserId)); 873 mHandler.removeMessages(REPORT_USER_SWITCH_MSG); 874 mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); 875 mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG, 876 oldUserId, userId, uss)); 877 mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG, 878 oldUserId, userId, uss), USER_SWITCH_TIMEOUT); 879 } 880 881 if (needStart) { 882 // Send USER_STARTED broadcast 883 Intent intent = new Intent(Intent.ACTION_USER_STARTED); 884 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 885 | Intent.FLAG_RECEIVER_FOREGROUND); 886 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 887 mService.broadcastIntentLocked(null, null, intent, 888 null, null, 0, null, null, null, AppOpsManager.OP_NONE, 889 null, false, false, MY_PID, SYSTEM_UID, userId); 890 } 891 892 if (foreground) { 893 moveUserToForegroundLocked(uss, oldUserId, userId); 894 } else { 895 mService.mUserController.finishUserBoot(uss); 896 } 897 898 if (needStart) { 899 Intent intent = new Intent(Intent.ACTION_USER_STARTING); 900 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 901 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 902 mService.broadcastIntentLocked(null, null, intent, 903 null, new IIntentReceiver.Stub() { 904 @Override 905 public void performReceive(Intent intent, int resultCode, 906 String data, Bundle extras, boolean ordered, boolean sticky, 907 int sendingUser) throws RemoteException { 908 } 909 }, 0, null, null, 910 new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, 911 null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL); 912 } 913 } 914 } finally { 915 Binder.restoreCallingIdentity(ident); 916 } 917 918 return true; 919 }
1144 void moveUserToForegroundLocked(UserState uss, int oldUserId, int newUserId) { 1145 boolean homeInFront = mService.mStackSupervisor.switchUserLocked(newUserId, uss); 1146 if (homeInFront) { 1147 mService.startHomeActivityLocked(newUserId, "moveUserToForeground"); // if home stack is in the front, start home activity. 1148 } else { 1149 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); // if home stack is not at the front, resume the top activity. 1150 } 1151 EventLogTags.writeAmSwitchUser(newUserId); 1152 sendUserSwitchBroadcastsLocked(oldUserId, newUserId); 1153 }
My User Manager class.
MyUserManager.java
MyUserManagerImpl.java
MyUserInfo.java
MyUserManagerHelper.java
MyUserManagerService.java
My User Manager implementation.
Infireos/base/features/MyUserManager/services/java/com/my/android/server/pm/MyUserManagerService.java
64 public class MyUserManagerService extends SystemService { 116 117 public MyUserManagerService(Context context) { 118 super(context); 119 mContext = context; 120 mUserManagerHelper = new MyUserManagerHelper(context); 121 } 122 123 @Override 124 public void onStart() { 125 mBinderService = new BinderService(); 126 publishBinderService(getSystemServiceName(), mBinderService); 127 } 128 129 @Override 130 public void onBootPhase(int phase) { 131 if (phase == PHASE_SYSTEM_SERVICES_READY) { 132 if (DBG) Log.d(TAG, "System ready called"); 133 mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE); 134 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 135 disableNavBarFeatureForKids(); // disable recent button on navigation bar in Child profile 136 mAmznPackageManager = (MyPackageManager) mContext.getPackageManager(); 137 mDpm = mUserManagerHelper.getDevicePolicyManager(); 138 139 if (mAmznPackageManager.isUpgrade()) { 140 List<UserInfo> userInfo = mUserManager.getUsers(); 141 final int N = userInfo.size(); 142 for (int i=0; i < N; i++) { 143 UserInfo user = userInfo.get(i); 144 if (mUserManagerHelper.isChildUser(user)) { 145 mBinderService.enableKftLauncher(user); 146 mBinderService.setUserSetupComplete(user); 147 } 148 } 149 } 150 } 151 } 152 153 private void disableNavBarFeatureForKids() { 154 // Register to userswitch observer. 155 try { 156 mUserManagerHelper.getActivityManagerDefault().registerUserSwitchObserver( 157 new IUserSwitchObserver.Stub() { 158 @Override 159 public void onUserSwitching(int newUserId, IRemoteCallback reply) { 166 } 167 168 @Override 169 public void onUserSwitchComplete(int newUserId) throws RemoteException { 170 // disable recent task button for kid. 175 mStatusBarManager.disable(View.STATUS_BAR_DISABLE_RECENT); 180 } 181 @Override 182 public void onForegroundProfileSwitch(int newProfileId) { 185 } 186 }, TAG); 187 } catch (RemoteException e) { 188 Log.e(TAG,e.toString()); 189 } 190 } 191 290 291 public class BinderService extends IMyUserManager.Stub {// enable launcher for current profile and disable launcher for other users. Different users have different home activities. // AMS will try to start home activity for current user if it detect that old running home activity is not available for current user.
380 public boolean enableKftLauncher(UserInfo info) {
381 if (mDpm != null) {
382 // Set Free Time as profile owner by default
383 try {
384 mDpm
385 .setProfileOwner(new ComponentName(FREE_TIME_PACKAGE_NAME,
386 FREE_TIME_ADMIN_RECEIVER), FREE_TIME_NAME, info.getUserHandle()
387 .getIdentifier());
388 } catch (RemoteException e) {
389 Log.e(TAG, "Failed to setProfileOwner. DeviceProfileManager issue.", e);
390 return false;
391 } catch (IllegalArgumentException e) {
392 Log.e(TAG, "Failed to setProfileOwner. FreeTime package not found.", e);
393 return false;
394 } catch (Exception e) {
395 Log.wtf(TAG, "Failed to setProfileOwner. We don't know why", e);
396 return false;
397 }
398 } else {
399 Log.d(TAG, "Device Policy Manager Service is not available");
400 return false;
401 }
402
403 if (mAmznPackageManager !=null) {
404 try {
405 if (mUserManagerHelper.isActivityInstalled(FREE_TIME_TV_LAUNCHER_PACKAGE, FREE_TIME_TV_LAUNCHER_ACTIVITY)) {
406 // The activity typically exists on TV
407 Log.i(TAG,"Enabling KFT TV Launcher for user: " + info.id);
408 mAmznPackageManager.setComponentEnabledSetting(new ComponentName(FREE_TIME_TV_LAUNCHER_PACKAGE,
409 FREE_TIME_TV_LAUNCHER_ACTIVITY), PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
410 PackageManager.DONT_KILL_APP, info.id);
411 mAmznPackageManager.setComponentEnabledSetting(new ComponentName(TV_LAUNCHER_PACKAGE,
412 TV_LAUNCHER_ACTIVITY), PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
413 0, info.id);
414 } else if (mUserManagerHelper.isActivityInstalled(FREE_TIME_KINDLE_LAUNCHER_PACKAGE, FREE_TIME_KINDLE_LAUNCHER_ACTIVITY)){
415 // The activity typically exists on tablet
416 Log.i(TAG,"Enabling KFT Tablet Launcher for user: " + info.id);
417 mAmznPackageManager.setComponentEnabledSetting(new ComponentName(FREE_TIME_KINDLE_LAUNCHER_PACKAGE,
418 FREE_TIME_KINDLE_LAUNCHER_ACTIVITY), PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
419 PackageManager.DONT_KILL_APP, info.id);
420 mAmznPackageManager.setComponentEnabledSetting(new ComponentName(KINDLE5_LAUNCHER_PACKAGE,
421 KINDLE5_LAUNCHER_ACTIVITY), PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
422 0, info.id);
423 } else {
424 // cannot enable KFT on other devices.
425 return false;
426 }
427 } catch (Exception e) {
428 Log.e(TAG, "Could not enable KFT Launcher", e);
429 return false;
430 }
431 } else {
432 Log.d(TAG, "My Package Manager is not available");
433 return false;
434 }
435 return true;
436 }
437
438 /**
439 * Called to set user_setup_complete flag to 1 after child user is created.
440 * For adult users, we set during wizard
441 * @return true if setup is complete
442 * @hide
443 */
444 public boolean setUserSetupComplete(UserInfo info) {
445 final long origId = Binder.clearCallingIdentity();
446 try {
447 mUserManagerHelper.putIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1, info.id);
448 } catch (Exception e) {
449 Log.e(TAG, "Failed to setUserSetupComplete", e);
450 return false;
451 } finally {
452 Binder.restoreCallingIdentity(origId);
453 }
454 return true;
455 }
456 }
457}
Infireos/base/features/MyUserManager/framework/java/my/os/MyUserManager.java
public abstract class MyUserManager extends UserManager
Infireos/base/features/MyUserManager/framework/java/my/os/MyUserManagerImpl.java
public class MyUserManagerImpl extends MyUserManager
142 public MyUserInfo createChildUser(String name) { 143 UserInfo info = createUser(name, MyUserInfo.FLAG_CHILD); 157 if (!mService.enableKftLauncher(info) || !mService.setUserSetupComplete(info)) { // enable current user's launcher and disable other user's launcher 168 return new MyUserInfo(info); 169 } 170 171 /** 172 * Creates an adult profile with the specified name and options. 173 * Requires android.Manifest.permission.MANAGE_USERS permission. 174 * 175 * @param name the user's name 176 * 177 * @return the MyUserInfo object for the created user, or null if the user could not be created. 178 */ 179 @Override 180 public MyUserInfo createAdultUser(String name) { 181 UserInfo info = createUser(name, UserInfo.FLAG_ADMIN); 190 // Set Parental Controls as profile owner by default 191 mDpm.setProfileOwner(new ComponentName( // set target user's profile owner. Refer to http://www.greenbot.com/article/2109083/getting-started-with-androids-user-profiles.html for details of profile and user. 192 PARENTAL_CONTROL_PACKAGE_NAME, PARENTAL_CONTROL_ADMIN_RECEIVER), 193 PARENTAL_CONTROLS_NAME, info.getUserHandle().getIdentifier()); 208 209 // Disable demo package on tablets. 211 mAmznPackageManager.setComponentEnabledSetting(new ComponentName(KINDLE5_DEMO_PACKAGE, 212 KINDLE5_DEMO_ACTIVITY), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 213 PackageManager.DONT_KILL_APP, info.id); 219 220 return new MyUserInfo(info); 221 } 222