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 android.window;
18 
19 import android.annotation.BinderThread;
20 import android.annotation.CallSuper;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SuppressLint;
25 import android.annotation.TestApi;
26 import android.app.ActivityManager;
27 import android.app.CameraCompatTaskInfo.CameraCompatControlState;
28 import android.os.IBinder;
29 import android.os.RemoteException;
30 import android.view.SurfaceControl;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 import java.util.List;
35 import java.util.concurrent.Executor;
36 
37 /**
38  * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
39  * @hide
40  */
41 @TestApi
42 public class TaskOrganizer extends WindowOrganizer {
43 
44     private final ITaskOrganizerController mTaskOrganizerController;
45     // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are
46     // made on the incoming binder call.
47     private final Executor mExecutor;
48 
TaskOrganizer()49     public TaskOrganizer() {
50         this(null /*taskOrganizerController*/, null /*executor*/);
51     }
52 
53     /** @hide */
54     @VisibleForTesting
TaskOrganizer(ITaskOrganizerController taskOrganizerController, Executor executor)55     public TaskOrganizer(ITaskOrganizerController taskOrganizerController, Executor executor) {
56         mExecutor = executor != null ? executor : Runnable::run;
57         mTaskOrganizerController = taskOrganizerController != null
58                 ? taskOrganizerController : getController();
59     }
60 
61     /**
62      * Register a TaskOrganizer to manage tasks as they enter a supported windowing mode.
63      *
64      * @return a list of the tasks that should be managed by the organizer, not including tasks
65      *         created via {@link #createRootTask}.
66      */
67     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
68     @CallSuper
69     @NonNull
registerOrganizer()70     public List<TaskAppearedInfo> registerOrganizer() {
71         try {
72             return mTaskOrganizerController.registerTaskOrganizer(mInterface).getList();
73         } catch (RemoteException e) {
74             throw e.rethrowFromSystemServer();
75         }
76     }
77 
78     /** Unregisters a previously registered task organizer. */
79     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
80     @CallSuper
unregisterOrganizer()81     public void unregisterOrganizer() {
82         try {
83             mTaskOrganizerController.unregisterTaskOrganizer(mInterface);
84         } catch (RemoteException e) {
85             throw e.rethrowFromSystemServer();
86         }
87     }
88 
89     /**
90      * Called when a Task is starting and the system would like to show a UI to indicate that an
91      * application is starting. The client is responsible to add/remove the starting window if it
92      * has create a starting window for the Task.
93      *
94      * @param info The information about the Task that's available
95      * @hide
96      */
97     @BinderThread
addStartingWindow(@onNull StartingWindowInfo info)98     public void addStartingWindow(@NonNull StartingWindowInfo info) {}
99 
100     /**
101      * Called when the Task want to remove the starting window.
102      * @param removalInfo The information used to remove the starting window.
103      * @hide
104      */
105     @BinderThread
removeStartingWindow(@onNull StartingWindowRemovalInfo removalInfo)106     public void removeStartingWindow(@NonNull StartingWindowRemovalInfo removalInfo) {}
107 
108     /**
109      * Called when the Task want to copy the splash screen.
110      */
111     @BinderThread
copySplashScreenView(int taskId)112     public void copySplashScreenView(int taskId) {}
113 
114     /**
115      * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has
116      * removed the splash screen view.
117      * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int)
118      * @see SplashScreenView#remove()
119      */
120     @BinderThread
onAppSplashScreenViewRemoved(int taskId)121     public void onAppSplashScreenViewRemoved(int taskId) {
122     }
123 
124     /**
125      * Called when a task with the registered windowing mode can be controlled by this task
126      * organizer. For non-root tasks, the leash may initially be hidden so it is up to the organizer
127      * to show this task.
128      */
129     @BinderThread
onTaskAppeared(@onNull ActivityManager.RunningTaskInfo taskInfo, @NonNull SurfaceControl leash)130     public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo,
131             @NonNull SurfaceControl leash) {}
132 
133     @BinderThread
onTaskVanished(@onNull ActivityManager.RunningTaskInfo taskInfo)134     public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
135 
136     @BinderThread
onTaskInfoChanged(@onNull ActivityManager.RunningTaskInfo taskInfo)137     public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
138 
139     @BinderThread
onBackPressedOnTaskRoot(@onNull ActivityManager.RunningTaskInfo taskInfo)140     public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
141 
142     /** @hide */
143     @BinderThread
onImeDrawnOnTask(int taskId)144     public void onImeDrawnOnTask(int taskId) {}
145 
146     /**
147      * Creates a persistent root task in WM for a particular windowing-mode.
148      * @param displayId The display to create the root task on.
149      * @param windowingMode Windowing mode to put the root task in.
150      * @param launchCookie Launch cookie to associate with the task so that is can be identified
151      *                     when the {@link ITaskOrganizer#onTaskAppeared} callback is called.
152      * @param removeWithTaskOrganizer True if this task should be removed when organizer destroyed.
153      * @hide
154      */
155     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)156     public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie,
157             boolean removeWithTaskOrganizer) {
158         try {
159             mTaskOrganizerController.createRootTask(displayId, windowingMode, launchCookie,
160                     removeWithTaskOrganizer);
161         } catch (RemoteException e) {
162             throw e.rethrowFromSystemServer();
163         }
164     }
165 
166     /**
167      * Creates a persistent root task in WM for a particular windowing-mode.
168      * @param displayId The display to create the root task on.
169      * @param windowingMode Windowing mode to put the root task in.
170      * @param launchCookie Launch cookie to associate with the task so that is can be identified
171      *                     when the {@link ITaskOrganizer#onTaskAppeared} callback is called.
172      */
173     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
174     @Nullable
createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie)175     public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie) {
176         createRootTask(displayId, windowingMode, launchCookie, false /* removeWithTaskOrganizer */);
177     }
178 
179     /** Deletes a persistent root task in WM */
180     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
deleteRootTask(@onNull WindowContainerToken task)181     public boolean deleteRootTask(@NonNull WindowContainerToken task) {
182         try {
183             return mTaskOrganizerController.deleteRootTask(task);
184         } catch (RemoteException e) {
185             throw e.rethrowFromSystemServer();
186         }
187     }
188 
189     /** Gets direct child tasks (ordered from top-to-bottom) */
190     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
191     @Nullable
192     @SuppressLint("NullableCollection")
getChildTasks( @onNull WindowContainerToken parent, @NonNull int[] activityTypes)193     public List<ActivityManager.RunningTaskInfo> getChildTasks(
194             @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) {
195         try {
196             return mTaskOrganizerController.getChildTasks(parent, activityTypes);
197         } catch (RemoteException e) {
198             throw e.rethrowFromSystemServer();
199         }
200     }
201 
202     /** Gets all root tasks on a display (ordered from top-to-bottom) */
203     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
204     @Nullable
205     @SuppressLint("NullableCollection")
getRootTasks( int displayId, @NonNull int[] activityTypes)206     public List<ActivityManager.RunningTaskInfo> getRootTasks(
207             int displayId, @NonNull int[] activityTypes) {
208         try {
209             return mTaskOrganizerController.getRootTasks(displayId, activityTypes);
210         } catch (RemoteException e) {
211             throw e.rethrowFromSystemServer();
212         }
213     }
214 
215     /** Get the {@link WindowContainerToken} of the task which contains the current ime target */
216     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
217     @Nullable
getImeTarget(int display)218     public WindowContainerToken getImeTarget(int display) {
219         try {
220             return mTaskOrganizerController.getImeTarget(display);
221         } catch (RemoteException e) {
222             throw e.rethrowFromSystemServer();
223         }
224     }
225 
226     /**
227      * Requests that the given task organizer is notified when back is pressed on the root activity
228      * of one of its controlled tasks.
229      */
230     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
setInterceptBackPressedOnTaskRoot(@onNull WindowContainerToken task, boolean interceptBackPressed)231     public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task,
232             boolean interceptBackPressed) {
233         try {
234             mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(task, interceptBackPressed);
235         } catch (RemoteException e) {
236             throw e.rethrowFromSystemServer();
237         }
238     }
239 
240 
241     /**
242      * Restarts the top activity in the given task by killing its process if it is visible.
243      * @hide
244      */
245     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
restartTaskTopActivityProcessIfVisible(@onNull WindowContainerToken task)246     public void restartTaskTopActivityProcessIfVisible(@NonNull WindowContainerToken task) {
247         try {
248             mTaskOrganizerController.restartTaskTopActivityProcessIfVisible(task);
249         } catch (RemoteException e) {
250             throw e.rethrowFromSystemServer();
251         }
252     }
253 
254     /**
255      * Updates a state of camera compat control for stretched issues in the viewfinder.
256      * @hide
257      */
258     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
updateCameraCompatControlState(@onNull WindowContainerToken task, @CameraCompatControlState int state)259     public void updateCameraCompatControlState(@NonNull WindowContainerToken task,
260             @CameraCompatControlState int state) {
261         try {
262             mTaskOrganizerController.updateCameraCompatControlState(task, state);
263         } catch (RemoteException e) {
264             throw e.rethrowFromSystemServer();
265         }
266     }
267 
268     /**
269      * Gets the executor to run callbacks on.
270      * @hide
271      */
272     @NonNull
getExecutor()273     public Executor getExecutor() {
274         return mExecutor;
275     }
276 
277     private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
278         @Override
279         public void addStartingWindow(StartingWindowInfo windowInfo) {
280             mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo));
281         }
282 
283         @Override
284         public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
285             mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(removalInfo));
286         }
287 
288         @Override
289         public void copySplashScreenView(int taskId)  {
290             mExecutor.execute(() -> TaskOrganizer.this.copySplashScreenView(taskId));
291         }
292 
293         @Override
294         public void onAppSplashScreenViewRemoved(int taskId) {
295             mExecutor.execute(() -> TaskOrganizer.this.onAppSplashScreenViewRemoved(taskId));
296         }
297 
298         @Override
299         public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
300             mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash));
301         }
302 
303         @Override
304         public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
305             mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo));
306         }
307 
308         @Override
309         public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
310             mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info));
311         }
312 
313         @Override
314         public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
315             mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info));
316         }
317 
318         @Override
319         public void onImeDrawnOnTask(int taskId) {
320             mExecutor.execute(() -> TaskOrganizer.this.onImeDrawnOnTask(taskId));
321         }
322     };
323 
324     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
getController()325     private ITaskOrganizerController getController() {
326         try {
327             return getWindowOrganizerController().getTaskOrganizerController();
328         } catch (RemoteException e) {
329             return null;
330         }
331     }
332 }
333