前言
从一个简单Android视图切入,探索Android平台显示流程。剖析从Activity启动到界面完全显示过程中发生的故事,从而对Android框架层知识有一个初步了解。
启动Activity组件
Intent intent = new Intent(mActivity.this, xActivity.class);
startActivityForResult(intent, requestCode);
通过Activity#startActivityForResult启动Activity组件,Intent是启动意图,包含被启动Activity类组件,传递的数据。
Activity#startActivityForResult方法
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
...
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());
...
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
...
}
Activity对象内部有一个Instrumentation,Activity#attach时赋值初始化,对象保存在ActivityThread,在ActivityThread#handleBindApplicationActivity创建。
Instrumentation#execStartActivity方法。
public ActivityResult execStartActivity(Context who, IBinder contextThread,
IBinder token, Activity target,
Intent intent, int requestCode, Bundle options){
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
...
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);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
Instrumentation#execStartActivity方法负责和system_sever系统服务进程通信,AMS提供服务。
向AMS传递参数如下表所示
主要参数 | 功能 |
---|---|
IApplicationThread whoThread | Binder,App进程ApplicationThread,封装在ActivityThread。 |
Intent | 启动意图。 |
Context who.getBasePackageName() | who是当前发起者,发起者的上下文的包名。 |
IBinder token | 发起者Activity内部IBinder,attach时初始化赋值,代表发起者组件。 |
requestCode | 发起者请求code。 |
Bundle | 传递参数,key-value。 |
IApplicationThread定义系统服务进程访问App进程的业务逻辑。每个Activity都包含ActivityThread,通过ActivityThread#getApplicationThread()获取ApplicationThread对象。
Context who代表当前发起者,如果在Activity组件启动另一个Activity,who代表Activity。
IBinder token在Activity#attach方法中被赋值,在发起者Activity被启动,AMS回调App方法ApplicationThread#scheduleLaunchActivity时回传的token。当发起者Activity启动另一个Activity时,带着token。
启动Activity组件的主要逻辑由系统服务进程的AMS服务完成,App进程通过AMS代理调用ServiceApi方法请求服务,线程休眠等待结果。
system_server进程开启一个Binder线程处理请求,处理过程中会回调App进程,同样是App开启Binder线程处理system_server进程请求,此时休眠的App主线程不受影响,仍等待。
ApplicationThread负责处理AMS回调App进程的业务逻辑,大部分服务方法仅发送一个消息到App主线程消息队列,并无其他耗时操作,对AMS的Binder线程来说,休眠时间不会长,在处理业务时中间休息一下告诉App主线程一个消息。
AMS的Binder线程不会有太多耗时操作逻辑,及时返回App主线程结果,防止App主线程阻塞时间过长。
结果返回,发起者负责启动的任务结束,暂停上一个(如果存在)活动Activity以及开启新Activity生命周期的任务将继续从主线程消息队列里获取消息去执行。
AMS服务处理Activity组件启动
App进程中启动Activity与AMS的交互流程图
一个普通Activity的启动流程图_AMS服务流程.png
从上图看出,AMS中启动Activity组件入口AMS#startActivity,依次调用startActivityMayWait、startActivityLocked、startActivityUncheckedLocked等,涉及两个类ActivityStackSupervisor与ActivityStack。
Activity启动模式默认是standard。
-
1:在ActivityStackSupervisor#startActivityLocked中,根据传入的App进程IApplicationThread解析ProcessRecord,每个App进程都通过IApplicationThread与AMS中的一个ProcessRecord对应。
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中存储一条进程记录。
根据传入的IBinder token解析发起者Activity在AMS中存储的ActivityRecord,作为接收结果的ActivityRecord。
ActivityStackSupervisor#startActivityLocked方法代码段
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {//resultTo是IBinder resultTo
sourceRecord = isInAnyStackLocked(resultTo);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
遍历ActivityDisplay集合,在ActivityDisplay中ArrayList<ActivityStack> mStacks中查找,mStacks是一个ActivityStack栈列表。遍历每项ActivityStack,从ActivityStack中查找符合token的ActivityRecord。
ActivityDisplay的ActivityStack列表.pngIBinder转换Token业务类型,从Token内部获取弱引用ActivityRecord,判断ActivityRecord是否在某个ActivityStack中。
每个启动的Activity在AMS中对应一个ActivityRecord记录。
- 2:从Intent中解析Flags,启动时未设置默认是0。
final int launchFlags = intent.getFlags();
-
3:创建ActivityRecord,在内部做很多初始化工作,如解析启动模式。
ActivityStackSupervisor#startActivityLocked方法代码段
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
ActivityRecord构造方法中创建Token对象,内部弱引用ActivityRecord,用于传递给App进程,存储在Activity中。
ActivityStackSupervisor#startActivityLocked方法代码段
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
触发startActivityUncheckedLocked方法,传入新建的ActivityRecord与发起者ActivityRecord。
- 4:在ActivityStackSupervisor#startActivityUncheckedLocked中,确定ActivityStack栈。
启动模式在ActivityInfo,ActivityRecord构造方法时将lauchMode存储到ActivityRecord内。
ActivityStackSupervisor#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;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
入参doResume是true。
sourceRecord发起者不空时,新ActivityRecord的TaskRecord和发起者ActivityRecord保持一致,新ActivityRecord设置TaskRecord,并获取TaskRecord内部的ActivityStack栈。
前期工作寻找目标栈targetStack,在得到目标栈ActivityStack后,将触发ActivityStack的startActivityLocked方法。
根据不同的情况获取目标栈。当Intent存在FLAG_ACTIVITY_NEW_TASK标志时,createTaskRecord新建TaskRecord。
TaskRecord、ActivityStack、ActivityRecord的关系图如下:
ActivityRecord、ActivityStack和TaskRecord的关系 (1).pngActivityStack栈中有一个TaskRecord列表mTaskHistory,每一项TaskRecord内部有ActivityStack。
TaskRecord中有一个ActivityRecord列表mActivities,每一项ActivityRecord内部有TaskRecord。
ActivityRecord关联TaskRecord,TaskRecord关联ActivityStack。
TaskRecord、ActivityStack、ActivityRecord图
ActivityRecord.png
从上图中可知这里有两个ActivityStack,一个存放系统UI相关的ActivityStack,另一个存放App的TaskRecord。开启了四个应用,两个自己编译的App,两个手机系统App。如图对应四个TaskRecord,自己的App启动三个Activity,存储在TaskRecord的mActivitys中。
ActivityStackSupervisor#startActivityUncheckedLocked方法启动模式singleTop处理代码段
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {//同一个Activity类
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;
}
}
}
满足top的realActivity与新ActivityRecord的realActivity相等 ,说明最上面的组件与新组件的组件类名相同,是同一个Activity。
当launchSingleTop是true时,不用确定ActivityStack栈,也不需addActivityToTop方法将ActivityRecord加入到ActivityStack的TaskRecord中,直接调用resumeTopActivitiesLocked方法。
ActivityStack#resumeTopActivityInnerLocked代码段
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
...
return false;
}
mResumedActivity与最上面栈顶next相同,返回。因为新ActivityRecord未addActivityToTop加入,因此next还是以前的,与当前活跃的mResumedActivity相等。
配置了singleTop启动模式Activity组件,如果栈顶最上层已经存在该Activity,将不会再启动一次。
ActivityStackSupervisor#startActivityUncheckedLocked方法启动模式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 (){
}
找到ActivityRecord对应的TaskRecord,清理内部部分mActivitys,从后向前遍历,如果发现一个ActivityRecord与当前新建的ActivityRecord的组件名相同,finishActivityLocked将他们中间的一些Activity清理,最后Resume发现的那个ActivityRecord。
配置了singleTask启动模式Activity组件,如果栈中已经存在该Activity,将不会再启动一次,将顶部的所有Activity清除。
- 5:触发ActivityStack#startActivityLocked方法,newTask表示是否需新建TaskRecord,与启动模式与FLAG_ACTIVITY_NEW_TASK等相关,这里不需新建。
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) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
ActivityRecord关联的TaskRecord,将ActivityRecord加入到TaskRecord中列表mActivities的尾部。
调用WMS#addAppToken方法,为Activity组件界面提前注入窗体Token。
最后,因doResume是true,触发ActivityStackSupervisor监管者的resumeTopActivitiesLocked方法。
判断传入的this即targetStack是不是Top的ActivityStack。
触发ActivityStack的resumeTopActivityInnerLocked方法。
- 6:ActivityStack#resumeTopActivityInnerLocked的工作是负责让ActivityStack栈中最Top的ActivityRecord记录Resume。
最上面ActivityRecord即next通过topRunningActivityLocked获取,此时mResumedActivity保存的仍是上一个ActivityRecord,与最上面的next不同。通过startPausingLocked方法让该ActivityRecord暂停,让mPausingActivity指向它。
ActivityStack#resumeTopActivityInnerLocked方法代码段
final ActivityRecord next = topRunningActivityLocked(null);
...
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
- 7:ActivityStack#startPausingLocked方法,Pause上一个Resume的Activity,即mResumedActivity,设置mResumedActivity是null。
ProcessRecord的ApplicationThread,schedulePauseActivity方法,向App主线程发送一个PAUSE_ACTIVITY消息。完成上一个Activity的onPause生命周期方法。
同时发送一个延迟500毫秒的PAUSE_TIMEOUT_MSG消息到system_server进程的ActivityManager线程消息队列。
ActivityStack#startPausingLocked方法代码段
ActivityRecord prev = 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;
}
}
- 8:startPausingLocked方法后,结果pausing是true。ActivityStack#resumeTopActivityInnerLocked方法返回,一步步按原路返回,系统服务进程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(result, intent)处理result,继续从主消息队列中取消息,下一个应该是在服务进程ApplicationThread#schedulePauseActivity处发送的PAUSE_ACTIVITY消息。
- 9:在App主线程和system_server的ActivityManager线程均有待处理的消息,并行。
两者进入AMS执行的代码都是activityPausedLocked方法。
在App进程中,处理前一个Activity生命周期onPause方法。token是App与AMS中表示Activity的唯一标识。
ActivityThread#handlePauseActivity方法
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);
}
发起system_server进程AMS调用,触发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);
}
}
...
}
system_server进程启动一个新Binder线程处理。进入ActivityStack#activityPausedLocked方法。同时,ActivityManager线程消息队列中get待处理的消息,也会执行ActivityStack#activityPausedLocked方法,不过它有一个延迟,所以一般情况下新Binder线程快一些。两个线程执行activityPausedLocked代码块需synchronized同步。
public void handleMessage(Message msg) {
synchronized (mService) {
...
activityPausedLocked(r.appToken, true);
}
}
- 10:ActivityStack#activityPausedLocked,触发completePauseLocked。
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设置为空,则另一个线程判断后就不会继续执行。
从completePauseLocked中到ActivityStackSupervisor#resumeTopActivitiesLocked,已完成前Activity的暂停,接下来要Resume新的ActivityRecord,此时mResumedActivity已设置为空,因此pause状态是false,继续走流程。
程序调试截图如下:
pause为false.png
- 11:在ActivityStack#resumeTopActivityInnerLocked中,next代表要启动的ActivityRecord,此时ActivityRecord内部ProcessRecord还未设置,next.app是空,所以会进入方法ActivityStackSupervisor#startSpecificActivityLocked。
ActivityStack#resumeTopActivityInnerLocked代码片段
if (next.app != null && next.app.thread != null) {
.....
}else{
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
- 12:获取ProcessRecord,判断是否需创建进程。根据ActivityRecord包名以及application的uid获取ProcessRecord,它代表此ActivityRecord的进程。
ActivityStackSupervisor#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);
}
- 13:ActivityStackSupervisor#realStartActivityLocked,将ProcessRecord赋值到ActivityRecord内部,scheduleLaunchActivity调用App进程,App进程启动一个Binder线程,向App主线程发送一个LAUNCH_ACTIVITY消息。
LAUNCH_ACTIVITY消息将开启Activity对象创建及生命周期。
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
mWindowManager.setAppVisibility(r.appToken, true);
...
r.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线程执行到这里,PAUSE_TIMEOUT_MSG消息处理完毕。
如果AMS是Binder线程先执行,也是同样的逻辑,处理完返回到以下代码处。
ActivityManagerNative.getDefault().activityPaused(token)
PAUSE_ACTIVITY消息就处理完啦。
当App主线程接收到LAUNCH_ACTIVITY消息,开始Activity对象创建,生命周期。AMS进程传递给App的参数包含token,最终存储在Activity内部,其他参数如ActivityInfo等。
^^
网友评论