赞
踩
Activity作为作为安卓中直接与用户进行交互的页面,我们可以点击桌面Launcher的shortcut图标来进入应用程序主页面,在应用程序内也可以启动其他应用内或其他应用的Activity,虽然场景不同,但其启动方式却大同小异。
多数应用的Activity都是通过startActivity()的方式启动的;如果应用需要启动结果则可以通过startActivityForResult()的方式来启动,这样结果会通过回调onActivityResult()返回;如果当前的安卓手机支持多用户模式,那么应用还可以使用startActivityAsUser()来指定这个Activity归属的用户。虽然这些方法名不尽相同,但其方法的调用链最后都合而为一,走向一处。
本文旨在从源码层面上还原Activity从发起startActivity()到页面真正onResume()这期间的整个调用链及各处理过程的用意。
startActivity()方法来源于Context类,是其待实现的一个抽象方法,所以从原则上来说,任何继承了Context的类都可以拥有启动一个Activity的能力。对于我们的安卓framework来说,startActivity()至少在Context类簇中的两个地方被实现了:
下边我们就从这两种发起方式来一一说起。
下边就是Activity调用startActivity()的流程图。
在上述代码中在Activity中,startActivity()有两个重载方法,但无论如何调用这个方法调用链都会进入到以下startActivityForResult()中。
// frameworks/base/core/java/android/app/Activity.java public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { 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; } //... }
上述代码中主要分为两个部分:
就发起阶段来说,此处我们主要关注Instrumentation的execStartActivity()方法调用。
// frameworks/base/core/java/android/app/Instrumentation.java public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Fragment target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; //... try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, requestCode, 0, null, options);//此处涉及binder机制,跨进程调用到AMS中 checkStartActivityResult(result, intent);//检查启动结果 } catch (RemoteException e) { } return null; }
在execStartActivity()方法中则是真正进行binder通信(对binder机制不了解的读者可以阅读深入理解binder机制一文)中向AMS发送启动Activity请求的部分。通过阅读AMN代码可以发现,因此处运行于client应用端,所以AMN.getDefault()获取到的是ActivityManagerProxy。
AMP是binder机制的一部分,在上述代码中,启动Activity是调用的AMP.startActivity()方法,这个方法源自IActivityManager接口,此接口定义了Activity管理的各种方法,其中就包括startActivity(),根据binder机制的特点,此处client端AMP所调用的startActivity()方法在binder server端(即AMS)必然有其实现体。
我们先来看一下IActivityManager.startActivity()的接口参数定义。
// frameworks/base/core/java/android/app/IActivityManager.java
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
此处startActivity()各参数对应到方法调用链上来看,其对应值如下:
参数(正序) | 参数的值 |
---|---|
caller | 即ActivityThread与AMS之间进行通信的binder,即ApplicationThread |
callingPackage | 从调用链上来看是startActivity调用者(即Context子类)所属的包名 |
intent | 即startActivity()所传入的intent |
resolvedType | 返回intent可能有的MIME类型 |
resultTo | 如果调用者是Activity,则当前值为Activity的token(该token即调用者Activity对应到AMS中的ActivityRecord$Token),如果调用者是ContextImpl,则为null |
resultWho | 为Activity的mEmbeddedID |
requestCode | 请求码,如果当前调用的是startActivityForResult()则表明需要返回结构,用于后续onActivityResult()判断 |
flags | 值为0 |
profilerInfo | 值为null |
options | 一般而言,此处为null |
至AMP.startActivity()被调用,我们client端发起的启动请求就通过binder机制传给了Activity管理者即AMS。
对于Service、Application等这些后台Context或者某些拥有Context能力的组件而言,其发起启动请求的方式与Activity发起略有不同。
//frameworks/base/core/java/android/app/ContextImpl.java
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
从上述代码来看,非Activity的Context子类发起启动请求需要指明new task,即新建一个Task来承载这个启动的目标Activity;而且在传参上也多有缺失,主要体现在对调用者(调用者一般指Activity,AMS会根据调用者来决定Task、Stack的切换关系)相关的描述上。
除此之外在方法调用链与Activity发起是一致的,都是通过Instrumentation调用AMP.startActivity()向AMS发起启动请求。
先上一幅AMS服务端对启动Activity请求的处理时序图。
上一小节client端发起启动请求的最后会通过AMS代理AMP.startActivity()把请求通过binder方式传给server端,也就是AMS中(AMP与AMS之间的通信过程这里不展开说明)。AMS继承自ActivityManagerNative类,它负责处理AMP传过来的binder通信请求。
在AMS中与Activity启动请求相关的binder接口方法有多个,此处我们仅阅读就上一小节参数个数相同的startActivity(),其调用如下:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public final int startActivity(IApplicationThread caller/*调用进程*/, String callingPackage/*调用者包名*/, Intent intent, String resolvedType, IBinder resultTo/*返回者token*/, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options, UserHandle.getCallingUserId()); } @Override 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) { enforceNotIsolatedCaller("startActivity"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, options, userId, null, null); }
在AMS中四大组件的处理都分发交由指定的模块:
自然的,我们的startActivity请求也会交由ASS处理,这就是ASS.startActivityMayWait()方法,具体内容如下:
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java 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, int userId, IActivityContainer iContainer, TaskRecord inTask) { //part1 intent = new Intent(intent); ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId); ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { callingPid = -1; } else if (caller == null) { callingPid = realCallingPid; callingUid = realCallingUid; } else { callingPid = callingUid = -1; } //part2 final ActivityStack stack; if (container == null || container.mStack.isOnHomeDisplay()) { stack = getFocusedStack(); } else { stack = container.mStack; } stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; final long origId = Binder.clearCallingIdentity();//清除应用进程的pid、uid //...省略掉heavy weight进程判断 //part3 int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, componentSpecified, null, container, inTask); Binder.restoreCallingIdentity(origId);//还原binder client的uid、pid //part4 if (stack.mConfigWillChange) { mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); stack.mConfigWillChange = false; mService.updateConfigurationLocked(config, null, false, false); } //part5 if (outResult != null) { outResult.result = res; if (res == ActivityManager.START_SUCCESS) { mWaitingActivityLaunched.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } else if (res == ActivityManager.START_TASK_TO_FRONT) { ActivityRecord r = stack.topRunningActivityLocked(null); if (r.nowVisible && r.state == ActivityState.RESUMED) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mWaitingActivityVisible.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } } } return res; } }
ASS.startActivityMayWait()方法主要分为以下几个部分:
从上边代码中的启动过程来看,其核心启动逻辑显然交给了ASS.startActivityLocked()负责。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java 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 componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS;//默认值 ProcessRecord callerApp = null; if (caller != null) {//相比于IPC取出来的uid、pid,此处更愿意选择caller的uid与pid,虽然两者相同 callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { err = ActivityManager.START_PERMISSION_DENIED; } } if (err == ActivityManager.START_SUCCESS) { final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; //... 省略日志打印 } ActivityRecord sourceRecord = null;//调用者 ActivityRecord resultRecord = null;//结果返回者,通常两者一致 if (resultTo != null) { sourceRecord = isInAnyStackLocked(resultTo);/*resultTo即是startActivity的调用方的token*/ if (DEBUG_RESULTS) Slog.v( TAG, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } } ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;//找出返回者所在的stack final int launchFlags = intent.getFlags(); if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { if (requestCode >= 0) { ActivityOptions.abort(options); return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; } resultRecord = sourceRecord.resultTo; resultWho = sourceRecord.resultWho; requestCode = sourceRecord.requestCode; sourceRecord.resultTo = null; if (resultRecord != null) { resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode); } if (sourceRecord.launchedFromUid == callingUid) { callingPackage = sourceRecord.launchedFromPackage;//在forward情形下,调用者包名也需改变 } } if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {//组件未找到 err = ActivityManager.START_INTENT_NOT_RESOLVED; } if (err == ActivityManager.START_SUCCESS && aInfo == null) {//清单文件中未找到 err = ActivityManager.START_CLASS_NOT_FOUND; } if (err == ActivityManager.START_SUCCESS && sourceRecord != null && sourceRecord.task.voiceSession != null) { if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { if (!AppGlobals.getPackageManager().activitySupportsIntent( intent.getComponent(), intent, resolvedType)) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } catch (RemoteException e) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } } if (err == ActivityManager.START_SUCCESS && voiceSession != null) { try { if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(), intent, resolvedType)) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } catch (RemoteException e) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } if (err != ActivityManager.START_SUCCESS) {//如果检查的各项权能不通过,则取消start if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); return err; } final int startAnyPerm = mService.checkPermission( START_ANY_ACTIVITY, callingPid, callingUid);//调用者有无权限 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, callingUid, aInfo.applicationInfo.uid, aInfo.exported);//启动目标有无授权 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {//权限不足,则抛出异常 if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } String msg; //...省略对异常msg的更新 throw new SecurityException(msg);//阻塞式,当前一直在binder线程中,所有的异常都已RemoteExcepiton形式抛给调用方 } boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); if (mService.mController != null) { try { Intent watchIntent = intent.cloneFilter(); abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } } if (abort) {//如果要启动的activity已被屏蔽,则取消start操作,并假装start成功 if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); return ActivityManager.START_SUCCESS; } //此处说明进入的启动流程 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, this, container, options);//在Record创建时其token也被创建 if (outActivity != null) { outActivity[0] = r; } final ActivityStack stack = getFocusedStack();//焦点stask if (voiceSession == null && (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {//如果是通过后台服务启动,则有可能被延时5s启动 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack); mPendingActivityLaunches.add(pal); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; } } if (mService.mDidAppSwitch) { mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } doPendingActivityLaunchesLocked(false);//先启动被延时的activity //此前是对能否启动进行判断,如果能启动,则进入unchecked start逻辑,真正启动 err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); if (err < 0) { notifyActivityDrawnForKeyguard(); } return err; }
startActivityLocked()主要负责真正启动前的权能上边的判断,诸如目标组件的正确性、调用者合法性、是否越权等。
值得注意的是,调用者在启动Activity时可能会要求被启动者在启动完成时返回启动结果(通过startActivityForResult()来控制),会有请求码requestCode和返回码resultCode的概念。那么有种场景可能是这样的,A启动B时要求结果,而这个结果需要依赖于B启动C来完成。
那么对于这种情形,如果似上图般这样则没有问题,但如果B在启动C时带上了FLAG_ACTIVITY_FORWARD_RESULT即result向前传递,则B的请求码就不能指明(实质上不大于等于0即可,android系统中请求码大于等于0才有效);如 intent指明了result向前传递而又要求c返回结果则会如上述代码所看到的那样产生result返回冲突异常。
在经历完权能判断后就认为当前Activity是可以被启动的,那么会继续进入真正启动的过程,这就是ASS.startActivityUncheckedLocked()方法。
ASS.startActivityUncheckedLocked()是一个非常庞大复杂的方法,简直让人瞠目,只能通过分段来阅读。
首先此方法对启动模式做了一些解析。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part1 final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) { final Intent intent = r.intent; final int callingUid = r.launchedFromUid; if (inTask != null && !inTask.inRecents) {//如果task不在最近任务列表里边,则inTask无效 inTask = null; } 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; int launchFlags = intent.getFlags(); if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && (launchSingleInstance || launchSingleTask)) { launchFlags &= ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);//先将multi task去掉,后边根据情况在加回来 } else { switch (r.info.documentLaunchMode) { case ActivityInfo.DOCUMENT_LAUNCH_NONE: break; case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING: launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS://总是创建 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_NEVER://不创建task launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;//去掉multi task break; } }
上述代码分为两个部分:
接下来的则继续上边的内容,是对某些启动场景的具化。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part2 final boolean launchTaskBehind = r.mLaunchTaskBehind && !launchSingleTask && !launchSingleInstance && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;//是否task是behind静默启动(后台) if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {//跨task情形,result无法传递 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null); r.resultTo = null; } if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;//new document可以理解为new task } if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if (launchTaskBehind || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) { launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;//若指明了always则总是新建task } } mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;//是否回调onUserLeaveHint() if (!doResume) {//是否延时显示 r.delayedResume = true; } ActivityRecord notTop = (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {//查看当前栈顶元素是否是要启动的r ActivityRecord checkedCaller = sourceRecord; if (checkedCaller == null) { checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop); } if (!checkedCaller.realActivity.equals(r.realActivity)) {//如果不是,则only if need就不应继续存在 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED; } }
上述代码分为三个部分:
在某些情况下,调用者可能指明了目标task,这时候我们需要根据启动类型判断这个task是否可用。如下:
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part3 boolean addingToTask = false;//是否找到承载task TaskRecord reuseTask = null; if (sourceRecord == null && inTask != null && inTask.stack != null) {//没有调用者,但指明目标task final Intent baseIntent = inTask.getBaseIntent(); final ActivityRecord root = inTask.getRootActivity(); if (baseIntent == null) { ActivityOptions.abort(options); throw new IllegalArgumentException("Launching into task without base intent: " + inTask); } //单例、单任务的承载task中的root不能是其他,其base组件不能是其他 if (launchSingleInstance || launchSingleTask) { if (!baseIntent.getComponent().equals(r.intent.getComponent())) {//单例、单任务的承载task ActivityOptions.abort(options); throw new IllegalArgumentException("Trying to launch singleInstance/Task " + r + " into different task " + inTask); } if (root != null) { ActivityOptions.abort(options); throw new IllegalArgumentException("Caller with inTask " + inTask + " has root " + root + " but target is singleInstance/Task"); } } if (root == null) {//如果root为空,则说明目标栈内并无组件,可直接使用 final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;//因为指定了task,所以launchFlag不能再指明新建task,此处去掉 launchFlags = (launchFlags&~flagsOfInterest) | (baseIntent.getFlags()&flagsOfInterest); intent.setFlags(launchFlags); inTask.setIntent(r); addingToTask = true;//表明找到承载task } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { addingToTask = false;//指明了要新建task,但指定task拥有activity,所以指定的承载task不能使用 } else { addingToTask = true;//其他情况,默许为指定的task可用 } reuseTask = inTask;//重用task即指定的task } else { inTask = null;//其他情形下,指定的task皆无用,所以此处置空 } if (inTask == null) {//此处为没有指定task的情形,这是接着上边来的,用于寻找承载task if (sourceRecord == null) {//没有调用者,所以要新建task来承载 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;//此处intask判断多余,主要用new task标志位来表示需要新建 } } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {//launchMode指定单例,所以任务要新建task launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;//原调用者为单例则显然要新建task } else if (launchSingleInstance || launchSingleTask) {//launchFlag为单例、单任务,所以要新建承载task launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;//指定了需要新建task的启动模式 } }
首先,有个变量我们需要持续关注,即addingToTask,这个变量用于表明我们是否找到承载task(承载task与目标task含义不同,请注意区分)。
上述代码是对指定了目标task情形的启动做处理,如果指定了inTask,则这个目标task需要对单例、单任务栈做兼容处理,最后的结果是addingToTask和reuseTask(重用task)的赋值情况。如果没有指定目标task则进入以下三种情形:
接下来则找出调用者所在stack。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part4 ActivityInfo newTaskInfo = null; Intent newTaskIntent = null; ActivityStack sourceStack; if (sourceRecord != null) {//如果调用者不为空,则寻找调用者stack if (sourceRecord.finishing) {//调用者正在finish,则调用者所在stack不必找 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; } else {//进入此处则找到了调用者所在stack sourceStack = sourceRecord.task.stack; } } else { sourceStack = null;//调用者为空,则调用者所在stack为空 }
虽然代码走到了此处,那是否就一定需要新建task了呢?
答案是否定的,在以下还有两处代码是可以用旧task挽留一下的,即part5和part6。
先来阅读part5。part5的先决条件很多,这也间接导致后续需要part6来捕获剩余情形。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part5 boolean movedHome = false; ActivityStack targetStack; intent.setFlags(launchFlags);//至此,就要根据launchFlag来启动,之前从逻辑上处理了launchFlag的正确性 if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)//如果只是指明new task,而没有一定要multi,则还可寻找下承载task || launchSingleInstance || launchSingleTask) { if (inTask == null && r.resultTo == null) {//没有指定task ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); if (intentActivity != null) {//找到了目标activity if (isLockTaskModeViolation(intentActivity.task)) { showLockTaskToast(); Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (r.task == null) { r.task = intentActivity.task; } targetStack = intentActivity.task.stack;//找出目标所在stack targetStack.mLastPausedActivity = null;//目标stack的paused类置空 if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack + " from " + intentActivity); targetStack.moveToFront(); if (intentActivity.task.intent == null) { intentActivity.task.setIntent(r); } final ActivityStack lastStack = getLastStack(); //上一个焦点stack的task有变动或与当前stack的task不一致,则需调整task,且指明task按返回键退到何处,home task type则按back键时退到桌面 ActivityRecord curTop = lastStack == null? null : lastStack.topRunningNonDelayedActivityLocked(notTop); if (curTop != null && (curTop.task != intentActivity.task || curTop.task != lastStack.topTask())) { r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); if (sourceRecord == null || (sourceStack.topActivity() != null && sourceStack.topActivity().task == sourceRecord.task)) { if (launchTaskBehind && sourceRecord != null) { intentActivity.setTaskToAffiliateWith(sourceRecord.task); } movedHome = true; targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } options = null; } } //是否需要reset task栈 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r); } if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {//上边已经对这些flag进行判断,如果此处还能进去,说明已有承载task if (doResume) {//因为已有承载task,且已有对应Activity实例启动,所以此处直接resume那个实例并返回 resumeTopActivitiesLocked(targetStack, null, options); } else { ActivityOptions.abort(options); } return ActivityManager.START_RETURN_INTENT_TO_CALLER; } if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { //鸠占鹊巢,将task所有元素清理掉 reuseTask = intentActivity.task; reuseTask.performClearTaskLocked(); reuseTask.setIntent(r); } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 || launchSingleInstance || launchSingleTask) { //清理栈内元素直到待启动Activity在栈顶 ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); if (top != null) {//如果栈顶清理后,确实有实例 if (top.frontOfTask) { top.task.setIntent(r); } ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent); } else { sourceRecord = intentActivity; } } else if (r.realActivity.equals(intentActivity.task.realActivity)) { //如果待启动Activity和寻找到的旧task的栈内实例相同 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop) && intentActivity.realActivity.equals(r.realActivity)) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, intentActivity.task); if (intentActivity.frontOfTask) { intentActivity.task.setIntent(r); } intentActivity.deliverNewIntentLocked(callingUid, r.intent); } else if (!r.intent.filterEquals(intentActivity.task.intent)) { addingToTask = true; sourceRecord = intentActivity; } } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { addingToTask = true; sourceRecord = intentActivity; } else if (!intentActivity.task.rootWasReset) { intentActivity.task.setIntent(r); } if (!addingToTask && reuseTask == null) {//如果没有添加且重用task为空 if (doResume) { targetStack.resumeTopActivityLocked(null, options); } else { ActivityOptions.abort(options); } return ActivityManager.START_TASK_TO_FRONT; } } } }
上述代码详细寻找了旧task中已有待启动Activity实例的情形,如果确实有,则会连带一部分stack变动和task栈清理,最后会通过resumeTopActivityLocked()将栈顶元素即这个实例给显示出来。
因为part5进入旧task中寻找已有实例是有先决条件的(即new task而非multi task),这难免会漏掉一些情形,所以接下来的part6则对这些剩余情形做捕获处理。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part6 if (r.packageName != null) {//这是new task之前的最后一道检查关卡,用于检查r已然处于栈顶的情形,如果当前focused stack已经是目标启动activity,则此处过滤掉 ActivityStack topStack = getFocusedStack(); ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { 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) {//满足非new task情形 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); topStack.mLastPausedActivity = null; if (doResume) {//直接resume resumeTopActivitiesLocked(); } ActivityOptions.abort(options); if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent);//最终回调onNewIntent() return ActivityManager.START_DELIVERED_TO_TOP; } } } } } else {//启动包名为空,则类没找到 if (r.resultTo != null) {//如果需要返回结果,则返回cancel r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); return ActivityManager.START_CLASS_NOT_FOUND;//类没找到 }
如果一个待启动的Activity(AMS记录为ActivityRecord)没有包名,则该Activity并不满足启动条件;如果有包名,则part6会判断当前FocusedStack栈顶是否就是待启动实例且属于单例、单栈顶、单任务栈类型的话,就与上边处理new task+multi task类似,通过方法resumeTopActivitiesLocked()将这个实例显示出来。
接着往下,进入part7部分。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part7 boolean newTask = false; boolean keepCurTransition = false; TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ? sourceRecord.task : null; //resultTo,前边已经对跨task情况给置空。指定task前边在处理时把不适情形给置空 //addingToTask表明当前是否找到承载task,此处没有找到 //且拥有new task标志,前边已经对需要加上的情形给加上了 if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {//新建task来承载 if (isLockTaskModeViolation(reuseTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } newTask = true; targetStack = adjustStackFocus(r, newTask);//调整focus if (!launchTaskBehind) {//只要不是静默启动,此处都将目标stack移到mStacks栈顶(集合末尾) targetStack.moveToFront(); } //此处只是将task绑定到r中,但是task还未有r的信息 if (reuseTask == null) {//如果重用task为空,则此处新建task并设置给ActivityRecord r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, !launchTaskBehind /* toTop */), taskToAffiliate); } else { r.setTask(reuseTask, taskToAffiliate);//如果已有重用task,则直接设置 } if (!movedHome) {//按back按键,当前task退出时是否直接回到home task而不是上一个显示状态的task if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } } else if (sourceRecord != null) {//如果调用者不为空,则继续细分 final TaskRecord sourceTask = sourceRecord.task; if (isLockTaskModeViolation(sourceTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } targetStack = sourceTask.stack; targetStack.moveToFront(); final TaskRecord topTask = targetStack.topTask(); if (topTask != sourceTask) {//调用者task位置移动 targetStack.moveTaskToFrontLocked(sourceTask, r, options); } else { mWindowManager.moveTaskToTop(topTask.taskId); } if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { //直接对调用者所处栈做处理,此处清理r实例之上所有元素 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags); keepCurTransition = true; if (top != null) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent); targetStack.mLastPausedActivity = null; if (doResume) {//一如既往,找到实例则resume并返回 targetStack.resumeTopActivityLocked(null); } ActivityOptions.abort(options); return ActivityManager.START_DELIVERED_TO_TOP; } } else if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { //重新排序情形,如在调用者所在task中找到实例,则将实例挪至栈顶,并resume返回 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r); if (top != null) { final TaskRecord task = top.task; task.moveActivityToFrontLocked(top); ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task); top.updateOptionsLocked(options); top.deliverNewIntentLocked(callingUid, r.intent); targetStack.mLastPausedActivity = null; if (doResume) { targetStack.resumeTopActivityLocked(null); } return ActivityManager.START_DELIVERED_TO_TOP; } } //其他情形都是正常启动,需新建实例(即需完成走完launch过程) r.setTask(sourceTask, null); if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in existing task " + r.task + " from source " + sourceRecord); } else if (inTask != null) { //如果指定的task不为空,则又进行细分 if (isLockTaskModeViolation(inTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } targetStack = inTask.stack;//先对目标task做挪动,挪至stack栈顶 targetStack.moveTaskToFrontLocked(inTask, r, options); targetStack.moveToFront(); mWindowManager.moveTaskToTop(inTask.taskId); ActivityRecord top = inTask.getTopActivity(); if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {// if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop || launchSingleTask) {//满足单栈或单栈顶 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {//对于if need标志位来说,直接返回启动成功 return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent);//onNewIntent()被调用 return ActivityManager.START_DELIVERED_TO_TOP; } } if (!addingToTask) {//如果没有承载task,虽然启动失败,但告知结果返回者目标task已被置到栈顶了 ActivityOptions.abort(options); return ActivityManager.START_TASK_TO_FRONT;//当前activity没有实际启动,但task已经被置到栈顶 } r.setTask(inTask, null);//目标task作为承载task if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in explicit task " + r.task); } else {//其他情形则视为当前谁在栈顶,就近指定其task为承载task,若无,则新建task targetStack = adjustStackFocus(r, newTask); targetStack.moveToFront(); ActivityRecord prev = targetStack.topActivity(); r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true), null); mWindowManager.moveTaskToTop(r.task.taskId); if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new guessed " + r.task); }
上述代码的分支比较多,我们详细捋一下:
上述各种分支的核心都是把不需要继续走launch流程的给过滤掉,这些不需要launch的分支都直接根据doResume来决定是否显示实例r。如果需要走launch流程,则实例r会通过setTask()方法将task与之关联(注意,此处是r关联task,并非task关联了r,这中间含义还请自行体会)。
继续走launch流程就需要进入part8,也是ASS.startActivityUncheckedLocked()方法的最后部分。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#startActivityUncheckedLocked part8 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, intent, r.getUriPermissionsLocked(), r.userId); if (sourceRecord != null && sourceRecord.isRecentsActivity()) { r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);//当前栈退出时进入的task } if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); } ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); targetStack.mLastPausedActivity = null; //至此,已经找到task并添加进去了,接下来就是launch targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); if (!launchTaskBehind) {//如果不是静默启动,则需要调整焦点 // Don't set focus on an activity that's going to the back. mService.setFocusedActivityLocked(r);//调整focus stack } return ActivityManager.START_SUCCESS;//launch意为着启动成功 }
part8的核心是调用ActivityStack.startActivityLocked()方法,它负责处理那种需要走完整launch流程(即Activity从无到有的过程)。
ActivityStack.startActivityLocked则主要处理添加appToken到WMS中的逻辑,这是Activity启动前的必要步骤,因为client端Activity在launch过程中会创建一个PhoneWindow并添加到WMS中,这个添加过程WMS要求有档可查,档就是此处的appToken。
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) { TaskRecord rTask = r.task;//承载task final int taskId = rTask.taskId; if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { //此处将创建的task加入到stack栈中,然后关联WMS。 insertTaskAtTop(rTask); mWindowManager.moveTaskToTop(taskId); } TaskRecord task = null; if (!newTask) {//不需要新建task的情形,说明某task中已存在这个r实例,直接切换其即可 boolean startIt = true; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { task = mTaskHistory.get(taskNdx); if (task.getTopActivity() == null) {//当前task为空,不满足非newTask的条件,跳过 // All activities in task are finishing. continue; } if (task == r.task) {//task相同 if (!startIt) { //如果startIt为true,则表明当前task在stack的栈顶,如果为false,则说明不在栈顶,进入逻辑 task.addActivityToTop(r);//r挪至task返回栈栈顶 r.putInHistory(); mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId, r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } ActivityOptions.abort(options); return; } break; } else if (task.numFullscreen > 0) { startIt = false; } } } //如果task不在stack栈顶,那么就不需要回调onUserLeavingHint() if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { mStackSupervisor.mUserLeaving = false; if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false"); } task = r.task;//task角色换为待启动实例所在task task.addActivityToTop(r);//将task与r关联,注意与之前setTask的区别,此处之后,r与task互知存在 task.setFrontOfTask();//task置到stack栈顶 r.putInHistory();//r放入历史记录中 if (!isHomeStack() || numActivities() > 0) {//WMS添加token并判断你是否要添加启动窗口 boolean showStartingIcon = newTask;//如果是新建task,则需要启动窗口(appStartingWindow) ProcessRecord proc = r.app; if (proc == null) {//获取r所在进程 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid); } if (proc == null || proc.thread == null) {//进程没有创建或还没有attach showStartingIcon = true;//如果当前是新建task或新建进程,则显示starting icon } if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { //当前activity指定不需动画 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition); mNoAnimActivities.add(r); } else {//添加窗口动画,根据是否创建task等决定动画类型 mWindowManager.prepareAppTransition(newTask ? r.mLaunchTaskBehind ? AppTransition.TRANSIT_TASK_OPEN_BEHIND : AppTransition.TRANSIT_TASK_OPEN : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);//分为task动画、activity动画 mNoAnimActivities.remove(r); } //将当前待启动ActivityRecord对应的appToken添加进WMS中,后续有档可查 mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId, r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind); boolean doShow = true;//是否显示启动窗口 if (newTask) { //如果有标志位reset task,则试图在所有栈中寻找 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { resetTaskIfNeededLocked(r, r); doShow = topRunningNonDelayedActivityLocked(null) == r;//栈顶元素是否是r } } else if (options != null && new ActivityOptions(options).getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {//如果非新建task,且options指定了场景动画,则无需启动窗口 doShow = false; } if (r.mLaunchTaskBehind) {//如果是behind,则直接将r置为显示态 mWindowManager.setAppVisibility(r.appToken, true); ensureActivitiesVisibleLocked(null, 0); } else if (SHOW_APP_STARTING_PREVIEW && doShow) {//显示启动窗口 ActivityRecord prev = mResumedActivity; if (prev != null) { if (prev.task != r.task) { prev = null; } else if (prev.nowVisible) { prev = null; } } mWindowManager.setAppStartingWindow( r.appToken, r.packageName, r.theme, mService.compatibilityInfoForPackageLocked( r.info.applicationInfo), r.nonLocalizedLabel, r.labelRes, r.icon, r.logo, r.windowFlags, prev != null ? prev.appToken : null, showStartingIcon); r.mStartingWindowShown = true;//记录当前正在显示启动窗口 } } else {//如果当前stack还没有任何actiivty,则不需动画 mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId, r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);//添加appToken值WMS,有档可查 ActivityOptions.abort(options); options = null; } if (VALIDATE_TOKENS) { validateAppTokensLocked(); } if (doResume) { //如果当前需要resume,即显示这个启动的activity,则进入此逻辑 mStackSupervisor.resumeTopActivitiesLocked(this, r, options); } }
在上述代码中,主要对三方面进行了分析:
resumeTopActivitiesLocked()这个方法在很多地方都会调用到,当不同的场景调用此方法时会走入不同的逻辑,这也是它比较复杂的地方。它经过数次中转,最终调用ActivityStack的resumeTopActivityInnerLocked()方法,其意思也很明显,主要是resume栈顶元素。
下边我们依例将这个方法分为三个作用不同的部分。
首先,我们先来看part1。
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java#resumeTopActivityInnerLocked part1 final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { if (!mService.mBooting && !mService.mBooted) {//当前AMS还未启动完成,则直接返回 return false; } ActivityRecord parent = mActivityContainer.mParentActivity;//待考证,parent是啥含义,看样子是stack首先要启动的activity if ((parent != null && parent.state != ActivityState.RESUMED) || !mActivityContainer.isAttachedLocked()) { return false; } cancelInitializingActivities();//移除所有正在初始化且启动了启动窗口的非栈顶activity //寻找到当前stack中正在运行的栈顶元素,正常情况下至少有当前要启动的activity,此处一般为要resume的activity ActivityRecord next = topRunningActivityLocked(null); final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; final TaskRecord prevTask = prev != null ? prev.task : null; if (next == null) {//当前并无正在运行的activity,所以先显示launcher,resume失败 ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); // Only resume home if on home display final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } next.delayedResume = false;//既然当前要resume栈顶,则其控制变量当然要变为false if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { //当前栈顶元素已经resume了,所以退出流程 mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); mStackSupervisor.notifyActivityDrawnForKeyguard(); return false; } final TaskRecord nextTask = next.task; if (prevTask != null && prevTask.stack == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {//prev正在finish if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else {//直接返回launcher final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } } //当前正处于sleep或关机状态 if (mService.isSleepingOrShuttingDown() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); return false; } //非启动user,则无法继续resume if (mService.mStartedUsers.get(next.userId) == null) { return false; } // The activity may be waiting for stop, but that is no longer // appropriate for it. mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mWaitingVisibleActivities.remove(next); //当前正在暂停另一个Activity if (!mStackSupervisor.allPausedActivitiesComplete()) { return false; }
part1主要是对能不能resume指定的元素做判断,目前来看,不能resume的场景有:
若上述场景未满足则取消此次resume。如若通过这些检验,则继续往下执行。
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java#resumeTopActivityInnerLocked part1 boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;//是否等待pause,通常为false boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);//内部调用startPausingLocked if (mResumedActivity != null) { pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } if (pausing) { if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } return true; } if (mService.isSleeping() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, null, "no-history", false); mLastNoHistoryActivity = null; } if (prev != null && prev != next) { if (!prev.waitingVisible && next != null && !next.nowVisible) { prev.waitingVisible = true; mStackSupervisor.mWaitingVisibleActivities.add(prev); } else { if (prev.finishing) { mWindowManager.setAppVisibility(prev.appToken, false); } else { } } } try { AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false, next.userId); /* TODO: Verify if correct userid */ } catch (RemoteException e1) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + next.packageName + ": " + e); } boolean anim = true; if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare close transition: prev=" + prev); if (mNoAnimActivities.contains(prev)) { anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.task == next.task ? AppTransition.TRANSIT_ACTIVITY_CLOSE : AppTransition.TRANSIT_TASK_CLOSE, false); } mWindowManager.setAppWillBeHidden(prev.appToken); mWindowManager.setAppVisibility(prev.appToken, false); } else { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev); if (mNoAnimActivities.contains(next)) { anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.task == next.task ? AppTransition.TRANSIT_ACTIVITY_OPEN : next.mLaunchTaskBehind ? AppTransition.TRANSIT_TASK_OPEN_BEHIND : AppTransition.TRANSIT_TASK_OPEN, false); } } } else { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous"); if (mNoAnimActivities.contains(next)) { anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false); } } Bundle resumeAnimOptions = null; if (anim) { ActivityOptions opts = next.getOptionsForTargetActivityLocked(); if (opts != null) { resumeAnimOptions = opts.toBundle(); } next.applyOptionsLocked(); } else { next.clearOptionsLocked(); }
这一阶段(part2)主要是暂停(pause)上一处于resume状态的元素,并为要执行resume(即栈顶next)的元素准备窗口动画。
窗口动画是通过WMS的方法prepareAppTransition()来设置的,他可以根据场景不同选择不同的类型,这些类型大致可分为Activity类型、Task类型、壁纸类型。
在一切准备就绪之后我们就要建立resume环境了,这就是part3部分。
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java#resumeTopActivityInnerLocked part3 ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null) { //如果当前要启动的进程存在,需要注意的是如果是未启动过的activity,next.app是不会有值的 mWindowManager.setAppVisibility(next.appToken, true);//窗口设为可见 next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastStack == null ? null :lastStack.mResumedActivity; ActivityState lastState = next.state; mService.updateCpuStats(); //AMS端状态记录,将要resume的实例标记为对应状态 next.state = ActivityState.RESUMED; mResumedActivity = next; next.task.touchActiveTime(); mService.addRecentTaskLocked(next.task);//任务列表调整 mService.updateLruProcessLocked(next.app, true, null);//lru调整 updateLRUListLocked(next); mService.updateOomAdjLocked();//优先级调整 boolean notUpdated = true; if (mStackSupervisor.isFrontStack(this)) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, next.mayFreezeScreenLocked(next.app) ? next.appToken : null); if (config != null) { next.frozenBeforeDestroy = true; } notUpdated = !mService.updateConfigurationLocked(config, next, false, false); } if (notUpdated) { ActivityRecord nextNext = topRunningActivityLocked(null); if (nextNext != next) { mStackSupervisor.scheduleResumeTopActivities(); } if (mStackSupervisor.reportResumedActivityLocked(next)) { mNoAnimActivities.clear(); return true; } return false; } try { // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v( TAG, "Delivering results to " + next + ": " + a); next.app.thread.scheduleSendResult(next.appToken, a); } } if (next.newIntents != null) { next.app.thread.scheduleNewIntent(next.newIntents, next.appToken); } EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, System.identityHashCode(next), next.task.taskId, next.shortComponentName); next.sleeping = false; mService.showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP); next.clearOptionsLocked(); next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions); mStackSupervisor.checkReadyForSleepLocked(); if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { // Whoops, need to restart this activity! if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to " + lastState + ": " + next); next.state = lastState; if (lastStack != null) { lastStack.mResumedActivity = lastResumedActivity; } Slog.i(TAG, "Restarting because process died: " + next); if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && mStackSupervisor.isFrontStack(lastStack)) { mWindowManager.setAppStartingWindow( next.appToken, next.packageName, next.theme, mService.compatibilityInfoForPackageLocked(next.info.applicationInfo), next.nonLocalizedLabel, next.labelRes, next.icon, next.logo, next.windowFlags, null, true); } mStackSupervisor.startSpecificActivityLocked(next, true, false); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } // From this point on, if something goes wrong there is no way // to recover the activity. try { next.visible = true; completeResumeLocked(next); } catch (Exception e) { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception", true); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } next.stopped = false; } else {//如果当前进程时第一次启动,则调用startSpecificActivityLocked // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) {//打开启动窗口 mWindowManager.setAppStartingWindow( next.appToken, next.packageName, next.theme, mService.compatibilityInfoForPackageLocked( next.info.applicationInfo), next.nonLocalizedLabel, next.labelRes, next.icon, next.logo, next.windowFlags, null, true); } if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next); } if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next); mStackSupervisor.startSpecificActivityLocked(next, true, true); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }
在part3中根据next即栈顶元素的app成员是否为空,分别进入不同的逻辑。为什么要判断next.app呢,这个值有什么含义?
next.app主要用于判断next实例是否已经启动过,如果next没有启动过,则此处的app变量是不会有值的(赋值过程后续小节可见到)。
根据next.app值得不同分为两种情况:
从本文研究的角度来看,我们着重探究第一次启动时的情形。这个情形是通过调用ASS.startSpecificActivityLocked()完成的。
ASS.startSpecificActivityLocked()如下:
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) {//已有承载进程,只需启动对应activity即可 try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } } //承载进程还未启动,进入进程启动逻辑 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
在上述代码中,可以通过app及app.thread是否为空来判断ActivityRecord的承载进程是否已经创建,如果没有创建则还要进入进程创建流程,此流程在深入理解AMS之应用进程创建有讲解,有兴趣的读者可移步阅读。
此处我们假设进程已经创建完毕,则进入if中执行realStartActivityLocked()方法,见名知意这个方法才是真正启动Activity的地方。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mWindowManager.setAppVisibility(r.appToken, true);//窗口设置可见 //... r.app = app;//启动后赋值给r----关键点 app.waitingToKill = null; r.launchCount++;//启动次数 r.lastLaunchTime = SystemClock.uptimeMillis();//启动时间记录 int idx = app.activities.indexOf(r);//是否r加入到进程的activities中管理 if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true, null);//更新lru及优先级 mService.updateOomAdjLocked(); final ActivityStack stack = r.task.stack; try { if (app.thread == null) {//异常情形,承载进程为空 throw new RemoteException(); } //... app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP); app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);//通知client端launch,异步完成 //... } catch (RemoteException e) { //启动失败的清理过程 if (r.launchFailed) { mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } app.activities.remove(r); throw e; } r.launchFailed = false;//启动成功了 if (stack.updateLRUListLocked(r)) { Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } if (andResume) { // As part of the process of launching, ActivityThread also performs // a resume. stack.minimalResumeActivityLocked(r); } else { r.state = ActivityState.STOPPED; r.stopped = true; } if (isFrontStack(stack)) { mService.startSetupActivityLocked(); } mService.mServices.updateServiceConnectionActivitiesLocked(r.app); return true; }
在这个方法中,待启动的ActivityRecord®终于将自己与进程app关联了起来,但最显眼的无疑是通过app.thread调用client方法scheduleLaunchActivity()通知其调度目标Activity的启动。
在client端Activity的启动则通过ActivityThread内的H(实质上是Handler)将启动请求转发给主线程执行。其具体流程如下:
这个流程很清晰的说明了Activity在client端是如何创建,其生命周期是如何被调用到的。
如果对此还不甚了解的可移步至深入理解AMS之Activity了解client端Activity的创建过程,此处就不在赘述。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。