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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemService; 23 import android.annotation.TestApi; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.Context; 26 import android.content.pm.PackageManager; 27 import android.content.res.Configuration; 28 import android.content.res.Resources; 29 import android.graphics.Rect; 30 import android.os.Build; 31 import android.os.IBinder; 32 import android.os.Parcel; 33 import android.os.Parcelable; 34 import android.os.RemoteException; 35 import android.os.ServiceManager; 36 import android.util.DisplayMetrics; 37 import android.util.Singleton; 38 import android.view.RemoteAnimationDefinition; 39 import android.window.SplashScreenView.SplashScreenViewParcelable; 40 41 import java.util.List; 42 43 /** 44 * This class gives information about, and interacts with activities and their containers like task, 45 * stacks, and displays. 46 * 47 * @hide 48 */ 49 @TestApi 50 @SystemService(Context.ACTIVITY_TASK_SERVICE) 51 public class ActivityTaskManager { 52 53 /** Invalid stack ID. */ 54 public static final int INVALID_STACK_ID = -1; 55 56 /** 57 * Invalid task ID. 58 * @hide 59 */ 60 public static final int INVALID_TASK_ID = -1; 61 62 /** 63 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 64 * that the resize doesn't need to preserve the window, and can be skipped if bounds 65 * is unchanged. This mode is used by window manager in most cases. 66 * @hide 67 */ 68 public static final int RESIZE_MODE_SYSTEM = 0; 69 70 /** 71 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 72 * that the resize should preserve the window if possible. 73 * @hide 74 */ 75 public static final int RESIZE_MODE_PRESERVE_WINDOW = (0x1 << 0); 76 77 /** 78 * Input parameter to {@link IActivityTaskManager#resizeTask} used when the 79 * resize is due to a drag action. 80 * @hide 81 */ 82 public static final int RESIZE_MODE_USER = RESIZE_MODE_PRESERVE_WINDOW; 83 84 /** 85 * Input parameter to {@link IActivityTaskManager#resizeTask} used by window 86 * manager during a screen rotation. 87 * @hide 88 */ 89 public static final int RESIZE_MODE_SYSTEM_SCREEN_ROTATION = RESIZE_MODE_PRESERVE_WINDOW; 90 91 /** 92 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 93 * that the resize should be performed even if the bounds appears unchanged. 94 * @hide 95 */ 96 public static final int RESIZE_MODE_FORCED = (0x1 << 1); 97 98 /** 99 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 100 * that the resize should preserve the window if possible, and should not be skipped 101 * even if the bounds is unchanged. Usually used to force a resizing when a drag action 102 * is ending. 103 * @hide 104 */ 105 public static final int RESIZE_MODE_USER_FORCED = 106 RESIZE_MODE_PRESERVE_WINDOW | RESIZE_MODE_FORCED; 107 108 /** 109 * Extra included on intents that are delegating the call to 110 * ActivityManager#startActivityAsCaller to another app. This token is necessary for that call 111 * to succeed. Type is IBinder. 112 * @hide 113 */ 114 public static final String EXTRA_PERMISSION_TOKEN = "android.app.extra.PERMISSION_TOKEN"; 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 */); 381 } 382 383 /** 384 * @return List of running tasks that can be filtered by visibility in recents. 385 * @hide 386 */ getTasks( int maxNum, boolean filterOnlyVisibleRecents)387 public List<ActivityManager.RunningTaskInfo> getTasks( 388 int maxNum, boolean filterOnlyVisibleRecents) { 389 return getTasks(maxNum, filterOnlyVisibleRecents, false /* keepIntentExtra */); 390 } 391 392 /** 393 * @return List of running tasks that can be filtered by visibility in recents and keep intent 394 * extra. 395 * @hide 396 */ getTasks( int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra)397 public List<ActivityManager.RunningTaskInfo> getTasks( 398 int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra) { 399 try { 400 return getService().getTasks(maxNum, filterOnlyVisibleRecents, keepIntentExtra); 401 } catch (RemoteException e) { 402 throw e.rethrowFromSystemServer(); 403 } 404 } 405 406 /** 407 * @return List of recent tasks. 408 * @hide 409 */ getRecentTasks( int maxNum, int flags, int userId)410 public List<ActivityManager.RecentTaskInfo> getRecentTasks( 411 int maxNum, int flags, int userId) { 412 try { 413 return getService().getRecentTasks(maxNum, flags, userId).getList(); 414 } catch (RemoteException e) { 415 throw e.rethrowFromSystemServer(); 416 } 417 } 418 419 /** @hide */ registerTaskStackListener(TaskStackListener listener)420 public void registerTaskStackListener(TaskStackListener listener) { 421 try { 422 getService().registerTaskStackListener(listener); 423 } catch (RemoteException e) { 424 throw e.rethrowFromSystemServer(); 425 } 426 } 427 428 /** @hide */ unregisterTaskStackListener(TaskStackListener listener)429 public void unregisterTaskStackListener(TaskStackListener listener) { 430 try { 431 getService().unregisterTaskStackListener(listener); 432 } catch (RemoteException e) { 433 throw e.rethrowFromSystemServer(); 434 } 435 } 436 437 /** @hide */ getTaskBounds(int taskId)438 public Rect getTaskBounds(int taskId) { 439 try { 440 return getService().getTaskBounds(taskId); 441 } catch (RemoteException e) { 442 throw e.rethrowFromSystemServer(); 443 } 444 } 445 446 /** 447 * Registers remote animations for a display. 448 * @hide 449 */ registerRemoteAnimationsForDisplay( int displayId, RemoteAnimationDefinition definition)450 public void registerRemoteAnimationsForDisplay( 451 int displayId, RemoteAnimationDefinition definition) { 452 try { 453 getService().registerRemoteAnimationsForDisplay(displayId, definition); 454 } catch (RemoteException e) { 455 throw e.rethrowFromSystemServer(); 456 } 457 } 458 459 /** @hide */ isInLockTaskMode()460 public boolean isInLockTaskMode() { 461 try { 462 return getService().isInLockTaskMode(); 463 } catch (RemoteException e) { 464 throw e.rethrowFromSystemServer(); 465 } 466 } 467 468 /** Removes task by a given taskId */ 469 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) removeTask(int taskId)470 public boolean removeTask(int taskId) { 471 try { 472 return getService().removeTask(taskId); 473 } catch (RemoteException e) { 474 throw e.rethrowFromSystemServer(); 475 } 476 } 477 478 /** 479 * Information you can retrieve about a root task in the system. 480 * @hide 481 */ 482 public static class RootTaskInfo extends TaskInfo implements Parcelable { 483 // TODO(b/148895075): Move some of the fields to TaskInfo. 484 public Rect bounds = new Rect(); 485 public int[] childTaskIds; 486 public String[] childTaskNames; 487 public Rect[] childTaskBounds; 488 public int[] childTaskUserIds; 489 public boolean visible; 490 // Index of the stack in the display's stack list, can be used for comparison of stack order 491 public int position; 492 493 @Override describeContents()494 public int describeContents() { 495 return 0; 496 } 497 498 @Override writeToParcel(Parcel dest, int flags)499 public void writeToParcel(Parcel dest, int flags) { 500 dest.writeTypedObject(bounds, flags); 501 dest.writeIntArray(childTaskIds); 502 dest.writeStringArray(childTaskNames); 503 dest.writeTypedArray(childTaskBounds, flags); 504 dest.writeIntArray(childTaskUserIds); 505 dest.writeInt(visible ? 1 : 0); 506 dest.writeInt(position); 507 super.writeToParcel(dest, flags); 508 } 509 510 @Override readFromParcel(Parcel source)511 void readFromParcel(Parcel source) { 512 bounds = source.readTypedObject(Rect.CREATOR); 513 childTaskIds = source.createIntArray(); 514 childTaskNames = source.createStringArray(); 515 childTaskBounds = source.createTypedArray(Rect.CREATOR); 516 childTaskUserIds = source.createIntArray(); 517 visible = source.readInt() > 0; 518 position = source.readInt(); 519 super.readFromParcel(source); 520 } 521 522 public static final @NonNull Creator<RootTaskInfo> CREATOR = new Creator<>() { 523 @Override 524 public RootTaskInfo createFromParcel(Parcel source) { 525 return new RootTaskInfo(source); 526 } 527 528 @Override 529 public RootTaskInfo[] newArray(int size) { 530 return new RootTaskInfo[size]; 531 } 532 }; 533 RootTaskInfo()534 public RootTaskInfo() { 535 } 536 RootTaskInfo(Parcel source)537 private RootTaskInfo(Parcel source) { 538 readFromParcel(source); 539 } 540 541 @Override toString()542 public String toString() { 543 StringBuilder sb = new StringBuilder(256); 544 sb.append("RootTask id="); sb.append(taskId); 545 sb.append(" bounds="); sb.append(bounds.toShortString()); 546 sb.append(" displayId="); sb.append(displayId); 547 sb.append(" userId="); sb.append(userId); 548 sb.append("\n"); 549 550 sb.append(" configuration="); sb.append(configuration); 551 sb.append("\n"); 552 553 for (int i = 0; i < childTaskIds.length; ++i) { 554 sb.append(" taskId="); sb.append(childTaskIds[i]); 555 sb.append(": "); sb.append(childTaskNames[i]); 556 if (childTaskBounds != null) { 557 sb.append(" bounds="); sb.append(childTaskBounds[i].toShortString()); 558 } 559 sb.append(" userId=").append(childTaskUserIds[i]); 560 sb.append(" visible=").append(visible); 561 if (topActivity != null) { 562 sb.append(" topActivity=").append(topActivity); 563 } 564 sb.append("\n"); 565 } 566 return sb.toString(); 567 } 568 } 569 } 570