android launcher目录,【 Android 10 系统启动 】系列 -- Launcher(应用门户)
前言
由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 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(应用门户)相关推荐
- android+proguard目录,Android Proguard 详解
一般的商业项目都需要对代码进行加密,Android提供了一种代码混淆方法,介绍如下: 一.简介 1.简介 混淆器通过删除从未用过的代码和使用晦涩名字重命名类.字段和方法,对代码进行压缩,优化和混淆.结 ...
- android proc目录,Android系统/proc目录详解
/proc是一个虚拟文件系统,其下面的文件不是真实存在的,不占用实际存储空间. /proc/cmdline:显示内核启动的命令行. 示例: /proc/cpuinfo:显示系统cpu的信息. 示例: ...
- android+proguard目录,Android proguard问题:路径可能不是null或空字符串.路径=“空”...
在设置之前,每件事情都很好 minifyEnabled true 和 shrinkResources true 设置这些值后,每当我运行项目时,我都会收到此错误: Information:Gradle ...
- Android——Framework目录分析及系统启动过程以及目录简介
转自:http://blog.csdn.net/cubelee/article/details/7392552 1.目录树 /framework/base/api /framework/base/a ...
- android packagemanagerservice目录,Android重学系列 PackageManagerService的启动与安装(下)
前言 PMS installStage PMS中的安装步骤 void installStage(String packageName, File stagedDir, IPackageInstallO ...
- android 模拟器目录,Android 获取APP 文件目录 模拟器检测
1. 获取app 目录 context.getFilesDir() Android 6.0的分身应用为了能与原应用区分开来,会更改手机的UserId,默认手机的UserId为0. 获取到的App应用位 ...
- android 得到目录,android 获取路径的获取
1 内部存储 1.1 根目录( applicationDir): applicationDir/cache,通过Context.getCacheDir()获取. 应用文件目录:$application ...
- android device目录,Android源码下device目录的分析
一般源码的编译前都会执行lunch命令,选择编译目标: source build/envsetup.sh lunch BUILD_BUILDTYPE 其中BUILDTYPE可以为user.userde ...
- android gradle 目录,Android Gradle:将目录列入文件
我正在尝试将ANT构建中的任务转换为Gradle: ${assets} 我想我还没有完全掌握基本的Gradle概念,但这是我尝试过的: task indexAssets << { def ...
- android资产目录,android – 从非目录设备中的资产文件夹复制数据库
我正在尝试从资产文件夹将数据库复制到设备.此代码在模拟器和根设备上正常工作.我只是想知道是否在无人看管的设备上创建任何问题,否则它会相同. private void StoreDatabase() { ...
最新文章
- 敏捷开发之道(二)极限编程XP
- eclipse常用快捷键排行
- Exchange环境搭建心得
- 代码的世界中,一个逻辑套着另外一个逻辑,如何让每一种逻辑在代码中都有迹可循?...
- SQL取最大值编码(自动编码)
- 【开发者成长】每个人都在编写草率代码
- sqlite3修改表内容python_python之sqlite3使用详解(转载)
- python3程序设计基础答案刘德山_!求大学python3程序设计基础答案 刘德山主编 网上找不到 希望大家帮帮忙...
- 吸顶灯怎么固定天花板_什么是吸顶灯?吸顶灯的材质和其与吊顶灯的区别分析...
- 28181之安装SPVMN的视频插件
- 编程语言-初学者常见的几个问题
- OpenGL学习之颜色
- nmds与mds的区别_数量生态学笔记||非约束排序|NMDS
- stc15流水灯c语言,STC89C52单片机流水灯
- 走进tensorflow第六步——拟合一元二次函数
- 趣图 | EDG牛逼!!!
- 洛谷 P4147 玉蟾宫
- android 播放多个音频文件,android – 如何同时播放多个ogg或mp3 ..?
- 群晖linux文件夹颜色红色,技术干货分享 | 群晖备份Linux文件夹~
- 如何设计一个API快速开发平台?
热门文章
- JVM重要知识点整理和学习
- 计算机应用基础Excel课程,《计算机应用基础》课程教学大纲
- vue微信浏览器安卓正常 ios config 报错 “errMsg“:“config:invalid问题
- 如何在网页中用上自己下载的字体
- 婚前需要聊清楚的问题
- Android 分析ANR和死锁(1)
- 快手切入蓝领招聘,58同城准备好了吗?
- USB2.0端口设备静电防护方案设计压敏电阻或TVS管
- IT软件工程师求职记,有点启发吧
- 使用PXI设备做IC的开短路测试