前言补充
当系统决定要在一个新的进程中启动一个Activity或者Service时,ActivityManagerService组件负责通知Zygote创建一个新的进程,然后在这个新的进程中启动这个Activity或者Service。
Android应用程序架构中非常核心的一点:MainActivity不需要知道SubActivity的存在,即它不直接拥有SubActivity的接口,但是它可以通过一个字符串来告诉应用程序框架层,它要启动的Activity的名称是什么,其它的事情就交给应用程序框架层来做,这种模式大大降低了模块间的耦合,利于开发。
对于每一个应用程序来说,都有一个ActivityThread来表示应用程序的主进程,而每一个ActivityThread都包含有一个ApplicationThread实例,它是一个Binder对象,负责和其它进程进行通信。
Binder是Android系统进程间通信(IPC)方式之一。
目前linux支持的IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。
而Client-Server的通信方式在android系统中被广泛使用,诸如媒体播放,视音频频捕获,到各种让手机更智能的传感器(加速度,方位,温度,光亮度等)都由不同的Server负责管理,应用程序只需做为Client与这些Server建立连接便可以使用这些服务,花很少的时间和精力就能开发出令人眩目的功能。因此需要高效的CS通信。
传输性能方面:socket通用主用于跨网络性能低,消息队列与管道都是二次拷贝,共享性能控制复杂。binder只有一次拷贝。
安全性:传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。接入点开放,无法私有通道。
Binder是一个实体位于Server的对象,client使用它的句柄调用其方法
Binder模糊了进程边界,淡化了进程间通信过程,整个系统仿佛运行于同一个面向对象的程序之中。形形色色的Binder对象以及星罗棋布的引用仿佛粘接各个应用程序的胶水,这也是Binder在英文里的原意。
Binder的四个角色:Server、Client、ServiceManager、Binder驱动。驱动位于内核空间。与互联网类似:服务器、客户端、域名服务器、路由器
https://blog.csdn.net/universus/article/details/6211589
目前知道:可用于进程间通信,大量用于android各层即可。
参考文:
http://duanqz.github.io/2016-07-29-Activity-LaunchProcess-Part1#%E6%A6%82%E8%BF%B0
老罗
gityuan
不得不说http://duanqz.github.io/ 这位大佬的博客写的太详细了而且版本很新……接下来尽量都看完
概览
一张图:
启动部分涉及4个进程:发起进程、system_server进程、Zygote进程、新建进程。
本篇我们先看启动部分的前俩个进程的工作,值得注意的是各安装的应用都会有自己的信息记录在AMS中,启动的Task也由其间接管理,对于将要启动的app,它会首先将其信息放入栈中再去执行进程的启动任务。
开始
1-Launcher3
点击屏幕最后会调用到:
可见它是在一个新的TASK中启动intent。
启动activity的规则为activity可以规定多个action与多个category。隐式启动activity发送的intent也可以指定一个action与多个category,当有activity匹配了intent的一个action与全部category时即可响应该意图。
ACTION-MAIN标识该Activity为入口,CATEGORY-LAUNCHER设置该组件为在当前应用程序启动器中优先级最高的Activity,通常为入口ACTION_MAIN配合使用。这俩个保证该组件导出可被其它启动。为系统规定所识别。
获取方式为:View->ItemInfo ->PromiseAppInfo
最后执行的是startActivity
此时还是应用之中。Activity的方法
Activity.startActivity
android-8.0.0_r1\frameworks\base\core\java\android\app\Activity.java
|
|
2-startActivityForResult
|
|
调用mInstrumentation.execStartActivity,Intrumentation成员变量用来监控程序和系统的交互
这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,负责与其它进程通信。
mMainThread是ActivityThread类型的,代表应用程序的主线程。
ActivityThread与ApplicationThread分别是同应用进程的不同线程。
3-execStartActivity
Instrumentation.execStartActivity
frameworks\base\core\java\android\app\Instrumentation.java
|
|
ActivityManager.getService()拿到的是IActivityManager,IActivityManager是一个aidl文件
ActivityManagerService存在于system_server进程,ActivityManagerService继承自IActivityManager.Stub成为远程调用服务,所以上面ActivityManager.getService().startActivity调用的其实是ActivityManagerService里面的方法
注意这里是aidl跨进程调用。
关于aidl……我的理解就是android中的RPC方案:android进程间CS通信常用Binder,RPC远程调用除了传输问题还有接口定义问题,aidl就是用来定义RPC接口的。
这样就可以实现仿佛自我调用般的RPC远程调用。
4、5-startActivity、startActivityAsUser
ActivityManagerService存在于system_server进程
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
mActivityStarter为ActivityStarter类型的对象,该方法中取得userId调用其startActivityMayWait
接下来
ActivityStarter.java
–>startActivityMayWait
–>startActivityLocked
–>startActivity
–>startActivity
–>startActivityUnchecked
6-startActivityMayWait
ActivityStarter
frameworks\base\services\core\java\com\android\server\am\ActivityStarter.java
|
|
aInfo为应用信息
7、8-startActivityLocked、startActivity
startActivityLocked :
r中是要启动的Activity相关信息。
resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息。callerApp也是Launcher的信息。
9、10-startActivityUnchecked
|
|
该方法中获取activity的启动模式,activity的栈管理。若app未启动,在本方法中入栈并记录。
startActivityLocked 内切换界面,通知活动界面执行Paused
根据是否需要新栈创建新栈。调用resumeFocusedStackTopActivityLocked激活顶端的要启动的activity
11-resumeFocusedStackTopActivityLocked
ActivityStackSupervisor.java
–>resumeFocusedStackTopActivityLocked
frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
12、13-ActivityStack
ActivityStack.java
–>resumeTopActivityUncheckedLocked
–>resumeTopActivityInnerLocked
frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
|
|
当前在堆栈顶端的Activity为我们即将要启动的MainActivity,这里通过调用topRunningActivityLocked将它取回来,保存在next变量中。之前最后一个Resumed状态的Activity,即Launcher,到了这里已经处于Paused状态了,因此,mResumedActivity为null。最后一个处于Paused状态的Activity为Launcher,因此,这里的mLastPausedActivity就为Launcher。前面我们为MainActivity创建了ActivityRecord后,它的app域一直保持为null。
14-startSpecificActivityLocked
ActivityStackSupervisor.java
–>startSpecificActivityLocked
frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
|
|
第一次启动时
ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
为null。
在Activity应用程序中的AndroidManifest.xml配置文件中,我们没有指定Application标签的process属性,系统就会默认使用package的名称。每一个应用程序都有自己的uid,因此,这里uid + process的组合就可以为每一个应用程序创建一个ProcessRecord。当然,我们可以配置两个应用程序具有相同的uid和package,或者在AndroidManifest.xml配置文件的application标签或者activity标签中显式指定相同的process属性值,这样,不同的应用程序也可以在同一个进程中启动。
15、16、17-startProcessLocked
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
ActivityManagerService.startProcessLocked
|
|
三个startProcessLocked方法,最后一个设置进程属性,entryPoint表示入口方法android.app.ActivityThread。Process.start开始进程。
18-start
Process.start
frameworks\base\core\java\android\os\Process.java
zygoteProcess进程是final static的,可见其唯一性,调用其产生进程。
此时还在server
19、20-start、startViaZygote
ZygoteProcess.start
frameworks\base\core\java\android\os\ZygoteProcess.java
|
|
设置参数。ZygoteState一共有俩个,都是与zygote通信用的,openZygoteSocketIfNeeded内尝试连接zygote返回ZygoteState。为socket连接
21-zygoteSendArgsAndGetResult
|
|
开启对zygote的写与读,发送args。注意此时还在AMS进程
这里就与之前android系统启动的文章相接了。
后记
这部分主要完成了以下几个工作:
- Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
- ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态–10中的startActivityLocked
- 暂停成功后通过Task管理保存新应用信息并向zygote发送消息进行分裂新进程。