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