目录
- 场景
场景
当类似上面的Task状态,我们自定义的三个按钮,启动新的Activity的时候,并没有去设置需要launche的task。
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.dialer",
"com.android.dialer.main.impl.MainActivity"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
但是直接启动后windowmode和task都是展示正常的,并没有像普通launcher启动App后的全屏展示。
经过源码查看,其实就是会直接使用sourceTask的往上寻找mCreatedByOrganizer的Task
TaskDisplayArea.java
// If a task is launching from a created-by-organizer task, it should be launched into the
// same created-by-organizer task as well. Unless, the candidate task is already positioned
// in the another adjacent task.
if (sourceTask != null) {
Task launchTarget = sourceTask.getCreatedByOrganizerTask();
if (launchTarget != null && launchTarget.getAdjacentTaskFragment() != null) {
if (candidateTask != null) {
final Task candidateRoot = candidateTask.getCreatedByOrganizerTask();
if (candidateRoot != null && candidateRoot != launchTarget
&& launchTarget == candidateRoot.getAdjacentTaskFragment()) {
launchTarget = candidateRoot;
}
}
return launchTarget;
}
}
Task.java
/** @return the first create-by-organizer task. */
@Nullable
Task getCreatedByOrganizerTask() {
if (mCreatedByOrganizer) {
return this;
}
final WindowContainer parent = getParent();
if (parent == null) {
return null;
}
final Task parentTask = parent.asTask();
return parentTask == null ? null : parentTask.getCreatedByOrganizerTask();
}
那么这个类型的task是什么时候初始化的呢,经过查找
StageCoordinator.java
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
ShellTaskOrganizer taskOrganizer, DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, Transitions transitions,
TransactionPool transactionPool, SplitscreenEventLogger logger,
IconProvider iconProvider, ShellExecutor mainExecutor,
Optional<RecentTasksController> recentTasks,
Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
mTaskOrganizer = taskOrganizer;
mLogger = logger;
mMainExecutor = mainExecutor;
mRecentTasks = recentTasks;
mMainUnfoldController = unfoldControllerProvider.get().orElse(null);
mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
//初始化分屏的roottask
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);
//初始化上下分屏的task, new的时候会去创建task,然后回调回来拿到taskinfo
mMainStage = new MainStage(
mContext,
mTaskOrganizer,
mDisplayId,
mMainStageListener,
mSyncQueue,
mSurfaceSession,
iconProvider,
mMainUnfoldController);
mSideStage = new SideStage(
mContext,
mTaskOrganizer,
mDisplayId,
mSideStageListener,
mSyncQueue,
mSurfaceSession,
iconProvider,
mSideUnfoldController);
mDisplayController = displayController;
mDisplayImeController = displayImeController;
mDisplayInsetsController = displayInsetsController;
mTransactionPool = transactionPool;
final DeviceStateManager deviceStateManager =
mContext.getSystemService(DeviceStateManager.class);
deviceStateManager.registerCallback(taskOrganizer.getExecutor(),
new DeviceStateManager.FoldStateListener(mContext, this::onFoldedStateChanged));
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
this::onTransitionAnimationComplete, this);
mDisplayController.addDisplayWindowListener(this);
mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
transitions.addHandler(this);
}
这里跨进程创建的task就是mCreatedByOrganizer==true的类型了
@VisibleForTesting
Task createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Create root task displayId=%d winMode=%d",
display.mDisplayId, windowingMode);
// We want to defer the task appear signal until the task is fully created and attached to
// to the hierarchy so that the complete starting configuration is in the task info we send
// over to the organizer.
final Task task = new Task.Builder(mService)
.setWindowingMode(windowingMode)
.setIntent(new Intent())
.setCreatedByOrganizer(true)
.setDeferTaskAppear(true)
.setLaunchCookie(launchCookie)
.setParent(display.getDefaultTaskDisplayArea())
.build();
task.setDeferTaskAppear(false /* deferTaskAppear */);
return task;
}
可以看一下层级结构树
原始
#1 Task=6 type=standard mode=multi-window override-mode=multi-window requested-bounds=[0,1498][1440,2960] bounds=[0,1498][1440,2960]
#0 Task=183 type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 ActivityRecord{fa1ec4b u0 com.android.launcher3/.SplitScreenActivity} t183} type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 5dffcd4 com.android.launcher3/com.android.launcher3.SplitScreenActivity type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 Task=5 type=standard mode=multi-window override-mode=multi-window requested-bounds=[0,0][1440,1463] bounds=[0,0][1440,1463]
#0 Task=182 type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1440,1463]
#0 ActivityRecord{49e57de u0 com.android.messaging/.ui.conversationlist.ConversationListActivity} t182} type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1440,1463]
#0 72fe958 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1440,1463]
启动新的后
#1 Task=6 type=standard mode=multi-window override-mode=multi-window requested-bounds=[0,1498][1440,2960] bounds=[0,1498][1440,2960]
#1 Task=184 type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 ActivityRecord{2d84183 u0 com.android.dialer/.main.impl.MainActivity} t184} type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 72a75f4 com.android.dialer/com.android.dialer.main.impl.MainActivity type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 Task=183 type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 ActivityRecord{fa1ec4b u0 com.android.launcher3/.SplitScreenActivity} t183} type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
#0 5dffcd4 com.android.launcher3/com.android.launcher3.SplitScreenActivity type=standard mode=multi-window override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,1498][1440,2960]
由此可以简单总结,在需要启动新的Task的情况下,会查找organizer创建的task,如果不需要就直接ActivityRecord挂载了,至于organizer创建的task特性可以看注释。
/**
* This TaskFragment was created by an organizer which has the following implementations.
* <ul>
* <li>The TaskFragment won't be removed when it is empty. Removal has to be an explicit
* request from the organizer.</li>
* <li>If this fragment is a Task object then unlike other non-root tasks, it's direct
* children are visible to the organizer for ordering purposes.</li>
* <li>A TaskFragment can be created by {@link android.window.TaskFragmentOrganizer}, and
* a Task can be created by {@link android.window.TaskOrganizer}.</li>
* </ul>
*/
可以看到这类型的task是就孩子算是空也不会被移除,Launcher桌面直接启动的时候可以挂载的parent就是TaskDisplayArea了,和这里分屏的情况又有所区别,也就解释了分屏情况或者在桌面都直接启动的情况下,task位置和bound都显示正常。