1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.carlauncher;
18 
19 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
20 
21 import static com.android.car.carlauncher.CarLauncher.TAG;
22 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
23 
24 import android.annotation.UiContext;
25 import android.app.ActivityTaskManager;
26 import android.app.TaskInfo;
27 import android.content.Context;
28 import android.util.Slog;
29 import android.window.TaskAppearedInfo;
30 
31 import com.android.launcher3.icons.IconProvider;
32 import com.android.wm.shell.ShellTaskOrganizer;
33 import com.android.wm.shell.TaskView;
34 import com.android.wm.shell.TaskViewFactory;
35 import com.android.wm.shell.TaskViewFactoryController;
36 import com.android.wm.shell.common.HandlerExecutor;
37 import com.android.wm.shell.common.SyncTransactionQueue;
38 import com.android.wm.shell.common.TransactionPool;
39 import com.android.wm.shell.fullscreen.FullscreenTaskListener;
40 import com.android.wm.shell.startingsurface.StartingWindowController;
41 import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
42 
43 import java.util.List;
44 import java.util.Optional;
45 import java.util.function.Consumer;
46 
47 public final class TaskViewManager {
48     private static final boolean DBG = false;
49 
50     private final Context mContext;
51     private final HandlerExecutor mExecutor;
52     private final TaskViewFactory mTaskViewFactory;
53     private final ShellTaskOrganizer mTaskOrganizer;
54 
TaskViewManager(@iContext Context context, HandlerExecutor handlerExecutor)55     public TaskViewManager(@UiContext Context context, HandlerExecutor handlerExecutor) {
56         mContext = context;
57         mExecutor = handlerExecutor;
58         mTaskOrganizer = new ShellTaskOrganizer(mExecutor, mContext);
59         mTaskViewFactory = initWmShell();
60         if (DBG) Slog.d(TAG, "TaskViewManager.create");
61     }
62 
initWmShell()63     private TaskViewFactory initWmShell() {
64         TransactionPool transactionPool = new TransactionPool();
65         SyncTransactionQueue syncQueue = new SyncTransactionQueue(transactionPool, mExecutor);
66         FullscreenTaskListener fullscreenTaskListener = new FullscreenTaskListener(syncQueue,
67                 Optional.empty());
68         mTaskOrganizer.addListenerForType(fullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
69         StartingWindowController startingController =
70                 new StartingWindowController(mContext, mExecutor,
71                         new PhoneStartingWindowTypeAlgorithm(), new IconProvider(mContext),
72                         transactionPool);
73         mTaskOrganizer.initStartingWindow(startingController);
74         List<TaskAppearedInfo> taskAppearedInfos = mTaskOrganizer.registerOrganizer();
75         cleanUpExistingTaskViewTasks(taskAppearedInfos);
76 
77         return new TaskViewFactoryController(mTaskOrganizer, mExecutor, syncQueue)
78                 .asTaskViewFactory();
79     }
80 
release()81     void release() {
82         if (DBG) Slog.d(TAG, "TaskViewManager.release");
83         mTaskOrganizer.unregisterOrganizer();
84     }
85 
createTaskView(Consumer<TaskView> onCreate)86     void createTaskView(Consumer<TaskView> onCreate) {
87         mTaskViewFactory.create(mContext, mExecutor, onCreate);
88     }
89 
cleanUpExistingTaskViewTasks(List<TaskAppearedInfo> taskAppearedInfos)90     private static void cleanUpExistingTaskViewTasks(List<TaskAppearedInfo> taskAppearedInfos) {
91         ActivityTaskManager atm = ActivityTaskManager.getInstance();
92         for (TaskAppearedInfo taskAppearedInfo : taskAppearedInfos) {
93             TaskInfo taskInfo = taskAppearedInfo.getTaskInfo();
94             // Only TaskView tasks have WINDOWING_MODE_MULTI_WINDOW.
95             if (taskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
96                 if (DBG) Slog.d(TAG, "Found the dangling task, removing: " + taskInfo.taskId);
97                 atm.removeTask(taskInfo.taskId);
98             }
99         }
100     }
101 }
102