1.Launcher概述
Android系统启动的最后一步是启动一个Home应用程序,这个应用程序用来显示系统中已经安装的应用程序,这个Home应用程序就叫做Launcher。应用程序Launcher在启动过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。
2.启动过程
SyetemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的ActivityManagerService会将Launcher启动起来。
frameworks\base\services\java\com\android\server\SystemServer.java的startOtherServices方法
mActivityManagerService.systemReady(() -> { Slog.i(TAG, "Making services ready"); t.traceBegin("StartActivityManagerReadyPhase"); mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
systemReady方法中调用了frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerInternal.java的resumeTopActivities方法,ActivityTaskManagerInternal是抽象类,ActivityTaskManagerService 实现了对应的抽象方法。
t.traceBegin("resumeTopActivities"); mAtmInternal.resumeTopActivities(false /* scheduleIdle */); t.traceEnd();
frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override public void resumeTopActivities(boolean scheduleIdle) { synchronized (mGlobalLock) { mRootWindowContainer.resumeFocusedStacksTopActivities(); if (scheduleIdle) { mStackSupervisor.scheduleIdle(); } } }
调用RootWindowContainer的resumeFocusedStacksTopActivities方法
frameworks\base\services\core\java\com\android\server\wm\RootWindowContainer.java
boolean resumeFocusedStacksTopActivities() { return resumeFocusedStacksTopActivities(null, null, null); }
boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (!mStackSupervisor.readyToResume()) { return false; } boolean result = false; if (targetStack != null && (targetStack.isTopStackInDisplayArea() || getTopDisplayFocusedStack() == targetStack)) { result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { boolean resumedOnDisplay = false; final DisplayContent display = getChildAt(displayNdx); for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) { final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx); for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final ActivityStack stack = taskDisplayArea.getStackAt(sNdx); final ActivityRecord topRunningActivity = stack.topRunningActivity(); 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 (taskDisplayArea.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) { result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } else if (targetStack == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } } return result; }
调用ActivityStack的resumeTopActivityUncheckedLocked函数,ActivityStack对象是用来描述Activity堆栈的,
frameworks\base\services\core\java\com\android\server\wm\ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mInResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivity(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); } } finally { mInResumeTopActivity = false; } return result; }
调用resumeTopActivityInnerLocked方法
if (!hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); }
resumeNextFocusableActivityWhenStackIsEmpty方法调用
mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
boolean resumeHomeActivity(ActivityRecord prev, String reason, TaskDisplayArea taskDisplayArea) { if (!mService.isBooting() && !mService.isBooted()) { // Not ready yet! return false; } if (taskDisplayArea == null) { taskDisplayArea = getDefaultTaskDisplayArea(); } final ActivityRecord r = taskDisplayArea.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.getRootTask(), prev, null); } return startHomeOnTaskDisplayArea(mCurrentUser, myReason, taskDisplayArea, false /* allowInstrumenting */, false /* fromHomeKey */); }
最后调用startHomeOnTaskDisplayArea方法
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting, boolean fromHomeKey) { // Fallback to top focused display area if the provided one is invalid. if (taskDisplayArea == null) { final ActivityStack stack = getTopDisplayFocusedStack(); taskDisplayArea = stack != null ? stack.getDisplayArea() : getDefaultTaskDisplayArea(); } Intent homeIntent = null; ActivityInfo aInfo = null; if (taskDisplayArea == getDefaultTaskDisplayArea()) { homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea); aInfo = info.first; homeIntent = info.second; } if (aInfo == null || homeIntent == null) { return false; } if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, 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); mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "startHomeActivity"); } homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason); // 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) + ":" + taskDisplayArea.getDisplayId(); mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);//启动launcher return true; }
frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
mService.getHomeIntent();
mService为ActivityTaskManagerService
这个被启动的应用程序就是Launcher,因为Launcher的Manifest文件中的intent-filter标签匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。
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; }
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);//启动launcher
ActivityStartController getActivityStartController() { return mActivityStartController; }
frameworks\base\services\core\java\com\android\server\wm\ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea) { 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); } final int displayId = taskDisplayArea.getDisplayId(); options.setLaunchDisplayId(displayId); options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken .toWindowContainerToken()); // The home activity will be started later, defer resuming to avoid unneccerary operations // (e.g. start home recursively) when creating home stack. mSupervisor.beginDeferResume(); final ActivityStack homeStack; try { // Make sure home stack exists on display area. homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP); } finally { mSupervisor.endDeferResume(); } mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) .setOutActivity(tmpOutRecord) .setCallingUid(0) .setActivityInfo(aInfo) .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; if (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(); } }
这样,应用程序Launcher就会被启动起来,并执行它的onCreate函数。