intent.addCategory(Intent.CATEGORY_HOME); //2
 }
 return intent;
 }注释1中创建了Intent,并将mTopAction和mTopData传入。mTopAction的值为Intent.ACTION_MAIN。
 注释2如果系统运行模式不是低级工厂模式则将intent的Category设置为Intent.CATEGORY_HOME。之后被启动的应用程序就是Launcher,因为Launcher的Manifest文件中的intent-filter标签匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。Launcher的Manifest文件如下所示。packages/apps/Launcher3/AndroidManifest.xml

 …
 <application
 …
 <activity
 android:name=“com.android.launcher3.Launcher”
 android:launchMode=“singleTask”
 android:clearTaskOnLaunch=“true”
 android:stateNotNeede

 d=“true”
 android:theme="@style/Theme"
 android:windowSoftInputMode=“adjustPan”
 android:screenOrientatinotallow=“nosensor”
 android:cnotallow=“keyboard|keyboardHidden|navigation”
 android:resumeWhilePausing=“true”
 android:taskAffinity=""
 android:enabled=“true”>







 …
ActivityManagerService的startHomeActivityLocked()的注释3就是启动符合条件的应用程序,即Launcher。
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
ActivityStarter#startHomeActivityLocked()
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
 startActivityLocked(null /caller/, intent, null /ephemeralIntent/,
 null /resolvedType/, aInfo, null /rInfo/, null /voiceSession/,
 null /voiceInteractor/, null /resultTo/, null /resultWho/,
 0 /requestCode/, 0 /callingPid/, 0 /callingUid/, null /callingPackage/,
 0 /realCallingPid/, 0 /realCallingUid/, 0 /startFlags/, null /options/,
 false /ignoreTargetSecurity/, false /componentSpecified/, null /outActivity/,
 null /container/, null /inTask/);
 if (mSupervisor.inResumeTopActivity) {
 // 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(); //1
 }
 }注释1调用的是scheduleResumeTopActivities()方法,这个方法其实是关于Activity的启动流程的逻辑了,这里我们就不详细说明了,关于Activity的启动流程可以参考我后面文章。
这样Launcher就会被启动起来,并执行它的onCreate函数。
Android应用程序安装
 Android系统在启动的过程中,Zygote进程启动SystemServer进程,SystemServer启动PackageManagerService服务,这个服务负责扫描系统中特定的目录,找到里面的应用程序文件,即以Apk为后缀的文件,然后对这些文件进解析(其实就是解析应用程序配置文件AndroidManifest.xml的过程),并从里面得到得到应用程序的相关信息,例如得到应用程序的组件Package、Activity、Service、Broadcast Receiver和Content Provider等信息,保存到PackageManagerService的mPackages、mActivities、mServices、mReceivers等成员变量(HashMap类型)中,得到应用程序的相关信息之后,完成应用程序的安装过程。这些应用程序只是相当于在PackageManagerService服务注册好了,如果我们想要在Android桌面上看到这些应用程序,还需要有一个Home应用程序(Android系统默认的Home应用程序就是Launcher),负责从PackageManagerService服务中把这些安装好的应用程序取出来,并以友好的方式在桌面上展现出来,例如以快捷图标的形式,接着往下看。
Launcher中应用图标显示流程
 从Launcher的onCreate函数开始分析。packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
Launcher#onCreate()
@Override
 protected void onCreate(Bundle savedInstanceState) {
 …
 LauncherAppState app = LauncherAppState.getInstance();//1
 mDeviceProfile = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ?
 app.getInvariantDeviceProfile().landscapeProfile
 : app.getInvariantDeviceProfile().portraitProfile;
 mSharedPrefs = Utilities.getPrefs(this);
 mIsSafeModeEnabled = getPackageManager().isSafeMode();
 mModel = app.setLauncher(this);//2
 …
 if (!mRestoring) {
 if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
 mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);//3
 } else {
 mModel.startLoader(mWorkspace.getRestorePage());
 }
 }
 …
 }注释1处获取LauncherAppState的实例。
 注释2处调用它的setLauncher函数并将Launcher对象传入。packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java
LauncherAppState#setLauncher()
LauncherModel setLauncher(Launcher launcher) {
 getLauncherProvider().setLauncherProviderChangeListener(launcher);
 mModel.initialize(launcher);//1
 mAccessibilityDelegate = ((launcher != null) && Utilities.ATLEAST_LOLLIPOP) ? new LauncherAccessibilityDelegate(launcher) : null;
 return mModel;
 }注释1处会调用LauncherModel的initialize函数。
packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
LauncherModel#initialize()
public void initialize(Callbacks callbacks) {
 synchronized (mLock) {
 unbindItemInfosAndClearQueuedBindRunnables();
 mCallbacks = new WeakReference(callbacks);
 }
 }在initialize函数中会将Callbacks,也就是传入的Launcher封装成一个弱引用对象。因此我们得知mCallbacks变量指的就是封装成弱引用对象的Launcher,这个mCallbacks后文会用到它。
