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