【Android framework】am命令启动Activity流程
源码基于Android 4.4。
am start -W -n com.dfp.test/.TEstActivity
-W:等目标Activity启动后才返回
-n:用于设置Intent的Component
Am.java->run()->runStart()
——intent = makeIntent();
——intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
——mAm.startActivityAndWait(); //调用AMS处理startActivityAndWait
ActivityManagerService.java->startActivityAndWait(......)
//一般情况下Activity是由另一个应用发起的,此时IApplicationThread是应用和AMS交互的通道,也可算是调用进程的表示。am不是一个应用进程,所以IApplicationThread caller变量为null。
//requestCode为调用者发送的代码,具体含义由调用者解释。如果该值大于0,AMS会保存该值并通过onActivityResult返回给调用者。用于记录启动了哪个Activity的功能
————mMainStack.startActivityMayWait() //4.4中为mStackSupervisor.startActivityMayWait()
//Activity调度需要ActivityStack,是核心角色
//Activity对应管理类为ActivityRecord表示
//Task由一组Activity组成,用于完成一组特定的功能,对应管理类为TaskRecord表示。同一时间只有以个Task可以显示在前台,其余在后台。Task中只有最前端的Activity可以运行,其他会停止运行。以前很多应用,一个Task里的Activity都在同一个Application中,现在很多Task可以由不同Application的Activity组成。
//ActivityStack只保存ActivityStack不保存TaskRecord。直接管理ActivityStack,弱化了Task的概念。提高了效率,降低了结构清晰度。
ActivityStackSupervisor.java->startActivityMayWait()
4.4中新增了mStackSupervisor,部分函数从ActivityStack移到ActivityStackSupervisor,ActivityStack的一些调用会使用mActivityStackSupervisor进行,反之亦是。
对 Task 的操作,AMS 使用 mStackSupervisor 来进行。对于 Acitivity 的操作,AMS 使用 ActivityStack 来进行。
系统中只有两个 ActivityStack,一个是 mHomeStack,用于保存 Launcher 的Activity,另一个是 mFocusedStack,用于保存非 Launcher 的 App 的 Activity。
第一阶段:获取资源和变量
——intnent.getcomponent(); //查找Component,如果Component存在,则省去匹配搜索Intent(本例不为null)
——aInfo = resolveActivity(); //查询满足条件的ActivityInfo,在resolveActivity内部与uPKMS交互
——callingPid = Binder.getCallingPid(); //获取调用进程的PID,UID
——callingUid = Binder.getCallingUid();
第二阶段:启动Activity
——int res = startActivityLocked(); //启动Activity
————sourceRecord = isInAnyStackLocked(); //发送请求的ActivityRecord
————resultRecord = sourceRecord.resultTo; //接收启动结果的ActivityRecord。通常是同一个
————callerApp = mService.getRecordForAppLocked(caller); //如果caller不为空,需要找到对应的ProcessRecord,从而获得PID/VID
————launchFlags = intent.getFlags(); //获取启动Flags
————mService.checkPermission(); //检查权限
————mService.checkComponentPermission();
————mService.mController.activityStarting(); //(Monkey测试)交给回调对象处理,由他判断是否能继续后面的行程
————ActivityRecord r = new ActivityRecord(); //创建一个ActivityRecord对象
————mService.checkAppSwitchAllowedLocked(callingPid, callingUid); //检查调用进程是否有权限切换Application,如果没有则储存起来,有机会再启动它。将保存到mPendingActivityLaunchers中
————mService.checkAppSwitchAllowedLocked(callingPid, callingUid); //检查调用进程是否有权限切换Application,如果没有则储存起来,有机会再启动它。将保存到mPendingActivityLaunchers中
//没有权限切换意味着当前显示的应用进行了stopAppSwitches。这个方法会使其他Task的Activity无法显示在前端,但同一个Task中的Activity则不受制约。取消禁止切换使用resumeAppSwitches。为了防止使用者不调用resumeAppSwitches,系统设置了一个超时时间(5s),超时则自动resume。在resume中不会处理Pending起来的Activity,但超时会触发处理Pending的Activity。
————mService.doPendingActivityLaunchesLockedd(false); //启动处于Pending状态的Activity,即之前由于上一步被禁止切换而保存起来的请求。它将先于本次需要启动的Activity处理
————startActivityUncheckedLocked(); //处理启动请求,为新建的ActivityRecord找到合适的Task
——————//单独分析
——mService.updateConfigureationLocked(); //如果configuration发生变化,则调用AMS更新configuration
第三阶段:处理结果
——outResult.result = res; //设置启动结果
——if (res == IActivityManager.START_SUCCESS) mService.wait(); //如果启动成功了,等待启动结果。为什么res返回成功还要等待呢?因为Activity要运行在一个新的应用i进程中,就必须等待那个应用进程正常启动并处理相关请求。注意,只有am设置了-W选项,才会进入wait状态。
——if (err != START_SUCCRSS) sendActivityResultLocked(); return err; //如果有问题,则返回错误
startActivityUncheckedLocked()
第一阶段
int launchFlags = intent.getFlags();
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; //根据sourceRecord.launchMode判断是否需要设置FLAG_ACTIVITY_NEW_TASK。
第二阶段
boolean addingToTask = false;
boolean movedHome = false;
ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE ? findTaskLocked(r) : findActivityLocked(intent, r.info);
r.task = intentActivity.task; //ActivityRecord r
targetStack = intentActivity.task.stack;
//找到合适的Task做一些ActivityStack中的处理
第三阶段
boolean newTask = false;
boolean keepCurTransition = false;
//增加一个Task,如果前面设置了FLAG_ACTIVITY_NEW_TASK
mService.curTask++; //当前Task数量加一