“桌面展示” -- Launcher

核心源码(Android_10.0)

关键类 路径
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

1
2
3
4
5
6
7
8
9
10
11
12
// frameworks/base/services/java/com/android/server/SystemServer.java

private ActivityManagerService mActivityManagerService;

private void startOtherServices() {
... ...
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
... ...
}
... ...
}

1.2 ActivityManagerService.systemReady

startOtherServices 函数中,会调用 ActivityManagerServicesystemReady 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@VisibleForTesting
public ActivityTaskManagerInternal mAtmInternal;

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
traceLog.traceBegin("PhaseActivityManagerReady");
... ...

synchronized (this) {
... ...
// 调用 resumeTopActivities 方法,这是一个抽象方法
mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
}

... ...
}

1.3 ActivityTaskManagerService.resumeTopActivities

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdleLocked();
}
}
}
... ...
}

}

1.4 RootActivityContainer.resumeFocusedStacksTopActivities

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
27
28
29
// 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;
}
... ...
}

1.5 ActivityStack.resumeTopActivityUncheckedLocked

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
27
28
29
30
31
// 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;
// 调用 resumeTopActivityInnerLocked 方法
result = resumeTopActivityInnerLocked(prev, options);

final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}

return result;
}

... ...
}

1.6 ActivityStack.resumeTopActivityInnerLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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);
}
... ...
}

... ...
}

1.7 ActivityStack.resumeNextFocusableActivityWhenStackIsEmpty

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
27
28
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

class ActivityStack extends ConfigurationContainer {
... ...

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

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
27
28
29
30
// 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);
}

... ...
}

1.9 RootActivityContainer.startHomeOnDisplay

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 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);
// Updates the extra information of the intent.
if (fromHomeKey) {
homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
}
// Update the reason for ANR debugging to verify if the user activity is the one that
// actually launched.
final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
aInfo.applicationInfo.uid) + ":" + displayId;
// 启动 Launcher
/*
ActivityStartController getActivityStartController() {
return mActivityStartController;
}
*/
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
displayId);
return true;
}

... ...
}

二、应用图标显示流程

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

2.1 Launcher.onCreate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

@Override
protected void onCreate(Bundle savedInstanceState) {
... ...
LauncherAppState app = LauncherAppState.getInstance(this);
... ...
mModel = app.setLauncher(this);
... ...
if (!mModel.startLoader(currentScreen)) {
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

1
2
3
4
5
6
7
// packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java

LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
return mModel;
}

2.3 LauncherModel.initialize

1
2
3
4
5
6
7
8
9
10
11
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java

/**
* 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

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
27
28
29
30
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java

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) {
loaderResults.bindWorkspace();
loaderResults.bindAllApps();
loaderResults.bindDeepShortcuts();
loaderResults.bindWidgets();
return true;
} else {
// 调用 startLoaderForResults 方法
startLoaderForResults(loaderResults);
}
}
}
return false;
}

2.5 LauncherModel.startLoaderForResults

1
2
3
4
5
6
7
8
9
10
11
12
13
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java

@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 方法:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 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);
}
... ...
}

2.7 loadAllApps

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
27
28
29
30
31
32
33
34
35
36
// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java

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);
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 的启动和应用加载的流程源码分析完毕。