hi,粉丝朋友们:
背景回顾
上一节已经对分屏的systemui端分析完成,systemui端主要干的事情还是以下几点: 1、分割线显示及分割上下屏区域的计算确定 2、对分屏roottask的位置放到最top 3、对上下屏幕task的启动 上面会涉及到task任何操作都需要包装到WindowContainerTransition中进行跨进程传递到systemserver端 这里其实也可以猜想出systemserver端也一样要有类似的3步操作。
b站免费视频教程讲解:
www.bilibili.com/video/BV1wj…
可以看看通过下图先有个大概的Task区域及结构的了解,其实这个如果前期学习过wms专题的话这个看起来也很简单,对上面3个步骤也非常好理解,甚至可以自己写出相关的代码
systemserver端的源码分析
这里跨进程会调用到WindowOrganizerController的applyTransaction
//frameworks/base/services/core/java/com/android/server/wm/WindowOrganizerController.java
private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition, @NonNull CallerInfo caller,
@Nullable Transition finishTransition) {
try {
Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
t.getChanges().entrySet().iterator();//获取transition的change部分,这里主要是我们的bounds这部分数据带有这个
while (entries.hasNext()) {//遍历每个Change
final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
//获取一个的change,而且取出change中包裹的具体WindowContainer,这里就一般是前面说过的上屏和下屏的对应Task,然后调用applyWindowContainerChange进行对应处理
int containerEffect = applyWindowContainerChange(wc, entry.getValue(),
t.getErrorCallbackToken());
}
// Hierarchy changes
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
if (hopSize > 0) {
final boolean isInLockTaskMode = mService.isInLockTaskMode();
for (int i = 0; i < hopSize; ++i) {
//这里就是对reorder和starTask的操作进行处理
effects |= applyHierarchyOp(hops.get(i), effects, syncId, transition,
isInLockTaskMode, caller, t.getErrorCallbackToken(),
t.getTaskFragmentOrganizer(), finishTransition);
}
}
//省略
}
总结一下systemserver端处理其实和systemui客户端一样的: 1、针对区域大小bounds类变化变成是Change类型,就对这个Change相关进行applyWindowContainerChange 2、针对task相关的2类操作,reorder和startTask两类都是包装成了HierarchyOp,对这类也是调用了applyHierarchyOp方法来进行处理
下面一一进行详细分析
Task区域大小bounds变化处理applyWindowContainerChange
private int applyWindowContainerChange(WindowContainer wc,
WindowContainerTransaction.Change c, @Nullable IBinder errorCallbackToken) {
//省略
//这里主要会调用applyChanges
int effects = applyChanges(wc, c, errorCallbackToken);
if (wc instanceof DisplayArea) {
effects |= applyDisplayAreaChanges(wc.asDisplayArea(), c);
} else if (wc instanceof Task) {
effects |= applyTaskChanges(wc.asTask(), c);
}
return effects;
}
private int applyChanges(WindowContainer<?> container,
WindowContainerTransaction.Change change, @Nullable IBinder errorCallbackToken) {
//最重要就是获取change的configration,因为bounds变化被包在了configration里面,这里再调用container的进行通知configration的变化
final Configuration c =
new Configuration(container.getRequestedOverrideConfiguration());
c.setTo(change.getConfiguration(), configMask, windowMask);
//Task容器调用这个onRequestedOverrideConfigurationChanged,代表根据传递过来的Configration作为自己的覆盖变化,即也就把对应的bounds设置给了Task
container.onRequestedOverrideConfigurationChanged(c);
return effects;
}
applyHierarchyOp的RootTask的reorder操作
private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
@NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
@Nullable ITaskFragmentOrganizer organizer, @Nullable Transition finishTransition) {
final int type = hop.getType();
//省略
switch (type) {
case HIERARCHY_OP_TYPE_REORDER:
case HIERARCHY_OP_TYPE_REPARENT: {
//首相要从hop中获取出WindowContainer
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
//省略
//调用sanitizeAndApplyHierarchyOp进行处理
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
break;
}
//省略
return effects;
}
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
WindowContainerTransaction.HierarchyOp hop) {
//这里获取task,其实就是RootTask,分屏最顶端那个taskId为4的
final Task task = container.asTask();
//省略
//需要把task进行位置放到所有task顶端位置
task.getParent().positionChildAt(
hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
task, false /* includingParents */);
//省略
//因为进行了task的位置变化,所以这里返回了一个会影响各个Activity生命周期的mask
return TRANSACT_EFFECTS_LIFECYCLE;
}
总体来看这个reorder相对来说操作还是比较简单,就是一个把RootTask放到第一位,即显示再最前面
applyHierarchyOp的startTask操作
private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
@NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
@Nullable ITaskFragmentOrganizer organizer, @Nullable Transition finishTransition) {
final int type = hop.getType();
switch (type) {
case HIERARCHY_OP_TYPE_LAUNCH_TASK: {
//这个launchOpts就是systemui传递时候的mainOptions和sideOptions,注意一下这个launchOpts里面有一个非常关键数据KEY_LAUNCH_ROOT_TASK_TOKEN,即stage.mRootTaskInfo.token
final Bundle launchOpts = hop.getLaunchOptions();
//注意这里是获取具体要启动app的taskId,不是上下分屏的id
final int taskId = launchOpts.getInt(
WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
//转化成SafeActivityOptions类型
final SafeActivityOptions safeOptions =
SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
//这里有个线程切换操作,而且还会等执行完成,所以核心是mService.mTaskSupervisor.startActivityFromRecents
waitAsyncStart(() -> mService.mTaskSupervisor.startActivityFromRecents(
caller.mPid, caller.mUid, taskId, safeOptions));
break;
}
}
}
上面可以简单看出就是对数据进行拆解出来,然后调用mService.mTaskSupervisor.startActivityFromRecents方法:
int startActivityFromRecents(int callingPid, int callingUid, int taskId,
SafeActivityOptions options) {
final Task task;
final int taskCallingUid;
final String callingPackage;
final String callingFeatureId;
final Intent intent;
final int userId;
//获取传递进来的options,通过它主要可以获取上下分屏的容器task(示意图第二层)
final ActivityOptions activityOptions = options != null
? options.getOptions(this)
: null;
boolean moveHomeTaskForward = true;
synchronized (mService.mGlobalLock) {
int activityType = ACTIVITY_TYPE_UNDEFINED;
if (activityOptions != null) {
activityType = activityOptions.getLaunchActivityType();
//省略
//这里主要通过taskId来获取一个Task,但是这个方法不仅仅只干了获取task的事情,还干了把taskId对应的Task进行reparent到新上下分屏的容器Task,这样实现了层级结构树上面的挂载完成,剩下就是一系列操作来保证Activiyt生命周期正常相关
task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
//获取了task之后进行相关的Activity操作
if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
&& task.getRootActivity() != null) {
//获取task的Activity
final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
try {
//这里非常关键的把task移动到前台,在里面会对focus和resume进行设置
mService.moveTaskToFrontLocked(null /* appThread */,
null /* callingPackage */, task.mTaskId, 0, options);
//省略
这里补充一下anyTaskForId的不起眼,但是非常重要一些特点
Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
@Nullable ActivityOptions aOptions, boolean onTop) {
final PooledPredicate p = PooledLambda.obtainPredicate(
Task::isTaskId, PooledLambda.__(Task.class), id);
Task task = getTask(p);//遍历获取Task
p.recycle();
if (task != null) {
if (aOptions != null) {//注意这里aOptions不为null,而且携带了task
//这里有调用了getOrCreateRootTask来获取targetRootTask
final Task targetRootTask =
getOrCreateRootTask(null, aOptions, task, onTop);
if (targetRootTask != null && task.getRootTask() != targetRootTask) {
final int reparentMode = onTop
? REPARENT_MOVE_ROOT_TASK_TO_FRONT : REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
task.reparent(targetRootTask, onTop, reparentMode, ANIMATE, DEFER_RESUME,
"anyTaskForId");
}
}
return task;
}
//省略
}
Task getOrCreateRootTask(@Nullable ActivityRecord r,
@Nullable ActivityOptions options, @Nullable Task candidateTask,
@Nullable Task sourceTask, boolean onTop,
@Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
// First preference goes to the launch root task set in the activity options.
if (options != null) {
//这里终于体现systemui传递的mainoptions作用了
final Task candidateRoot = Task.fromWindowContainerToken(options.getLaunchRootTask());
if (candidateRoot != null && canLaunchOnDisplay(r, candidateRoot)) {
return candidateRoot;//大家看这里就直接返回了options带的task
}
}
//省略
}
最后看看最重要的moveTaskToFrontLocked方法:
void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
@Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options) {
//省略
try {
final Task task = mRootWindowContainer.anyTaskForId(taskId);
//省略
ActivityOptions realOptions = options != null
? options.getOptions(mTaskSupervisor)
: null;
//这方法最为关键,寻找到task而且移到最前端
mTaskSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront",
false /* forceNonResizable */);
//开始启动StartingWindow
final ActivityRecord topActivity = task.getTopNonFinishingActivity();
if (topActivity != null) {
// We are reshowing a task, use a starting window to hide the initial draw delay
// so the transition can start earlier.
topActivity.showStartingWindow(true /* taskSwitch */);
}
//省略
}
下面看看这个关键方法findTaskToMoveToFront
/** This doesn't just find a task, it also moves the task to front. */
void findTaskToMoveToFront(Task task, int flags, ActivityOptions options, String reason,
boolean forceNonResizeable) {
//这里currentRootTask就是taskId =4的根task
Task currentRootTask = task.getRootTask();
//省略
final ActivityRecord r = task.getTopNonFinishingActivity();
//这里又调用到了关键moveTaskToFront方法
currentRootTask.moveTaskToFront(task, false /* noAnimation */, options,
r == null ? null : r.appTimeTracker, reason);
//省略
}
final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, boolean deferResume, String reason) {
//省略
//这里又关键调用到了顶部ActivityRecord的moveFocusableActivityToTop方法
// Set focus to the top running activity of this task and move all its parents to top.
top.moveFocusableActivityToTop(reason);
//省略
if (!deferResume) {//进行对应resume操作
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
//省略
}
下面看看最后关键方法moveFocusableActivityToTop
boolean moveFocusableActivityToTop(String reason) {
final Task rootTask = getRootTask();
//这里调用了rootTask把当前app的task移到最前
rootTask.moveToFront(reason, task);
// Report top activity change to tracking services and WM
if (mRootWindowContainer.getTopResumedActivity() == this) { //注意这里可能大家有疑问为啥都可以getTopResumedActivity到了,还需要设置,那是因为getTopResumedActivity可能真正ResumedActivity为null,但是会通过获取getFocusedActivity获取作为ResumedActivity
//这个操作关键,把ActivityRecord开始要变成Resumed状态了,这个就不展开,前面课程视频讲解
mAtmService.setResumedActivityUncheckLocked(this, reason);
}
return true;
}
@Nullable
ActivityRecord getTopResumedActivity() {
final Task focusedRootTask = getTopDisplayFocusedRootTask();
//getTopResumedActivity这个时候是为null哦
final ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity();
if (resumedActivity != null && resumedActivity.app != null) {
return resumedActivity;
}
// The top focused root task might not have a resumed activity yet - look on all displays in
// focus order.
//前面发现为null后就获取getFocusedActivity
return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
}
下面来个总结时序图: