Android SystemServer 系列专题【篇五:UserController用户状态控制】

本篇接着SystemServer的启动流程,围绕SystemServer最后阶段关于主用户的启动和解锁的流程,作为切入点,来看看SystemServer是如何讲用户状态同步到所有的系统级服务中。

  • ssm.onStartUser
  • ssm.onUnlockingUser
  • ssm.onUnlockedUser

本篇先介绍UserController是如何管理用户状态,SystemServiceManager是如何把用户状态通知到所有的系统级服务,如上三个场景的触发条件来分别介绍。

1、UserController

UserController从命名来看,就是用户控制器,他仅仅是一个控制器,即不是进程,不是系统服务,仅仅用来封装用户状态的对象。先看看他的定义:

1)UserController持有者

从构造函数都可以看到传递了ams,即ams和他息息相关。这里值得注意的是存在一个Injector,这其实就是一个典型的依赖注入设计模型。

usercontroller的持有者不用怀疑就是ams,如下搜索在fw的源码中,除了ams,就没有谁敢去实例化它。

2)UserController提供的三大方法

UserController完成的事情比较多,概括了多用户切换,用户解锁等方方面面相关逻辑。这里只针对主用户的启动、解锁、解锁完成来进行说明。

A onSystemUserStarting启动主用户

USER_SYSTEM就是主用户又叫系统用户,userid为0

B finishUserUnlocking用户解锁过程中
C finishUserUnlockedCompleted用户解锁完成

在判断用户解锁完成之后,该方法做了如下两件事情:

  • 发送USER_UNLOCKED_MSG
  • 发送ACTION_BOOT_COMPLETED广播

3)mInjector回调到ssm

UserController提供了如上三大方法,用来启动用户,用户解锁过程中,用户解锁完成。接下来我们看看mInjector是如何把这三个操作通知到SystemServiceManager的。

A onSystemUserStarting启动主用户

这里传递的userId就是前文中的USER_SYSTEM,即userid=0。系统主用户

B USER_UNLOCK_MSG用户解锁中消息处理

用户解锁过程中的消息处理主要也分为两个操作:

  • 通过injector通知ssm回调onUserUnlocking方法
  • 调用finishUserUnlocked方法去完成解锁:这又回到了UserController的finishUserUnlockedCompleted消息处理完成方法
C USER_UNLOCKED_MSG用户解锁完成消息处理

通过通过injector通知ssm回调onUserUnlocked方法

4)UserController其他操作

前文针对三大场景来介绍UserController是如何通知到ssm,其实还可以理解为ams是如何通知到ssm的。除了这三大回调之外,其实还有很多ssm也需要的其他接口:

  • ssm.onUserSwitching
  • ssm.onUserStopping
  • ssm.onUserStopped
  • ssm.onUserCompletedEvent

这里就暂时不一一介绍了。值得注意的是, 后续可以在研究一下哪个开机完成广播是怎么回事。

2、SSM对所有SystemServer回调

1)ssm.onUserXXX

SystemServiceManager在实现onUserXXX的时候,统一调用了onUser方法,传递了不同的状态值进去,如下代码:

2)onUser遍历前的日志准备

如上代码,ssm在接收到ams的UserController的回调,在遍历所有服务之前,先进行Calling on关键日志打印,并且决定是否使用线程池,从后续的异步日志来看,肯定是使用了线程池。日志如下:

bash 复制代码
    #流程1:AMS启动系统主用户
	Line 18973: 09-02 03:40:32.080  2207  2207 D SystemServerTiming: getCurrentUser
	Line 18975: 09-02 03:40:32.080  2207  2207 D SystemServerTiming: ActivityManagerStartApps
	Line 18976: 09-02 03:40:32.080  2207  2207 D SystemServerTimingAsync: ssm.StartUser-0
	Line 18977: 09-02 03:40:32.081  2207  2207 I SystemServiceManager: Calling onStartUser 0
	Line 18975: 09-02 03:40:32.080  2207  2207 D SystemServerTiming: ActivityManagerStartApps
	Line 18976: 09-02 03:40:32.080  2207  2207 D SystemServerTimingAsync: ssm.StartUser-0
	Line 18977: 09-02 03:40:32.081  2207  2207 I SystemServiceManager: Calling onStartUser 0
    #流程2:阶段1000
	Line 22129: 09-02 03:40:34.622  2207  2231 I SystemServiceManager: Starting phase 1000
    #流程3:主用户解锁过程中
	Line 22364: 09-02 03:40:34.689  2207  2231 D SystemServerTiming: finishUserUnlocking-0
	Line 22368: 09-02 03:40:34.690  2207  2228 D SystemServerTiming: UM.onBeforeUnlockUser-0
	Line 22369: 09-02 03:40:34.690  2207  2228 D SystemServerTiming: prepareUserData-0
	Line 22563: 09-02 03:40:34.808  2207  2228 D SystemServerTiming: reconcileAppsData-0
	Line 23124: 09-02 03:40:35.348  2207  2237 D SystemServerTimingAsync: ssm.UnlockingUser-0
	Line 23125: 09-02 03:40:35.348  2207  2237 I SystemServiceManager: Calling onUnlockingUser 0
    #流程4:主用户解锁完成
	Line 23424: 09-02 03:40:35.506  2207  2237 D SystemServerTiming: finishUserUnlocked-0
	Line 23427: 09-02 03:40:35.508  2207  2237 V SystemServerTiming: SystemUserUnlock took to complete: 818ms
	Line 23521: 09-02 03:40:35.612  2207  2224 D SystemServerTiming: getUserSwitchability-0
	Line 23522: 09-02 03:40:35.612  2207  2224 D SystemServerTiming: TM.isInCall
	Line 23525: 09-02 03:40:35.612  2207  2224 D SystemServerTiming: hasUserRestriction-DISALLOW_USER_SWITCH
	Line 23526: 09-02 03:40:35.612  2207  2224 D SystemServerTiming: getInt-ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED
	Line 23530: 09-02 03:40:35.613  2207  2612 D SystemServerTiming: isUserUnlocked-USER_SYSTEM
	Line 23562: 09-02 03:40:35.656  2207  2237 D SystemServerTimingAsync: ssm.UnlockedUser-0
	Line 23563: 09-02 03:40:35.656  2207  2237 I SystemServiceManager: Calling onUnlockedUser 0

3)onUser遍历所有SystemServer

如上代码,获取所有服务并进行遍历,依次解析ssm的这几个状态,因此在开机过程中有如下日志打印:

3、AMS开机完成

接着如上的话题研究,我们了解到主用户启动是ams调用,那么用户解锁是不是也是ams调用的呢?答案真的是。跟读代码这段调用流程的开端是在ams的finishBooting方法中。

1)ams.finishBooting
2)UserController.onBootComplete
相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台6 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone6 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc6 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo6 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077006 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼6 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone6 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen6 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone6 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui