因为源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,因此您也能够直接查看 《 Thinking in Android 》 来阅读这边文章,但愿这篇文章能帮你梳理清楚 “Launcher 启动流程”。java
关键类 | 路径 |
---|---|
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 |
Android 系统启动的最后一步是启动一个 Home 应用程序
,这个应用程序用来显示系统中已经安装的应用程序,咱们称呼这个应用程序为 Launcher
。android
应用程序 Launcher 在启动过程当中会请求 PackageManagerService 返回系统中已经安装的应用程序的信息
,并将这些信息封装成一个 快捷图标
列表显示在系统屏幕上,这样用户能够经过点击这些快捷图标来启动相应的应用程序了。session
// frameworks/base/services/java/com/android/server/SystemServer.java public final class SystemServer { private ActivityManagerService mActivityManagerService; private void startOtherServices() { ... ... mActivityManagerService.systemReady(() -> { // 调用 ActivityManagerService 的 systemReady() 方法 Slog.i(TAG, "Making services ready"); ... ... } ... ... } }
在 startOtherServices()
方法中,会调用 ActivityManagerService
的 systemReady()
方法。app
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public 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); ... ... } ... ... } }
resumeTopActivities()
方法由 ActivityTaskManagerService
的内部类 LocalService
实现。async
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java public 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(); } } } ... ... } }
// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java class 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; } }
// frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java class 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; } }
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java class 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); } ... ... } }
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java class 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); } }
// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java class 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); } }
// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java class 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
的:ide
// 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); } ... ... } }
// packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java public class LauncherAppState { LauncherModel setLauncher(Launcher launcher) { getLocalProvider(mContext).setLauncherProviderChangeListener(launcher); mModel.initialize(launcher); // 调用 initialize() 方法 return mModel; } }
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java public 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()
方法!oop
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java public 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; } }
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java public 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); } } }
当 LoaderTask
所描述的消息被处理时则会调用它的 run()
方法:源码分析
// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java public 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); } }
// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java public 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 的启动和应用加载的流程源码分析完毕。post