Activity是Android应用程序的四大组件之一,负责管理Android应用程序的用户界面,一般一个应用程序中包含很多个Activity,他们可能运行在一个进程中,也可能运行在不同的进程中。
我们主要通过启动在不同进程中的Activity,来分析Activity的启动流程及AMS对Activity的管理逻辑。
有两个应用程序App1和App2,在App1的Activity A中点击button 启动 App2中的Activity B。
通过分析以上ActivityB的启动过程来了解AMS对Activity的管理逻辑。
步骤1:Activity A告诉AMS服务准备启动Activity B
步骤2:AMS服务处理并通知Activity A所在的进程pause Activity A,Activity A所在的进程处理完成之后,通知AMS服务Activity A已经完成pause工作。
步骤3:Activity B所在的进程没有启动,AMS服务首先启动一个新的进程。新的进程启动完成之后,通知AMS服务进程启动完成。
步骤4:AMS服务通知新的进程来启动Activity B,新的进程启动Activity B完成之后,通知AMS服务Activity B启动完成。
在分析Activity启动流程之前我们先简单介绍下应用进程和AMS服务通信方法,AMS服务和应用进程间属于不同的进程,两者之间通信肯定和Binder有关。我们知道系统的服务都是实现了Binder的服务端,应用进程要想和它通信需要获取它的代理端。
然而AMS服务是如何和应用进程通信的呢?在创建一个新的应用进程之后,系统首先会启动ActivityThread,ActivityThread是应用进程的主线程,在ActivityThread创建的时候会创建一个ApplicationThread的对象。这个ApplicationThread实现了一个Binder的服务端。新的进程创建完成之后通知AMS服务的之后同时把自己进程的ApplicationThread的代理端送给AMS服务。AMS服务中保存了所有应用进程的ApplicationThread的代理对象。
所以AMS要想给应用进程发送消息,只需要得到目标应景进程的ApplicationThread的代理端对象即可。
由于Activity的启动流程比较复杂,一步一步来分析,这样比较容易理解。
第一步:准备启动
1. Activity.startActivity
在activity A中点击button启动activity B调用了 Activity的startActivity方法。
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
……
}
在该方法中调用了activity的startActivityForResult方法来启动Intent描述的Activity B,第二个参数-1表示不需要返回结果
2. Activity. startActivityForResult
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
……
}
在这个方法中最终调用了Instrumentation的execStartActivity方法来启动Activity。应用程序和系统之间的交互都集中交给Instrumentation来做,方便系统对这些活动的监视。
下面我们看下参数mMainThread.getApplicationThread(),mMainThread就是应用app1所在进程的主线程ActivityThread,getApplicationThread返回的是一个ActivityThread的内部类ApplicationThread,该类是一个Binder对象,实现了Binder的服务端,通过参数传入到AMS服务中,AMS服务中则会保存它的客户端,这样AMS就可以通过它和应用进程通信了。
参数mToken是一个Binder代理对象,它指向了AMS中一个保存的ActivityRecord信息,mToken代表了Activity A,它通过参数传递给AMS后,AMS根据它就可以得到Activity A的信息了。
3. Instrumentation. execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
try {
//intent做进程间传输的准备工作
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//进程间传输,最终调用到AMS服务中
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
}
……
}
该方法中通过ActivityManagerNative的getDefault方法来获得AMS的代理对象,然后调用它的startActivity方法通过进程间传输调用到AMS服务startActivity方法,进程间的通信此处不再详细介绍。
到此处为止,以上的操作都是在应用程序App1的进程中执行的。以下代码就进入了SystemServer进程的AMS服务中
4. AMS.startActivity
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
该方法的参数中caller就是App1进程的ApplicationThread的binder对象,IBinder就是指向Activity A的ActivityRecord的Binder对象,紧接着这个方法就调用了startActivityAsUser方法
5. AMS. startActivityAsUser
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
……
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}
调用了activityStackSupervisor的startActivityMayWait方法,ActivityStackSupervisor是Activity调度的核心类,Activity的调度相关的工作都是在ActivityStackSuperVisor中处理,主要管理Task和Stack.它是在AMS启动的时候创建的。
6. startActivityMayWait
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
……
//PMS服务根据intent查询要启动的Activity B的信息,保存到ActivityInfo中
intent = new Intent(intent);
ActivityInfo aInfo =
resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
……
//决定当前活动的stack
ActivityContainer container = (ActivityContainer)iContainer;
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
stack = mFocusedStack;
} else {
stack = container.mStack;
}
……
//将PMS中查询到的Activity B的信息当做参数
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
……
}
resolveActivity方法中最终是PMS服务根据Intent信息去查询即将要启动的ActivityB的详细信息,
然后是查找对应的ActivityStack,即将要启动的Activity应该在放到哪个ActivityStack中,从参数传递过来的iContainer为null,所以要启动的Activity应该在mFocusStack中来管理。mFocusStack指的是当前获得焦点的ActivityStack。
Android中一般情况下有以下几种ActivityStack
· Home Stack,这个是Launcher所在的Stack。 其实还有一些系统界面也运行在这个Stack上,例如近期任务.SystemUI等
· FullScreen Stack,全屏的Activity所在的Stack。 但其实在分屏模式下,Id为1的Stack只占了半个屏幕。
· Freeform模式的Activity所在Stack
· Docked Stack 下文中我们将看到,在分屏模式下,屏幕有一半运行了一个固定的应用,这个就是这里的Docked Stack
· Pinned Stack 这个是画中画Activity所在的Stack
第一个和第二个是较常用的Stack,后边三个的Stack主要和多窗口模式有关。由此可见,大部分应用程序其实都是在同一个Stack中即FullScreenStack中。
然后调用startActivityLocked方法继续启动Activity.
7. startActivityLocked
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
//callerApp 代表调用方的应用进程,即App1的应用进程
ProcessRecord callerApp = null;
if (caller != null) {
//根据caller找到AMS中保存的App1的processRecord对象
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//得到App1应用进程的pid和应用的uid
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}
……
}
……
//即调用者的Activity组件
ActivityRecord sourceRecord = null;
//返回结果的Activity组件
ActivityRecord resultRecord = null;
if (resultTo != null) {
//根据resultTo Binder对象得到其指向的ActivityRecord,即Activity A的ActivityRecord信息
sourceRecord = isInAnyStackLocked(resultTo);
//一般情况下请求的Activity和要接收返回结果的Activity是同一个
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
……
//根据准备的信息,创建一个即将启动的ActivityRecord对象,即Activity B
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
……
//将刚创建的目标Activity的ActivityRecord作为参数,继续调用startActivityUncheckedLocked方法来启动
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInter