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