blob: 806678f23bb387108ff4d342dd7b8c2c140c3eb3 [file] [log] [blame]
Winson Chung6519c1b2017-10-13 17:12:56 -07001/*
2 * Copyright (C) 2015 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
17package com.android.systemui.shared.system;
18
Gustav Sennton5a4fc212019-02-28 16:12:27 +000019import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
Winson Chungb68213b2018-02-01 15:38:02 -080020import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
Matthew Ng6ff33b72018-02-27 13:47:38 -080021import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
Winson Chung6519c1b2017-10-13 17:12:56 -070022import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
Winson Chungb05b3982017-11-01 18:02:43 -070023import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Winson Chungb05b3982017-11-01 18:02:43 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
25import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
26import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chung6519c1b2017-10-13 17:12:56 -070027
28import android.annotation.NonNull;
Riddle Hsu440f88b2019-11-06 22:17:35 +080029import android.app.Activity;
Winson Chung6519c1b2017-10-13 17:12:56 -070030import android.app.ActivityManager;
31import android.app.ActivityManager.RecentTaskInfo;
Sunny Goyalf5b03e02019-07-12 10:38:37 -070032import android.app.ActivityManager.RunningTaskInfo;
Tracy Zhou8089ffa2019-07-30 17:30:43 -070033import android.app.ActivityManager.TaskSnapshot;
Winson Chungb05b3982017-11-01 18:02:43 -070034import android.app.ActivityOptions;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070035import android.app.ActivityTaskManager;
Winson Chung6519c1b2017-10-13 17:12:56 -070036import android.app.AppGlobals;
Winson Chung2cf6ad82017-11-09 17:36:59 -080037import android.app.IAssistDataReceiver;
Sunny Goyalf5b03e02019-07-12 10:38:37 -070038import android.app.WindowConfiguration;
Winson Chungb68213b2018-02-01 15:38:02 -080039import android.content.ContentResolver;
Winson Chung6519c1b2017-10-13 17:12:56 -070040import android.content.Context;
Winson Chungcbb15a92018-01-25 17:46:16 +000041import android.content.Intent;
Winson Chung6519c1b2017-10-13 17:12:56 -070042import android.content.pm.ActivityInfo;
43import android.content.pm.ApplicationInfo;
44import android.content.pm.PackageManager;
45import android.content.pm.UserInfo;
Winson Chung6519c1b2017-10-13 17:12:56 -070046import android.graphics.Bitmap;
Winson Chung584d6522018-02-07 23:57:38 +000047import android.graphics.Rect;
Winson Chung1c5aeff2017-11-08 17:32:28 -080048import android.os.Bundle;
Winson Chungb05b3982017-11-01 18:02:43 -070049import android.os.Handler;
Sunny Goyal50679092018-04-04 14:41:07 -070050import android.os.IBinder;
Winson Chung2cf6ad82017-11-09 17:36:59 -080051import android.os.Looper;
Winson Chung6519c1b2017-10-13 17:12:56 -070052import android.os.RemoteException;
Sunny Goyal50679092018-04-04 14:41:07 -070053import android.os.ServiceManager;
Winson Chung6519c1b2017-10-13 17:12:56 -070054import android.os.UserHandle;
Winson Chungb68213b2018-02-01 15:38:02 -080055import android.provider.Settings;
Winson Chung6519c1b2017-10-13 17:12:56 -070056import android.util.Log;
Winson Chungcbb15a92018-01-25 17:46:16 +000057import android.view.IRecentsAnimationController;
58import android.view.IRecentsAnimationRunner;
Winson Chungcbb15a92018-01-25 17:46:16 +000059import android.view.RemoteAnimationTarget;
Sunny Goyal50679092018-04-04 14:41:07 -070060
61import com.android.internal.app.IVoiceInteractionManagerService;
Winson Chungb05b3982017-11-01 18:02:43 -070062import com.android.systemui.shared.recents.model.Task;
63import com.android.systemui.shared.recents.model.Task.TaskKey;
Winson Chung6519c1b2017-10-13 17:12:56 -070064import com.android.systemui.shared.recents.model.ThumbnailData;
65
66import java.util.ArrayList;
67import java.util.List;
Matt Pietal777c82d2019-06-11 15:47:10 -040068import java.util.concurrent.Future;
Winson Chungb05b3982017-11-01 18:02:43 -070069import java.util.function.Consumer;
Winson Chung6519c1b2017-10-13 17:12:56 -070070
71public class ActivityManagerWrapper {
72
73 private static final String TAG = "ActivityManagerWrapper";
74
75 private static final ActivityManagerWrapper sInstance = new ActivityManagerWrapper();
76
Winson Chunge3dd59c2018-04-02 15:28:40 -070077 // Should match the values in PhoneWindowManager
78 public static final String CLOSE_SYSTEM_WINDOWS_REASON_RECENTS = "recentapps";
Andy Wickham709825d2019-10-16 15:01:46 -070079 public static final String CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY = "homekey";
Winson Chunge3dd59c2018-04-02 15:28:40 -070080
Winson Chung6519c1b2017-10-13 17:12:56 -070081 private final PackageManager mPackageManager;
Winson Chungaa357452017-10-31 11:35:30 -070082 private final BackgroundExecutor mBackgroundExecutor;
Winson Chung2cf6ad82017-11-09 17:36:59 -080083 private final TaskStackChangeListeners mTaskStackChangeListeners;
Winson Chung6519c1b2017-10-13 17:12:56 -070084
85 private ActivityManagerWrapper() {
86 final Context context = AppGlobals.getInitialApplication();
87 mPackageManager = context.getPackageManager();
Winson Chungaa357452017-10-31 11:35:30 -070088 mBackgroundExecutor = BackgroundExecutor.get();
Winson Chung2cf6ad82017-11-09 17:36:59 -080089 mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper());
Winson Chung6519c1b2017-10-13 17:12:56 -070090 }
91
92 public static ActivityManagerWrapper getInstance() {
93 return sInstance;
94 }
95
96 /**
97 * @return the current user's id.
98 */
99 public int getCurrentUserId() {
100 UserInfo ui;
101 try {
102 ui = ActivityManager.getService().getCurrentUser();
103 return ui != null ? ui.id : 0;
104 } catch (RemoteException e) {
105 throw e.rethrowFromSystemServer();
106 }
107 }
108
109 /**
Winson Chungb05b3982017-11-01 18:02:43 -0700110 * @return the top running task (can be {@code null}).
111 */
112 public ActivityManager.RunningTaskInfo getRunningTask() {
Winson Chunge5ab0172020-03-21 23:00:24 -0700113 return getRunningTask(false /* filterVisibleRecents */);
Tony Wickhamfb63fe82018-01-16 12:14:06 -0800114 }
115
Winson Chunge5ab0172020-03-21 23:00:24 -0700116 /**
117 * @return the top running task filtering only for tasks that can be visible in the recent tasks
118 * list (can be {@code null}).
119 */
120 public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
Winson Chungb05b3982017-11-01 18:02:43 -0700121 // Note: The set of running tasks from the system is ordered by recency
122 try {
123 List<ActivityManager.RunningTaskInfo> tasks =
Winson Chunge5ab0172020-03-21 23:00:24 -0700124 ActivityTaskManager.getService().getFilteredTasks(1, filterOnlyVisibleRecents);
Winson Chungb05b3982017-11-01 18:02:43 -0700125 if (tasks.isEmpty()) {
126 return null;
127 }
128 return tasks.get(0);
129 } catch (RemoteException e) {
130 return null;
131 }
132 }
133
134 /**
Winson Chung6519c1b2017-10-13 17:12:56 -0700135 * @return a list of the recents tasks.
136 */
137 public List<RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
138 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700139 return ActivityTaskManager.getService().getRecentTasks(numTasks,
Winson Chung6519c1b2017-10-13 17:12:56 -0700140 RECENT_IGNORE_UNAVAILABLE, userId).getList();
141 } catch (RemoteException e) {
142 Log.e(TAG, "Failed to get recent tasks", e);
143 return new ArrayList<>();
144 }
145 }
146
147 /**
148 * @return the task snapshot for the given {@param taskId}.
149 */
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800150 public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
Winson Chung6519c1b2017-10-13 17:12:56 -0700151 ActivityManager.TaskSnapshot snapshot = null;
152 try {
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800153 snapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
Winson Chung6519c1b2017-10-13 17:12:56 -0700154 } catch (RemoteException e) {
155 Log.w(TAG, "Failed to retrieve task snapshot", e);
156 }
157 if (snapshot != null) {
158 return new ThumbnailData(snapshot);
159 } else {
160 return new ThumbnailData();
161 }
162 }
163
164 /**
Riddle Hsu440f88b2019-11-06 22:17:35 +0800165 * Removes the outdated snapshot of home task.
166 */
167 public void invalidateHomeTaskSnapshot(final Activity homeActivity) {
168 mBackgroundExecutor.submit(new Runnable() {
169 @Override
170 public void run() {
171 try {
172 ActivityTaskManager.getService().invalidateHomeTaskSnapshot(
173 homeActivity.getActivityToken());
174 } catch (RemoteException e) {
175 Log.w(TAG, "Failed to invalidate home snapshot", e);
176 }
177 }
178 });
179 }
180
181 /**
Winson Chung6519c1b2017-10-13 17:12:56 -0700182 * @return the activity label, badging if necessary.
183 */
184 public String getBadgedActivityLabel(ActivityInfo info, int userId) {
185 return getBadgedLabel(info.loadLabel(mPackageManager).toString(), userId);
186 }
187
188 /**
189 * @return the application label, badging if necessary.
190 */
191 public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
192 return getBadgedLabel(appInfo.loadLabel(mPackageManager).toString(), userId);
193 }
194
195 /**
196 * @return the content description for a given task, badging it if necessary. The content
197 * description joins the app and activity labels.
198 */
199 public String getBadgedContentDescription(ActivityInfo info, int userId,
200 ActivityManager.TaskDescription td) {
201 String activityLabel;
202 if (td != null && td.getLabel() != null) {
203 activityLabel = td.getLabel();
204 } else {
205 activityLabel = info.loadLabel(mPackageManager).toString();
206 }
207 String applicationLabel = info.applicationInfo.loadLabel(mPackageManager).toString();
208 String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
209 return applicationLabel.equals(activityLabel)
210 ? badgedApplicationLabel
211 : badgedApplicationLabel + " " + activityLabel;
212 }
213
214 /**
215 * @return the given label for a user, badging if necessary.
216 */
217 private String getBadgedLabel(String label, int userId) {
218 if (userId != UserHandle.myUserId()) {
219 label = mPackageManager.getUserBadgedLabel(label, new UserHandle(userId)).toString();
220 }
221 return label;
222 }
Winson Chungaa357452017-10-31 11:35:30 -0700223
224 /**
Winson Chung2cf6ad82017-11-09 17:36:59 -0800225 * Starts the recents activity. The caller should manage the thread on which this is called.
Winson Chung1c5aeff2017-11-08 17:32:28 -0800226 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700227 public void startRecentsActivity(Intent intent, final AssistDataReceiver assistDataReceiver,
228 final RecentsAnimationListener animationHandler, final Consumer<Boolean> resultCallback,
Winson Chung1c5aeff2017-11-08 17:32:28 -0800229 Handler resultCallbackHandler) {
Winson Chung2cf6ad82017-11-09 17:36:59 -0800230 try {
231 IAssistDataReceiver receiver = null;
232 if (assistDataReceiver != null) {
233 receiver = new IAssistDataReceiver.Stub() {
234 public void onHandleAssistData(Bundle resultData) {
235 assistDataReceiver.onHandleAssistData(resultData);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800236 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800237 public void onHandleAssistScreenshot(Bitmap screenshot) {
238 assistDataReceiver.onHandleAssistScreenshot(screenshot);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800239 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800240 };
Winson Chung1c5aeff2017-11-08 17:32:28 -0800241 }
Winson Chungcbb15a92018-01-25 17:46:16 +0000242 IRecentsAnimationRunner runner = null;
243 if (animationHandler != null) {
244 runner = new IRecentsAnimationRunner.Stub() {
lumark54284462019-03-05 20:44:27 +0800245 @Override
Winson Chungcbb15a92018-01-25 17:46:16 +0000246 public void onAnimationStart(IRecentsAnimationController controller,
Winson Chungd5852192019-09-06 17:20:28 -0700247 RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
248 Rect homeContentInsets, Rect minimizedHomeBounds) {
Winson Chungcbb15a92018-01-25 17:46:16 +0000249 final RecentsAnimationControllerCompat controllerCompat =
250 new RecentsAnimationControllerCompat(controller);
251 final RemoteAnimationTargetCompat[] appsCompat =
252 RemoteAnimationTargetCompat.wrap(apps);
Winson Chungd5852192019-09-06 17:20:28 -0700253 final RemoteAnimationTargetCompat[] wallpapersCompat =
254 RemoteAnimationTargetCompat.wrap(wallpapers);
Winson Chung584d6522018-02-07 23:57:38 +0000255 animationHandler.onAnimationStart(controllerCompat, appsCompat,
Winson Chungd5852192019-09-06 17:20:28 -0700256 wallpapersCompat, homeContentInsets, minimizedHomeBounds);
Winson Chungcbb15a92018-01-25 17:46:16 +0000257 }
258
lumark54284462019-03-05 20:44:27 +0800259 @Override
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700260 public void onAnimationCanceled(TaskSnapshot taskSnapshot) {
Tracy Zhouf36321fc2019-07-31 12:16:40 -0700261 animationHandler.onAnimationCanceled(
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700262 taskSnapshot != null ? new ThumbnailData(taskSnapshot) : null);
Winson Chungcbb15a92018-01-25 17:46:16 +0000263 }
lumark04bceb92020-03-07 00:03:33 +0800264
265 @Override
266 public void onTaskAppeared(RemoteAnimationTarget app) {
267 animationHandler.onTaskAppeared(new RemoteAnimationTargetCompat(app));
268 }
Winson Chungcbb15a92018-01-25 17:46:16 +0000269 };
270 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700271 ActivityTaskManager.getService().startRecentsActivity(intent, receiver, runner);
Winson Chung2cf6ad82017-11-09 17:36:59 -0800272 if (resultCallback != null) {
273 resultCallbackHandler.post(new Runnable() {
274 @Override
275 public void run() {
276 resultCallback.accept(true);
277 }
278 });
279 }
280 } catch (Exception e) {
281 if (resultCallback != null) {
282 resultCallbackHandler.post(new Runnable() {
283 @Override
284 public void run() {
285 resultCallback.accept(false);
286 }
287 });
288 }
289 }
Winson Chung1c5aeff2017-11-08 17:32:28 -0800290 }
291
292 /**
Winson Chungddf62972018-02-12 11:10:04 -0800293 * Cancels the remote recents animation started from {@link #startRecentsActivity}.
294 */
Winson Chung6a38fca2018-03-28 17:57:09 -0700295 public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
Winson Chungddf62972018-02-12 11:10:04 -0800296 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700297 ActivityTaskManager.getService().cancelRecentsAnimation(restoreHomeStackPosition);
Winson Chungddf62972018-02-12 11:10:04 -0800298 } catch (RemoteException e) {
299 Log.e(TAG, "Failed to cancel recents animation", e);
300 }
301 }
302
303 /**
Winson Chungb05b3982017-11-01 18:02:43 -0700304 * Starts a task from Recents.
305 *
Winson Chung2cf6ad82017-11-09 17:36:59 -0800306 * @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
Winson Chungb05b3982017-11-01 18:02:43 -0700307 */
Winson Chung2cf6ad82017-11-09 17:36:59 -0800308 public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
Winson Chungb05b3982017-11-01 18:02:43 -0700309 Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
Winson Chung2cf6ad82017-11-09 17:36:59 -0800310 startActivityFromRecentsAsync(taskKey, options, WINDOWING_MODE_UNDEFINED,
Winson Chungb05b3982017-11-01 18:02:43 -0700311 ACTIVITY_TYPE_UNDEFINED, resultCallback, resultCallbackHandler);
312 }
313
314 /**
315 * Starts a task from Recents.
316 *
317 * @param resultCallback The result success callback
318 * @param resultCallbackHandler The handler to receive the result callback
319 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700320 public void startActivityFromRecentsAsync(final Task.TaskKey taskKey, ActivityOptions options,
321 int windowingMode, int activityType, final Consumer<Boolean> resultCallback,
322 final Handler resultCallbackHandler) {
Winson Chungb05b3982017-11-01 18:02:43 -0700323 if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
324 // We show non-visible docked tasks in Recents, but we always want to launch
325 // them in the fullscreen stack.
326 if (options == null) {
327 options = ActivityOptions.makeBasic();
328 }
329 options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
330 } else if (windowingMode != WINDOWING_MODE_UNDEFINED
331 || activityType != ACTIVITY_TYPE_UNDEFINED) {
332 if (options == null) {
333 options = ActivityOptions.makeBasic();
334 }
335 options.setLaunchWindowingMode(windowingMode);
336 options.setLaunchActivityType(activityType);
337 }
338 final ActivityOptions finalOptions = options;
339
Jorim Jaggid6f0a5c2019-07-08 16:53:08 +0200340
341 boolean result = false;
342 try {
343 result = startActivityFromRecents(taskKey.id, finalOptions);
344 } catch (Exception e) {
345 // Fall through
346 }
347 final boolean finalResult = result;
348 if (resultCallback != null) {
349 resultCallbackHandler.post(new Runnable() {
350 @Override
351 public void run() {
352 resultCallback.accept(finalResult);
Winson Chung42ce9002017-11-17 13:04:07 -0800353 }
Jorim Jaggid6f0a5c2019-07-08 16:53:08 +0200354 });
355 }
Winson Chungb05b3982017-11-01 18:02:43 -0700356 }
357
358 /**
Winson Chung42ce9002017-11-17 13:04:07 -0800359 * Starts a task from Recents synchronously.
360 */
361 public boolean startActivityFromRecents(int taskId, ActivityOptions options) {
362 try {
363 Bundle optsBundle = options == null ? null : options.toBundle();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700364 ActivityTaskManager.getService().startActivityFromRecents(taskId, optsBundle);
Winson Chung42ce9002017-11-17 13:04:07 -0800365 return true;
366 } catch (Exception e) {
367 return false;
368 }
369 }
370
371 /**
Winson Chung67f5c8b2018-09-24 12:09:19 -0700372 * Moves an already resumed task to the side of the screen to initiate split screen.
373 */
374 public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
375 Rect initialBounds) {
376 try {
377 return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId,
Evan Rosky73a7fe92019-11-18 18:28:01 -0800378 true /* onTop */);
Winson Chung67f5c8b2018-09-24 12:09:19 -0700379 } catch (RemoteException e) {
380 return false;
381 }
382 }
383
384 /**
Winson Chung2cf6ad82017-11-09 17:36:59 -0800385 * Registers a task stack listener with the system.
386 * This should be called on the main thread.
387 */
388 public void registerTaskStackListener(TaskStackChangeListener listener) {
389 synchronized (mTaskStackChangeListeners) {
390 mTaskStackChangeListeners.addListener(ActivityManager.getService(), listener);
391 }
392 }
393
394 /**
395 * Unregisters a task stack listener with the system.
396 * This should be called on the main thread.
397 */
398 public void unregisterTaskStackListener(TaskStackChangeListener listener) {
399 synchronized (mTaskStackChangeListeners) {
400 mTaskStackChangeListeners.removeListener(listener);
401 }
402 }
403
404 /**
Winson Chungaa357452017-10-31 11:35:30 -0700405 * Requests that the system close any open system windows (including other SystemUI).
406 */
Matt Pietal777c82d2019-06-11 15:47:10 -0400407 public Future<?> closeSystemWindows(final String reason) {
408 return mBackgroundExecutor.submit(new Runnable() {
Winson Chung1c5aeff2017-11-08 17:32:28 -0800409 @Override
410 public void run() {
411 try {
412 ActivityManager.getService().closeSystemDialogs(reason);
413 } catch (RemoteException e) {
414 Log.w(TAG, "Failed to close system windows", e);
415 }
Winson Chungaa357452017-10-31 11:35:30 -0700416 }
417 });
418 }
419
420 /**
421 * Removes a task by id.
422 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700423 public void removeTask(final int taskId) {
Winson Chung1c5aeff2017-11-08 17:32:28 -0800424 mBackgroundExecutor.submit(new Runnable() {
425 @Override
426 public void run() {
427 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700428 ActivityTaskManager.getService().removeTask(taskId);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800429 } catch (RemoteException e) {
430 Log.w(TAG, "Failed to remove task=" + taskId, e);
431 }
Winson Chungaa357452017-10-31 11:35:30 -0700432 }
433 });
434 }
435
436 /**
Winson Chunge6439102018-07-30 15:48:01 -0700437 * Removes all the recent tasks.
438 */
439 public void removeAllRecentTasks() {
440 mBackgroundExecutor.submit(new Runnable() {
441 @Override
442 public void run() {
443 try {
444 ActivityTaskManager.getService().removeAllVisibleRecentTasks();
445 } catch (RemoteException e) {
446 Log.w(TAG, "Failed to remove all tasks", e);
447 }
448 }
449 });
450 }
451
452 /**
Winson Chungaa357452017-10-31 11:35:30 -0700453 * Cancels the current window transtion to/from Recents for the given task id.
454 */
455 public void cancelWindowTransition(int taskId) {
456 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700457 ActivityTaskManager.getService().cancelTaskWindowTransition(taskId);
Winson Chungaa357452017-10-31 11:35:30 -0700458 } catch (RemoteException e) {
459 Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
460 }
461 }
Winson Chungb68213b2018-02-01 15:38:02 -0800462
463 /**
Matthew Ng6ff33b72018-02-27 13:47:38 -0800464 * @return whether screen pinning is active.
465 */
466 public boolean isScreenPinningActive() {
467 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700468 return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED;
Matthew Ng6ff33b72018-02-27 13:47:38 -0800469 } catch (RemoteException e) {
470 return false;
471 }
472 }
473
474 /**
475 * @return whether screen pinning is enabled.
476 */
477 public boolean isScreenPinningEnabled() {
478 final ContentResolver cr = AppGlobals.getInitialApplication().getContentResolver();
479 return Settings.System.getInt(cr, Settings.System.LOCK_TO_APP_ENABLED, 0) != 0;
480 }
481
482 /**
Winson Chungb68213b2018-02-01 15:38:02 -0800483 * @return whether there is currently a locked task (ie. in screen pinning).
484 */
485 public boolean isLockToAppActive() {
486 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700487 return ActivityTaskManager.getService().getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Winson Chungb68213b2018-02-01 15:38:02 -0800488 } catch (RemoteException e) {
489 return false;
490 }
491 }
Sunny Goyal50679092018-04-04 14:41:07 -0700492
493 /**
Gustav Sennton5a4fc212019-02-28 16:12:27 +0000494 * @return whether lock task mode is active in kiosk-mode (not screen pinning).
495 */
496 public boolean isLockTaskKioskModeActive() {
497 try {
498 return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_LOCKED;
499 } catch (RemoteException e) {
500 return false;
501 }
502 }
503
504 /**
Sunny Goyal50679092018-04-04 14:41:07 -0700505 * Shows a voice session identified by {@code token}
506 * @return true if the session was shown, false otherwise
507 */
508 public boolean showVoiceSession(IBinder token, Bundle args, int flags) {
509 IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface(
510 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
511 if (service == null) {
512 return false;
513 }
514 try {
515 return service.showSessionFromSession(token, args, flags);
516 } catch (RemoteException e) {
517 return false;
518 }
519 }
Evan Rosky575c68c2018-11-15 18:54:25 -0800520
521 /**
522 * Returns true if the system supports freeform multi-window.
523 */
524 public boolean supportsFreeformMultiWindow(Context context) {
525 final boolean freeformDevOption = Settings.Global.getInt(context.getContentResolver(),
526 Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
527 return ActivityTaskManager.supportsMultiWindow(context)
528 && (context.getPackageManager().hasSystemFeature(
529 PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
530 || freeformDevOption);
531 }
Sunny Goyalf5b03e02019-07-12 10:38:37 -0700532
533 /**
534 * Returns true if the running task represents the home task
535 */
536 public static boolean isHomeTask(RunningTaskInfo info) {
537 return info.configuration.windowConfiguration.getActivityType()
538 == WindowConfiguration.ACTIVITY_TYPE_HOME;
539 }
Winson Chung6519c1b2017-10-13 17:12:56 -0700540}