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