1、使用的是Android 7.1.2的源代码:
https://pan.baidu.com/s/1XcVD68cC_2wKtm8jJkdNQA
przv
2、感谢IT先森的系列博客:
Android应用进程创建流程大揭秘
Android四大组件之bindService源码实现详解
Android四大组件之Activity启动流程源码实现详解概要
Activity启动流程(一)发起端进程请求启动目标Activity
Activity启动流程(二)system_server进程处理启动Activity请求
Activity启动流程(三)-Activity Task调度算法复盘分析
Activity启动流程(四)-Pause前台显示Activity,Resume目标Activity
Activity启动流程(五)请求并创建目标Activity进程
Activity启动流程(六)注册目标Activity进程到system_server进程以及创建目标Activity进程Application
Activity启动流程(七)初始化目标Activity并执行相关生命周期流程
当Zygote创建完一个应用进程之后,得到的仅仅是一个可以运行的载体,但是,Android的四大组件还没有进入到这个新创建的进程之中。
当Zygote进程创建目标Activity进程之后,还需要创建一个运行环境Context,然后创建Application,然后再装载Provider等组件信息。
目标Activity所属的应用进程已经创建好了,接下来,包括如下流程:
- 注册目标Activity所属进程到system_server
- 为目标Activity所属进程创建Application实例对象
伪代码:
ATP.bindApplication()--->
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.bindApplication(...) --->
ApplicationThread.bindApplication(...) --->
ActivityThread.H.sendMessage(H.BIND_APPLICATION,...) --->
ActivityThread.handleBindApplication(...) --->
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//创建LoadedApk
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);//构建ContextImpl
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();//构建Instrumentation
installContentProviders(app, data.providers);//安装ContentProvider
mInstrumentation.callApplicationOnCreate(app);//调用Application的onCreate方法
一、注册(attach)目标Activity进程到system_server
问题:目标Activity进程是由AMS创建的,为什么还需要将其注册到system_server进程?
答:通过attach的Binder远程调用传递匿名Binder类IApplicationThread给AMS,然后AMS就可以通过上述的匿名Binder来继续对目标Activity进程的相关组件进行调度。
1、ActivityThread.main
- 调用attach,向system_server发起一个绑定操作,告诉AMS进程启动完毕,可以进行其他事情了
- 初始化应用进程的主线程的Looper,并开启loop消息循环
public static void main(String[] args) {
··· ···
Environment.initForCurrentUser();
··· ···
Process.setArgV0("<pre-initialized>");
//创建主线程Looper
Looper.prepareMainLooper();
//创建一个新的ActivityThread
ActivityThread thread = new ActivityThread();
//attach到系统进程
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//主线程进入循环状态
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
注意:
ActivityThread就是应用程序的主线程,这种说法是笼统的,因为ActivityThread并非真正意义上的线程,它不是Thread的子类。在ActivityThread对象构建时,会创建一个Handler对象,这个Handler对象所绑定的消息队列就是主线程的消息队列,后面主线程所做的任何事情都是往Handler中发送消息来完成的,所以说Android系统是基于消息驱动的。主线程实现Looper,就是在new ActivityThread()时实现的,即在ActivityThread.main()中构造ActivityThread对象时初始化的Looper。
public final class ActivityThread {
final Looper mLooper = Looper.myLooper();
final H mH = new H();
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
···
}
··· ···
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
··· ···
}
在构造函数初始化时,其上面的变量也都会初始化:
public class One {
private class H{
H(){
System.out.println("One::H():::");
}
}
H mH = new H();
int a = 3;
public One() {
System.out.println("One::One():::" + a);
}
}
public class Two {
public static void main(String args[]) {
One mOne = new One();
}
}
输出结果为:
One::H():::
One::One():::3
2、ActivityThread.attach
final ApplicationThread mAppThread = new ApplicationThread();
//system参数的作用是区别是system_server进程发起的绑定还是普通应用进程发起的绑定
//我们现在是子进程发起的绑定
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
//设置进程名。
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread); //这里的mAppThread是一个匿名Binder实例
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
··· ···
} else {
//系统进程走这里
}
}
上述流程中,通过AMP借助Binder调用AMS的方法attachApplication,注意这里传递的mAppThread是一个匿名Binder实例,因此可以作为跨进程传递的参数。这里的mAppThread对象存在于应用进程,但会被传递到系统进程,在系统进程看来,此时的mAppThread就是操作应用进程的一个通信工具。后续,系统进程system_server如果想要向应用进程发起跨进程调用,也都需要通过mAppThread这个对象来完成相关的调度。
AMP.attachApplication的调用逻辑:
3、AMS.attachApplication
// [AMS]
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//获取调用进程端pid
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
调用attachApplicationLocked进行下一步的处理,此时多了个参数pid。
注意,在Android源码中带Locked的方法,一般都需要进行加锁操作
在attachApplicationLocked中,会根据pid映射应用进程的ProcessRecord对象,在Android四大组件之Activity(五)——AMS:针对新启动的Activity创建一个新的进程 中的AMS.startProcessLocked中会将通过Process.start生成的pid给put到mPidsSelfLocked中。
// [AMS]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
/*
1、根据PID映射应用进程的ProcessRecord对象
那么此处的ProcessRecord是什么时候创建并加入到mPidsSelfLocked中的呢,这个在该系列博客的五中有详细描述
*/
if (pid != MY_PID && pid >= 0) {