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操作

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值