工作过程
App进程访问Ams服务,system_server进程开启Binder线程,处理注册请求,负责及时反馈App主线程组件注册结果,App主线程等待Ams服务线程的工作时,将休眠。
Ams服务处理,回调App进程,根据Binder机制,回调时重用休眠主线程或新建Binder线程,向主线程插入一个暂停上一个Activity组件的消息,返回Ams服务,结束。
Ams服务Binder线程不会耗时,否则会阻塞App主线程,导致ANR。
App主线程会从消息队列里查询消息,暂停上一个活动Activity的消息处理时,将再次访问Ams服务,继续新组件Resume逻辑。
Ams服务处理,回调App进程,插入通知Activity实例创建和开启生命周期的消息,然后结束Ams服务,App主线程将开启新Activity实例和生命周期的任务。
一、Ams服务流程
Ams服务流程包括,组件注册,进程创建(如必要),启动模式分析,任务栈管理,App进程通知。
Ams服务的入口是startActivity方法。ActivityStackSupervisor类是监管者,ActivityStack类是栈。
第一个方法,ActivityStackSupervisor类的startActivityMayWait方法。
// 不修改App传递的Intent,再次封装。
intent = new Intent(intent);
// 目标Activity信息。
ActivityInfo aInfo = resolveActivity(intent, resolvedType,
startFlags, profilerInfo, userId);
PackageManager类,根据Intent类解析ActiityInfo对象,如果组件未在AndroidManifest.xml文件注册时,返回空。
第二个方法,ActivityStackSupervisor的startActivityLocked方法。
ProcessRecord callerApp = null;
if (caller != null) {//caller是IApplicationThread caller
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
err = ActivityManager.START_PERMISSION_DENIED;
}
}
//ProcessRecord在Ams存储列表
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
//ProcessRecord类内部
IApplicationThread thread;
根据App进程的IApplicationThread,解析ProcessRecord,根据IBinder token入参查找发起者Activity在Ams服务的ActivityRecord记录。
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {//resultTo是IBinder resultTo
sourceRecord = isInAnyStackLocked(resultTo);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
//ActivityRecord resultRecord作为结果接收Activity。
resultRecord = sourceRecord;
}
}
}
//遍历ActivityDisplay集合,从mStacks中查找。
ArrayList<ActivityStack> mStacks,一个ActivityStack栈列表。
遍历每项ActivityStack,查找符合token的ActivityRecord。每一个Activity组件在Ams服务都有一个ActivityRecord记录对应。App进程通过IApplicationThread和Ams服务的一个ProcessRecord对应,表示在Ams服务中,保存一条进程记录。
从Intent类解析Flags,启动时未设置,默认是0。
final int launchFlags = intent.getFlags();
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
err = ActivityManager.START_CLASS_NOT_FOUND;
}
常见错误,解析的ActivityInfo是空,设置错误标志,表示类没有找到,直接返回App进程,不会创建ActivityRecord记录,App进程抛出异常。
创建ActivityRecord,构造方法有很多初始化工作,例如解析启动模式。
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
构造方法中,创建Token对象,弱引用ActivityRecord,用于传递给App进程。App进程中保存一份token和Activity的Map,Ams服务访问App进程时,可根据token唤起对应Activty组件。
startActivityLocked方法,最后,调用startActivityUncheckedLocked方法,入参中包含新建的ActivityRecord和发起者ActivityRecord。
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
第三个方法,startActivityUncheckedLocked方法。
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
...
if (r.resultTo == null && inTask == null && !addingToTask
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
targetStack = computeStackFocus(r, newTask);
targetStack.moveToFront("startingNewTask");
} else if (sourceRecord != null) {
//sourceRecord发起者不空,走这里的代码。
final TaskRecord sourceTask = sourceRecord.task;
...
targetStack = sourceTask.stack;
...
r.setTask(sourceTask, null);
} else if (inTask != null) {
....
targetStack = inTask.stack;
r.setTask(inTask, null);
} else {
targetStack = computeStackFocus(r, newTask);
targetStack.moveToFront("addingToTopTask");
ActivityRecord prev = targetStack.topActivity();
r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
r.info, intent, null, null, true), null);
...
}
...
targetStack.mLastPausedActivity = null;
//入参doResume是true。
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
如果发起者Activity组件的ActivityRecord(即sourceRecord)不是空,新创建ActivityRecord的TaskRecord和发起者相同,设置TaskRecord任务,同时获取TaskRecord内部ActivityStack栈,确定目标栈targetStack。
系统根据不同的情况获取目标栈,当Intent存在FLAG_ACTIVITY_NEW_TASK标志时,新建TaskRecord任务。
ActivityStack栈包含一个TaskRecord列表,每一项TaskRecord的内部引用外部ActivityStack。TaskRecord包含一个ActivityRecord列表,每一项ActivityRecord内部引用外部TaskRecord。ActivityRecord代表一个Activity记录,TaskRecord代表任务栈,进程与启动模式相关,TaskRecord关联到ActivityStack。
从上图可知,有两个ActivityStack,一个保存和系统UI相关的TaskRecord,另一个保存App的TaskRecord。开启了四个应用,两个自己编译的App,两个手机系统App,图中对应四个TaskRecord,其中,个人App启动了三个Activity,保存在TaskRecord的ActivityRecord列表mActivitys中。
二、启动模式处理
SingleTop模式
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
//同一个Activity类
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| launchSingleTop || launchSingleTask) {
topStack.mLastPausedActivity = null;
if (doResume) {
resumeTopActivitiesLocked();
}
...
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
如果满足栈顶记录的组件名ComponentName和新建ActivityRecord记录的组件名相等,组件类名相同属同一个Activity。不需要确定ActivityStack栈,也不需要addActivityToTop方法将ActivityRecord加入到ActivityStack的TaskRecord中,直接resumeTopActivitiesLocked方法。
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
...
return false;
}
此时,新ActivityRecord记录没有执行addActivityToTop加入方法,因此,next记录还是以前的,和当前活跃的mResumedActivity相等。
还原Android的基础知识点,配置启动模式是SingleTop的Activity组件,栈顶已经存在一个该Activity类组件,将复用。
SingleTask处理
if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
...
} else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| launchSingleInstance || launchSingleTask) {
//将最上面ActivityRecord对应task的部分内容清理。
ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags);
...
} else if (){
}
在任务栈TaskRecord查找ActivityRecord,从后向前遍历mActivitys列表,如果发现ActivityRecord与新建ActivityRecord组件类名相同,finishActivityLocked方法,将中间的一些Activity清理,最后,Resume恢复该ActivityRecord。
还原Android的基础知识点,启动模式是SingleTask的Activity组件,栈中已经存在一个该Activity类组件,将复用,并将它上部的所有Activity清除。
四、暂停前组件,恢复栈顶新组件
第四个方法,ActivityStack的startActivityLocked方法。
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
insertTaskAtTop(rTask, r);
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
if (!newTask) {
//遍历mTaskHistory中的TaskRecord
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
//TaskRecord 所有Activity全部finish,跳过继续
continue;
}
//与ActivityRecord关联的TaskRecord一致。
if (task == r.task) {
if (!startIt) {
...
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
...
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
r.putInHistory();
if (!isHomeStack() || numActivities() > 0) {
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
....
mWindowManager.addAppToken(task.mActivities.indexOf(r),
r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
boolean doShow = true;
...
} else {
...
}
if (doResume) {
//this即targetStack
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
newTask字段,代表是否为该ActivityRecord记录新建TaskRecord,启动模式和FLAG_ACTIVITY_NEW_TASK有关,这里不需新建。
将ActivityRecord加入TaskRecord中mActivities列表尾部,调用Wms服务的addAppToken方法,Activity组件界面提前注入窗体Token,token是前面介绍的IBinder token。最后,回到栈监管者ActivityStackSupervisor,恢复任务栈顶的ActivityRecord,调用ActivityStack的resumeTopActivitiesLocked方法。
第五个方法,ActivityStack#resumeTopActivityInnerLocked方法。
final ActivityRecord next = topRunningActivityLocked(null);
...
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
恢复栈ActivityStack中最Top的ActivityRecord记录。topRunningActivityLocked方法,获取任务栈顶ActivityRecord,即next。
此时,mResumedActivity字段,保存的仍是上一个ActivityRecord记录,和最上面的next不同,(标准启动模式时,新建记录已经入栈)。通过startPausingLocked方法,该记录暂停,让mPausingActivity指向它。
第六个方法,ActivityStack的startPausingLocked方法。
ActivityRecord prev = mResumedActivity;
...
//置空mResumedActivity
mResumedActivity = null;
mPausingActivity = prev;
...
if (prev.app != null && prev.app.thread != null) {
try {
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
}
if (mPausingActivity != null) {
if (dontWait) {
completePauseLocked(false);
return false;
} else {
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
prev.pauseTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
return true;
}
}
暂停上一个Resume的Activity,即mResumedActivity,并置空。
获取ProcessRecord的ApplicationThread对象,schedulePauseActivity方法,回调App进程,appToken标识暂停的是哪一个Activity。向App进程的主线程发送一个PAUSE_ACTIVITY消息,实现上一个Activity的onPause生命周期方法。同时,延迟500毫秒发送一个PAUSE_TIMEOUT_MSG消息到system_server进程ActivityManager线程消息队列。
暂停后,设置pausing标志,原路一步步返回,Ams服务的Binder线程结束。回到App进程启动Activity组件的Instrumentation的execStartActivity方法位置,返回结果。
if (pausing) {
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
App主线程从休眠中唤醒,checkStartActivityResult方法结果处理。然后,继续读取主消息队列,下一个消息应该PAUSE_ACTIVITY消息。
如果Ams服务的返回是START_SUCCESS成功,checkStartActivityResult方法直接返回,否则将抛出异常。
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
...
}
常见异常情况,组件未在AndroidManifest.xml文件注册,返回内容是未找到类,在App主线程和system_server进程ActivityManager线程均有待处理消息,并行。两者进入Ams的执行代码都是ActivityStack的activityPausedLocked()方法。在App进程中,ActivityThread处理前一个Activity生命周期onPause方法。
handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport){
ActivityClientRecord r = mActivities.get(token);
...
performPauseActivity(token, finished, r.isPreHoneycomb());
ActivityManagerNative.getDefault().activityPaused(token);
}
最后,Ams服务调用activityPaused方法,通知Ams服务,token标识的Activity生命周期onPause方法已完成。
//Ams#activityPaused方法。
@Override
public final void activityPaused(IBinder token) {
...
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityPausedLocked(token, false);
}
}
...
}
//ActivityStack内部Handler
public void handleMessage(Message msg) {
synchronized (mService) {//同步
...
activityPausedLocked(r.appToken, true);
}
}
Ams服务启动Binder线程,同时,ActivityManager线程消息队列get待处理的消息,两者都会并发进入activityPausedLocked方法,不过它有一个延迟,因此,一般情况Binder线程快一些。
第七个方法,ActivityStack的activityPausedLocked方法。
final void activityPausedLocked(IBinder token, boolean timeout) {
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
completePauseLocked(true);
} else {
....
}
}
}
如果一个线程已执行,mPausingActivity置空,另一个线程进入后判断,将停止执行。到栈监管者的resumeTopActivitiesLocked方法,已完成Activity组件暂停,mResumedActivity已置空,因此,无pause状态标志,继续向下走流程,恢复新ActivityRecord记录。
next代表即将启动的ActivityRecord。
//ActivityStack#resumeTopActivityInnerLocked代码片段
if (next.app != null && next.app.thread != null) {
...
}else{
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
ActivityRecord内部ProcessRecord还未设置,next.app是空,进入栈监管者的startSpecificActivityLocked方法。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
.....
//如果ProcessRecord不为空,说明进程已经存在,直接realStartActivityLocked后退出。
if (app != null && app.thread != null) {
try {
.....
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
}
}
//ProcessRecord不存在,创建进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
根据ActivityRecord的包名和application的uid获取ProcessRecord,它代表此ActivityRecord记录的进程,如果ProcessRecord不是空,不需要创建进程。
ActivityRecord引用ProcessRecord,scheduleLaunchActivity方法,回调App进程,向App主线程发送一个LAUNCH_ACTIVITY消息。
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
mWindowManager.setAppVisibility(r.appToken, true);
...
r.app = app;
...
//回调App进程,发起生命周期方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}
最后,不管是system_server进程的ActivityManager线程,或是Ams服务的Binder线程进入的ActivityStack的activityPausedLocked方法,处理逻辑相同,Binder线程执行完成后返回到App进程的以下代码位置。
ActivityManagerNative.getDefault().activityPaused(token)
以上代码,在App进程,说明主线程PAUSE_ACTIVITY消息处理结束,继续消息队列,下一个消息就是Ams服务回调的LAUNCH_ACTIVITY消息,即将开始Activity组件的对象创建,生命周期。Ams服务传给App的token参数,将作为一个IBinder连接,连接启动的该Activity组件和Ams服务的注册记录。
总结
启动一个Activity组件借助Instrumentation类的execStartActivity方法,跨进程访问system_server进程的Ams服务。
Ams服务负责注册启动的组件,包括创建ActivityRecord记录,根据启动模式进行组件的统一管理(暂停/恢复),进程判断及创建。
ActivityStack栈有一个TaskRecord列表,TaskRecord有一个ActivityRecord列表。在最普通情况下,TaskRecord保存相同栈的组件。
IApplicationThread是Ams服务回调客户端对象。启动时,Ams服务将多次回调App进程,如让前组件暂停,开启新组件生命周期,通过一个token标示客户端组件。
Ams服务会先暂停前组件,再发起新组件,因此,生命周期顺序是先onPause前Activity,后onCreate,onStart,onResume。
Ams服务回调App进程,通过ActivityThread类内部Handler向主线程发送消息。
任重而道远