再回到Launcher的onCreate函数,在注释3处调用了LauncherModel的startLoader函数:
LauncherModel#startLoader()
…
 @Thunk static final HandlerThread sWorkerThread = new HandlerThread(“launcher-loader”);//1
 static {
 sWorkerThread.start();
 }
 @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());//2
 …
 public void startLoader(int synchronousBindPage, int loadFlags) {
 InstallShortcutReceiver.enableInstallQueue();
 synchronized (mLock) {
 synchronized (mDeferredBindRunnables) {
 mDeferredBindRunnables.clear();
 }
 if (mCallbacks != null && mCallbacks.get() != null) {
 stopLoaderLocked();
 mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags); //3
 if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE && mAllAppsLoaded && mWorkspaceLoaded && !mIsLoaderTaskRunning) {
 mLoaderTask.runBindSynchronousPage(synchronousBindPage);
 } else {
 sWorkerThread.setPriority(Thread.NORM_PRIORITY);
 sWorker.post(mLoaderTask);//4
 }
 }
 }
 }注释1处创建了具有消息循环的线程HandlerThread对象。
 注释2处创建了Handler,并且传入HandlerThread的Looper。Hander的作用就是向HandlerThread发送消息。
 注释3处创建LoaderTask。
 注释4处将LoaderTask作为消息发送给HandlerThread 。LoaderTask类实现了Runnable接口。LoaderTask
private class LoaderTask implements Runnable {
 …
 public void run() {
 synchronized (mLock) {
 if (mStopped) {
 return;
 }
 mIsLoaderTaskRunning = true;
 }
 keep_running: {
 if (DEBUG_LOADERS) Log.d(TAG, “step 1: loading workspace”);
 loadAndBindWorkspace();//1
 if (mStopped) {
 break keep_running;
 }
 waitForIdle();
 if (DEBUG_LOADERS) Log.d(TAG, “step 2: loading all apps”);
 loadAndBindAllApps();//2
 }
 mContext = null;
 synchronized (mLock) {
 if (mLoaderTask == this) {
 mLoaderTask = null;
 }
 mIsLoaderTaskRunning = false;
 mHasLoaderCompletedOnce = true;
 }
 }
 …
 }Launcher是用工作区的形式来显示系统安装的应用程序的快捷图标,每一个工作区都是来描述一个抽象桌面的,它由n个屏幕组成,每个屏幕又分n个单元格,每个单元格用来显示一个应用程序的快捷图标。
 注释1处调用loadAndBindWorkspace函数用来加载工作区信息。
 注释2处的loadAndBindAllApps函数是用来加载系统已经安装的应用程序信息。LauncherModel#loadAndBindAllApps()
private void loadAndBindAllApps() {
 if (DEBUG_LOADERS) {
 Log.d(TAG, “loadAndBindAllApps mAllAppsLoaded=” + mAllAppsLoaded);
 }
 if (!mAllAppsLoaded) {
 loadAllApps();//1
 synchronized (LoaderTask.this) {
 if (mStopped) {
 return;
 }
 }
 updateIconCache();
 synchronized (LoaderTask.this) {
 if (mStopped) {
 return;
 }
 mAllAppsLoaded = true;
 }
 } else {
 onlyBindAllApps();
 }
 }如果系统没有加载已经安装的应用程序信息,则会调用注释1处的loadAllApps()函数。
LauncherModel#loadAllApps()
private void loadAllApps() {
 …
 final List apps = mLauncherApps.getActivityList(null, user); //1
 // Fail if we don’t have any apps
 // TODO: Fix this. Only fail for the current user.
 if (apps == null || apps.isEmpty()) {
 return;
 }
 // Create the ApplicationInfos
 for (int i = 0; i < apps.size(); i++) {
 LauncherActivityInfoCompat app = apps.get(i);
 // This builds the icon bitmaps.
 mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, quietMode)); //2
 }
 …
 // Huh? Shouldn’t this be inside the Runnable below?
 final ArrayList added = mBgAllAppsList.added;
 mBgAllAppsList.added = new ArrayList();mHandler.post(new Runnable() {
 public void run() {
 final long bindTime = SystemClock.uptimeMillis();
 final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
 if (callbacks != null) {
 callbacks.bindAllApplications(added); //3
 if (DEBUG_LOADERS) {
 Log.d(TAG, "bound " + added.size() + " apps in " + (SystemClock.uptimeMillis() - bindTime) + “ms”);
 }
 } else {
 Log.i(TAG, “not binding apps: no Launcher activity”);
 }
 }
 });
 …
 }注释1处获取所有已经安装的符合要求的Application信息。
 lications(added); //3
 if (DEBUG_LOADERS) {
 Log.d(TAG, "bound " + added.size() + " apps in " + (SystemClock.uptimeMillis() - bindTime) + “ms”);
 }
 } else {
 Log.i(TAG, “not binding apps: no Launcher activity”);
 }
 }
 });
 …
 }

注释1处获取所有已经安装的符合要求的Application信息。