Activity跳转那一节介绍了Activity跳转相关的使用和基础知识,那这节就来升华一下:分析下Activity的启动流程,看它到底是怎么启动的.(下面的分析都是基于app进程已经存在,并且要启动的Activity没有启动过)
Activity启动原理
上面两张图分别展示了:app启动app内某个Activity的过程和app启动其他app某个Activity的过程,当然上面的图中都是以app/app1进程本身已经存在为前提,app进程不存在的话还需要涉及到进程创建的过程(进程创建属于这节的讨论范畴)
先来介绍几个知识点:
- ActivityManagerService(为了方便简称为AMS)它位于系统进程,系统进程里面有很多的服务(比如WindowMnagerService),AMS只是其中的一个,它管理android中的四大组件.
- app是位于它自己进程的,与系统进程完全不同.
不管是启动app内还是app外的Activity,都会经历三个过程:
- app请求AMS启动Activity(在app进程)
- AMS处理请求(在系统进程)
- app接收并处理AMS发出的信息(在app进程)
那就从这三个过程来进行分析
1.app请求AMS启动Activity
在前面章节中介绍过,启动(或跳转)Activity会先配置一个Intent,这个Intent存放的数据可是很丰富了:包含了启动Activity的信息,传递给Activity的数据,甚至还有启动Activity的方式等等.app进程与AMS不处于同一进程,它们之间的通信使用的是binder,Intent会在"binder这条搭建好的公路"上传递到AMS.
2.AMS处理请求
AMS拿到Intent后会做以下处理:
2.1.根据Intent去查询Activity的信息,那去哪查呢?答案是PMS服务
既然涉及到了PMS那就先来了解下它,PMS是PackageManagerService的简称,它也是一个运行在系统进程内的服务。它主要做的事情就是把手机上安装的所有apk里面的AndroidManifest(清单)文件里面的信息解析出来并且存储在内存。还记得在编写一个Activity的时候,需要在AndroidManifest文件中配置该Activity,最终清单文件及Activity等信息全部会打包到apk的文件中。AndroidManifest文件主要就是给PMS来用的,还记得在清单文件中配置Activity的时候,会为Activity配置intent-filter吗?intent-filter里面会包含action,category,data这些配置项目,这些信息也会被PMS解析出来。
为啥要去查询Activity的信息呢,原因是这样的:Intent分为显示和隐示。对于显示Intent,虽然Intent中指明了目标Activity的class信息,但是这个信息太少了,Activity的启动模式,权限等等其他信息完全不知道. 对于隐示Intent,那更需要去查了,隐示的根本就不知道目标Activity是谁.
查到来的Activity信息大体有:目标Activity的class信息,包名,权限,启动模式,action,data等等.
若PMS根据Intent没有查找到Activity,则停止后面的流程,把错误信息返回给app;否则继续后面的流程
2.2.各种检查,校验
需要对启动的参数,启动的进程等等并且结合查询到的Activity信息进行检查,校验.比如权限校验了(有些Activity不是谁都能启动的),是否对外可以启动等校验流程,如果一系列的校验都通过了,继续后面的流程.
2.3.保存启动的Activity,并且放入task
把要启动的Activity信息记录下来(记录的类叫ActivityRecord),依据app传递过来的Intent设置的flag信息及启动Activity的launchmode等信息来决定是否要创建task(对应的类Task)。若新创建了task,则把ActivityRecord放入task中,否则在原先的task放入ActivityRecord。
2.4.把数据返回给app
若启动的Activity对应的进程没有启动,需要等待进程启动完成. AMS会把很多重要的数据(如Activity信息,Intent,token等)数据(数据会被放入ClientTransaction这个类)中返回给app.
到此AMS的流程就结束了。
3.app接收并处理AMS发出的信息
app的AtivityThread的ApplicationThread类的scheduleTransaction方法会收到AMS发过来的ClientTransaction数据, 从中拿到目标Activity信息,通过反射初始化目标Activity实例,实例初始化完成后会接着调用它的onAttach,onCreate回调方法.
同时AtivityThread类也会把启动的Activity记录下来(记录的类是ActivityClientRecord),最终会把AMS传递过来的token作为key,ActivityClientRecord作为value存放在ArrayMap中。
小结
Activity的启动的流程如下:
- app把包含启动Activity等其他数据的Intent通过binder调用发送给AMS
- AMS通知PMS依据Intent解析出对应的Activity的信息.若解析成功,则对各种参数,进程信息结合解析到的Activity信息进行检查,校验.若成功则记录下启动Activity并把记录放入创建或已有的task中. 把Activity信息,Intent等数据通过binder调用发送给app
- app那到Activity信息,通过反射实例化Activity,并且调用它的onAttach,onCreate方法.
Activity启动源码分析
在进行源码分析之前先介绍下用到的前置知识
前置知识
进程之间通信:android app进程之间使用binder进行通信,下面的内容会涉及到binder(关于binder通信后面的章节会介绍)
线程之间通信:线程之间通信方式很多,android中线程之间通信一般都使用handler,下面介绍的内容就会涉及到handler。
相关的类
app相关:
frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/app/Instrumentation.java
frameworks/base/core/java/android/app/ActivityThread.java
ams相关:
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
pms相关:
frameworks/base/core/java/android/content/pm/ResolveInfo.java
frameworks/base/core/java/android/content/pm/ActivityInfo.java
(以上源码版本是android 12)
关键类的介绍
ActivityThread:这个类的名字看上去容易造成误导,总以为是与Activity相关的Thread。其实它处理的事情可多了,在app进程创建成功后,ActivityThread中会启动一个主线程,这个主线程不断的在循环中取消息和执行消息,这样就能保证app一直能保持”活着“的状态。这个类还执行四大组件的初始化,并根据AMS发的指令调用四大组件的相应回调方法,并且还执行Application的相关初始化等工作。一个app进程中只有一个ActivityThread实例。
ApplicationThread:这个类继承了IApplicationThread.Stub,它也是Binder类型。它的主要作用就是接收来自AMS发送过来的消息。
Instrumentation:这个类的主要作用是对AMS传递过来四大组件及Application对应的字符串类型的Class,通过发射进行初始化;这个类还负责调用四大组件和Application的回调方法(比如Activity的onCreate方法,Application的onCreate方法)
ActivityClientRecord:这个类的主要作用就是在app进程保存启动的Activity等信息与AMS的ActivityRecord是一一对应关系。
ActivityTaskManagerService:简称ATMS,原先老版本的android代码里面是没有ATMS这个类的的。因为原先的AMS代码越来越臃肿,功能也很复杂(Service,Activity,Broadcast,ContentProvider相关的接口都在AMS中)。因此到了后面的android版本就AMS的代码进行了重构,把Activity相关的工作都放在了ATMS类中。
ActivityStarter:这个类的主要职责就是根据各种信息来决定如何启动Activity,并且根据各种信息来决定是把Activity放在一个新task中还是放在roottask中,为了节约宝贵的内存,该类的实例会被缓存在ActivityStartController类中。
ActivityRecord:这个类的主要作用是在系统进程中保存启动的Activity等信息。
ActivityRecord$Token:Token这个类,在原理篇提过,它是ActivityRecord与ActivityClientRecord的桥梁。
开始分析
如原理篇介绍,启动Activity有如下三个过程:
- app请求AMS启动Activity(在app进程)
- AMS处理请求(在系统进程)
- app接收并处理AMS发出的信息(在app进程)
因此整个源码分析也以这三个过程来进行分析。
1.app请求AMS启动Activity
从Activity的startActivity方法开始吧,下面方法的执行都在app进程。
1.1 Activity#startActivity
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
......省略代码
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
//因为options为null,因此进入这个环节
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
//增加了requestCode为-1的参数,代表不需要关注这个Activity的返回数据
startActivityForResult(intent, -1);
}
}
1.2 Activity#startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
//调用同名方法,增加了一个Bundle为null的参数
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
//主要分析mParent== null的情况
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//调用mInstrumentation.execStartActivity方法,
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
//对于requestCode大于0的情况,则把mStartedActivity置为true
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
......省略代码
}
}
上面的方法主要做的事情:会根据mParent是否存在执行不同的逻辑,但是最终都会调用到同一方法。咱们主要分析mParent== null的情况。
介绍下mInstrumentation.execStartActivity方法的几个关键参数:
- who:类型为Activity
- contextThread:类型为IBinder,mMainThread.getApplicationThread()获取的是一个类型为IApplicationThread的对象,这个对象同时也是一个Binder对象,它会被传递给AMS,AMS拿到它可以与app进程进行通信。 mMainThread是ActivityThread的实例,一个进程内就进存在一个
- token:类型IBinder,mToken是它的值,在上面原理篇介绍过。
- intent:启动信息,参数等都在Intent内
- requestCode:若是调用startActivityForResult方法,这个参数有用,否则没用。它若存在会传递给启动的Activity,Activity finish后并且调用了setResult方法,这个参数会被返回。当前值为-1
1.3 Instrumentation#execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//把contextThread转换为IApplicationThread
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
......省略代码
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
//binder调用到ActivityTaskManagerService
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
notifyStartActivityResult(result, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
该方法做的事情主要是为intent添加一些额外的信息外,最终通过binder调用把参数发送到系统进程。
ActivityTaskManager.getService():获取的是ActivityTaskManagerService在app进程内的代理类的实例,这个代理类实现了IActivityTaskManager,同时它也是BinderProxy类型。
介绍下ActivityTaskManager.getService().startActivity方法的几个关键的参数:
- caller:它的类型是IApplicationThread,whoThread是它的值
- callingPackage:String类型,代表启动者的包名。who.getOpPackageName()是它的值
- intent:自不必多说,包含启动的各项数据
- token:代表发起启动的Activity(称它为启动者),在app进程它的类型是BinderProxy
- requestCode:若使用的是startActivity这方法,这值是-1;否则是上层传递的值
小结
用一张时序图进行小结
2. AMS处理请求
下面方法的执行都在系统进程中
2.1 ActivityTaskManagerService#startActivity
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
//增加一个userId信息它的值是UserHandle.getCallingUserId()
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
//增加一个validateIncomingUser参数,它的值为true
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
[2.1 obtainStarter]
int res = getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
return res;
}
[2.1 obtainStarter]
getActivityStartController().obtainStarter方法的介绍。
getActivityStartController()会获取一个ActivityStartController类的实例,ActivityStartController中缓存了ActivityStarter,这样就不需要每次都new一个ActivityStarter出来,浪费宝贵的内存了。
obtainStarter方法会获取一个已有或创建一个新的ActivityStarter类实例,这个类的主要职责就是根据各种信息来决定如何启动Activity,并且根据各种信息来决定是把Activity放在一个新task中还是放在roottask中。
初始化ActivityStarter的几个关键参数介绍:
- caller:IApplicationThread类型,app进程中传递过来的IApplicationThread,它现在的类型是BinderProxy
- callingPackage:String类型,启动者包名,有了这个信息对于分析问题是非常重要的,比如:有时候Activity莫名其妙的就启动了,这时候去看callingPackage就可以知道是谁启动的。
- resultTo:IBinder类型,代表发起启动的Activity(启动者),在app进程中它的类型是BinderProxy。进入系统进程后它的类型会被转换为Binder。(这是binder机制,后面介绍binder机制的时候会介绍)
ActivityStarter定义了一套可以链式调用的方法,简单看下几个方法:
ActivityStarter setProfilerInfo(ProfilerInfo info) {
mRequest.profilerInfo = info;
return this;
}
ActivityStarter setGlobalConfiguration(Configuration config) {
mRequest.globalConfig = config;
return this;
}
ActivityStarter setUserId(int userId) {
mRequest.userId = userId;
return this;
}
在设置完属性后,返回this,这样就可以接着在调用另外的设置方法了。ActivityStarter设置的属性都存放在了mRequest这个实例中。
初始化完毕ActivityStarter,会调用它的execute方法。
2.2 ActivityStarter#execute
int execute() {
try {
省略代码......
final LaunchingState launchingState;
synchronized (mService.mGlobalLock) {
//获取启动者
final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
//获取callingUid
final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID
? Binder.getCallingUid() : mRequest.realCallingUid;
launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
mRequest.intent, caller, callingUid);
}
// If the caller hasn't already resolved the activity, we're willing
// to do so here. If the caller is already holding the WM lock here,
// and we need to check dynamic Uri permissions, then we're forced
// to assume those permissions are denied to avoid deadlocking.
//activityInfo为null 则需要去解析
if (mRequest.activityInfo == null) {
mRequest.resolveActivity(mSupervisor);
}
int res;
//启动的时候使用mService.mGlobalLock锁保持同步
synchronized (mService.mGlobalLock) {
final boolean globalConfigWillChange = mRequest.globalConfig != null
&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
省略代码......
res = executeRequest(mRequest);
省略代码......
if (mRequest.waitResult != null) {
mRequest.waitResult.result = res;
res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
launchingState);
}
return getExternalResult(res);
}
} finally {
onExecutionComplete();
}
}
该方法主要做了以下事情:
- 若mRequest.activityInfo为null,回调用mRequest.resolveActivity(mSupervisor)方法开始解析过程,最终会进入PMS(PackageManagerService)中根据intent解析出ResolveInfo和ActivityInfo
- 调用executeRequest方法开始进入下个流程
PMS根据intent解析ResolveInfo和ActivityInfo的流程在这就不赘述了,不过有必要介绍下ResolveInfo和ActivityInfo这两个类。
ResolveInfo
看下它的几个关键属性:
public class ResolveInfo implements Parcelable {
private static final String TAG = "ResolveInfo";
private static final String INTENT_FORWARDER_ACTIVITY =
"com.android.internal.app.IntentForwarderActivity";
/**
* The activity or broadcast receiver that corresponds to this resolution
* match, if this resolution is for an activity or broadcast receiver.
* Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or
* {@link #providerInfo} will be non-null.
*/
public ActivityInfo activityInfo;
/**
* The service that corresponds to this resolution match, if this resolution
* is for a service. Exactly one of {@link #activityInfo},
* {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
*/
public ServiceInfo serviceInfo;
/**
* The provider that corresponds to this resolution match, if this
* resolution is for a provider. Exactly one of {@link #activityInfo},
* {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
*/
public ProviderInfo providerInfo;
/**
* An auxiliary response that may modify the resolved information. This is
* only set under certain circumstances; such as when resolving instant apps
* or components defined in un-installed splits.
* @hide
*/
public AuxiliaryResolveInfo auxiliaryInfo;
/**
* Whether or not an instant app is available for the resolved intent.
*/
public boolean isInstantAppAvailable;
/**
* The IntentFilter that was matched for this ResolveInfo.
*/
public IntentFilter filter;
省略代码......
}
ResolveInfo实现了Parcelable,代表它可以通过binder在进程之间进行传递。在AndroidManifest配置的四大组件解析完后的数据会放入ResolveInfo类中。
如上,它里面的几个关键属性:
- activityInfo,serviceInfo,providerInfo:分别代表Activity,Broadcast,Service,ContentProvider
- filter:在AndroidManifest里面配置的Intent-filter这一项
用一个AndroidManifest.xml例子来说下ResolveInfo,
AndroidManifest.xml有如下信息:
上面的清单文件信息会被解析成两个ResolveInfo:
其中一个它的activityInfo包含的信息是MainActivity,它的filter包含的信息是action为android.intent.action.MAIN,category为android.intent.category.LAUNCHER。
另一个它的activityInfo包含的信息是SecondActivity,它的filter为null
介绍完ResolveInfo,介绍下ActivityInfo这个类。
ActivityInfo
主要显示它的几个关键属性:
public class ActivityInfo extends ComponentInfo implements Parcelable {
public int theme;
public int launchMode;
public String taskAffinity;
public String name;
public String packageName;
省略代码......
}
ActivityInfo包含了在AndroidManifest里面配置的Activity的信息,它上面的几个属性:
- theme:Activity的主题
- launchMode:配置的Activity的启动模式
- taskAffinity:指定Activity放在哪个名字下面的task
- name:Activity的完整的classname
- packageName:包名
2.3 ActivityStarter#executeRequest
private int executeRequest(Request request) {
if (TextUtils.isEmpty(request.reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = request.reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord = null;
final IApplicationThread caller = request.caller;
Intent intent = request.intent;
NeededUriGrants intentGrants = request.intentGrants;
String resolvedType = request.resolvedType;
ActivityInfo aInfo = request.activityInfo;
ResolveInfo rInfo = request.resolveInfo;
final IVoiceInteractionSession voiceSession = request.voiceSession;
final IBinder resultTo = request.resultTo;
String resultWho = request.resultWho;
int requestCode = request.requestCode;
int callingPid = request.callingPid;
int callingUid = request.callingUid;
String callingPackage = request.callingPackage;
String callingFeatureId = request.callingFeatureId;
final int realCallingPid = request.realCallingPid;
final int realCallingUid = request.realCallingUid;
final int startFlags = request.startFlags;
final SafeActivityOptions options = request.activityOptions;
Task inTask = request.inTask;
int err = ActivityManager.START_SUCCESS;
省略代码......
WindowProcessController callerApp = null;
//根据caller获取callerApp
if (caller != null) {
callerApp = mService.getProcessController(caller);
if (callerApp != null) {
callingPid = callerApp.getPid();
callingUid = callerApp.mInfo.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
+ ") when starting: " + intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
//获取userId
final int userId = aInfo != null && aInfo.applicationInfo != null
? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
//根据resultTo找到sourceRecord,resultTo是一个Token,sourceRecord启动者
sourceRecord = mRootWindowContainer.isInAnyTask(resultTo);
if (DEBUG_RESULTS) {
Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord);
}
if (sourceRecord != null) {
//如果是startActivityForResult启动的,则对resultRecord赋值
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
省略各种出错信息的判断代码......
//根据resultRecord找到resultRootTask
final Task resultRootTask = resultRecord == null
? null : resultRecord.getRootTask();
if (err != START_SUCCESS) {
if (resultRecord != null) {
resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
null /* data */, null /* dataGrants */);
}
SafeActivityOptions.abort(options);
return err;
}
省略权限判断等各种其他代码......
//构造ActivityRecord
final ActivityRecord r = new ActivityRecord.Builder(mService)
.setCaller(callerApp)
.setLaunchedFromPid(callingPid)
.setLaunchedFromUid(callingUid)
.setLaunchedFromPackage(callingPackage)
.setLaunchedFromFeature(callingFeatureId)
.setIntent(intent)
.setResolvedType(resolvedType)
.setActivityInfo(aInfo)
.setConfiguration(mService.getGlobalConfiguration())
.setResultTo(resultRecord)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setComponentSpecified(request.componentSpecified)
.setRootVoiceInteraction(voiceSession != null)
.setActivityOptions(checkedOptions)
.setSourceRecord(sourceRecord)
.build();
mLastStartActivityRecord = r;
//调用startActivityUnchecked方法开始进入下个启动
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}
该方法主要做了以下工作:
- 在启动之前,对各种基础的异常进行检测,发现有异常则退出启动Activity流程
- 检测通过后构造了一个ActivityRecord实例
- 开始进入启动Activity的流程
构造了一个ActivityRecord实例,对这个实例初始化主要用到了以下参数:
- callerApp:WindowProcessController类型,主要是启动者相关的信息
- callingPid:启动者的进程id
- callingUid:启动者的id,每个安装的app都会分配一个唯一的id,这个id在当前的用户空间内是不会变化的
- intent:把intent存起来
- aInfo:从AndroidManifest中解析出来的Activity信息
- resultRecord:对于startActivityForResult启动activity时候的启动这信息,用于把返回结果返回给resultRecord
- requestCode:对于startActivityForResult启动activity时候传递的值
- sourceRecord:启动者,代表谁启动了Activity
ActivityRecord就把app进程要启动的Activity及相关的其他信息保存下来了,要注意这里提到的Activity和app进程中要启动的Activity是两码事。
该方法调用startActivityUnchecked方法进入启动的下个流程,调用的时候关键参数有:
- r: ActivityRecord类型
- sourceRecord:启动者,是一个ActivityRecord
- doResume:它的值为true
- options:它的值为checkedOptions,checkedOptions的值现在是为null
- inTask:代表启动的Activity存放的task,当前它的值为null(因为在初始化ActivityRecord的时候就没有设置它)
2.4 ActivityStarter#startActivityUnchecked
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
int result = START_CANCELED;
final Task startedActivityRootTask;
省略代码......
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
[2.5]
//doResume:true,options值为null,inTask:null
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {
省略代码......
}
postStartActivityProcessing(r, result, startedActivityRootTask);
return result;
}
2.5 ActivityStarter#startActivityInner
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
//调用这个方法重置activityStarter的各种数据
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
//设置launchmode
computeLaunchingTaskFlags();
//查找mSourceRootTask
computeSourceRootTask();
mIntent.setFlags(mLaunchFlags);
//获取reusabletask
final Task reusedTask = getReusableTask();
省略冻结task代码......
// Compute if there is an existing task that should be used for.
//如果reusedTask为null,则调用computeTargetTask()方法获取
final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
//newTask是否是新task
final boolean newTask = targetTask == null;
mTargetTask = targetTask;
computeLaunchParams(r, sourceRecord, targetTask);
省略代码......
//如果mTargetRootTask为null,则调用getLaunchRootTask方法会获取或者创建一个task
if (mTargetRootTask == null) {
mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
}
//如果是新的task,则进行创建task流程,并且把ActivityRecord放置在task中
if (newTask) {
final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
setNewTask(taskToAffiliate);
} else if (mAddingToTask) {
//把ActivityRecord放置在找到的task中
addOrReparentStartingActivity(targetTask, "adding to task");
}
省略代码......
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
//不关注这块逻辑,直接看下面的else
if (!mTargetRootTask.isTopActivityFocusable()
|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
// Passing {@code null} as the start parameter ensures all activities are made
// visible.
mTargetRootTask.ensureActivitiesVisible(null /* starting */,
0 /* configChanges */, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetRootTask.mDisplayContent.executeAppTransition();
} else {
// If the target root-task was not previously focusable (previous top running
// activity on that root-task was not visible) then any prior calls to move the
// root-task to the will not update the focused root-task. If starting the new
// activity now allows the task root-task to be focusable, then ensure that we
// now update the focused root-task accordingly.
//如果mTargetRootTask在mRootWindowContainer不处于focus状态,则调用mTargetRootTask.moveToFront方法把它设置为focus状态
if (mTargetRootTask.isTopActivityFocusable()
&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
mTargetRootTask.moveToFront("startActivityInner");
}
// 开始进入下一步的启动Activity操作
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
}
}
省略代码......
return START_SUCCESS;
}
startActivityInner方法的逻辑相对复杂,下面先简要的分析下调用的几个方法做的事情:
-
setInitialState方法
该方法主要对当前ActivityStarter的相关属性进行初始化,介绍下ActivityStarter的几个关键属性:- mStartActivity:代表正在启动的Activity,类型为ActivityRecord
- mIntent:存放启动的其他信息
- mCallingUid:启动者的uid
- mSourceRecord:启动这,类型为ActivityRecord
- mLaunchMode:启动模式
- mLaunchFlags:启动的flags
- mInTask:ActivityRecord放入的task
- mNoAnimation:启动过程中是否有动画
- mInTask:启动的Activity放入的task
-
computeLaunchingTaskFlags方法
该方法做的工作是设置mLaunchFlags,依据以下条件进行设置:- 如果mSourceRecord为null并且mInTask为不null,在根据一些条件判断是否能使用mInTask(这个暂时不在这节的讨论范围)
- 如果不满足步骤1,则进入步骤2,把mInTask置为null
- 如果mInTask为null,则会有如下情况为mLaunchFlags增加FLAG_ACTIVITY_NEW_TASK
3.1. mSourceRecord为null(这种情况一般发生于比如在Service中或者Broadcast中启动Activity)
3.2. mSourceRecord启动者的启动模式是LAUNCH_SINGLE_INSTANCE(singleInstance启动模式代表Activity只能处于自己单独的task中)
3.3. 正在启动的Activity的mLaunchMode是LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK中的任意一个
computeSourceRootTask
该方法主要工作是获取mSourceRootTask,简单来介绍下rootTask和task,task不单单可以包含ActivityRecord,它还可以包含task,rootTask就是ActivityRecord的task的task的task等(直到task的parent不是task的时候就结束)-
getReusableTask
这个方法的主要工作就是获取是否有可以重用的task,如果有则返回,否则返回null,大概的一个过程如下:- putIntoExistingTask的值主要由 mInTask == null && mStartActivity.resultTo == null来决定,mInTask如果不为null,肯定不需要查找可重用的task了
- 如果putIntoExistingTask为true,则根据一些条件获取intentActivity
- 在根据一些条件决定intentActivity是否置为null
- 如果intentActivity不为null,则把它的task返回
-
computeTargetTask
该方法的主要工作是获取Activity可以放入的task,分以下条件获取:- 根据mInTask,mLaunchFlags,mStartActivity.resultTo,mAddingToTask判断是否需要创建新task,是的话返回null
- mSourceRecord不为null的话,返回它的task
- mInTask不为null,则返回它
- 其他情况获取task
startActivityInner方法主要做了以下事情:
- 根据一些条件来决定是创建一个新的task还是使用已有的task,并且把ActivityRecord放入task中
- 如果mDoResume为true,则最终会调用mRootWindowContainer.resumeFocusedTasksTopActivities方法进入下一步启动Activity的操作。
调用mRootWindowContainer.resumeFocusedTasksTopActivities方法,来介绍下它的参数:
- targetRootTask:Task类型,它的值是mTargetRootTask,正在启动的Activity对应的ActivityRecord已经放入了这个task内
- ActivityRecord: ActivityRecord类型,它的值是mStartActivity(保存了正在启动的activity等信息)
- targetOptions:ActivityOptions类型,它的值为null
- deferPause:代表是否延迟pause top Activity,它的值为false(mTransientLaunch默认是false)
2.6 RootWindowContainer#resumeFocusedTasksTopActivities
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
boolean deferPause) {
if (!mTaskSupervisor.readyToResume()) {
return false;
}
boolean result = false;
//targetRootTask不为null并且targetRootTask是在DisplayArea中是最顶层的roottask,则进入下面逻辑
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
[2.7]
//targetOptions为null,deferPause为false
result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
deferPause);
}
省略代码......
return result;
}
2.7 Task#resumeTopActivityUncheckedLocked
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
//正在resume top,则直接返回
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean someActivityResumed = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
//当前的task是叶子task(就是task的孩子都是ActivityRecord),就执行下面逻辑(咱们分析这个流程)
if (isLeafTask()) {
//task是否focus并且可见
if (isFocusableAndVisible()) {
[2.8]
//prev为正在启动的Activity对应的ActivityRecord,options:null,deferPause:false
someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
}
} else {
//当前的task的孩子还是task,走下面逻辑
int idx = mChildren.size() - 1;
while (idx >= 0) {
final Task child = (Task) getChildAt(idx--);
if (!child.isTopActivityFocusable()) {
continue;
}
if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
break;
}
someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
deferPause);
// Doing so in order to prevent IndexOOB since hierarchy might changes while
// resuming activities, for example dismissing split-screen while starting
// non-resizeable activity.
if (idx >= mChildren.size()) {
idx = mChildren.size() - 1;
}
}
}
省略代码......
} finally {
mInResumeTopActivity = false;
}
return someActivityResumed;
}
2.8 Task#resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this root task that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
//next代表当前task中已经显示的Activity
ActivityRecord next = topRunningActivity(true /* focusableOnly */);
省略代码......
//deferPause的值为false
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
//mResumedActivity代表当前task中已经显示的Activity,若不为null,说明在启动其他Activity的时候,需要让mResumedActivity进入pause状态
if (mResumedActivity != null) {
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
//下面方法会让mResumedActivity进入pause状态,为启动新的Activity做准备
pausing |= startPausingLocked(false /* uiSleeping */, next,
"resumeTopActivityInnerLocked");
}
//如果mResumedActivity正在处于pausing状态,进入下面的逻辑
if (pausing) {
ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: Skip resume: need to"
+ " start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
//next.attachedToProcess()为true,代表next已经启动过了,则更新它的进程等信息
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, false /* updateOomAdj */,
false /* addPendingTopUid */);
} else if (!next.isProcessRunning()) {
// Since the start-process is asynchronous, if we already know the process of next
// activity isn't running, we can start the process earlier to save the time to wait
// for the current activity to be paused.
final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
//next.isProcessRunning()为false,代表启动的activity的进程还没被启动,乘mResumedActivity处于pausing的状态,去异步启动进程
mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? "pre-top-activity" : "pre-activity");
}
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity resumed "
+ "(dontWaitForPause) %s", next);
return true;
}
省略代码......
//next.attachedToProcess()为true,代表next已经启动过了,执行下面的逻辑,会把让Activity进入resume状态
if (next.attachedToProcess()) {
省略代码......
try {
final ClientTransaction transaction =
ClientTransaction.obtain(next.app.getThread(), next.appToken);
// Deliver all pending results.
ArrayList a = next.results;
//a代表从上个Activity是否返回了一些数据
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
//从上个Activity返回了数据,则给transaction add一个ActivityResultItem
transaction.addCallback(ActivityResultItem.obtain(a));
}
}
if (next.newIntents != null) {
//若存在newIntents,则add 一个NewIntentItem,这种情况针对的Activity的启动模式是singleTask,singleInstance,singleTop
transaction.addCallback(
NewIntentItem.obtain(next.newIntents, true /* resume */));
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
next.getTask().mTaskId, next.shortComponentName);
mAtmService.getAppWarningsLocked().onResumeActivity(next);
next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
next.abortAndClearOptionsAnimation();
//通知Activity进入resume状态
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
mAtmService.getLifecycleManager().scheduleTransaction(transaction);
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
} catch (Exception e) {
省略代码......
return true;
}
省略代码......
} else {
省略代码......
//Activity需要从onCreate方法开始执行
mTaskSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
resumeTopActivityInnerLocked方法的逻辑相对复杂,下面就来介绍下它主要做的事情:
如果正在显示的Activity(mResumedActivity)存在,则需要让它进入pause状态(最终会把这个消息通知到app对应的Activity)
-
如果正在显示的Activity已处于pausing状态,这时候需要分情况来处理:
2.1 若正在启动的Activity(next)之前已经启动过了,则需要更新它对应的进程状态
2.2 若正在启动的Activity的进程还没有启动,这时候异步启动进程的操作接着暂停启动Activity的操作,直接返回。那什么时候继续开始启动Activity呢?答案是:当mResumedActivity对应的app端的Activity完全的进入pause状态后,才会接着继续启动Activity。
并且可以借助等待pause完毕的这个时机,更新进程状态或者异步启动进程 -
如果正在启动的Activity(next)已经启动过了(next.attachedToProcess()这值为true),则会走下面逻辑:
3.1 若从上个Activity返回了数据,则把数据返回给app端的Activity(onActivityForResult方法会被调用)
3.2 若存在newIntents,则把intent返回给app端的Activity(onNewIntent方法会被调用),这种情况针对的Activity的启动模式是singleTask,singleInstance,singleTop通知app端Activity进入resume状态(onResume方法会被调用)
否则,调用mTaskSupervisor.startSpecificActivity正真进入Activity的启动流程
2.9 ActivityTaskSupervisor#startSpecificActivity
//r:正在启动的Activity,andResume:当前值为true,checkConfig:当前值true
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
//对应的app进程是否启动,启动则进入下面逻辑
if (wpc != null && wpc.hasThread()) {
try {
[2.10]
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
//异步启动进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
2.10 ActivityTaskSupervisor#realStartActivityLocked
//r:正在启动的Activity,proc:对应的进程,andResume:true,checkConfig:true
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
ProtoLog.v(WM_DEBUG_STATES,
"realStartActivityLocked: Skipping start of r=%s some activities pausing...",
r);
return false;
}
final Task task = r.getTask();
final Task rootTask = task.getRootTask();
beginDeferResume();
// The LaunchActivityItem also contains process configuration, so the configuration change
// from WindowProcessController#setProcess can be deferred. The major reason is that if
// the activity has FixedRotationAdjustments, it needs to be applied with configuration.
// In general, this reduces a binder transaction if process configuration is changed.
proc.pauseConfigurationDispatch();
try {
r.startFreezingScreenLocked(proc, 0);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
//设置了proc后,r.attachedToProcess()的值就为true
r.setProcess(proc);
// Ensure activity is allowed to be resumed after process has set.
if (andResume && !r.canResumeByCompat()) {
andResume = false;
}
省略代码......
try {
//proc.hasThread()代表app端是否活着
if (!proc.hasThread()) {
throw new RemoteException();
}
List results = null;
List newIntents = null;
if (andResume) {
// We don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newIntents = r.newIntents;
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " savedState=" + r.getSavedState()
+ " with results=" + results + " newIntents=" + newIntents
+ " andResume=" + andResume);
EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
task.mTaskId, r.shortComponentName);
if (r.isActivityTypeHome()) {
// Home process is the root process of the task.
updateHomeProcess(task.getBottomMostActivity().app);
}
mService.getPackageManagerInternalLocked().notifyPackageUse(
r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
r.forceNewConfig = false;
mService.getAppWarningsLocked().onStartActivity(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
// Because we could be starting an Activity in the system process this may not go
// across a Binder interface which would create a new Configuration. Consequently
// we have to always create a new Configuration here.
final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
procConfig, r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.getSavedState());
if (r.isEmbedded()) {
// Sending TaskFragmentInfo to client to ensure the info is updated before
// the activity creation.
mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
r.getOrganizedTaskFragment());
}
// Create activity launch transaction.
//ClientTransaction主要用于添加各种callback以及Activity要执行的生命周期方法,它会通过binder传递到app进程
//proc.getThread()获取的是IApplicationThread的实例,主要通过它给app发送消息,r.appToken发送给app的token
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final boolean isTransitionForward = r.isTransitionForward();
//add一个LaunchActivityItem类型的callback
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
r.getLaunchedFromBubble()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
//因为andResume为true,进入这,构造一个ResumeActivityItem实例,Activity的onResume方法被执行
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
//否则构造一个PauseActivityItem实例,Activity的onPause方法会被执行
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
//clientTransaction会被传递到app进程
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
省略代码......
} catch (RemoteException e) {
省略代码......
}
} finally {
endDeferResume();
proc.resumeConfigurationDispatch();
}
r.launchFailed = false;
省略代码......
return true;
}
该方法主要做的事情是把各种数据整理收集好后,通过binder发送到app进程,那就来看下这个过程:
1.获取一个ClientTransaction实例
通过ClientTransaction.obtain方法获取一个ClientTransaction实例,为了避免浪费内存从缓存池中获取,ClientTransaction代表要传递给app的事务,它可以包含多个callback和一个lifecycleStateRequest。
来介绍下ClientTransaction.obtain这个方法它的参数:
- client:IApplicationThread类型,AMS通过它把消息发送给app,它的值是proc.getThread()
- activityToken:IBinder类型,它的值是r.appToken。AMS并没有把ActiviityRecord传递给app(传过去不安全),而是把ActiviityRecord的appToken传递过去,简单看下这个appToken,它的代码如下:
public final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
final ActivityRecord.Token appToken;
static class Token extends IApplicationToken.Stub {
private WeakReference weakActivity;
private final String name;
private final String tokenString;
Token(Intent intent) {
name = intent.getComponent().flattenToShortString();
tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
}
//attach到ActivityRecord,这样就持有它了
private void attach(ActivityRecord activity) {
if (weakActivity != null) {
throw new IllegalStateException("Already attached..." + this);
}
weakActivity = new WeakReference<>(activity);
}
//根据token来拿到ActivityRecord
private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
if (token == null) {
return null;
}
ActivityRecord r = token.weakActivity.get();
//r.getRootTask()为null,代表它也是个”废物“了
if (r == null || r.getRootTask() == null) {
return null;
}
return r;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Token{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
if (weakActivity != null) {
sb.append(weakActivity.get());
}
sb.append('}');
return sb.toString();
}
@Override
public String getName() {
return name;
}
}
}
ActivityRecord的appToken是一个类型为Token的实例。Token它继承了IApplicationToken.Stub说明它是一个IBinder类型,它用弱引用的方式持有ActivityRecord,appToken作为一个“令牌”被传递到app进程,就是告诉app,我给了你一个token,如果想给我发送消息,就带上这个token,我就能通过token找到ActivityRecord了(tokenToActivityRecordLocked方法)
Token这个类作为一个binder服务给使用者就提供了一个getName()方法,因此可以看出它在app端完全就是当作“令牌”来使用或者当作ActivityRecord的唯一标识来使用。
2.获取LaunchActivityItem实例
通过LaunchActivityItem.obtain方法获取实例,同样也为了效率和避免浪费内存,LaunchActivityItem也从缓冲池中获取,这个类包含了启动一个Activity的所有信息,来介绍下它的关键的属性:
- intent:启动时候的intent(包含传递给Activity的数据等等),最终会被传递到“终点”
- info:ActivityInfo类型,这个属性非常重要,它包含了app端具体Activity的类名,包名等信息
- curConfig:Configuration类型,配置信息
- state:Bundle类型,代表Activity在AMS中保存的信息,它会被传递给onCreate方法
会调用第一步ClientTransaction的addCallback方法加入LaunchActivityItem实例
3. 获取ResumeActivityItem实例
ResumeActivityItem代表需要执行Activity的onResume方法,会调用clientTransaction.setLifecycleStateRequest(lifecycleItem)
4. 最后把clientTransaction发送给app
调用mService.getLifecycleManager().scheduleTransaction(clientTransaction)方法把clientTransaction发送到app端
小结
用一张时序图进行小结
3. app接收并处理AMS发出的信息
AMS把clientTransaction发送到app端,因为mService.getLifecycleManager().scheduleTransaction(clientTransaction)方法最终执行的代码是mClient.scheduleTransaction(clientTransaction)(mClient是IApplicationThread类型)这是一个binder调用,mClient对应的是app进程的ActivityThread$ApplicationThread类型实例
,因此最终会进入ApplicationThread的scheduleTransaction方法
3.1 ApplicationThread#scheduleTransaction
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
3.2 ActivityThread#scheduleTransaction
public abstract class ClientTransactionHandler {
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
}
ActivityThread继承了ClientTransactionHandler,关于clientTransaction是如何分发的流程在这节中不介绍了,经过分发后会进入LaunchActivityItem的execute方法
3.3 LaunchActivityItem#execute
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
mLaunchedFromBubble, mTaskFragmentToken);
//ActivityThread继承了ClientTransactionHandler,最终进入它的对应方法
[3.4]
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
该方法,把AMS传递过来的参数放置在了ActivityClientRecord的实例中,还记得AMS中记录Activity的类是ActivityRecord吧,它俩是一一对应的。
ActivityClientRecord
/** Activity client record, used for bookkeeping for the real {@link Activity} instance. */
public static final class ActivityClientRecord {
//tokenAMS传递过来的令牌
@UnsupportedAppUsage
public IBinder token;
省略属性......
@UnsupportedAppUsage
Intent intent;
String referrer;
IVoiceInteractor voiceInteractor;
//AMS传递过来的保存的数据
Bundle state;
PersistableBundle persistentState;
//app端真正启动的Activity实例
@UnsupportedAppUsage
Activity activity;
//Activity对应的window
Window window;
Activity parent;
String embeddedID;
Activity.NonConfigurationInstances lastNonConfigurationInstances;
// TODO(lifecycler): Use mLifecycleState instead.
//是否paused
@UnsupportedAppUsage
boolean paused;
//是否stoped
@UnsupportedAppUsage
boolean stopped;
boolean hideForNow;
//config信息
Configuration createdConfig;
Configuration overrideConfig;
省略属性......
//AMS传递过来的activityinfo信息
@UnsupportedAppUsage
ActivityInfo activityInfo;
@UnsupportedAppUsage
CompatibilityInfo compatInfo;
@UnsupportedAppUsage
public LoadedApk packageInfo;
省略属性......
//生命周期状态值
@LifecycleState
private int mLifecycleState = PRE_ON_CREATE;
}
ActivityClientRecord不单单包含了AMS传递过来的信息,还包含app端真正启动的Activity实例以及对应的生命周期状态
3.4 ActivityThread#handleLaunchActivity
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
省略代码......
WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process.
GraphicsEnvironment.hintActivityLaunch();
//开始启动Activity
[3.5]
final Activity a = performLaunchActivity(r, customIntent);
省略代码......
return a;
}
3.5 ActivityThread#performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//ComponentName封装了mPackage和mClass,component是真正Activity的对应的信息,先从r.intent.getComponent()获取
ComponentName component = r.intent.getComponent();
if (component == null) {
//没获取到从PMS中去解析
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
//如果targetActivity存在,则从targetActivity获取
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
//初始化appContext它的类型是ContextImpl,像Activity调用到的Context的方法最终都是通过ContextImpl来实现的
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
//获取ClassLoader,来加载Activity
java.lang.ClassLoader cl = appContext.getClassLoader();
//mInstrumentation.newActivity方法中通过反射来实例化一个Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
//尝试去make Application(一般情况下都已经创建成功了),如果存在直接返回
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config =
new Configuration(mConfigurationController.getCompatConfiguration());
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// Activity resources must be initialized with the same loaders as the
// application context.
appContext.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
appContext.setOuterContext(activity);
//attach方法把各种数据传递给activity
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken, r.shareableActivityToken);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
if (r.mActivityOptions != null) {
activity.mPendingOptions = r.mActivityOptions;
r.mActivityOptions = null;
}
activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
activity.mCalled = false;
//下面是根据r.isPersistable(),分别调用Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
//如果自己实现的Activity的onCreate方法没有调用父类的onCreate方法,则抛异常
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
mLastReportedWindowingMode.put(activity.getActivityToken(),
config.windowConfiguration.getWindowingMode());
}
r.setState(ON_CREATE);
// updatePendingActivityConfiguration() reads from mActivities to update
// ActivityClientRecord which runs in a different thread. Protect modifications to
// mActivities to avoid race.
synchronized (mResourcesManager) {
//AMS传递过来的token作为key,r作为value存放在mActivities中
mActivities.put(r.token, r);
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
该方法是启动Activity的核心方法主要做了以下几件事:
- 获取到ComponentName,它包含了真正Activity的包名,class信息
- 使用ClassLoader,通过反射对第1步的类进行实例化,会实例化一个Activity
- 尝试创建/获取Application的实例
- 通过Activity的attach方法把各种信息传递给它
- 调用Activity的onCreate方法
- AMS传递过来的token作为key,r作为value存放在mActivities中(这样通过tokenActivityRecord和ActivityClientRecord就建立了关系)
最后分析下mInstrumentation.callActivityOnCreate这个方法
3.6 Instrumentation#callActivityOnCreate
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
[3.7]
activity.performCreate(icicle);
postPerformCreate(activity);
}
3.7 Activity#performCreate
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performCreate:"
+ mComponent.getClassName());
}
dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
// initialize mIsInMultiWindowMode and mIsInPictureInPictureMode before onCreate
final int windowingMode = getResources().getConfiguration().windowConfiguration
.getWindowingMode();
mIsInMultiWindowMode = inMultiWindowMode(windowingMode);
mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED;
restoreHasCurrentPermissionRequest(icicle);
//onCreate方法被调用
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
"performCreate");
mActivityTransitionState.readState(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
dispatchActivityPostCreated(icicle);
到此Activity的onCreate方法被调用,因为clientTransaction.setLifecycleStateRequest(lifecycleItem),lifecycleItem是ResumeActivityItem类型,Activity的onResume方法也会被调用,这个流程就不分析了.
小结
同样用一张时序图小结
总结
Activity启动源码分析的整个过程就结束了,更多的总结内容可以看上面的原理.
思考
为啥启动Activity必须要经过AMS?
想当年作为android新手的时候,认为app启动其他app内的Activity的时候经过AMS可以理解,毕竟app进程之间是不可以直接通信的,需要经过系统进程的AMS进行"中转".但是app启动自己内部的Activity的时候为啥也要经过AMS,经过AMS启动速度的话会慢,这里的慢是相对不经过AMS直接在app内启动的这样的假设.为啥会慢呢,如上面的分析流程,启动Activity需要在进程之间进行两次通信,Intent等数据也需要在进程之间传递来传递去的.
造成上面这种错误认识的原因是当时我只是把AMS认为只是起一个"中转"的功能.其实不是这样的,AMS的功能并非如此简单,AMS管理着所有的Activity(当然还管理着其他的三大组件),哪个Activity应该进入resume状态了,哪个应该进入pause或者stop状态,哪个应该进入destory状态等等生命周期状态的切换都是AMS来统一的协调处理;还有比如用户修改了系统的字体或者别的设置信息,那都需要AMS去通知Activity是否需要重新启动以来适配新的设置变化等等.
所以启动的目标Activity不管是app内的还是其他app的都需要去AMS,进行查询,检查,校验,记录流程,只有记录成功后,Activity启动才算在AMS环节成功了,AMS会通过记录下来的Activity信息进而来控制Activity的生命周期状态的切换.
AMS就是要管理控制Activity,如果没有它,那app内的Activity“各自为政”那岂不是乱套了。
再谈Token
如果做过web相关的开发,大家应该都了解,在用户登录后,服务器会返回给客户端一些信息,其中就有token,这个token它是一个字符串,并且是整个系统内唯一的.以后客户端与服务器进行通信就需要携带上这个token,服务器就知道到底是哪个用户在与之进行交互.
在启动Activity时候,AMS会返回一个Token类型的token实例给app进程,这里的token和web开发相关的token作用是一样的. AMS把这个token传递给app,app端也会把启动的Activity记录在本地的ActivityClientRecord类中,这个类中会记录下"真正启动的Activity的引用".app端会把token作为key值,ActivityClientRecord作为value值保存起来.ActivityRecord与ActivityClientRecord就通过token建立了联系.
AMS通知某个Activity进入某种生命周期状态,会把token值传递给app端,app端收到这个命令后,会通过这个token拿到ActivityClientRecord进而拿到真正启动的Activity的引用,进而调用它的对应回调方法.
app端某个Activity完成了某个操作后(比如pause操作),会携带token等其他信息通知AMS(因为token是一个IBinder类型,它进入AMS后会被转化为Binder),AMS通过token拿到对应的ActivityRecord,进而调用它相应的方法.
为啥要传递一个IBinder类型的token?
假如传递一个int类型或者String类型的token是不是也可行,当然是可行的,但是有一个问题就是复杂度要比使用IBinder类型高,复杂度高主要是体现在AMS.
原因是这样的:为了维护token与ActivityRecord之间建立一一对应关系可以使用有两种方式:其一token作为key值ActivityRecord作为value存储起来;其二每个ActivityRecord增加一个属性用来存储token. 这两种方式成本都挺高:其一方式使用的内存会多,并且维护成本也高,ActivityRecord的删除,增加,修改都需要去更新相应的存储容器;其二方式虽然不需要增加内存,但是多了查找成本,每次都需要从容器中拿出ActivityRecord依次进行对比.
那来看看IBinder类型的token是怎么解决上面的问题的.首先Token类([2.10]的代码)通过弱引用的方式持有ActivityRecord,这样也不会有内存泄漏的问题,在AMS端构造的token实例肯定是系统内唯一的,因为它是在系统进程中初始化完毕分发给其他进程使用的.
token传递到app进程后它会被转换为BinderProxy类型,并且binder机制是保证一个进程内的同一IBinder类型实例是仅存在一份的,意思就是即使AMS多次发送同一个Binder实例给进程,在这个进程内的BinderProxy类型的实例也是只有一个.在进程内可以通过使用"=="来比较两个token是否是一样的,这和使用int类型或者String类型的token也没有区别,更重要的是这种类型的token扩展性好,比如Token增加一些接口的话,其他进程内是可以使用的.
当app进程传递token到AMS后,token会被转换为Binder类型,这时候的token已经是Token了,直接可以通过它找到ActivityRecord.
IBinder类型的token复杂度也低,扩展性也好,这就是要使用IBinder类型的token的原因.