Android桌面Launcher3的启动
SystemServer启动会在startBootstrapServices()方法中启动引导带服务,其中就包括PackageManagerService(这里判断了手机是否是工厂模式)。而包管理服务和接下来要分析的Launcher启动有很大关系。SystemServer启动流程参考《SystemServer系统服务启动》。
private void startBootstrapServices() {
...
try {
Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
...
}startOtherServices
接着在SystemServer的run()方法中调用startOtherServices(),单个方法目前见到比较长的总共1300余行。Android系统为了尽可能的提高执行速度,不会考虑各种方法的差分,代码简洁。毕竟是系统,效率优先。
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices() {
...
traceBeginAndSlog("InstallSystemProviders");
mActivityManagerService.installSystemProviders();
// Now that SettingsProvider is ready, reactivate SQLiteCompatibilityWalFlags
SQLiteCompatibilityWalFlags.reset();
traceEnd();
...
mActivityManagerService.systemReady(() -> {...}, BOOT_TIMINGS_TRACE_LOG)
...
}在该方法中调用了ActivityManagerService的systemReady(Runnable , TimingsTraceLog)方法,用的是Lambda表达式(低API系统源码还没有,看来Google与时俱进,重构源码),其实展开又有200多行代码,主要执行:
mActivityManagerService.systemReady(() -> {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
try {
//看来从这个时候开始Android开始监控NE异常
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
...
}给SystemServiceManager设置一个标记:为到目前为止已启动所有系统服务指定的引导阶段。
/**
* Starts the specified boot phase for all system services that have been started up to
* this point.
*
* @param phase The boot phase to start.
*/
public void startBootPhase(final int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
mCurrentPhase = phase;
...
}标记值定义在SystemService中:
/**
* After receiving this boot phase, services can broadcast Intents.
*/
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;systemReady
回到systemReady(Runnable , TimingsTraceLog)方法继续,定义在ActivityManagerService中:
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
traceLog.traceBegin("PhaseActivityManagerReady");
synchronized(this) {
if (mSystemReady) {
// If we're done calling all the receivers, run the next "boot phase" passed in
// by the SystemServer
if (goingCallback != null) {
goingCallback.run();
}
return;
}
...
}
...
mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
...
}除了执行传入的Runnable类型的Lambda表达式,还有两部重要的方法调用(参考《Android进阶解密》)。
resumeTopActivities
先来看第一个方法,mAtmInternal是ActivityTaskManagerInternal类型,ActivityTaskManagerInternal是抽象类型,真正的实现类是ActivityTaskManagerService中的静态内部类LocalService。实现了resumeTopActivities(boolean scheduleIdle)方法:
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized (mGlobalLock) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdleLocked();
}
}
}相比之前的源码有所变化,这部分代码本来是直接放在ActivityManagerService中的systemReady(Runnable , TimingsTraceLog)方法中调用。
mRootActivityContainer对象是RootActivityContainer类型,resumeFocusedStacksTopActivities()定义:
boolean resumeFocusedStacksTopActivities() {
return resumeFocusedStacksTopActivities(null, null, null);
}继续追resumeFocusedStacksTopActivities(null, null, null)方法,该方法的完整定义如下:
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {
return false;
}
boolean result = false;
//由于传入的是null,在新的系统版本中不会执行这里
if (targetStack != null && (targetStack.isTopStackOnDisplay()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
boolean resumedOnDisplay = false;
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord topRunningActivity = stack.topRunningActivityLocked();
if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
continue;
}
if (stack == targetStack) {
// Simply update the result for targetStack because the targetStack had
// already resumed in above. We don't want to resume it again, especially in
// some cases, it would cause a second launch failure if app process was dead.
resumedOnDisplay |= result;
continue;
}
if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
// Kick off any lingering app transitions form the MoveTaskToFront operation,
// but only consider the top task and stack on that display.
stack.executeAppTransition(targetOptions);
} else {
resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
}
}
if (!resumedOnDisplay) {
// In cases when there are no valid activities (e.g. device just booted or launcher
// crashed) it's possible that nothing was resumed on a display. Requesting resume
// of top activity in focused stack explicitly will make sure that at least home
// activity is started and resumed, and no recursion occurs.
final ActivityStack focusedStack = display.getFocusedStack();
if (focusedStack != null) {
//执行这里
focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
}
}
return result;
}注意,源码重构之后与以往的代码流程不同,之前是调用resumeFocusedStacksTopActivities(null, null, null)方法,传入的参数均为null,不会执行老版系统的逻辑,而是走下面的新增的代码段:
...
if (focusedStack != null) {
//执行这里
focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...focusedStack是ActivityStack类型,用来描述Activity堆栈,resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)方法
/**
* 确保堆栈中的置顶Activity已恢复resumed。
*
* @param prev 在暂停过程中先前恢复的活动; 可以为null,以从其他地方调用。
* @param options Activity 选项。
*
* @return 如果正在恢复某些操作,则返回true;否则,则返回false。
*
* NOTE: 直接调用此方法并不安全,因为它可能导致非焦点堆栈中的活动恢复。 使用
* RootActivityContainer#resumeFocusedStacksTopActivities恢复当前系统状态的正确活动。
*/
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
mInResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}方法中调又用了resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)方法,该方法定义如下:
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && !isAttached()) {
return false;
}
...
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else.
return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
}
...
}这里查看的是Android Q的系统源码,和以往的源码有很大不同,稍有不慎就追踪方法丢了。hasRunningActivity为false,表示已经没有Activity活动,也就是需要返回到桌面Launcher了,这里走的是resumeNextFocusableActivityWhenStackIsEmpty(...)方法:
private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev,
ActivityOptions options) {
final String reason = "noMoreActivities";
if (!isActivityTypeHome()) {
final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason);
if (nextFocusedStack != null) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display with no home
// stack.
return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack,
prev, null /* targetOptions */);
}
}
// If the current stack is a home stack, or if focus didn't switch to a different stack -
// just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home");
return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}在方法最后调用mRootActivityContainer对象,也就是RootActivityContainer 类中的resumeHomeActivity(...)方法
boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}
if (displayId == INVALID_DISPLAY) {
displayId = DEFAULT_DISPLAY;
}
final ActivityRecord r = getActivityDisplay(displayId).getHomeActivity();
final String myReason = reason + " resumeHomeActivity";
// Only resume home activity if isn't finishing.
if (r != null && !r.finishing) {
r.moveFocusableActivityToTop(myReason);
return resumeFocusedStacksTopActivities(r.getActivityStack(), prev, null);
}
return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}调用链->startHomeOnDisplay(int userId, String reason, int displayId)
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
false /* fromHomeKey */);
}调用链->startHomeOnDisplay(...)
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
boolean fromHomeKey) {
// Fallback to top focused display if the displayId is invalid.
if (displayId == INVALID_DISPLAY) {
displayId = getTopDisplayFocusedStack().mDisplayId;
}
Intent homeIntent = null;
ActivityInfo aInfo = null;
if (displayId == DEFAULT_DISPLAY) {
homeIntent = mService.getHomeIntent();
aInfo = resolveHomeActivity(userId, homeIntent);
} else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
aInfo = info.first;
homeIntent = info.second;
}
if (aInfo == null || homeIntent == null) {
return false;
}
if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) {
return false;
}
// Updates the home component of the intent.
homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
// Updates the extra information of the intent.
if (fromHomeKey) {
homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
}
// Update the reason for ANR debugging to verify if the user activity is the one that
// actually launched.
final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
aInfo.applicationInfo.uid) + ":" + displayId;
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
displayId);
return true;
}通过调用mService的getHomeIntent()方法获取桌面启动的Intent并且设置各种参数、flag。这里明显和之前的不同,之前该方法是在当前类中,现在移动到了ActivityTaskManagerService中去获取桌面的Intent。
最后通过调用mService的getActivityStartController()方法获取ActivityStartController对象mActivityStartController,调用ActivityStartController的startHomeActivity(...)方法启动桌面:
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
if (!ActivityRecord.isResolverActivity(aInfo.name)) {
// The resolver activity shouldn't be put in home stack because when the foreground is
// standard type activity, the resolver activity should be put on the top of current
// foreground instead of bring home stack to front.
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
}
options.setLaunchDisplayId(displayId);
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
final ActivityDisplay display =
mService.mRootActivityContainer.getActivityDisplay(displayId);
final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
if (homeStack != null && homeStack.mInResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}接下来就和启动普通的应用一样,通过Intent启动桌面应用。桌面到此随着系统的启动而启动完成!Launcher3系统APP启动加载桌面图标见《Launcher加载APP图标流程》
参考资料:
Android高级进阶>第二章 Android系统启动

