android10 wms源码梳理launcher启动-2
在上一节中已经梳理了系统Ui绘制
应用视图

`DecorView` 是 Android 应用窗口的最顶层视图(root view)
ViewStub` 初始时不会加载占用资源,它仅在调用 `inflate()` 方法时才会被替换为实际的视图。 - 一旦 `ViewStub` 被替换或扩展,`ViewStub` 本身将被从视图层次中移除,不再存在
`ContentParent` 通常指的是 `DecorView` 中用于容纳应用内容视图的部分。它通常是 `DecorView` 的子视图,用于承载通过 `setContentView()` 设置的布局。
以 launcher 应用程序为例
launcher启动
SystemServer 拉起各种server 其中就有ActivityManagerService
public final class SystemServer implements Dumpable {private void run() { ...其他省略 t.traceBegin("StartServices"); //启动一些核心的services startBootstrapServices(t); startCoreServices(t); //启动一些其他的service 比如systemUI,lanuncer startOtherServices(t); startApexServices(t); }private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) { ....省略 //开启StartActivityManager t.traceBegin("StartActivityManager"); // 创建一个ActivityTaskManagerService-->10版本以后引入主要用于分担ActivityManagerService部分功能 ActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); //开始创建 mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); t.traceEnd();
} }private void startOtherServices(@NonNull TimingsTraceAndSlog t) {//告诉可以运用第三方的代码activity mActivityManagerService.systemReady(() -> { } //这里会添加一个默认的home视图 //最终调用RootActivityContainer.setWindowManager t.traceBegin("SetWindowManagerService"); mActivityManagerService.setWindowManager(wm); t.traceEnd(); //上一章关联的服务 t.traceBegin("StartSystemUI"); try { startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } }
ActivityManagerService
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ...其他省略 if (bootingSystemUser) { //开启houme //mAtmInternal的实现是ActivityTaskManagerInternal.LocalService mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); } }
ActivityTaskManagerService
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
//实现类
final class LocalService extends ActivityTaskManagerInternal {
@Override
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
//开始调用home
return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
}
}}
//下述获取homeintent会用到
Intent getHomeIntent() {
//mTopAction=Intent.ACTION_MAIN
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Launcher` 被视为 `Home` Activity,它是通过 `Intent` 来匹配 `ACTION_MAIN` 和 `CATEGORY_HOME` 的 `Activity`,这也是为什么点击 `Home` 按钮会回到主屏幕
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME); }
return intent;
}
}
RootActivityContainer
RootActivityContainer` 是 Android 系统中一个负责管理和组织所有 `Activity` 栈的核心类。它是 `ActivityTaskManager` 相关模块的一部分,在 Android 10 及其之前的版本中起到了组织和管理多窗口、多任务的关键作用。
不过,随着 Android 系统架构的演进,Android 10 之后的版本将 `RootActivityContainer` 重构为 `RootWindowContainer`
boolean startHomeOnAllDisplays(int userId, String reason) { boolean homeStarted = false; //判断activity显示列表 //在上述的初始化中就已经添加了一个默认home视图 for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { final int displayId = mActivityDisplays.get(i).mDisplayId; homeStarted |= startHomeOnDisplay(userId, reason, displayId); } return homeStarted; }//最后调用
这将在可以基于displayId进行系统装饰的显示器上启动主页活动-默认显示器始终使用主主页组件。
对于次要显示器,主页活动必须具有类别Secondary_home,然后解析
*根据下面列出的优先级。
*-如果未设置默认主页,请始终使用配置中定义的次要主页。
*-使用当前选定的主要家庭活动。
*-使用与当前选定的主要家庭活动相同的包中的活动。
*如果有多个匹配的活动,请使用第一个。boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { //如果id无效则重新过去 if (displayId == INVALID_DISPLAY) { displayId = getTopDisplayFocusedStack().mDisplayId; } //开始初始化home Intent homeIntent = null; ActivityInfo aInfo = null; //判断home显示 if (displayId == DEFAULT_DISPLAY) { //上述有详细获取代码 homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); //判断次要显示 //说明可以不用默认的显示,可以切换二级home显示 } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId); aInfo = info.first; homeIntent = info.second; } if (aInfo == null || homeIntent == null) { return false; } if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) { return false; } //开始配置 homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); if (fromHomeKey) { homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); } final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + displayId; //启动home mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,displayId); }//最终调用的是ActivityStartController.startHomeActivity ->在调用ActivityStarter.execute
->在调用ActivityStarter.startActivity
ActivityStarter
private int startActivity(....) { 1. **日志记录与初始化**: - 记录活动启动日志。 - 初始化一些变量,包括`verificationBundle`、`callerApp`、`userId`等。 2. **调用者处理**: - 如果`caller`不为空,尝试获取调用者的进程控制器。如果找不到,记录警告并返回权限拒绝错误。 3. **启动条件检查**: - 根据Intent的Flags和当前状态检查是否可以继续启动。如果有转发结果的请求,处理相关的Activity记录。 4. **有效性检查**: - 检查Intent和`ActivityInfo`是否有效,确保能够找到可以处理Intent的Activity。 5. **语音会话处理**: - 如果在语音会话中启动,检查目标Activity是否支持语音类别 ..省略以上代码 //6.**权限检查**: - 检查启动Activity的权限,包括防火墙和政策检查,如果未通过,发送结果并返回错误 boolean abort = !mSupervisor.checkStartAnyActivityPermission(....); //7.选项合并**: - 处理活动选项,合并选项包,并处理任何待定的远程动画 ActivityOptions checkedOptions = options != null ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; //8.**权限审核**: - 如果目标Activity需要权限审核,则启动审核活动并设置相应的Intent if (aInfo != null) { if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { ...省略 }} //9.启动临时应用**: - 如果有临时应用(ephemeral app),则创建并启动临时安装器 if (rInfo != null && rInfo.auxiliaryInfo != null) { ...省略 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } //10.**创建Activity记录**: - 创建一个`ActivityRecord`对象,保存关于新活动的信息ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); //11.应用切换检查**: - 如果新活动不是来自当前已恢复的活动,检查是否允许应用切换 if (voiceSession == null && (stack.getResumedActivity() == null || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) { ...省略 } //- 记录应用切换的状态 mService.onStartActivitySetDidAppSwitch(); //执行任何待处理的活动启动,确保它们在适当的时机被处理 mController.doPendingActivityLaunches(false); //启动活动的调用->跳转最终调用startActivityUnchecked final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity); //向活动指标记录器发送活动已启动的通知mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);return res;
}
ActivityStarter
private int startActivityUnchecked() {
//设置初始状态,这一步也会确定是否要将 Activity 放入后台任务队列或创建新任务
setInitialState();
//这些方法的主要作用是计算与启动标志(`LaunchFlags`)相关的行为,比如启动是否会创建新的任务栈或是否要复用已存在的任务
computeLaunchingTaskFlags();
//则是确定启动来源(`sourceRecord`)的任务栈,通常是在用户从另一个 Activity 发起启动的情况
computeSourceStack();
//根据flags决定是新建还是复用
ActivityRecord reusedActivity = getReusableIntentActivity();
if (reusedActivity != null) {
...省略
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
if (top != null) {
//如果复用了某个 Activity 并且传入了新的 Intent,该方法负责将新的 Intent 传递给复用的 Activity,从而触发 `onNewIntent` 的调用
deliverNewIntent(top);
}
...省略
//启动acitivity,
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
}
ActivityStack
//主要做了两部分, 把activity插入栈顶, 创建窗口 void startActivityLocked(.....) { //mLaunchTaskBehind在后台启动任务栈 //allowMoveToFront允许切换到前台 if (!r.mLaunchTaskBehind && allowMoveToFront && (taskForIdLocked(taskId) == null || newTask)) { //插入到栈顶到 insertTaskAtTop(rTask, r); } //创建窗口显示 if (r.mAppWindowToken == null) { r.createAppWindowToken(); } //设置为前台 task.setFrontOfTask();if ((!isHomeOrRecentsStack() || numActivities() > 0) && allowMoveToFront) { ..处理动画和窗口过渡 } else { //第一个acitivity不走动画 ActivityOptions.abort(options); } }到此为止,activity就插入到栈顶后续不会在做操作,而activity启动是插入到栈顶后,其他方法触发栈顶显示activity操作
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)