Launcher启动流程

Launcher概述

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

Launcher启动

在分析 SystemServer启动流程AMS启动流程 中可以知道,在SystemServer的最后,会调用 startHomeActivityLocked 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
boolean startHomeActivityLocked(int userId, String reason) {
// 第一步
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
return false;
}
//第二步
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
//第三步
if (app == null || app.instrumentationClass == null) {/
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}

return true;
}

分为三个核心步骤:

  1. mFactoryTest代表系统的运行模式,系统的运行模式分为三种,分别是非工厂模式、低级工厂模式和高级工厂模式,mTopAction则用来描述第一个被启动Activity组件的Action,它的值为Intent.ACTION_MAIN。因此注释1的代码意思就是mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低级工厂模式)并且mTopAction=null时,直接返回false

  2. getHomeIntent函数中创建了Intent,并将mTopAction和mTopData传入。mTopAction的值为Intent.ACTION_MAIN,并且如果系统运行模式不是低级工厂模式则将intent的Category设置为Intent.CATEGORY_HOME

  3. 判断符合Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME的应用程序是否已经启动,如果没启动则调用 startHomeActivityLocked 方法启动该应用程序。
    这个被启动的应用程序就是Launcher,因为Launcher的Manifest文件中的intent-filter标签匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME

根Activity组件的启动流程

这个流程涉及到三个进程,假设我们要启动的Activity为 A

  1. AMS进程
  2. Launcher进程
  3. A所在的进程

点击app的大致流程

那么点击app的大致流程为:

  1. Launcher向AMS发送一个启动 A组件 的进程通信请求
  2. AMS首先将 A组件 的信息保存下来,再向Launcher组件发送一个进入中止状态的的进程通信请求
  3. Launcher组件进入中止状态后,向AMS发送一个已进入中止状态的进程通信请求
  4. AMS继续执行启动 A组件 的操作
  5. AMS发现运行 A组件 的进程不存在,就会通知 zygote 创建一个新的进程
  6. 新的进程启动完毕后,新进程会发送一个启动完成的进程通信请求
  7. AMS将保存下来的A组件信息发送给新的进程,新的进程启动 A组件

Launcher向AMS发送一个启动A组件的进程通信请求

首先,用户点击app就是走 Launcher 这个应用程序的代码.

点击某一个app,会调用Launcher的的onClick并调用函数 startActivitySafely

Intent

在click中, final Intent intent = ((ShortcutInfo) tag).intent; 是获取Launcher组件的Intent信息

这个Intent信息包括什么呢?

是我们在 AndroidManifest 中进行配置的信息

比如:

1
2
action="android.intent.action.MAIN"
category="android.intent.category.LAUNCHER"

这些数据信息在应用被安装的时候就会被一个叫PMS服务记录,PMA就是包信息管理服务,和AMS一样运行在system_server中,因此想要获取Launcher组件的Intent信息只要和PMS查询即可

同时注意,Launcher会 addFlags 为 FLAG_ACTIVITY_NEW_TASK,表示在一个新任务中启动

Launcher和AMS是两个不同的进程,用的通信方式是Binder

Launcher 发送消息给 AMS ,Binder中的接口为 IActivityManager,客户端为 ActivityManagerProxy,服务端为 AMS

1
2
3
public class ActivityManagerService extends IActivityManager.Stub{}

class ActivityManagerProxy implements IActivityManager{}

注意
ActivityManagerProxy 的 startActivity函数有一个caller参数,它的类型是IApplicationThread,是一个Binder,服务端为ApplicationThread,客户端为 IApplicationThread.Stub.asInterface(whoThread)

下篇讲解Launcher启动在AMS中的逻辑