1 /*
2  * Copyright (C) 2020 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.window;
18 
19 import android.annotation.BinderThread;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresPermission;
23 import android.annotation.TestApi;
24 import android.app.ActivityManager;
25 import android.os.RemoteException;
26 import android.util.Singleton;
27 import android.view.SurfaceControl;
28 
29 import java.util.List;
30 
31 /**
32  * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
33  * @hide
34  */
35 @TestApi
36 public class TaskOrganizer extends WindowOrganizer {
37 
38     /**
39      * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
40      * If there was already a TaskOrganizer for this windowing mode it will be evicted
41      * and receive taskVanished callbacks in the process.
42      */
43     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
registerOrganizer(int windowingMode)44     public final void registerOrganizer(int windowingMode) {
45         try {
46             getController().registerTaskOrganizer(mInterface, windowingMode);
47         } catch (RemoteException e) {
48             throw e.rethrowFromSystemServer();
49         }
50     }
51 
52     /** Unregisters a previously registered task organizer. */
53     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
unregisterOrganizer()54     public final void unregisterOrganizer() {
55         try {
56             getController().unregisterTaskOrganizer(mInterface);
57         } catch (RemoteException e) {
58             throw e.rethrowFromSystemServer();
59         }
60     }
61 
62     /**
63      * Called when a task with the registered windowing mode can be controlled by this task
64      * organizer. For non-root tasks, the leash may initially be hidden so it is up to the organizer
65      * to show this task.
66      */
67     @BinderThread
onTaskAppeared(@onNull ActivityManager.RunningTaskInfo taskInfo, @NonNull SurfaceControl leash)68     public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo,
69             @NonNull SurfaceControl leash) {}
70 
71     @BinderThread
onTaskVanished(@onNull ActivityManager.RunningTaskInfo taskInfo)72     public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
73 
74     @BinderThread
onTaskInfoChanged(@onNull ActivityManager.RunningTaskInfo taskInfo)75     public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
76 
77     @BinderThread
onBackPressedOnTaskRoot(@onNull ActivityManager.RunningTaskInfo taskInfo)78     public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
79 
80     /** Creates a persistent root task in WM for a particular windowing-mode. */
81     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
82     @Nullable
createRootTask(int displayId, int windowingMode)83     public static ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) {
84         try {
85             return getController().createRootTask(displayId, windowingMode);
86         } catch (RemoteException e) {
87             throw e.rethrowFromSystemServer();
88         }
89     }
90 
91     /** Deletes a persistent root task in WM */
92     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
deleteRootTask(@onNull WindowContainerToken task)93     public static boolean deleteRootTask(@NonNull WindowContainerToken task) {
94         try {
95             return getController().deleteRootTask(task);
96         } catch (RemoteException e) {
97             throw e.rethrowFromSystemServer();
98         }
99     }
100 
101     /** Gets direct child tasks (ordered from top-to-bottom) */
102     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
103     @Nullable
getChildTasks( @onNull WindowContainerToken parent, @NonNull int[] activityTypes)104     public static List<ActivityManager.RunningTaskInfo> getChildTasks(
105             @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) {
106         try {
107             return getController().getChildTasks(parent, activityTypes);
108         } catch (RemoteException e) {
109             throw e.rethrowFromSystemServer();
110         }
111     }
112 
113     /** Gets all root tasks on a display (ordered from top-to-bottom) */
114     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
115     @Nullable
getRootTasks( int displayId, @NonNull int[] activityTypes)116     public static List<ActivityManager.RunningTaskInfo> getRootTasks(
117             int displayId, @NonNull int[] activityTypes) {
118         try {
119             return getController().getRootTasks(displayId, activityTypes);
120         } catch (RemoteException e) {
121             throw e.rethrowFromSystemServer();
122         }
123     }
124 
125     /** Get the root task which contains the current ime target */
126     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
127     @Nullable
getImeTarget(int display)128     public static WindowContainerToken getImeTarget(int display) {
129         try {
130             return getController().getImeTarget(display);
131         } catch (RemoteException e) {
132             throw e.rethrowFromSystemServer();
133         }
134     }
135 
136     /**
137      * Set's the root task to launch new tasks into on a display. {@code null} means no launch
138      * root and thus new tasks just end up directly on the display.
139      */
140     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
setLaunchRoot(int displayId, @NonNull WindowContainerToken root)141     public static void setLaunchRoot(int displayId, @NonNull WindowContainerToken root) {
142         try {
143             getController().setLaunchRoot(displayId, root);
144         } catch (RemoteException e) {
145             throw e.rethrowFromSystemServer();
146         }
147     }
148 
149     /**
150      * Requests that the given task organizer is notified when back is pressed on the root activity
151      * of one of its controlled tasks.
152      */
153     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed)154     public void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
155         try {
156             getController().setInterceptBackPressedOnTaskRoot(mInterface, interceptBackPressed);
157         } catch (RemoteException e) {
158             throw e.rethrowFromSystemServer();
159         }
160     }
161 
162     private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
163 
164         @Override
165         public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
166             TaskOrganizer.this.onTaskAppeared(taskInfo, leash);
167         }
168 
169         @Override
170         public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
171             TaskOrganizer.this.onTaskVanished(taskInfo);
172         }
173 
174         @Override
175         public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
176             TaskOrganizer.this.onTaskInfoChanged(info);
177         }
178 
179         @Override
180         public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
181             TaskOrganizer.this.onBackPressedOnTaskRoot(info);
182         }
183     };
184 
getController()185     private static ITaskOrganizerController getController() {
186         return ITaskOrganizerControllerSingleton.get();
187     }
188 
189     private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
190             new Singleton<ITaskOrganizerController>() {
191                 @Override
192                 protected ITaskOrganizerController create() {
193                     try {
194                         return getWindowOrganizerController().getTaskOrganizerController();
195                     } catch (RemoteException e) {
196                         return null;
197                     }
198                 }
199             };
200 }
201