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