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 * @param appToken Token of the application being started. 95 * context to for resources 96 * @hide 97 */ 98 @BinderThread addStartingWindow(@onNull StartingWindowInfo info, @NonNull IBinder appToken)99 public void addStartingWindow(@NonNull StartingWindowInfo info, 100 @NonNull IBinder appToken) {} 101 102 /** 103 * Called when the Task want to remove the starting window. 104 * @param removalInfo The information used to remove the starting window. 105 * @hide 106 */ 107 @BinderThread removeStartingWindow(@onNull StartingWindowRemovalInfo removalInfo)108 public void removeStartingWindow(@NonNull StartingWindowRemovalInfo removalInfo) {} 109 110 /** 111 * Called when the Task want to copy the splash screen. 112 */ 113 @BinderThread copySplashScreenView(int taskId)114 public void copySplashScreenView(int taskId) {} 115 116 /** 117 * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has 118 * removed the splash screen view. 119 * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) 120 * @see SplashScreenView#remove() 121 */ 122 @BinderThread onAppSplashScreenViewRemoved(int taskId)123 public void onAppSplashScreenViewRemoved(int taskId) { 124 } 125 126 /** 127 * Called when a task with the registered windowing mode can be controlled by this task 128 * organizer. For non-root tasks, the leash may initially be hidden so it is up to the organizer 129 * to show this task. 130 */ 131 @BinderThread onTaskAppeared(@onNull ActivityManager.RunningTaskInfo taskInfo, @NonNull SurfaceControl leash)132 public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo, 133 @NonNull SurfaceControl leash) {} 134 135 @BinderThread onTaskVanished(@onNull ActivityManager.RunningTaskInfo taskInfo)136 public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 137 138 @BinderThread onTaskInfoChanged(@onNull ActivityManager.RunningTaskInfo taskInfo)139 public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 140 141 @BinderThread onBackPressedOnTaskRoot(@onNull ActivityManager.RunningTaskInfo taskInfo)142 public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} 143 144 /** @hide */ 145 @BinderThread onImeDrawnOnTask(int taskId)146 public void onImeDrawnOnTask(int taskId) {} 147 148 /** 149 * Creates a persistent root task in WM for a particular windowing-mode. 150 * @param displayId The display to create the root task on. 151 * @param windowingMode Windowing mode to put the root task in. 152 * @param launchCookie Launch cookie to associate with the task so that is can be identified 153 * when the {@link ITaskOrganizer#onTaskAppeared} callback is called. 154 */ 155 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 156 @Nullable createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie)157 public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie) { 158 try { 159 mTaskOrganizerController.createRootTask(displayId, windowingMode, launchCookie); 160 } catch (RemoteException e) { 161 throw e.rethrowFromSystemServer(); 162 } 163 } 164 165 /** Deletes a persistent root task in WM */ 166 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) deleteRootTask(@onNull WindowContainerToken task)167 public boolean deleteRootTask(@NonNull WindowContainerToken task) { 168 try { 169 return mTaskOrganizerController.deleteRootTask(task); 170 } catch (RemoteException e) { 171 throw e.rethrowFromSystemServer(); 172 } 173 } 174 175 /** Gets direct child tasks (ordered from top-to-bottom) */ 176 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 177 @Nullable 178 @SuppressLint("NullableCollection") getChildTasks( @onNull WindowContainerToken parent, @NonNull int[] activityTypes)179 public List<ActivityManager.RunningTaskInfo> getChildTasks( 180 @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) { 181 try { 182 return mTaskOrganizerController.getChildTasks(parent, activityTypes); 183 } catch (RemoteException e) { 184 throw e.rethrowFromSystemServer(); 185 } 186 } 187 188 /** Gets all root tasks on a display (ordered from top-to-bottom) */ 189 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 190 @Nullable 191 @SuppressLint("NullableCollection") getRootTasks( int displayId, @NonNull int[] activityTypes)192 public List<ActivityManager.RunningTaskInfo> getRootTasks( 193 int displayId, @NonNull int[] activityTypes) { 194 try { 195 return mTaskOrganizerController.getRootTasks(displayId, activityTypes); 196 } catch (RemoteException e) { 197 throw e.rethrowFromSystemServer(); 198 } 199 } 200 201 /** Get the root task which contains the current ime target */ 202 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 203 @Nullable getImeTarget(int display)204 public WindowContainerToken getImeTarget(int display) { 205 try { 206 return mTaskOrganizerController.getImeTarget(display); 207 } catch (RemoteException e) { 208 throw e.rethrowFromSystemServer(); 209 } 210 } 211 212 /** 213 * Requests that the given task organizer is notified when back is pressed on the root activity 214 * of one of its controlled tasks. 215 */ 216 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) setInterceptBackPressedOnTaskRoot(@onNull WindowContainerToken task, boolean interceptBackPressed)217 public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task, 218 boolean interceptBackPressed) { 219 try { 220 mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(task, interceptBackPressed); 221 } catch (RemoteException e) { 222 throw e.rethrowFromSystemServer(); 223 } 224 } 225 226 227 /** 228 * Restarts the top activity in the given task by killing its process if it is visible. 229 * @hide 230 */ 231 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) restartTaskTopActivityProcessIfVisible(@onNull WindowContainerToken task)232 public void restartTaskTopActivityProcessIfVisible(@NonNull WindowContainerToken task) { 233 try { 234 mTaskOrganizerController.restartTaskTopActivityProcessIfVisible(task); 235 } catch (RemoteException e) { 236 throw e.rethrowFromSystemServer(); 237 } 238 } 239 240 /** 241 * Gets the executor to run callbacks on. 242 * @hide 243 */ 244 @NonNull getExecutor()245 public Executor getExecutor() { 246 return mExecutor; 247 } 248 249 private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() { 250 @Override 251 public void addStartingWindow(StartingWindowInfo windowInfo, 252 IBinder appToken) { 253 mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken)); 254 } 255 256 @Override 257 public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) { 258 mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(removalInfo)); 259 } 260 261 @Override 262 public void copySplashScreenView(int taskId) { 263 mExecutor.execute(() -> TaskOrganizer.this.copySplashScreenView(taskId)); 264 } 265 266 @Override 267 public void onAppSplashScreenViewRemoved(int taskId) { 268 mExecutor.execute(() -> TaskOrganizer.this.onAppSplashScreenViewRemoved(taskId)); 269 } 270 271 @Override 272 public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { 273 mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash)); 274 } 275 276 @Override 277 public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { 278 mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo)); 279 } 280 281 @Override 282 public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { 283 mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info)); 284 } 285 286 @Override 287 public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) { 288 mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info)); 289 } 290 291 @Override 292 public void onImeDrawnOnTask(int taskId) { 293 mExecutor.execute(() -> TaskOrganizer.this.onImeDrawnOnTask(taskId)); 294 } 295 }; 296 297 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) getController()298 private ITaskOrganizerController getController() { 299 try { 300 return getWindowOrganizerController().getTaskOrganizerController(); 301 } catch (RemoteException e) { 302 return null; 303 } 304 } 305 } 306