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.TaskInfo.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 * @param appToken Token of the application being started. 96 * context to for resources 97 * @hide 98 */ 99 @BinderThread addStartingWindow(@onNull StartingWindowInfo info, @NonNull IBinder appToken)100 public void addStartingWindow(@NonNull StartingWindowInfo info, 101 @NonNull IBinder appToken) {} 102 103 /** 104 * Called when the Task want to remove the starting window. 105 * @param removalInfo The information used to remove the starting window. 106 * @hide 107 */ 108 @BinderThread removeStartingWindow(@onNull StartingWindowRemovalInfo removalInfo)109 public void removeStartingWindow(@NonNull StartingWindowRemovalInfo removalInfo) {} 110 111 /** 112 * Called when the Task want to copy the splash screen. 113 */ 114 @BinderThread copySplashScreenView(int taskId)115 public void copySplashScreenView(int taskId) {} 116 117 /** 118 * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has 119 * removed the splash screen view. 120 * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) 121 * @see SplashScreenView#remove() 122 */ 123 @BinderThread onAppSplashScreenViewRemoved(int taskId)124 public void onAppSplashScreenViewRemoved(int taskId) { 125 } 126 127 /** 128 * Called when a task with the registered windowing mode can be controlled by this task 129 * organizer. For non-root tasks, the leash may initially be hidden so it is up to the organizer 130 * to show this task. 131 */ 132 @BinderThread onTaskAppeared(@onNull ActivityManager.RunningTaskInfo taskInfo, @NonNull SurfaceControl leash)133 public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo, 134 @NonNull SurfaceControl leash) {} 135 136 @BinderThread onTaskVanished(@onNull ActivityManager.RunningTaskInfo taskInfo)137 public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 138 139 @BinderThread onTaskInfoChanged(@onNull ActivityManager.RunningTaskInfo taskInfo)140 public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 141 142 @BinderThread onBackPressedOnTaskRoot(@onNull ActivityManager.RunningTaskInfo taskInfo)143 public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 144 145 /** @hide */ 146 @BinderThread onImeDrawnOnTask(int taskId)147 public void onImeDrawnOnTask(int taskId) {} 148 149 /** 150 * Creates a persistent root task in WM for a particular windowing-mode. 151 * @param displayId The display to create the root task on. 152 * @param windowingMode Windowing mode to put the root task in. 153 * @param launchCookie Launch cookie to associate with the task so that is can be identified 154 * when the {@link ITaskOrganizer#onTaskAppeared} callback is called. 155 * @param removeWithTaskOrganizer True if this task should be removed when organizer destroyed. 156 * @hide 157 */ 158 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)159 public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, 160 boolean removeWithTaskOrganizer) { 161 try { 162 mTaskOrganizerController.createRootTask(displayId, windowingMode, launchCookie, 163 removeWithTaskOrganizer); 164 } catch (RemoteException e) { 165 throw e.rethrowFromSystemServer(); 166 } 167 } 168 169 /** 170 * Creates a persistent root task in WM for a particular windowing-mode. 171 * @param displayId The display to create the root task on. 172 * @param windowingMode Windowing mode to put the root task in. 173 * @param launchCookie Launch cookie to associate with the task so that is can be identified 174 * when the {@link ITaskOrganizer#onTaskAppeared} callback is called. 175 */ 176 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 177 @Nullable createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie)178 public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie) { 179 createRootTask(displayId, windowingMode, launchCookie, false /* removeWithTaskOrganizer */); 180 } 181 182 /** Deletes a persistent root task in WM */ 183 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) deleteRootTask(@onNull WindowContainerToken task)184 public boolean deleteRootTask(@NonNull WindowContainerToken task) { 185 try { 186 return mTaskOrganizerController.deleteRootTask(task); 187 } catch (RemoteException e) { 188 throw e.rethrowFromSystemServer(); 189 } 190 } 191 192 /** Gets direct child tasks (ordered from top-to-bottom) */ 193 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 194 @Nullable 195 @SuppressLint("NullableCollection") getChildTasks( @onNull WindowContainerToken parent, @NonNull int[] activityTypes)196 public List<ActivityManager.RunningTaskInfo> getChildTasks( 197 @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) { 198 try { 199 return mTaskOrganizerController.getChildTasks(parent, activityTypes); 200 } catch (RemoteException e) { 201 throw e.rethrowFromSystemServer(); 202 } 203 } 204 205 /** Gets all root tasks on a display (ordered from top-to-bottom) */ 206 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 207 @Nullable 208 @SuppressLint("NullableCollection") getRootTasks( int displayId, @NonNull int[] activityTypes)209 public List<ActivityManager.RunningTaskInfo> getRootTasks( 210 int displayId, @NonNull int[] activityTypes) { 211 try { 212 return mTaskOrganizerController.getRootTasks(displayId, activityTypes); 213 } catch (RemoteException e) { 214 throw e.rethrowFromSystemServer(); 215 } 216 } 217 218 /** Get the {@link WindowContainerToken} of the task which contains the current ime target */ 219 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 220 @Nullable getImeTarget(int display)221 public WindowContainerToken getImeTarget(int display) { 222 try { 223 return mTaskOrganizerController.getImeTarget(display); 224 } catch (RemoteException e) { 225 throw e.rethrowFromSystemServer(); 226 } 227 } 228 229 /** 230 * Requests that the given task organizer is notified when back is pressed on the root activity 231 * of one of its controlled tasks. 232 */ 233 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) setInterceptBackPressedOnTaskRoot(@onNull WindowContainerToken task, boolean interceptBackPressed)234 public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task, 235 boolean interceptBackPressed) { 236 try { 237 mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(task, interceptBackPressed); 238 } catch (RemoteException e) { 239 throw e.rethrowFromSystemServer(); 240 } 241 } 242 243 244 /** 245 * Restarts the top activity in the given task by killing its process if it is visible. 246 * @hide 247 */ 248 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) restartTaskTopActivityProcessIfVisible(@onNull WindowContainerToken task)249 public void restartTaskTopActivityProcessIfVisible(@NonNull WindowContainerToken task) { 250 try { 251 mTaskOrganizerController.restartTaskTopActivityProcessIfVisible(task); 252 } catch (RemoteException e) { 253 throw e.rethrowFromSystemServer(); 254 } 255 } 256 257 /** 258 * Updates a state of camera compat control for stretched issues in the viewfinder. 259 * @hide 260 */ 261 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) updateCameraCompatControlState(@onNull WindowContainerToken task, @CameraCompatControlState int state)262 public void updateCameraCompatControlState(@NonNull WindowContainerToken task, 263 @CameraCompatControlState int state) { 264 try { 265 mTaskOrganizerController.updateCameraCompatControlState(task, state); 266 } catch (RemoteException e) { 267 throw e.rethrowFromSystemServer(); 268 } 269 } 270 271 /** 272 * Controls whether ignore orientation request logic in {@link 273 * com.android.server.wm.DisplayArea} is disabled at runtime and how to optionally map some 274 * requested orientation to others. 275 * 276 * @param isIgnoreOrientationRequestDisabled when {@code true}, the system always ignores the 277 * value of {@link com.android.server.wm.DisplayArea#getIgnoreOrientationRequest} 278 * and app requested orientation is respected. 279 * @param fromOrientations The orientations we want to map to the correspondent orientations 280 * in toOrientation. 281 * @param toOrientations The orientations we map to the ones in fromOrientations at the same 282 * index 283 * @hide 284 */ 285 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, @Nullable int[] fromOrientations, @Nullable int[] toOrientations)286 public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, 287 @Nullable int[] fromOrientations, @Nullable int[] toOrientations) { 288 try { 289 mTaskOrganizerController.setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled, 290 fromOrientations, toOrientations); 291 } catch (RemoteException e) { 292 throw e.rethrowFromSystemServer(); 293 } 294 } 295 296 /** 297 * Gets the executor to run callbacks on. 298 * @hide 299 */ 300 @NonNull getExecutor()301 public Executor getExecutor() { 302 return mExecutor; 303 } 304 305 private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() { 306 @Override 307 public void addStartingWindow(StartingWindowInfo windowInfo, 308 IBinder appToken) { 309 mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken)); 310 } 311 312 @Override 313 public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) { 314 mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(removalInfo)); 315 } 316 317 @Override 318 public void copySplashScreenView(int taskId) { 319 mExecutor.execute(() -> TaskOrganizer.this.copySplashScreenView(taskId)); 320 } 321 322 @Override 323 public void onAppSplashScreenViewRemoved(int taskId) { 324 mExecutor.execute(() -> TaskOrganizer.this.onAppSplashScreenViewRemoved(taskId)); 325 } 326 327 @Override 328 public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { 329 mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash)); 330 } 331 332 @Override 333 public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { 334 mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo)); 335 } 336 337 @Override 338 public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { 339 mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info)); 340 } 341 342 @Override 343 public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) { 344 mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info)); 345 } 346 347 @Override 348 public void onImeDrawnOnTask(int taskId) { 349 mExecutor.execute(() -> TaskOrganizer.this.onImeDrawnOnTask(taskId)); 350 } 351 }; 352 353 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) getController()354 private ITaskOrganizerController getController() { 355 try { 356 return getWindowOrganizerController().getTaskOrganizerController(); 357 } catch (RemoteException e) { 358 return null; 359 } 360 } 361 } 362