添加用户的流程分析

添加用户的流程分析

Settings的上层接口

settings中的文件:

/android/packages/apps/Settings/src/com/android/settings/users/UserSettings.java

/android/vendor/samsung/packages/apps/Settings/res/xml/user_settings.xml

添加用户item的key值为Preference key="user_add"

点击item之后,根据型号的不同分为两个不同的选择:

mCanAddRestrictedProfile == true 可以对不同的权限进行添加

mCanAddRestrictedProfile != true 一般型号是不能进行更深层次的管理的

->

 

弹出DIALOG_ADD_USER的对话框之后,对于有通话功能的平板,会有一个选择是否同意数据的过程

 

选择完就是dialog的本体了,layout在前面会有个简单的设置

 

其中的userType的值也是根据之前mCanAddRestrictedProfile来的,两者相互交叉,统一在这个地方就行用户的添加,一般型号的是走USER_TYPE_USER的流程。addUserNow(final int userType)方法是一个较长的方法,其中主要是包含一个新建用户的线程,在线程中会针对userType的不同新建不同级别的用户。

 

咱走的是USER_TYPE_USER, 在createTrustedUser方法中完成用户的新建,这里我们能看到新用户命名的过程以及新建用户的真正接口

 

新建完用户之后立即会起一个dialog,这个dialog是询问用户是否要立即切换至新用户(这个动作就会起用户的Setup),我们得搞明白这个流程,到底switchUserNow的过程中做了些什么

 

 

可以看到切换用户的接口是ActivityManagerNative的方法

切换用户流程

切换用户接口文件:

/android/frameworks/base/core/java/android/app/ActivityManagerNative.java

/android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

/android/frameworks/base/services/core/java/com/android/server/am/UserSwitchingDialog.java

/android/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

/android/vendor/samsung/packages/apps/Settings/src/com/android/settings/ManagedProfileSetup.java

/android/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

 

ActivityManagerNative类的getDefault 方法返回的是ActivityManagerService这个类的一个对象,ActivityManagerService的switchUser方法较为复杂,但也分为了很多小模块。

1、拿到切换到的userId对应的UserInfo,然后启动一个切换用户的dialog

 

 

2、在这个dialog里面对切换用户的信息有一些简单的设置用来作为显示,最主要的是回调了ActivityManagerService中的startUserInForeground方法,通过这个来进行用户的切换。

 

3、startUserInForeground直接转到startUser(final int userId, final boolean foreground)方法,在startUser中管理用户的启动,过程比较复杂,涉及到各个状态的处理。我们把这些过程也分为几个流程块:

A、启动新用户的准备工作,主要包括windowManagerService的窗口处理,userid的添加,启动过程对于window的冻结三部分,由于foreground值为true,我们只需要看前台启动的部分就行了。

 

B、获取user的状态,对于不同状态的处理方式,主要包括四种状态:STATE_STOPPING、STATE_SHUTDOWN、STATE_BOOTING和STATE_RUNNING,若是前两种状态则要让状态回到STATE_BOOTING,以启动user,启动完之后发一条消息:SYSTEM_USER_START_MSG,这条消息由SystemServiceManager来处理,启动新用户

 

 

 

C、第三部分在systemService结束启动用户之后,会连续地发几个广播:SYSTEM_USER_CURRENT_MSG、REPORT_USER_SWITCH_MSG、USER_SWITCH_TIMEOUT_MSG,这几个广播处理较复杂,稍等

 

D、接下来是检测User是否被初始化,若未初始化则发广播给接收处理用户初始化的文件就行初始化,intent为Intent.ACTION_USER_INITIALIZE= android.intent.action.USER_INITIALIZE,这一初始化是在settings中完成的: ManagedProfileSetup.java

这里面会对新用户的某些数据库进行设置

重要的方法是onUserInitialized(uss, foreground, oldUserId, userId)方法,这个方法就能能起Setupwizard的方法

 

onUserInitialized(uss, foreground, oldUserId, userId)方法调用moveUserToForeground方法引出startHomeActivityLocked(newUserId)方法进行Home级别的Activity启动

 

E、startHomeActivityLocked方法主要是根据userId判断启动Home级以及优先级最高的app(SetupWizard优先级比Launcher2更高),由getHomeIntent方法进行遍历。遍历完之后取到home级别的app,由startHomeActivity方法来启动。startHomeActivity方法是在下面这个文件中写的:

/android/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

 

 

 

 

ActivityManagerNative中也有设置switchUser的接口,其对switchUser方法的写法如下,把需要切换到的user的id传到mRemote中用transact方法进行进一步的解析工作。那么mRemote是个shen me gui 呢?

 

PS:关于Parcel,Parcel其实是一个存放读取数据的容器, Android系统中的binder进程间通信(IPC)就使用了Parcel类来进行客户端与服务端数据的交互,而且AIDL的数据也是通过Parcel来交互的。在Java空间和C++都实现了Parcel,由于它在C/C++中,直接使用了内存来读取数据,因此,它更有效率。

Parcel的方法:

l  obtain()    获得一个新的parcel ,相当于new一个Parcel对象

l  writeInterfaceToken(String interfaceName)   写入接口句柄,相当于把接口的文件路径给此Parcel

l  writeInt(int)     写入一个整数

l  readException()        在Parcel队头读取,若读取值为异常,则抛出该异常;否则,程序正常运行

l  recyle()     清空、回收parcel对象的内存

其中String descriptor = "android.app.IActivityManager";

由此我们可以看到switchUser方法new了两个内存区data、reply,data中存放了Binder机制的客户请求的服务端路径、需要切换到的用户id。mRemote其实是Ibinder 的一个对象,它把1、客户端请求的动作类型SWITCH_USER_TRANSACTION(int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129);2、服务端源、用户id;3、一段返回内存区reply传到Binder里进行处理。

新建用户流程

新建用户接口文件:

/android/frameworks/base/core/java/android/os/UserManager.java

/android/frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java

其中mService是(UserManager) context.getSystemService(Context.USER_SERVICE);用户的新建由这个服务来完成

 

我们拿到UserManagerService文件中关于createUser(String name, int flags)的写法:

 

可以看到新建用户的主要工作一、是在存储区里面开辟一块用户区域二、是发一个已经创建了新用户的广播。

posted @ 2015-03-16 10:12  Simba.Chen  阅读(896)  评论(0编辑  收藏  举报