==
上文Android系统启动概述分析了系统的启动,而启动的最后一步则是启动Launcher
什么是Launcher
如果你不知道什么Launcher的话,看到上面的页面应该就知道了,Launcher其实就是桌面。
桌面上的图标则是启动器,我们可以通过这些图标启动对应的应用程序。
Launcher的启动
因为各版本差别比较大,所以分开几个版本分析,不想看源码的同学可以直接滑文末看总结
Android 8,9
先过下整体时序图:
上文中我们知道Zygote进程启动了SystemServer进程, 而启动 Launcher的入口为AMS的systemReady方法, 在SystemServer的startOtherServices方法中被调用
如下所示:
frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private void run() {
…
// Start services.
try {
t.traceBegin(“StartServices”);
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
} catch (Throwable ex) {
Slog.e(“System”, “******************************");
Slog.e(“System”, " Failure starting system services”, ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
…
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
…
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, “Making services ready”);
t.traceBegin(“StartActivityManagerReadyPhase”);
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
…
}
…
}
}
看下systemReady的实现
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
…
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
traceLog.traceEnd(); // ActivityManagerStartApps
traceLog.traceEnd(); // PhaseActivityManagerReady
}
可知下面交给了ActivityStackSupervisor
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!readyToResume()) {
return false;
}
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
…
return false;
}
后面则是调用ActivityStack的resumeTopActivityUncheckedLocked方法
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don’t even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
…
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
…
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, “prevFinished”);
…
}
ActivityStack最终又调用了ActivityStackSupervisor的resumeHomeStackTask方法
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
…
mHomeStack.moveHomeStackTaskToTop();
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
// Only resume home activity if isn’t finishing.
if (r != null && !r.finishing) {
moveFocusableActivityStackToFrontLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
最后回到AMS,调用AMS的startHomeActivityLocked方法
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
boolean startHomeActivityLocked(int userId, String reason) {
//测试模式
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don’t try to start anything.
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));
// Don’t do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + “:” + userId + “:” + resolvedUserId;
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
这里启动了一个Intent,可以通过源码看到Launcher的清单配置
packages/apps/Launcher3/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
最终使用ActivityStarter启动Launcher,后面的流程可参考Activity的启动
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
mLastHomeActivityStartResult = 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/, mLastHomeActivityStartRecord /outActivity/,
null /inTask/, "startHomeActivity: " + reason);
…
}
小结
- SystemServer中使用AMS启动Launcher
- AMS调用 ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法
- 经历了ActivityStackSupervisor -> ActivityStack -> ActivityStackSupervisor ->AMS 的流程,期间处理了一些堆栈相关的工作,最终又回到了AMS
- AMS调用 ActivityStarter启动Launcher Activity
建议看完源码,回头看下时序图,会比较清晰
Android 10
时序图:
与安卓8一样从AMS启动,不同的是安卓10交给了一个ActivityTaskManagerInternal类型的服务mAtmInternal
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@VisibleForTesting
public ActivityTaskManagerInternal mAtmInternal;
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
…
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
…
t.traceBegin(“resumeTopActivities”);
mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
t.traceEnd();
…
}
我们看下mAtmInternal哪来的,LocalServices类里面是一个类与对象的键值对, 而ActivityTaskManagerInternal是一个抽象类,我们找到它的唯一继承类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) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
…
}
}
}
}
这里调用了RootActivityContainer的resumeFocusedStacksTopActivities方法
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities() {
return resumeFocusedStacksTopActivities(null, null, null);
}
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
…
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
…
if (!resumedOnDisplay) {
final ActivityStack focusedStack = display.getFocusedStack();
if (focusedStack != null) {
focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
}
}
return result;
}
老环节,接下来又走到了ActivityStack
frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
…
result = resumeTopActivityInnerLocked(prev, options);
…
}
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);
}
…
}
private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev,
ActivityOptions options) {
…
return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
resumeNextFocusableActivityWhenStackIsEmpty 方法又调用了RootActivityContainer的resumeHomeActivity
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
…
return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting /,
false / fromHomeKey */);
}
startHomeOnDisplay里面取到了homeIntent,然后我们看最后一行:
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
boolean fromHomeKey) {
…
Intent homeIntent = null;
ActivityInfo aInfo = null;
if (displayId == DEFAULT_DISPLAY) {
homeIntent = mService.getHomeIntent();
aInfo = resolveHomeActivity(userId, homeIntent);
} else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
aInfo = info.first;
homeIntent = info.second;
}
…
// 启动HomeActivity mService 是ActivityTaskManagerService
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
displayId);
return true;
}
mService.getActivityStartController()获取到的是ActivityStartController
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private ActivityStartController mActivityStartController;
ActivityStartController getActivityStartController() {
return mActivityStartController;
}
public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController,
Looper looper) {
…
mActivityStartController = new ActivityStartController(this);
…
}
最后使用ActivityStartController来启动Launcher
frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
TaskDisplayArea taskDisplayArea) {
…
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
…
if (homeStack.mInResumeTopActivity) {
mSupervisor.scheduleResumeTopActivities();
}
}
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)
![](https://img-blog.csdnimg.cn/img_convert/89f57a11d4e4293b62e59ba7ac301d05.jpeg)
学习宝典
对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。
不论遇到什么困难,都不应该成为我们放弃的理由!
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-uX6b03uZ-1711611190468)]
【算法合集】
[外链图片转存中…(img-8q8kaaf6-1711611190468)]
【延伸Android必备知识点】
[外链图片转存中…(img-GJzGow3z-1711611190468)]
【Android部分高级架构视频学习资源】