# 前言

由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章,希望这篇文章能帮你梳理清楚 “Launcher 启动流程”


# 核心源码

关键类 路径
SystemServer.java frameworks/base/services/java/com/android/server/SystemServer.java
ActivityManagerService.java frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityStack.java frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
ActivityTaskManagerService.java frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
RootActivityContainer.java frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
Launcher.java packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
LauncherModel.java packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
LauncherAppState.java packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java
LoaderTask.java packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java

一、Launcher 启动流程

Android 系统启动的最后一步是启动一个 Home 应用程序,这个应用程序用来显示系统中已经安装的应用程序,我们称呼这个应用程序为 Launcher

应用程序 Launcher 在启动过程中会请求 PackageManagerService 返回系统中已经安装的应用程序的信息,并将这些信息封装成一个 快捷图标 列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序了。

1.1 SystemServer.startOtherServices()

// frameworks/base/services/java/com/android/server/SystemServer.javapublic final class SystemServer {    private ActivityManagerService mActivityManagerService;    private void startOtherServices() {        ... ...        mActivityManagerService.systemReady(() -> {    // 调用 ActivityManagerService 的 systemReady() 方法            Slog.i(TAG, "Making services ready");            ... ...        }        ... ...    }}

startOtherServices() 方法中,会调用 ActivityManagerServicesystemReady() 方法。

