Write my own UserManager on Android

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值