Launcher 启动
Launcher是桌面应用程序 基于8.0 ,所以他的启动与应用程序启动类似,区别在于
- launcher 是系统第一个程序,调用方法栈传递的参数多数为空
- 应用呢 则是通过点击Launcher启动,调用方法栈传递参数多数不为空,二者大体流程相同 都是启动新进程在启动首页
都是调用栈,只说调用栈的话,跟没说一样,所以这里先总结一下流程
如果不了解Activity栈管理相关类 可以参看Activity栈管理类
流程总结
在SystemServer启动文章中我们最后提到,SyetemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的ActivityManagerService会将Launcher启动起来。入口就在Ams的systemReady()里Launcher的启动
- 通过AMS启动launcher,这个过程在pms启动所有应用之前,所以此时栈中没有任何活动
- 要想启动launcher,就得先获取启动 launcher的Intent,并设置其在单独的一个栈中启动
- 这里通过packageManagerService,查询注册Category类型为HOME的Activity的相关信息并设置给Intent,这个Activiy就是Launcher
- 类型为Home 说明当 设备启动时 这是主活动,即显示的第一个活动,符合条件的这里应该就是Launcher了
- 设置Intent 在新的栈中启动
- 然后通过AMS启动该Activity
- 此时会先判断当前Activity所属进程是否存在
- 存在就直接启动Activity
- 不存在就 让AMS通知给zygote 先fork 一个进程,fork完了之后启动该进程
- 启动进程的时候会调用ActivityThread的main 函数 ,main函数里调用attach方法,通过Binder给AMS 设置一个AppLicationThread 类型的Binder对象,这样AMS 通过这个BInder对象就能和launcher 交互了
- 当进程启动完了之后AMS会检测 是否有等待进程启动后才执行的Activity
- 这里当launcher进程启动后,之前要启动的LauncherActivity 还没执行呢
- 所以这里就要去启动launcher 进程的主界面了,
- AMS通过调用AppLicationThread#scheduleLaunchActivity
- 这里就是通过Binder驱动最终执行到了ActivityThread#scheduleLaunchActivity
- 这个主界面(Launcher)本身就是一个Activity
- 为了方便我们就叫它LauncherActivity
上面就是整体流程总结了
- 其实从第三步开始也就是获取到Intent 之后,就是Android启动(七)应用进程的启动过程中的步骤了
可能有点乱,有问题欢迎指出来谢谢
代码分析
1.1 SystemServer#通过AMS管理启动launcher
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
traceLog.traceEnd(); // ActivityManagerStartApps
traceLog.traceEnd(); // PhaseActivityManagerReady
}
Ams.systemready
#StackSupervisor.resumeFocusedStackTopActivityLocked()
恢复当前焦点栈顶的Activity
boolean resumeFocusedStackTopActivityLocked() {
//调用该方法 传递参数全部为null
return resumeFocusedStackTopActivityLocked(null, null, null);
}
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack,
ActivityRecord target, ActivityOptions targetOptions) {
//刚启动launcher ActivityRecord是空的
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.isState(RESUMED)) {
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
取可运行的栈顶ActivityRecord 因为这里启动的是Launcher 在此之前没有其他活动,所以取值一定为null
此时调用了
ActivityStack#resumeTopActivityUncheckedLocked(null,null)
向下执行
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
result = resumeTopActivityInnerLocked(prev, options);
}
参数传递,继续执行 调用
ActivityStack#resumeTopActivityInnerLocked(null,null)
在这里 启动launcher 和启动其他应用开有了区别
启动launcher 参数都为空 会向下执行调用到
mStackSupervisor.resumeHomeStackTask(prev, reason)
启动其他应用时 因为launcher已经启动 栈中有活动所以参数不为空会调用
mStackSupervisor.startSpecificActivityLocked(next, true, true)
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//在此堆栈中查找要恢复的下一个最上面的活动,且是可恢复的
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
...
if (!hasRunningActivity) {
// 堆栈中没有剩余的活动,让我们看看其他地方。
// 应该是走到这里的代码 因为当前是启动launcher prev 是空的
// 后面所有方法中判断prev是空的代码都不会执行
return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
}
}
获取要恢复且允许恢复的活动
这里next 是空的,栈中此时什么都没有 launcher 还没启动 所以继续向下执行
又是一个参数传递区别就是多了个参数 String reason = “noMoreActivities”
ActivityStack# resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities")
private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
ActivityOptions options, String reason) {
if ((!mFullscreen || !isOnHomeDisplay()) && adjustFocusToNextFocusableStackLocked(reason)) {
//如过没有HomeStack 则移动到下一个栈FocusedStack
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
mStackSupervisor.getFocusedStack(), prev, null);
}
// Let's just start up the Launcher... 如果存在HomeStack,让我们启动Launcher
ActivityOptions.abort(options);
// 仅当主屏幕可见时才恢复Activity,这里英文直译过来就是这意思, 此时也就是Launcher
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, reason);
}
传递参数向下执行
ActivityStackSupervisor.resumeHomeStackTask(prev, reason)
此时
prev=null reason ="noMoreActivities"
;
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
if (prev != null) {
// 指示恢复任务堆栈中此类型下的任务。这一步暂时不用管,因为prev 是空的
prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
//将焦点activites 调整到HomeStack中栈顶的位置
mHomeStack.moveHomeStackTaskToTop();
//从HomeStack中获取活动 HomeActivity
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
//HomeActivity不为空,且未被finish 这是launcher,所以这里目前也不用考虑
if (r != null && !r.finishing) {
moveFocusableActivityStackToFrontLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
//通过AMS调用到了startHomeActivityLocked
return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
mService就是AMS 参数传递向下执行
AMS#startHomeActivityLocked(mCurrentUser, myReason)
1.2 获取启动Launcher的Intent
boolean startHomeActivityLocked(int userId, String reason) {
//1 获取Intnet-》创建一个CATEGORY_HOME类型的Intent
Intent intent = getHomeIntent();
//2 根据intent,通过resolveActivityInfo函数向PackageManagerService查询Category类型为HOME的Activity,并收集相关信息,这里我们假设只有系统自带的Launcher应用程序注册了HOME类型的Activity
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
//3 获取到之后给Intent 设置包名
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); //由于是第一次启动这个Launcher,接下来调用函数getProcessRecordLocked返回来的ProcessRecord值为null
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
//4 设置falg,启动在一个新的task
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
//启动新的Activity
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
//创建一个CATEGORY_HOME类型的Intent
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
//根据intent,通过resolveActivityInfo函数向PackageManagerService查询Category类型为HOME的Activity的相关信息,这里我们假设只有系统自带的Launcher应用程序注册了HOME类型的Activity
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
ActivityInfo ai = null;
ComponentName comp = intent.getComponent();
try {
if (comp != null) {
// Factory test.
ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
} else {
ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags, userId);
if (info != null) {
ai = info.activityInfo;
}
}
} catch (RemoteException e) {
// ignore
}
return ai;
}
- 上面方法就有点多了,主要作用就是获取要启动的Activity
- 调用
ActivityStarte#startHomeActivityLocked
传递参数继续启动launcher
- 创建一个Catery类型为HOME的Inent
- 利用Intent去PackageManagerService里去找Catery为Home的Activiy 并收集相关的信息,例如报名
- 获取到相关信息后,将包名设置给Intent,并指定当前Intent在新的栈中执行
ActivityStarter#startHomeActivityLocked;
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/,0 /*callingUid*/,
null /*callingPackage*/,
0 /*realCallingPid*/, 0 /*realCallingUid*/,
0 /*startFlags*/, null /*options*/,
false /*ignoreTargetSecurity*/,
false /*componentSpecified*/,
mLastHomeActivityStartRecord /*outActivity*/,
null /*container*/, null /*inTask*/,
"startHomeActivity: " + reason);
}
}
2.调用 ActivityStarter#startActivityLocked 进一步操作
接下来的步骤就和Android启动(七)应用进程的启动过程
中
2.2 调用startActivityLocked进一步操作` 大体相同了
区别在于一个是启动Launcher一个是其他应用程序
各方法因为启动launcher 和 其他应用程序参数不同,所以方法内执行代码会略有不同,但是从这开始方法调用栈就是相同的了
因此不在重复 大家可以去参考Android启动(七)应用进程的启动过程