1.2 ActivityManagerService.systemReady()

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapublic class ActivityManagerService extends IActivityManager.Stub        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {    @VisibleForTesting    public ActivityTaskManagerInternal mAtmInternal;    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {        ... ...        synchronized (this) {            ... ...            // 调用 resumeTopActivities() 方法,这是一个抽象方法            mAtmInternal.resumeTopActivities(false /* scheduleIdle */);            mUserController.sendUserSwitchBroadcasts(-1, currentUserId);            ... ...        }        ... ...    }}

1.3 ActivityTaskManagerService.resumeTopActivities()

resumeTopActivities() 方法由 ActivityTaskManagerService 的内部类 LocalService 实现。

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.javapublic class ActivityTaskManagerService extends IActivityTaskManager.Stub {    RootActivityContainer mRootActivityContainer;    final class LocalService extends ActivityTaskManagerInternal {        ... ...        @Override        public void resumeTopActivities(boolean scheduleIdle) {            synchronized (mGlobalLock) {                // 调用 RootActivityContainer 的 resumeFocusedStacksTopActivities() 方法                mRootActivityContainer.resumeFocusedStacksTopActivities();                if (scheduleIdle) {                    mStackSupervisor.scheduleIdleLocked();                }            }        }        ... ...    }}

1.4 RootActivityContainer.resumeFocusedStacksTopActivities()

// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.javaclass RootActivityContainer extends ConfigurationContainer        implements DisplayManager.DisplayListener {    boolean resumeFocusedStacksTopActivities() {        return resumeFocusedStacksTopActivities(null, null, null);    }    boolean resumeFocusedStacksTopActivities(            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {        ... ...        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {            boolean resumedOnDisplay = false;            final ActivityDisplay display = mActivityDisplays.get(displayNdx);            ... ...            if (!resumedOnDisplay) {                final ActivityStack focusedStack = display.getFocusedStack();                if (focusedStack != null) {                    // 调用 resumeTopActivityUncheckedLocked() 方法                    focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);                }            }        }          return result;    }}

1.5 ActivityStack.resumeTopActivityUncheckedLocked()

// frameworks/base/services/core/java/com/android/server/wm/ActivityStack.javaclass ActivityStack extends ConfigurationContainer {    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);  // 调用 resumeTopActivityInnerLocked() 方法            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);            if (next == null || !next.canTurnScreenOn()) {                checkReadyForSleep();            }        } finally {            mInResumeTopActivity = false;        }          return result;    }}

1.6 ActivityStack.resumeTopActivityInnerLocked()

// frameworks/base/services/core/java/com/android/server/am/ActivityStack.javaclass ActivityStack extends ConfigurationContainer {    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {        ... ...        if (!hasRunningActivity) {            // There are no activities left in the stack, let's look somewhere else.            return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);        }        ... ...    }}

1.7 ActivityStack.resumeNextFocusableActivityWhenStackIsEmpty()

// frameworks/base/services/core/java/com/android/server/am/ActivityStack.javaclass ActivityStack extends ConfigurationContainer {    protected final RootActivityContainer mRootActivityContainer;    private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev,            ActivityOptions options) {        final String reason = "noMoreActivities";          if (!isActivityTypeHome()) {            final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason);            if (nextFocusedStack != null) {                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");        // 调用 resumeHomeActivity() 方法        return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);    }}

1.8 RootActivityContainer.resumeHomeActivity()

// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.javaclass RootActivityContainer extends ConfigurationContainer        implements DisplayManager.DisplayListener {    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);        }        // 调用 startHomeOnDisplay() 方法        return startHomeOnDisplay(mCurrentUser, myReason, displayId);    }}

1.9 RootActivityContainer.startHomeOnDisplay()

// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.javaclass RootActivityContainer extends ConfigurationContainer        implements DisplayManager.DisplayListener {    ActivityTaskManagerService mService;    boolean startHomeOnDisplay(int userId, String reason, int displayId) {        return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,                false /* fromHomeKey */);    }    boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,            boolean fromHomeKey) {        ... ...          // Updates the home component of the intent.        homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));        homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);        ... ...        // 启动 Launcher        mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,                displayId);        return true;    }}

二、应用图标显示流程

接下来我们看看 Launcher 是如何加载并显示所有已安装 Apk 的:

2.1 Launcher.onCreate()

// packages/apps/Launcher3/src/com/android/launcher3/Launcher.java/** * Default launcher application. */public class Launcher extends BaseDraggingActivity implements LauncherExterns,       LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate,       InvariantDeviceProfile.OnIDPChangeListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        ... ...        LauncherAppState app = LauncherAppState.getInstance(this);        ... ...        mModel = app.setLauncher(this);    // 调用 setLauncher() 方法        ... ...        if (!mModel.startLoader(currentScreen)) {    // 见 2.4            if (!internalStateHandled) {                // If we are not binding synchronously, show a fade in animation when                // the first page bind completes.                mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);            }        } else {            // Pages bound synchronously.            mWorkspace.setCurrentPage(currentScreen);            setWorkspaceLoading(true);        }        ... ...    }}

2.2 LauncherAppState.setLauncher()

// packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.javapublic class LauncherAppState {    LauncherModel setLauncher(Launcher launcher) {        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);        mModel.initialize(launcher);    // 调用 initialize() 方法        return mModel;    }}

2.3 LauncherModel.initialize()

// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.javapublic class LauncherModel extends BroadcastReceiver        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {    /**     * Set this as the current Launcher activity object for the loader.     */    public void initialize(Callbacks callbacks) {        synchronized (mLock) {            Preconditions.assertUIThread();            mCallbacks = new WeakReference<>(callbacks);        }    }}

initialize 方法中会将 Callbacks(也就是传入的 Launcher)封装成一个 弱引用对象,因此我们得知 mCallbacks 变量指的就是封装成弱引用对象的 Launcher

重新回到 oncreate() 函数,有个 startLoader() 方法!

2.4 LauncherModel.startLoader()

// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.javapublic class LauncherModel extends BroadcastReceiver        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {    public boolean startLoader(int synchronousBindPage) {        // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems        InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);        synchronized (mLock) {            // Don't bother to start the thread if we know it's not going to do anything            if (mCallbacks != null && mCallbacks.get() != null) {                final Callbacks oldCallbacks = mCallbacks.get();                // Clear any pending bind-runnables from the synchronized load process.                mUiExecutor.execute(oldCallbacks::clearPendingBinds);                // If there is already one running, tell it to stop.                stopLoader();                LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,                        mBgAllAppsList, synchronousBindPage, mCallbacks);                if (mModelLoaded && !mIsLoaderTaskRunning) {                    // Divide the set of loaded items into those that we are binding synchronously,                    // and everything else that is to be bound normally (asynchronously).                    loaderResults.bindWorkspace();                    // For now, continue posting the binding of AllApps as there are other                    // issues that arise from that.                    loaderResults.bindAllApps();                    loaderResults.bindDeepShortcuts();                    loaderResults.bindWidgets();                    return true;                } else {                    startLoaderForResults(loaderResults);    // 调用 startLoaderForResults() 方法                }            }        }        return false;    }}

2.5 LauncherModel.startLoaderForResults()

// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.javapublic class LauncherModel extends BroadcastReceiver        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {   @Thunk static final Handler sWorker = new Handler(mWorkerLooper);    public void startLoaderForResults(LoaderResults results) {        synchronized (mLock) {            stopLoader();            mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);            // Always post the loader task, instead of running directly (even on same thread) so            // that we exit any nested synchronized blocks            sWorker.post(mLoaderTask);        }    }}

2.6 LoaderTask.run()

LoaderTask 所描述的消息被处理时则会调用它的 run() 方法:

// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.javapublic class LoaderTask implements Runnable {    public void run() {        synchronized (this) {            // Skip fast if we are already stopped.            if (mStopped) {                return;            }        }        try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {            TraceHelper.partitionSection(TAG, "step 1.1: loading workspace");            loadWorkspace();    // 加载工作区信息            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");            mResults.bindWorkspace();            ... ...            // second step            TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");            List<LauncherActivityInfo> allActivityList = loadAllApps();    // 加载系统已经安装的应用程序信息            TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");            verifyNotStopped();            mResults.bindAllApps();            ... ...            // third step            TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts");            loadDeepShortcuts();            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts");            mResults.bindDeepShortcuts();            ... ...            // fourth step            TraceHelper.partitionSection(TAG, "step 4.1: loading widgets");            List<ComponentWithLabel> allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null);            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets");            mResults.bindWidgets();            ... ...            transaction.commit();        } catch (CancellationException e) {            // Loader stopped, ignore            TraceHelper.partitionSection(TAG, "Cancelled");        }        TraceHelper.endSection(TAG);    }}

2.7 LoaderTask.loadAllApps()

// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.javapublic class LoaderTask implements Runnable {    private List<LauncherActivityInfo> loadAllApps() {        final List<UserHandle> profiles = mUserManager.getUserProfiles();        List<LauncherActivityInfo> allActivityList = new ArrayList<>();        // Clear the list of apps        mBgAllAppsList.clear();        for (UserHandle user : profiles) {            // Query for the set of apps            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);            // Fail if we don't have any apps            // TODO: Fix this. Only fail for the current user.            if (apps == null || apps.isEmpty()) {                return allActivityList;            }            boolean quietMode = mUserManager.isQuietModeEnabled(user);            // Create the ApplicationInfos            for (int i = 0; i < apps.size(); i++) {                LauncherActivityInfo app = apps.get(i);                // This builds the icon bitmaps.                mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);            }            allActivityList.addAll(apps);        }        if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {            // get all active sessions and add them to the all apps list            for (PackageInstaller.SessionInfo info :                    mPackageInstaller.getAllVerifiedSessions()) {                mBgAllAppsList.addPromiseApp(mApp.getContext(),                        PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info));            }        }        mBgAllAppsList.added = new ArrayList<>();        return allActivityList;    }}

自此,Launcher 的启动和应用加载的流程源码分析完毕。

更多相关文章

  1. EventThread线程对VSync的接收
  2. android MediaCodec ACodec OMX tips
  3. Android判断现在所处界面是否为home主桌面的方法
  4. Android获得内/外置存储卡路径的方法
  5. android 获取网络数据,回传到本地用TextView显示乱码问题解决方法
  6. Android进程间通信(二):通过AIDL介绍Binder的工作机制
  7. Android实现ListView异步加载图片的方法
  8. 在android中使用USB进行通信的4种方法
  9. Android(安卓)重写物理返回键

随机推荐

  1. android.util包下的几个集合类 SparseArr
  2. Android异步加载获取网络数据(图片)
  3. android hook方法收集及选择优化
  4. Android系统板子上电启动流程
  5. 编译Android内核时遇到的jdk问题
  6. Android布局——帧布局、表格布局、网格
  7. Android动态权限(兼容6.0以下和魅族手机方
  8. Unity3D之移植学习笔记:移植到Android平台
  9. android 破解软件
  10. Android中,怎么优雅的生成代码?