因爲源碼分析的代碼量比較大,大部分博客網站的內容顯示頁面都比較窄,顯示出來的效果都異常醜陋,因此您也能夠直接查看 《 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