系列文章索引
新系列:Android11系统源码解析
-
Android11源码分析:binder是如何实现跨进程的?(创作中)
经典系列:Android10系统启动流程
前言
众所周知,四大组件都是可以跑在单独的进程中的
在Android中,一个Application(应用)对应着一个或多个进程
对于应用开发者层来说,开启进程往往是被动开启
所谓的“被动开启”,即通过应用的组件,比如Activity,Service来启动对应的进程
今天我们通过Activity和Service的启动流程,来分析下在组件的启动过程中是如何将进程启动起来的
从Activity看如何开启一个进程
要启动一个Activity,我们首先要调用的,是startActivity()
/frameworks/base/core/java/android/app/ContextImpl.java
public void startActivity(Intent intent, Bundle options) {
...
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
此处的mMainThread
是ActivityThread
的对象实例
ActivityThread
虽然名字叫Thread,但其实只是一个普通的Java类对象,继承了ClientTransactionHandler
,内部持有ApplicationThread
的Binder对象,用来跟ActiviyManagerService
(后面简称AMS)交互
startActiviy()函数最终调用了Instrumentation
的execStartActivity()
如果这个Activity已经被启动过且没有回收,则对其进行拦截
如果未被启动,则调用ActivityManagerService
的startActivity()
启动对应的activity
public ActivityResult execStartActivity(
...
int result = ActivityTaskManager.getService().startActivity(...);
checkStartActivityResult(result, intent);
return null;
}
在android11的源码中,将启动actvity的任务细化给了ActivityTaskManagerService
(后面简称ATM)这个系统服务
在SystemServer
中启动系统服务时,ATM
与AMS
是组合的关系,当ATM
启动后再执行AMS
相关的创建启动逻辑
经过一系列的流程,最终调用到了ActvitiyStarter
的execute()
函数
每一个开启activity的行为,都被封装成一个Request
对象,调用到executeRequest()
函数来开启activity
如果进程未被启动,则调用到AMS
的startProcessLocked()
,通过AMS
与Zygote
进行通信,fork出新的进程,并通过反射执行ActivityThread
的main函数完成ActivityThread
的初始化, 然后调用attachApplication()
函数将binder对象注册到AMS
至此,进程初始化完成,可以继续启动进程的activity组件,创建对应的ActivityRecord
对象,并添加到ActvityStack中进行管理
小结
通过activity的启动流程,我们发现在启动activty时会先检查其对应的进程(ProcessRecord)是否启动,并通过AMS和Zygote进行通信,fork出对应的进程,调用ActivityThread
的main函数进行初始化操作
ActivityThread
是整个进程在Java层的管理类,在main函数中,会调用prepareMainLooper()
完成主线程(即创建ActvitiyThread所在的线程)Looper的初始化,并进入loop()无限循环中。所以在创建Handler对象接收消息时,主线程的Looper已经准备完成
主线程的Looper只能创建一次,且不能退出,因为主线程退出也就意味着进程的结束
从Service看进程启动
开启一个Service,首先要调用startService()
,其内部又调用了startServiceCommon()
/frameworks/base/core/java/android/app/ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
...
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService( //AMS binder调用
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
...
return cn;
}
其中 ActivityManager.getService()
是通过ServiceManager获取到AMS
的binder对象进行binder调用,执行到AMS
中的startService()
方法,最终调用到bringUpServiceLocked()
函数
如果serviceRecord中的ProcessRecord对象和ApplicationThread对象不为空,表示进程已经启动,可以直接启动Service(通过binder调用ActivityThread中的scheduleServiceArgs(),通过hander发送消息,交给mH进行进一步初始化)
Service作为四大组件之一,是可以跑在单独的进程空间中的,此时我们需要通过AMS
查询该Service是否又对应的ProcessRecord
如果获取到service对应的ProcessRecord不为空,说明宿主进程(HostingRecord)已经启动
假如需要启动的Service是单独的进程(isolated),则需要通过AMS与Zygote
交互fork出子进程
如果跟宿主进程是同一个进程,则调用realStartServiceLocked()
去启动service组件
/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//判断service所在的进程是否启动
if (app != null && app.thread != null) { //说明进程已经启动
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg); //启动service组件
return null;
}
} else {
...
hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
r.definingUid);
}
如果未获取到宿主进程的ProcessRecord
,说明宿主进程也没有启动,需要先启动对应的进程, 需要通过AMS与Zygote通信fork出新的进程,此处流程与启动activiy处的流程判断是一致的
if (app == null && !permissionsReviewRequired) { //如果开启进程时app为空,则需要先通过AMS启动对应的进程
...
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
...
}
}
小结
service启动时,需要判断是否是独立的进程,如果是独立进程,则fork出一个新进程;如果不是独立进程,先判断下进程是否已经启动,已启动时直接调用realStartServiceLocked()
去执行service组件的启动流程即可,如果未启动则仍需要通过AMS与zygote
通信fork出新的进程
加餐:聊聊Binder调用那些事
ActivityThread
是应用层进程的入口类, 在上面的分析中,我们反复提到了binder调用
所有的系统服务都需要注册到ServiceManager中进行管理
下面是通过ServiceManager获取对应的ActivityManagerService
的binder对象的函数
/frameworks/base/core/java/android/app/ActivityManager.java
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
应用层需要调用系统服务的函数时,需要获取到对应的系统服务的binder对象,从而调用系统服务中的函数
比如在启动activity和service时都调用了ActivityManagerServcie
中的方法
在ActivityThread
内部,也持有一个ApplicationThread
的binder对象,在完成java层的应用初始化后,同样需要调用AMS的attach()方法将这个binder对象传递过去,以完成AMS和ActivityThread的双向调用,AMS也可以通过持有的这个binder对象与ActivityThread进行通信
关于更多的binder细节,我们将在以后的文章中来探讨
写在最后
如果觉得我的文章对你有价值,请多多点赞支持下
接下来我们将探讨四大组件相关的源码内容
下期文章再见啦