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