原生分屏原理

分屏代码在AOSP其实老早就存在了,就一直没有开启而已,在6.0版本可以通过设置系统属性ro.build.type改为userdebug,并在开发者选项中开启多窗口模式,然后在最近任务上就会个按钮可以实现分屏。

通过adb命令也可以实现分屏

1
$ am task resize 25 0 720 1080 1920

在最近任务的调用链

1
2
3
4
5
6
RecentsActivity#onTaskResize ->
RecentsResizeTaskDialog#placeTasks ->
SystemServicesProxy#resizeTask ->
ActivityManagerNative#resizeTask ->
ActivityManagerService#resizeTask ->
ActivityStackSupervisor#resizeStackLocked

在am的调用链

1
2
3
4
Am#runTaskResize-> 
ActivityManagerNative#resizeTask ->
ActivityManagerService#resizeTask ->
ActivityStackSupervisor#resizeTaskLocked

ActivityStackSupervisor的实现

1
2
3
4
5
6
7
8
9
foundStackWithBounds ->
ActivityStackSupervisor#moveTaskToStackLocked ->
ActivityStackSupervisor#resizeStackLocked

ActivityStackSupervisor#moveTaskToStackLocked - >
WindowManagerService#moveTaskToStack

ActivityStackSupervisor#resizeStackLocked ->
WindowManagerService#resizeStack

WindowManagerService的实现

1
2
3
4
WindowManagerService#resizeStack ->
TaskStack#setBounds
TaskStack#resizeWindows ->
updateLayout??

看来让人心情不好的乱七八糟源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//---> frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
void resizeTaskLocked(TaskRecord task, Rect bounds) {
task.mResizeable = true;
final ActivityStack currentStack = task.stack;
if (currentStack.isHomeStack()) {
// Can't move task off the home stack. Sorry!
return;
}

// 找到给定区域相同的栈
final int matchingStackId = mWindowManager.getStackIdWithBounds(bounds);
if (matchingStackId != -1) {
// There is already a stack with the right bounds!
if (currentStack != null &&
currentStack.mStackId == matchingStackId) {
// Nothing to do here. Already in the right stack...
return;
}
// Move task to stack with matching bounds.
moveTaskToStackLocked(task.taskId, matchingStackId, true);
return;
}

// 栈里只有一个task,直接resize栈
if (currentStack != null && currentStack.numTasks() == 1) {
// Just resize the current stack since this is the task in it.
resizeStackLocked(currentStack.mStackId, bounds);
return;
}

// 挪动task到新的栈
// Create new stack and move the task to it.
final int displayId =
(currentStack != null && currentStack.mDisplayId != -1)
? currentStack.mDisplayId : Display.DEFAULT_DISPLAY;
ActivityStack newStack = createStackOnDisplay(getNextStackId(), displayId);

if (newStack == null) {
Slog.e(TAG, "resizeTaskLocked: Can't create stack for task=" + task);
return;
}
moveTaskToStackLocked(task.taskId, newStack.mStackId, true);
resizeStackLocked(newStack.mStackId, bounds);
}

分屏的核心是task跟bound,需要看一下task是怎么裂变的