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

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

ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}

小结

  • 除了RootActivityContainer的工作替换给了RootWindowContainer,其他流程与安卓10变化不大

Launcher 启动Activity

Launcher通过startActivitySafely方法启动Activity packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {

// 新任务栈启动
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {

startActivity(intent, optsBundle);

} catch (ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, “Unable to launch. tag=” + item + " intent=" + intent, e);
}
return false;
}

总结

最后

一线互联网Android面试题含详解(初级到高级专题)

这些题目是今年群友去腾讯、百度、小米、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。并且大多数都整理了答案,熟悉这些知识点会大大增加通过前两轮技术面试的几率

如果设置门槛,很多开发者朋友会因此错过这套高级架构资料,错过提升成为架构师的可能。这就失去了我们的初衷;让更多人都能通过高效高质量的学习,提升自己的技术和格局,升职加薪。

最后送给大家一句话,望共勉,永远不要放弃自己的梦想和追求;

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

、小米、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。并且大多数都整理了答案,熟悉这些知识点会大大增加通过前两轮技术面试的几率

[外链图片转存中…(img-VToRZoe9-1714447257157)]

如果设置门槛,很多开发者朋友会因此错过这套高级架构资料,错过提升成为架构师的可能。这就失去了我们的初衷;让更多人都能通过高效高质量的学习,提升自己的技术和格局,升职加薪。

最后送给大家一句话,望共勉,永远不要放弃自己的梦想和追求;

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值