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.compat.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 
ActivityTaskManager(Context context, Handler handler)142     ActivityTaskManager(Context context, Handler handler) {
143     }
144 
145     /** @hide */
getService()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)
setTaskWindowingMode(int taskId, int windowingMode, boolean toTop)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)
setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, boolean animate, Rect initialBounds, boolean showRecents)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)
resizeStack(int stackId, Rect bounds)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)
removeStacksInWindowingModes(int[] windowingModes)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)
removeStacksWithActivityTypes(int[] activityTypes)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)
removeAllVisibleRecentTasks()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      */
getMaxRecentTasksStatic()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      */
getDefaultAppRecentsLimitStatic()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      */
getMaxAppRecentsLimitStatic()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      */
supportsMultiWindow(Context context)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. */
supportsSplitScreenMultiWindow(Context context)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)
moveTopActivityToPinnedStack(int stackId, Rect bounds)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)
startSystemLockTaskMode(int taskId)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)
stopSystemLockTaskMode()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)
moveTaskToStack(int taskId, int stackId, boolean toTop)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)
resizeStack(int stackId, Rect bounds, boolean animate)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)
resizeTask(int taskId, Rect bounds)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)
resizeDockedStack(Rect stackBounds, Rect taskBounds)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)
listAllStacks()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)
clearLaunchParamsForPackages(List<String> packageNames)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)
setDisplayToSingleTaskInstance(int displayId)441     public void setDisplayToSingleTaskInstance(int displayId) {
442         try {
443             getService().setDisplayToSingleTaskInstance(displayId);
444         } catch (RemoteException e) {
445             throw e.rethrowFromSystemServer();
446         }
447     }
448 }
449