Android系统揭秘(四)-Launcher的启动

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

时序图:
img

与安卓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);
}

结下来的流程就可以参考Activity的启动了

小结

  • SystemServer中使用AMS启动Launcher
  • AMS调用 ActivityTaskManagerInternal的resumeTopActivities方法
  • 在 RootActivityContainer处理显示相关事情,然后使用ActivityStack处理了一些堆栈相关的工作,再回到RootActivityContainer
  • 使用 ActivityStartController启动LauncherActivity

建议看完源码,回头看下时序图,会比较清晰

Android 11

时序图:
img
Android 11的Launcher启动其实跟Android 10差不多

与Android 10一样在AMS调用resumeTopActivities

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

}

不同的是,Android11使用了RootWindowContainer而不是RootActivityContainer来启动Launcher

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {

RootWindowContainer mRootWindowContainer;
final class LocalService extends ActivityTaskManagerInternal {
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized (mGlobalLock) {
// 10为mRootActivityContainer
mRootWindowContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdle();
}
}
}
}
}

后面的代码也有些差异,当ActivityDisplay里面不存在ActivityStack,即focusedStack == null 的时候,Android 11直接启动resumeHomeActivity方法

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.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) {
result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
} else if (targetStack == null) {
result |= resumeHomeActivity(null /* prev */, “no-focusable-task”,
display.getDefaultTaskDisplayArea());
}
}
}

return result;
}

这段流程与安卓10差不多,使用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);
}

兜兜转转,最终又回到RootWindowContainer的resumeHomeActivity方法

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean resumeHomeActivity(ActivityRecord prev, String reason,
TaskDisplayArea taskDisplayArea) {
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}

if (taskDisplayArea == null) {
taskDisplayArea = getDefaultTaskDisplayArea();
}

final ActivityRecord r = taskDisplayArea.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.getRootTask(), prev, null);
}
return startHomeOnTaskDisplayArea(mCurrentUser, myReason, taskDisplayArea,
false /* allowInstrumenting /, false / fromHomeKey */);
}

走到startHomeOnTaskDisplayArea方法(这个方法名跟之前不一样的)

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowInstrumenting, boolean fromHomeKey) {

Intent homeIntent = null;
ActivityInfo aInfo = null;
if (taskDisplayArea == getDefaultTaskDisplayArea()) {
homeIntent = mService.getHomeIntent();
aInfo = resolveHomeActivity(userId, homeIntent);
} else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
aInfo = info.first;
homeIntent = info.second;
}
if (aInfo == null || homeIntent == null) {
return false;
}

if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
return false;
}

// 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);
mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, “startHomeActivity”);
}

final String myReason = reason + “:” + userId + “:” + UserHandle.getUserId(
aInfo.applicationInfo.uid) + “:” + taskDisplayArea.getDisplayId();
// 启动HomeActivity mService 是ActivityTaskManagerService
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
taskDisplayArea);
return true;
}

最后RootWindowContainer又使用ActivityStartControlle来启动,后面流程基本与Android 10 一样了,不(懒)做(得)赘(说)述(了)

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

}

frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
TaskDisplayArea taskDisplayArea) {

mSupervisor.beginDeferResume();
final ActivityStack homeStack;
try {
// Make sure home stack exists on display area.
homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
} finally {
mSupervisor.endDeferResume();
}

mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
if (homeStack.mInResumeTopActivity) {
mSupervisor.scheduleResumeTopActivities();
}
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

image

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

[外链图片转存中…(img-v8DGMM1J-1713275072149)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 14
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值