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.RequiresPermission; 21 import android.annotation.SystemService; 22 import android.annotation.TestApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.content.Context; 25 import android.content.pm.PackageManager; 26 import android.content.res.Configuration; 27 import android.content.res.Resources; 28 import android.graphics.Rect; 29 import android.os.Build; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.os.ServiceManager; 34 import android.util.Singleton; 35 36 import java.util.List; 37 38 /** 39 * This class gives information about, and interacts with activities and their containers like task, 40 * stacks, and displays. 41 * 42 * @hide 43 */ 44 @TestApi 45 @SystemService(Context.ACTIVITY_TASK_SERVICE) 46 public class ActivityTaskManager { 47 48 /** Invalid stack ID. */ 49 public static final int INVALID_STACK_ID = -1; 50 51 /** 52 * Invalid task ID. 53 * @hide 54 */ 55 public static final int INVALID_TASK_ID = -1; 56 57 /** 58 * Parameter to {@link IActivityTaskManager#setTaskWindowingModeSplitScreenPrimary} which 59 * specifies the position of the created docked stack at the top half of the screen if 60 * in portrait mode or at the left half of the screen if in landscape mode. 61 */ 62 public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; 63 64 /** 65 * Parameter to {@link IActivityTaskManager#setTaskWindowingModeSplitScreenPrimary} which 66 * specifies the position of the created docked stack at the bottom half of the screen if 67 * in portrait mode or at the right half of the screen if in landscape mode. 68 */ 69 public static final int SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT = 1; 70 71 /** 72 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 73 * that the resize doesn't need to preserve the window, and can be skipped if bounds 74 * is unchanged. This mode is used by window manager in most cases. 75 * @hide 76 */ 77 public static final int RESIZE_MODE_SYSTEM = 0; 78 79 /** 80 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 81 * that the resize should preserve the window if possible. 82 * @hide 83 */ 84 public static final int RESIZE_MODE_PRESERVE_WINDOW = (0x1 << 0); 85 86 /** 87 * Input parameter to {@link IActivityTaskManager#resizeTask} used when the 88 * resize is due to a drag action. 89 * @hide 90 */ 91 public static final int RESIZE_MODE_USER = RESIZE_MODE_PRESERVE_WINDOW; 92 93 /** 94 * Input parameter to {@link IActivityTaskManager#resizeTask} used by window 95 * manager during a screen rotation. 96 * @hide 97 */ 98 public static final int RESIZE_MODE_SYSTEM_SCREEN_ROTATION = RESIZE_MODE_PRESERVE_WINDOW; 99 100 /** 101 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 102 * that the resize should be performed even if the bounds appears unchanged. 103 * @hide 104 */ 105 public static final int RESIZE_MODE_FORCED = (0x1 << 1); 106 107 /** 108 * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates 109 * that the resize should preserve the window if possible, and should not be skipped 110 * even if the bounds is unchanged. Usually used to force a resizing when a drag action 111 * is ending. 112 * @hide 113 */ 114 public static final int RESIZE_MODE_USER_FORCED = 115 RESIZE_MODE_PRESERVE_WINDOW | RESIZE_MODE_FORCED; 116 117 /** 118 * Extra included on intents that are delegating the call to 119 * ActivityManager#startActivityAsCaller to another app. This token is necessary for that call 120 * to succeed. Type is IBinder. 121 * @hide 122 */ 123 public static final String EXTRA_PERMISSION_TOKEN = "android.app.extra.PERMISSION_TOKEN"; 124 125 /** 126 * Extra included on intents that contain an EXTRA_INTENT, with options that the contained 127 * intent may want to be started with. Type is Bundle. 128 * TODO: remove once the ChooserActivity moves to systemui 129 * @hide 130 */ 131 public static final String EXTRA_OPTIONS = "android.app.extra.OPTIONS"; 132 133 /** 134 * Extra included on intents that contain an EXTRA_INTENT, use this boolean value for the 135 * parameter of the same name when starting the contained intent. 136 * TODO: remove once the ChooserActivity moves to systemui 137 * @hide 138 */ 139 public static final String EXTRA_IGNORE_TARGET_SECURITY = 140 "android.app.extra.EXTRA_IGNORE_TARGET_SECURITY"; 141 142 143 private static int sMaxRecentTasks = -1; 144 ActivityTaskManager(Context context, Handler handler)145 ActivityTaskManager(Context context, Handler handler) { 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 * Sets the windowing mode for a specific task. Only works on tasks of type 165 * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} 166 * @param taskId The id of the task to set the windowing mode for. 167 * @param windowingMode The windowing mode to set for the task. 168 * @param toTop If the task should be moved to the top once the windowing mode changes. 169 * @return Whether the task was successfully put into the specified windowing mode. 170 */ 171 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) setTaskWindowingMode(int taskId, int windowingMode, boolean toTop)172 public boolean setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) 173 throws SecurityException { 174 try { 175 return getService().setTaskWindowingMode(taskId, windowingMode, toTop); 176 } catch (RemoteException e) { 177 throw e.rethrowFromSystemServer(); 178 } 179 } 180 181 /** 182 * Moves the input task to the primary-split-screen stack. 183 * @param taskId Id of task to move. 184 * @param createMode The mode the primary split screen stack should be created in if it doesn't 185 * exist already. See 186 * {@link ActivityTaskManager#SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT} 187 * and 188 * {@link android.app.ActivityManager 189 * #SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT} 190 * @param toTop If the task and stack should be moved to the top. 191 * @param animate Whether we should play an animation for the moving the task 192 * @param initialBounds If the primary stack gets created, it will use these bounds for the 193 * docked stack. Pass {@code null} to use default bounds. 194 * @param showRecents If the recents activity should be shown on the other side of the task 195 * going into split-screen mode. 196 * @return Whether the task was successfully put into splitscreen. 197 */ 198 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, boolean animate, Rect initialBounds, boolean showRecents)199 public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, 200 boolean animate, Rect initialBounds, boolean showRecents) throws SecurityException { 201 try { 202 return getService().setTaskWindowingModeSplitScreenPrimary(taskId, toTop); 203 } catch (RemoteException e) { 204 throw e.rethrowFromSystemServer(); 205 } 206 } 207 208 /** 209 * Removes stacks in the windowing modes from the system if they are of activity type 210 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 211 */ 212 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) removeStacksInWindowingModes(int[] windowingModes)213 public void removeStacksInWindowingModes(int[] windowingModes) throws SecurityException { 214 try { 215 getService().removeStacksInWindowingModes(windowingModes); 216 } catch (RemoteException e) { 217 throw e.rethrowFromSystemServer(); 218 } 219 } 220 221 /** Removes stack of the activity types from the system. */ 222 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) removeStacksWithActivityTypes(int[] activityTypes)223 public void removeStacksWithActivityTypes(int[] activityTypes) throws SecurityException { 224 try { 225 getService().removeStacksWithActivityTypes(activityTypes); 226 } catch (RemoteException e) { 227 throw e.rethrowFromSystemServer(); 228 } 229 } 230 231 /** 232 * Removes all visible recent tasks from the system. 233 * @hide 234 */ 235 @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) removeAllVisibleRecentTasks()236 public void removeAllVisibleRecentTasks() { 237 try { 238 getService().removeAllVisibleRecentTasks(); 239 } catch (RemoteException e) { 240 throw e.rethrowFromSystemServer(); 241 } 242 } 243 244 /** 245 * Return the maximum number of recents entries that we will maintain and show. 246 * @hide 247 */ getMaxRecentTasksStatic()248 public static int getMaxRecentTasksStatic() { 249 if (sMaxRecentTasks < 0) { 250 return sMaxRecentTasks = ActivityManager.isLowRamDeviceStatic() ? 36 : 48; 251 } 252 return sMaxRecentTasks; 253 } 254 255 /** 256 * Return the default limit on the number of recents that an app can make. 257 * @hide 258 */ getDefaultAppRecentsLimitStatic()259 public static int getDefaultAppRecentsLimitStatic() { 260 return getMaxRecentTasksStatic() / 6; 261 } 262 263 /** 264 * Return the maximum limit on the number of recents that an app can make. 265 * @hide 266 */ getMaxAppRecentsLimitStatic()267 public static int getMaxAppRecentsLimitStatic() { 268 return getMaxRecentTasksStatic() / 2; 269 } 270 271 /** 272 * Returns true if the system supports at least one form of multi-window. 273 * E.g. freeform, split-screen, picture-in-picture. 274 */ supportsMultiWindow(Context context)275 public static boolean supportsMultiWindow(Context context) { 276 // On watches, multi-window is used to present essential system UI, and thus it must be 277 // supported regardless of device memory characteristics. 278 boolean isWatch = context.getPackageManager().hasSystemFeature( 279 PackageManager.FEATURE_WATCH); 280 return (!ActivityManager.isLowRamDeviceStatic() || isWatch) 281 && Resources.getSystem().getBoolean( 282 com.android.internal.R.bool.config_supportsMultiWindow); 283 } 284 285 /** Returns true if the system supports split screen multi-window. */ supportsSplitScreenMultiWindow(Context context)286 public static boolean supportsSplitScreenMultiWindow(Context context) { 287 return supportsMultiWindow(context) 288 && Resources.getSystem().getBoolean( 289 com.android.internal.R.bool.config_supportsSplitScreenMultiWindow); 290 } 291 292 /** 293 * Moves the top activity in the input stackId to the pinned stack. 294 * @param stackId Id of stack to move the top activity to pinned stack. 295 * @param bounds Bounds to use for pinned stack. 296 * @return True if the top activity of stack was successfully moved to the pinned stack. 297 */ 298 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) moveTopActivityToPinnedStack(int stackId, Rect bounds)299 public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) { 300 try { 301 return getService().moveTopActivityToPinnedStack(stackId, bounds); 302 } catch (RemoteException e) { 303 throw e.rethrowFromSystemServer(); 304 } 305 } 306 307 /** 308 * Start to enter lock task mode for given task by system(UI). 309 * @param taskId Id of task to lock. 310 */ 311 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) startSystemLockTaskMode(int taskId)312 public void startSystemLockTaskMode(int taskId) { 313 try { 314 getService().startSystemLockTaskMode(taskId); 315 } catch (RemoteException e) { 316 throw e.rethrowFromSystemServer(); 317 } 318 } 319 320 /** 321 * Stop lock task mode by system(UI). 322 */ 323 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) stopSystemLockTaskMode()324 public void stopSystemLockTaskMode() { 325 try { 326 getService().stopSystemLockTaskMode(); 327 } catch (RemoteException e) { 328 throw e.rethrowFromSystemServer(); 329 } 330 } 331 332 /** 333 * Move task to stack with given id. 334 * @param taskId Id of the task to move. 335 * @param stackId Id of the stack for task moving. 336 * @param toTop Whether the given task should shown to top of stack. 337 */ 338 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) moveTaskToStack(int taskId, int stackId, boolean toTop)339 public void moveTaskToStack(int taskId, int stackId, boolean toTop) { 340 try { 341 getService().moveTaskToStack(taskId, stackId, toTop); 342 } catch (RemoteException e) { 343 throw e.rethrowFromSystemServer(); 344 } 345 } 346 347 /** 348 * Resize task to given bounds. 349 * @param taskId Id of task to resize. 350 * @param bounds Bounds to resize task. 351 */ 352 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) resizeTask(int taskId, Rect bounds)353 public void resizeTask(int taskId, Rect bounds) { 354 try { 355 getService().resizeTask(taskId, bounds, RESIZE_MODE_SYSTEM); 356 } catch (RemoteException e) { 357 throw e.rethrowFromSystemServer(); 358 } 359 } 360 361 /** 362 * Resize docked stack & its task to given stack & task bounds. 363 * @param stackBounds Bounds to resize stack. 364 * @param taskBounds Bounds to resize task. 365 */ 366 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) resizeDockedStack(Rect stackBounds, Rect taskBounds)367 public void resizeDockedStack(Rect stackBounds, Rect taskBounds) { 368 try { 369 getService().resizeDockedStack(stackBounds, taskBounds, null, null, null); 370 } catch (RemoteException e) { 371 throw e.rethrowFromSystemServer(); 372 } 373 } 374 375 /** 376 * List all activity stacks information. 377 */ 378 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) listAllStacks()379 public String listAllStacks() { 380 final List<ActivityManager.StackInfo> stacks; 381 try { 382 stacks = getService().getAllStackInfos(); 383 } catch (RemoteException e) { 384 throw e.rethrowFromSystemServer(); 385 } 386 387 final StringBuilder sb = new StringBuilder(); 388 if (stacks != null) { 389 for (ActivityManager.StackInfo info : stacks) { 390 sb.append(info).append("\n"); 391 } 392 } 393 return sb.toString(); 394 } 395 396 /** 397 * Clears launch params for the given package. 398 * @param packageNames the names of the packages of which the launch params are to be cleared 399 */ 400 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) clearLaunchParamsForPackages(List<String> packageNames)401 public void clearLaunchParamsForPackages(List<String> packageNames) { 402 try { 403 getService().clearLaunchParamsForPackages(packageNames); 404 } catch (RemoteException e) { 405 e.rethrowFromSystemServer(); 406 } 407 } 408 409 /** 410 * Makes the display with the given id a single task instance display. I.e the display can only 411 * contain one task. 412 */ 413 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) setDisplayToSingleTaskInstance(int displayId)414 public void setDisplayToSingleTaskInstance(int displayId) { 415 try { 416 getService().setDisplayToSingleTaskInstance(displayId); 417 } catch (RemoteException e) { 418 throw e.rethrowFromSystemServer(); 419 } 420 } 421 422 /** 423 * Requests that an activity should enter picture-in-picture mode if possible. 424 * @hide 425 */ 426 @TestApi 427 @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) requestPictureInPictureMode(@onNull IBinder token)428 public void requestPictureInPictureMode(@NonNull IBinder token) { 429 try { 430 getService().requestPictureInPictureMode(token); 431 } catch (RemoteException e) { 432 throw e.rethrowFromSystemServer(); 433 } 434 } 435 436 /** 437 * @return whether the UI mode of the given config supports error dialogs (ANR, crash, etc). 438 * @hide 439 */ currentUiModeSupportsErrorDialogs(@onNull Configuration config)440 public static boolean currentUiModeSupportsErrorDialogs(@NonNull Configuration config) { 441 int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK; 442 return (modeType != Configuration.UI_MODE_TYPE_CAR 443 && !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER) 444 && modeType != Configuration.UI_MODE_TYPE_TELEVISION 445 && modeType != Configuration.UI_MODE_TYPE_VR_HEADSET); 446 } 447 448 /** @return whether the current UI mode supports error dialogs (ANR, crash, etc). */ currentUiModeSupportsErrorDialogs(@onNull Context context)449 public static boolean currentUiModeSupportsErrorDialogs(@NonNull Context context) { 450 final Configuration config = context.getResources().getConfiguration(); 451 return currentUiModeSupportsErrorDialogs(config); 452 } 453 } 454