前言

由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章,希望这篇文章能帮你梳理清楚 “Launcher 启动流程”。

核心源码

关键类

路径

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()

// 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() 方法。

1.2 ActivityManagerService.systemReady()

// 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);

... ...

}

... ...

}

}

1.3 ActivityTaskManagerService.resumeTopActivities()

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

// 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();

}

}

}

... ...

}

}

1.4 RootActivityContainer.resumeFocusedStacksTopActivities()

// 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()

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

}

}

1.6 ActivityStack.resumeTopActivityInnerLocked()

// 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()

// 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);

}

}

1.8 RootActivityContainer.resumeHomeActivity()

// 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()

// 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 的:

2.1 Launcher.onCreate()

// 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);

}

... ...

}

}

2.2 LauncherAppState.setLauncher()

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

}

}

2.3 LauncherModel.initialize()

// 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() 方法!

2.4 LauncherModel.startLoader()

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

}

}

2.5 LauncherModel.startLoaderForResults()

// 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);

}

}

}

2.6 LoaderTask.run()

当 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 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 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 LoaderTask.loadAllApps()

// packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java

public class LoaderTask implements Runnable {

private List loadAllApps() {

final List profiles = mUserManager.getUserProfiles();

List allActivityList = new ArrayList<>();

// Clear the list of apps

mBgAllAppsList.clear();

for (UserHandle user : profiles) {

// Query for the set of apps

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

android launcher目录,【 Android 10 系统启动 】系列 -- Launcher(应用门户)相关推荐

  1. android+proguard目录,Android Proguard 详解

    一般的商业项目都需要对代码进行加密,Android提供了一种代码混淆方法,介绍如下: 一.简介 1.简介 混淆器通过删除从未用过的代码和使用晦涩名字重命名类.字段和方法,对代码进行压缩,优化和混淆.结 ...

  2. android proc目录,Android系统/proc目录详解

    /proc是一个虚拟文件系统,其下面的文件不是真实存在的,不占用实际存储空间. /proc/cmdline:显示内核启动的命令行. 示例: /proc/cpuinfo:显示系统cpu的信息. 示例: ...

  3. android+proguard目录,Android proguard问题:路径可能不是null或空字符串.路径=“空”...

    在设置之前,每件事情都很好 minifyEnabled true 和 shrinkResources true 设置这些值后,每当我运行项目时,我都会收到此错误: Information:Gradle ...

  4. Android——Framework目录分析及系统启动过程以及目录简介

    转自:http://blog.csdn.net/cubelee/article/details/7392552 1.目录树 /framework/base/api  /framework/base/a ...

  5. android packagemanagerservice目录,Android重学系列 PackageManagerService的启动与安装(下)

    前言 PMS installStage PMS中的安装步骤 void installStage(String packageName, File stagedDir, IPackageInstallO ...

  6. android 模拟器目录,Android 获取APP 文件目录 模拟器检测

    1. 获取app 目录 context.getFilesDir() Android 6.0的分身应用为了能与原应用区分开来,会更改手机的UserId,默认手机的UserId为0. 获取到的App应用位 ...

  7. android 得到目录,android 获取路径的获取

    1 内部存储 1.1 根目录( applicationDir): applicationDir/cache,通过Context.getCacheDir()获取. 应用文件目录:$application ...

  8. android device目录,Android源码下device目录的分析

    一般源码的编译前都会执行lunch命令,选择编译目标: source build/envsetup.sh lunch BUILD_BUILDTYPE 其中BUILDTYPE可以为user.userde ...

  9. android gradle 目录,Android Gradle:将目录列入文件

    我正在尝试将ANT构建中的任务转换为Gradle: ${assets} 我想我还没有完全掌握基本的Gradle概念,但这是我尝试过的: task indexAssets << { def ...

  10. android资产目录,android – 从非目录设备中的资产文件夹复制数据库

    我正在尝试从资产文件夹将数据库复制到设备.此代码在模拟器和根设备上正常工作.我只是想知道是否在无人看管的设备上创建任何问题,否则它会相同. private void StoreDatabase() { ...

最新文章

  1. 敏捷开发之道(二)极限编程XP
  2. eclipse常用快捷键排行
  3. Exchange环境搭建心得
  4. 代码的世界中,一个逻辑套着另外一个逻辑,如何让每一种逻辑在代码中都有迹可循?...
  5. SQL取最大值编码(自动编码)
  6. 【开发者成长】每个人都在编写草率代码
  7. sqlite3修改表内容python_python之sqlite3使用详解(转载)
  8. python3程序设计基础答案刘德山_!求大学python3程序设计基础答案 刘德山主编 网上找不到 希望大家帮帮忙...
  9. 吸顶灯怎么固定天花板_什么是吸顶灯?吸顶灯的材质和其与吊顶灯的区别分析...
  10. 28181之安装SPVMN的视频插件
  11. 编程语言-初学者常见的几个问题
  12. OpenGL学习之颜色
  13. nmds与mds的区别_数量生态学笔记||非约束排序|NMDS
  14. stc15流水灯c语言,STC89C52单片机流水灯
  15. 走进tensorflow第六步——拟合一元二次函数
  16. 趣图 | EDG牛逼!!!
  17. 洛谷 P4147 玉蟾宫
  18. android 播放多个音频文件,android – 如何同时播放多个ogg或mp3 ..?
  19. 群晖linux文件夹颜色红色,技术干货分享 | 群晖备份Linux文件夹~
  20. 如何设计一个API快速开发平台?

热门文章

  1. JVM重要知识点整理和学习
  2. 计算机应用基础Excel课程,《计算机应用基础》课程教学大纲
  3. vue微信浏览器安卓正常 ios config 报错 “errMsg“:“config:invalid问题
  4. 如何在网页中用上自己下载的字体
  5. 婚前需要聊清楚的问题
  6. Android 分析ANR和死锁(1)
  7. 快手切入蓝领招聘,58同城准备好了吗?
  8. USB2.0端口设备静电防护方案设计压敏电阻或TVS管
  9. IT软件工程师求职记,有点启发吧
  10. 使用PXI设备做IC的开短路测试