1 /* 2 * Copyright (C) 2018 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.app; 18 19 import static android.view.Display.INVALID_DISPLAY; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemService; 25 import android.annotation.TestApi; 26 import android.compat.annotation.UnsupportedAppUsage; 27 import android.content.Context; 28 import android.content.pm.PackageManager; 29 import android.content.res.Configuration; 30 import android.content.res.Resources; 31 import android.graphics.Rect; 32 import android.os.Build; 33 import android.os.IBinder; 34 import android.os.Parcel; 35 import android.os.Parcelable; 36 import android.os.RemoteException; 37 import android.os.ServiceManager; 38 import android.util.DisplayMetrics; 39 import android.util.Singleton; 40 import android.view.RemoteAnimationDefinition; 41 import android.window.SplashScreenView.SplashScreenViewParcelable; 42 43 import java.util.List; 44 45 /** 46 * This class gives information about, and interacts with activities and their containers like task, 47 * stacks, and displays. 48 * 49 * @hide 50 */ 51 @TestApi 52 @SystemService(Context.ACTIVITY_TASK_SERVICE) 53 public class ActivityTaskManager { 54 55 /** Invalid stack ID. */ 56 public static final int INVALID_STACK_ID = -1; 57 58 /** 59 * Invalid task ID. 60 * @hide 61 */ 62 public static final int INVALID_TASK_ID = -1; 63 64 /** 65 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 66 * that the resize doesn't need to preserve the window, and can be skipped if bounds 67 * is unchanged. This mode is used by window manager in most cases. 68 * @hide 69 */ 70 public static final int RESIZE_MODE_SYSTEM = 0; 71 72 /** 73 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 74 * that the resize should preserve the window if possible. 75 * @hide 76 */ 77 public static final int RESIZE_MODE_PRESERVE_WINDOW = (0x1 << 0); 78 79 /** 80 * Input parameter to {@link IActivityTaskManager#resizeTask} used when the 81 * resize is due to a drag action. 82 * @hide 83 */ 84 public static final int RESIZE_MODE_USER = RESIZE_MODE_PRESERVE_WINDOW; 85 86 /** 87 * Input parameter to {@link IActivityTaskManager#resizeTask} used by window 88 * manager during a screen rotation. 89 * @hide 90 */ 91 public static final int RESIZE_MODE_SYSTEM_SCREEN_ROTATION = RESIZE_MODE_PRESERVE_WINDOW; 92 93 /** 94 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 95 * that the resize should be performed even if the bounds appears unchanged. 96 * @hide 97 */ 98 public static final int RESIZE_MODE_FORCED = (0x1 << 1); 99 100 /** 101 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 102 * that the resize should preserve the window if possible, and should not be skipped 103 * even if the bounds is unchanged. Usually used to force a resizing when a drag action 104 * is ending. 105 * @hide 106 */ 107 public static final int RESIZE_MODE_USER_FORCED = 108 RESIZE_MODE_PRESERVE_WINDOW | RESIZE_MODE_FORCED; 109 110 /** 111 * Extra included on intents that contain an EXTRA_INTENT, with options that the contained 112 * intent may want to be started with. Type is Bundle. 113 * TODO: remove once the ChooserActivity moves to systemui 114 * @hide 115 */ 116 public static final String EXTRA_OPTIONS = "android.app.extra.OPTIONS"; 117 118 /** 119 * Extra included on intents that contain an EXTRA_INTENT, use this boolean value for the 120 * parameter of the same name when starting the contained intent. 121 * TODO: remove once the ChooserActivity moves to systemui 122 * @hide 123 */ 124 public static final String EXTRA_IGNORE_TARGET_SECURITY = 125 "android.app.extra.EXTRA_IGNORE_TARGET_SECURITY"; 126 127 /** The minimal size of a display's long-edge needed to support split-screen multi-window. */ 128 public static final int DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP = 440; 129 130 private static int sMaxRecentTasks = -1; 131 132 private static final Singleton<ActivityTaskManager> sInstance = 133 new Singleton<ActivityTaskManager>() { 134 @Override 135 protected ActivityTaskManager create() { 136 return new ActivityTaskManager(); 137 } 138 }; 139 ActivityTaskManager()140 private ActivityTaskManager() { 141 } 142 143 /** @hide */ getInstance()144 public static ActivityTaskManager getInstance() { 145 return sInstance.get(); 146 } 147 148 /** @hide */ getService()149 public static IActivityTaskManager getService() { 150 return IActivityTaskManagerSingleton.get(); 151 } 152 153 @UnsupportedAppUsage(trackingBug = 129726065) 154 private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = 155 new Singleton<IActivityTaskManager>() { 156 @Override 157 protected IActivityTaskManager create() { 158 final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE); 159 return IActivityTaskManager.Stub.asInterface(b); 160 } 161 }; 162 163 /** 164 * Removes root tasks in the windowing modes from the system if they are of activity type 165 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 166 */ 167 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) removeRootTasksInWindowingModes(@onNull int[] windowingModes)168 public void removeRootTasksInWindowingModes(@NonNull int[] windowingModes) { 169 try { 170 getService().removeRootTasksInWindowingModes(windowingModes); 171 } catch (RemoteException e) { 172 throw e.rethrowFromSystemServer(); 173 } 174 } 175 176 /** Removes root tasks of the activity types from the system. */ 177 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) removeRootTasksWithActivityTypes(@onNull int[] activityTypes)178 public void removeRootTasksWithActivityTypes(@NonNull int[] activityTypes) { 179 try { 180 getService().removeRootTasksWithActivityTypes(activityTypes); 181 } catch (RemoteException e) { 182 throw e.rethrowFromSystemServer(); 183 } 184 } 185 186 /** 187 * Removes all visible recent tasks from the system. 188 * @hide 189 */ 190 @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) removeAllVisibleRecentTasks()191 public void removeAllVisibleRecentTasks() { 192 try { 193 getService().removeAllVisibleRecentTasks(); 194 } catch (RemoteException e) { 195 throw e.rethrowFromSystemServer(); 196 } 197 } 198 199 /** 200 * Return the maximum number of recents entries that we will maintain and show. 201 * @hide 202 */ getMaxRecentTasksStatic()203 public static int getMaxRecentTasksStatic() { 204 if (sMaxRecentTasks < 0) { 205 return sMaxRecentTasks = ActivityManager.isLowRamDeviceStatic() ? 36 : 48; 206 } 207 return sMaxRecentTasks; 208 } 209 210 /** 211 * Notify the server that splash screen of the given task has been copied" 212 * 213 * @param taskId Id of task to handle the material to reconstruct the splash screen view. 214 * @param parcelable Used to reconstruct the view, null means the surface is un-copyable. 215 * @hide 216 */ onSplashScreenViewCopyFinished(int taskId, @Nullable SplashScreenViewParcelable parcelable)217 public void onSplashScreenViewCopyFinished(int taskId, 218 @Nullable SplashScreenViewParcelable parcelable) { 219 try { 220 getService().onSplashScreenViewCopyFinished(taskId, parcelable); 221 } catch (RemoteException e) { 222 throw e.rethrowFromSystemServer(); 223 } 224 } 225 226 /** 227 * Return the default limit on the number of recents that an app can make. 228 * @hide 229 */ getDefaultAppRecentsLimitStatic()230 public static int getDefaultAppRecentsLimitStatic() { 231 return getMaxRecentTasksStatic() / 6; 232 } 233 234 /** 235 * Return the maximum limit on the number of recents that an app can make. 236 * @hide 237 */ getMaxAppRecentsLimitStatic()238 public static int getMaxAppRecentsLimitStatic() { 239 return getMaxRecentTasksStatic() / 2; 240 } 241 242 /** 243 * Returns true if the system supports at least one form of multi-window. 244 * E.g. freeform, split-screen, picture-in-picture. 245 */ supportsMultiWindow(Context context)246 public static boolean supportsMultiWindow(Context context) { 247 // On watches, multi-window is used to present essential system UI, and thus it must be 248 // supported regardless of device memory characteristics. 249 boolean isWatch = context.getPackageManager().hasSystemFeature( 250 PackageManager.FEATURE_WATCH); 251 return (!ActivityManager.isLowRamDeviceStatic() || isWatch) 252 && Resources.getSystem().getBoolean( 253 com.android.internal.R.bool.config_supportsMultiWindow); 254 } 255 256 /** 257 * Returns {@code true} if the display the context is associated with supports split screen 258 * multi-window. 259 * 260 * @throws UnsupportedOperationException if the supplied {@link Context} is not associated with 261 * a display. 262 */ supportsSplitScreenMultiWindow(Context context)263 public static boolean supportsSplitScreenMultiWindow(Context context) { 264 DisplayMetrics dm = new DisplayMetrics(); 265 context.getDisplay().getRealMetrics(dm); 266 267 int widthDp = (int) (dm.widthPixels / dm.density); 268 int heightDp = (int) (dm.heightPixels / dm.density); 269 if (Math.max(widthDp, heightDp) < DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP) { 270 return false; 271 } 272 273 return supportsMultiWindow(context) 274 && Resources.getSystem().getBoolean( 275 com.android.internal.R.bool.config_supportsSplitScreenMultiWindow); 276 } 277 278 /** 279 * Start to enter lock task mode for given task by system(UI). 280 * @param taskId Id of task to lock. 281 */ 282 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) startSystemLockTaskMode(int taskId)283 public void startSystemLockTaskMode(int taskId) { 284 try { 285 getService().startSystemLockTaskMode(taskId); 286 } catch (RemoteException e) { 287 throw e.rethrowFromSystemServer(); 288 } 289 } 290 291 /** 292 * Stop lock task mode by system(UI). 293 */ 294 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) stopSystemLockTaskMode()295 public void stopSystemLockTaskMode() { 296 try { 297 getService().stopSystemLockTaskMode(); 298 } catch (RemoteException e) { 299 throw e.rethrowFromSystemServer(); 300 } 301 } 302 303 /** 304 * Move task to root task with given id. 305 * @param taskId Id of the task to move. 306 * @param rootTaskId Id of the rootTask for task moving. 307 * @param toTop Whether the given task should shown to top of stack. 308 */ 309 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) moveTaskToRootTask(int taskId, int rootTaskId, boolean toTop)310 public void moveTaskToRootTask(int taskId, int rootTaskId, boolean toTop) { 311 try { 312 getService().moveTaskToRootTask(taskId, rootTaskId, toTop); 313 } catch (RemoteException e) { 314 throw e.rethrowFromSystemServer(); 315 } 316 } 317 318 /** 319 * Resize task to given bounds. 320 * @param taskId Id of task to resize. 321 * @param bounds Bounds to resize task. 322 */ 323 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) resizeTask(int taskId, Rect bounds)324 public void resizeTask(int taskId, Rect bounds) { 325 try { 326 getService().resizeTask(taskId, bounds, RESIZE_MODE_SYSTEM); 327 } catch (RemoteException e) { 328 throw e.rethrowFromSystemServer(); 329 } 330 } 331 332 /** 333 * Clears launch params for the given package. 334 * @param packageNames the names of the packages of which the launch params are to be cleared 335 */ 336 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) clearLaunchParamsForPackages(List<String> packageNames)337 public void clearLaunchParamsForPackages(List<String> packageNames) { 338 try { 339 getService().clearLaunchParamsForPackages(packageNames); 340 } catch (RemoteException e) { 341 e.rethrowFromSystemServer(); 342 } 343 } 344 345 /** 346 * @return whether the UI mode of the given config supports error dialogs (ANR, crash, etc). 347 * @hide 348 */ currentUiModeSupportsErrorDialogs(@onNull Configuration config)349 public static boolean currentUiModeSupportsErrorDialogs(@NonNull Configuration config) { 350 int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK; 351 return (modeType != Configuration.UI_MODE_TYPE_CAR 352 && !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER) 353 && modeType != Configuration.UI_MODE_TYPE_TELEVISION 354 && modeType != Configuration.UI_MODE_TYPE_VR_HEADSET); 355 } 356 357 /** @return whether the current UI mode supports error dialogs (ANR, crash, etc). */ currentUiModeSupportsErrorDialogs(@onNull Context context)358 public static boolean currentUiModeSupportsErrorDialogs(@NonNull Context context) { 359 final Configuration config = context.getResources().getConfiguration(); 360 return currentUiModeSupportsErrorDialogs(config); 361 } 362 363 /** @return max allowed number of actions in picture-in-picture mode. */ getMaxNumPictureInPictureActions(@onNull Context context)364 public static int getMaxNumPictureInPictureActions(@NonNull Context context) { 365 return context.getResources().getInteger( 366 com.android.internal.R.integer.config_pictureInPictureMaxNumberOfActions); 367 } 368 369 /** 370 * @return List of running tasks. 371 * @hide 372 */ getTasks(int maxNum)373 public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum) { 374 return getTasks(maxNum, false /* filterForVisibleRecents */, false /* keepIntentExtra */, 375 INVALID_DISPLAY); 376 } 377 378 /** 379 * @return List of running tasks that can be filtered by visibility in recents. 380 * @hide 381 */ getTasks( int maxNum, boolean filterOnlyVisibleRecents)382 public List<ActivityManager.RunningTaskInfo> getTasks( 383 int maxNum, boolean filterOnlyVisibleRecents) { 384 return getTasks(maxNum, filterOnlyVisibleRecents, false /* keepIntentExtra */, 385 INVALID_DISPLAY); 386 } 387 388 /** 389 * @return List of running tasks that can be filtered by visibility in recents and keep intent 390 * extra. 391 * @hide 392 */ getTasks( int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra)393 public List<ActivityManager.RunningTaskInfo> getTasks( 394 int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra) { 395 return getTasks(maxNum, filterOnlyVisibleRecents, keepIntentExtra, INVALID_DISPLAY); 396 } 397 398 /** 399 * @return List of running tasks that can be filtered by visibility and displayId in recents 400 * and keep intent extra. 401 * @param displayId the target display id, or {@link INVALID_DISPLAY} not to filter by displayId 402 * @hide 403 */ getTasks( int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra, int displayId)404 public List<ActivityManager.RunningTaskInfo> getTasks( 405 int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra, int displayId) { 406 try { 407 return getService().getTasks(maxNum, filterOnlyVisibleRecents, keepIntentExtra, 408 displayId); 409 } catch (RemoteException e) { 410 throw e.rethrowFromSystemServer(); 411 } 412 } 413 414 /** 415 * @return List of recent tasks. 416 * @hide 417 */ getRecentTasks( int maxNum, int flags, int userId)418 public List<ActivityManager.RecentTaskInfo> getRecentTasks( 419 int maxNum, int flags, int userId) { 420 try { 421 return getService().getRecentTasks(maxNum, flags, userId).getList(); 422 } catch (RemoteException e) { 423 throw e.rethrowFromSystemServer(); 424 } 425 } 426 427 /** @hide */ registerTaskStackListener(TaskStackListener listener)428 public void registerTaskStackListener(TaskStackListener listener) { 429 try { 430 getService().registerTaskStackListener(listener); 431 } catch (RemoteException e) { 432 throw e.rethrowFromSystemServer(); 433 } 434 } 435 436 /** @hide */ unregisterTaskStackListener(TaskStackListener listener)437 public void unregisterTaskStackListener(TaskStackListener listener) { 438 try { 439 getService().unregisterTaskStackListener(listener); 440 } catch (RemoteException e) { 441 throw e.rethrowFromSystemServer(); 442 } 443 } 444 445 /** @hide */ getTaskBounds(int taskId)446 public Rect getTaskBounds(int taskId) { 447 try { 448 return getService().getTaskBounds(taskId); 449 } catch (RemoteException e) { 450 throw e.rethrowFromSystemServer(); 451 } 452 } 453 454 /** 455 * Registers remote animations for a display. 456 * @hide 457 */ registerRemoteAnimationsForDisplay( int displayId, RemoteAnimationDefinition definition)458 public void registerRemoteAnimationsForDisplay( 459 int displayId, RemoteAnimationDefinition definition) { 460 try { 461 getService().registerRemoteAnimationsForDisplay(displayId, definition); 462 } catch (RemoteException e) { 463 throw e.rethrowFromSystemServer(); 464 } 465 } 466 467 /** @hide */ isInLockTaskMode()468 public boolean isInLockTaskMode() { 469 try { 470 return getService().isInLockTaskMode(); 471 } catch (RemoteException e) { 472 throw e.rethrowFromSystemServer(); 473 } 474 } 475 476 /** Removes task by a given taskId */ 477 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) removeTask(int taskId)478 public boolean removeTask(int taskId) { 479 try { 480 return getService().removeTask(taskId); 481 } catch (RemoteException e) { 482 throw e.rethrowFromSystemServer(); 483 } 484 } 485 486 /** 487 * Detaches the navigation bar from the app it was attached to during a transition. 488 * @hide 489 */ 490 @RequiresPermission(android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS) detachNavigationBarFromApp(@onNull IBinder transition)491 public void detachNavigationBarFromApp(@NonNull IBinder transition) { 492 try { 493 getService().detachNavigationBarFromApp(transition); 494 } catch (RemoteException e) { 495 throw e.rethrowFromSystemServer(); 496 } 497 } 498 499 /** 500 * Information you can retrieve about a root task in the system. 501 * @hide 502 */ 503 public static class RootTaskInfo extends TaskInfo implements Parcelable { 504 // TODO(b/148895075): Move some of the fields to TaskInfo. 505 public Rect bounds = new Rect(); 506 public int[] childTaskIds; 507 public String[] childTaskNames; 508 public Rect[] childTaskBounds; 509 public int[] childTaskUserIds; 510 public boolean visible; 511 // Index of the stack in the display's stack list, can be used for comparison of stack order 512 public int position; 513 514 @Override describeContents()515 public int describeContents() { 516 return 0; 517 } 518 519 @Override writeToParcel(Parcel dest, int flags)520 public void writeToParcel(Parcel dest, int flags) { 521 dest.writeTypedObject(bounds, flags); 522 dest.writeIntArray(childTaskIds); 523 dest.writeStringArray(childTaskNames); 524 dest.writeTypedArray(childTaskBounds, flags); 525 dest.writeIntArray(childTaskUserIds); 526 dest.writeInt(visible ? 1 : 0); 527 dest.writeInt(position); 528 super.writeToParcel(dest, flags); 529 } 530 531 @Override readFromParcel(Parcel source)532 void readFromParcel(Parcel source) { 533 bounds = source.readTypedObject(Rect.CREATOR); 534 childTaskIds = source.createIntArray(); 535 childTaskNames = source.createStringArray(); 536 childTaskBounds = source.createTypedArray(Rect.CREATOR); 537 childTaskUserIds = source.createIntArray(); 538 visible = source.readInt() > 0; 539 position = source.readInt(); 540 super.readFromParcel(source); 541 } 542 543 public static final @NonNull Creator<RootTaskInfo> CREATOR = new Creator<>() { 544 @Override 545 public RootTaskInfo createFromParcel(Parcel source) { 546 return new RootTaskInfo(source); 547 } 548 549 @Override 550 public RootTaskInfo[] newArray(int size) { 551 return new RootTaskInfo[size]; 552 } 553 }; 554 RootTaskInfo()555 public RootTaskInfo() { 556 } 557 RootTaskInfo(Parcel source)558 private RootTaskInfo(Parcel source) { 559 readFromParcel(source); 560 } 561 562 @Override toString()563 public String toString() { 564 StringBuilder sb = new StringBuilder(256); 565 sb.append("RootTask id="); sb.append(taskId); 566 sb.append(" bounds="); sb.append(bounds.toShortString()); 567 sb.append(" displayId="); sb.append(displayId); 568 sb.append(" userId="); sb.append(userId); 569 sb.append("\n"); 570 571 sb.append(" configuration="); sb.append(configuration); 572 sb.append("\n"); 573 574 for (int i = 0; i < childTaskIds.length; ++i) { 575 sb.append(" taskId="); sb.append(childTaskIds[i]); 576 sb.append(": "); sb.append(childTaskNames[i]); 577 if (childTaskBounds != null) { 578 sb.append(" bounds="); sb.append(childTaskBounds[i].toShortString()); 579 } 580 sb.append(" userId=").append(childTaskUserIds[i]); 581 sb.append(" visible=").append(visible); 582 if (topActivity != null) { 583 sb.append(" topActivity=").append(topActivity); 584 } 585 sb.append("\n"); 586 } 587 return sb.toString(); 588 } 589 } 590 } 591