blob: 13fc702aa0a0fbbdd38a36f4bdd3eb81b5ebad4a [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_RECENTS;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
26import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
28import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chung6519c1b2017-10-13 17:12:56 -070029
30import android.annotation.NonNull;
31import android.app.ActivityManager;
32import android.app.ActivityManager.RecentTaskInfo;
Sunny Goyalf5b03e02019-07-12 10:38:37 -070033import android.app.ActivityManager.RunningTaskInfo;
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;
Tony Wickhamfb63fe82018-01-16 12:14:06 -080039import android.app.WindowConfiguration.ActivityType;
Winson Chungb68213b2018-02-01 15:38:02 -080040import android.content.ContentResolver;
Winson Chung6519c1b2017-10-13 17:12:56 -070041import android.content.Context;
Winson Chungcbb15a92018-01-25 17:46:16 +000042import android.content.Intent;
Winson Chung6519c1b2017-10-13 17:12:56 -070043import android.content.pm.ActivityInfo;
44import android.content.pm.ApplicationInfo;
45import android.content.pm.PackageManager;
46import android.content.pm.UserInfo;
Winson Chung6519c1b2017-10-13 17:12:56 -070047import android.graphics.Bitmap;
Winson Chung584d6522018-02-07 23:57:38 +000048import android.graphics.Rect;
Winson Chung1c5aeff2017-11-08 17:32:28 -080049import android.os.Bundle;
Winson Chungb05b3982017-11-01 18:02:43 -070050import android.os.Handler;
Sunny Goyal50679092018-04-04 14:41:07 -070051import android.os.IBinder;
Winson Chung2cf6ad82017-11-09 17:36:59 -080052import android.os.Looper;
Winson Chung6519c1b2017-10-13 17:12:56 -070053import android.os.RemoteException;
Sunny Goyal50679092018-04-04 14:41:07 -070054import android.os.ServiceManager;
Winson Chung6519c1b2017-10-13 17:12:56 -070055import android.os.UserHandle;
Winson Chungb68213b2018-02-01 15:38:02 -080056import android.provider.Settings;
Winson Chung6519c1b2017-10-13 17:12:56 -070057import android.util.Log;
Winson Chungcbb15a92018-01-25 17:46:16 +000058import android.view.IRecentsAnimationController;
59import android.view.IRecentsAnimationRunner;
Winson Chungcbb15a92018-01-25 17:46:16 +000060import android.view.RemoteAnimationTarget;
Sunny Goyal50679092018-04-04 14:41:07 -070061
62import com.android.internal.app.IVoiceInteractionManagerService;
Winson Chungb05b3982017-11-01 18:02:43 -070063import com.android.systemui.shared.recents.model.Task;
64import com.android.systemui.shared.recents.model.Task.TaskKey;
Winson Chung6519c1b2017-10-13 17:12:56 -070065import com.android.systemui.shared.recents.model.ThumbnailData;
66
67import java.util.ArrayList;
68import java.util.List;
Matt Pietal777c82d2019-06-11 15:47:10 -040069import java.util.concurrent.Future;
Winson Chungb05b3982017-11-01 18:02:43 -070070import java.util.function.Consumer;
Winson Chung6519c1b2017-10-13 17:12:56 -070071
72public class ActivityManagerWrapper {
73
74 private static final String TAG = "ActivityManagerWrapper";
75
76 private static final ActivityManagerWrapper sInstance = new ActivityManagerWrapper();
77
Winson Chunge3dd59c2018-04-02 15:28:40 -070078 // Should match the values in PhoneWindowManager
79 public static final String CLOSE_SYSTEM_WINDOWS_REASON_RECENTS = "recentapps";
80
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() {
Tony Wickhamfb63fe82018-01-16 12:14:06 -0800113 return getRunningTask(ACTIVITY_TYPE_RECENTS /* ignoreActivityType */);
114 }
115
116 public ActivityManager.RunningTaskInfo getRunningTask(@ActivityType int ignoreActivityType) {
Winson Chungb05b3982017-11-01 18:02:43 -0700117 // Note: The set of running tasks from the system is ordered by recency
118 try {
119 List<ActivityManager.RunningTaskInfo> tasks =
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700120 ActivityTaskManager.getService().getFilteredTasks(1, ignoreActivityType,
Winson Chungb05b3982017-11-01 18:02:43 -0700121 WINDOWING_MODE_PINNED /* ignoreWindowingMode */);
122 if (tasks.isEmpty()) {
123 return null;
124 }
125 return tasks.get(0);
126 } catch (RemoteException e) {
127 return null;
128 }
129 }
130
131 /**
Winson Chung6519c1b2017-10-13 17:12:56 -0700132 * @return a list of the recents tasks.
133 */
134 public List<RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
135 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700136 return ActivityTaskManager.getService().getRecentTasks(numTasks,
Winson Chung6519c1b2017-10-13 17:12:56 -0700137 RECENT_IGNORE_UNAVAILABLE, userId).getList();
138 } catch (RemoteException e) {
139 Log.e(TAG, "Failed to get recent tasks", e);
140 return new ArrayList<>();
141 }
142 }
143
144 /**
145 * @return the task snapshot for the given {@param taskId}.
146 */
147 public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean reducedResolution) {
148 ActivityManager.TaskSnapshot snapshot = null;
149 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700150 snapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, reducedResolution);
Winson Chung6519c1b2017-10-13 17:12:56 -0700151 } catch (RemoteException e) {
152 Log.w(TAG, "Failed to retrieve task snapshot", e);
153 }
154 if (snapshot != null) {
155 return new ThumbnailData(snapshot);
156 } else {
157 return new ThumbnailData();
158 }
159 }
160
161 /**
Winson Chung6519c1b2017-10-13 17:12:56 -0700162 * @return the activity label, badging if necessary.
163 */
164 public String getBadgedActivityLabel(ActivityInfo info, int userId) {
165 return getBadgedLabel(info.loadLabel(mPackageManager).toString(), userId);
166 }
167
168 /**
169 * @return the application label, badging if necessary.
170 */
171 public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
172 return getBadgedLabel(appInfo.loadLabel(mPackageManager).toString(), userId);
173 }
174
175 /**
176 * @return the content description for a given task, badging it if necessary. The content
177 * description joins the app and activity labels.
178 */
179 public String getBadgedContentDescription(ActivityInfo info, int userId,
180 ActivityManager.TaskDescription td) {
181 String activityLabel;
182 if (td != null && td.getLabel() != null) {
183 activityLabel = td.getLabel();
184 } else {
185 activityLabel = info.loadLabel(mPackageManager).toString();
186 }
187 String applicationLabel = info.applicationInfo.loadLabel(mPackageManager).toString();
188 String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
189 return applicationLabel.equals(activityLabel)
190 ? badgedApplicationLabel
191 : badgedApplicationLabel + " " + activityLabel;
192 }
193
194 /**
195 * @return the given label for a user, badging if necessary.
196 */
197 private String getBadgedLabel(String label, int userId) {
198 if (userId != UserHandle.myUserId()) {
199 label = mPackageManager.getUserBadgedLabel(label, new UserHandle(userId)).toString();
200 }
201 return label;
202 }
Winson Chungaa357452017-10-31 11:35:30 -0700203
204 /**
Winson Chung2cf6ad82017-11-09 17:36:59 -0800205 * Starts the recents activity. The caller should manage the thread on which this is called.
Winson Chung1c5aeff2017-11-08 17:32:28 -0800206 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700207 public void startRecentsActivity(Intent intent, final AssistDataReceiver assistDataReceiver,
208 final RecentsAnimationListener animationHandler, final Consumer<Boolean> resultCallback,
Winson Chung1c5aeff2017-11-08 17:32:28 -0800209 Handler resultCallbackHandler) {
Winson Chung2cf6ad82017-11-09 17:36:59 -0800210 try {
211 IAssistDataReceiver receiver = null;
212 if (assistDataReceiver != null) {
213 receiver = new IAssistDataReceiver.Stub() {
214 public void onHandleAssistData(Bundle resultData) {
215 assistDataReceiver.onHandleAssistData(resultData);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800216 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800217 public void onHandleAssistScreenshot(Bitmap screenshot) {
218 assistDataReceiver.onHandleAssistScreenshot(screenshot);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800219 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800220 };
Winson Chung1c5aeff2017-11-08 17:32:28 -0800221 }
Winson Chungcbb15a92018-01-25 17:46:16 +0000222 IRecentsAnimationRunner runner = null;
223 if (animationHandler != null) {
224 runner = new IRecentsAnimationRunner.Stub() {
lumark54284462019-03-05 20:44:27 +0800225 @Override
Winson Chungcbb15a92018-01-25 17:46:16 +0000226 public void onAnimationStart(IRecentsAnimationController controller,
Winson Chung584d6522018-02-07 23:57:38 +0000227 RemoteAnimationTarget[] apps, Rect homeContentInsets,
228 Rect minimizedHomeBounds) {
Winson Chungcbb15a92018-01-25 17:46:16 +0000229 final RecentsAnimationControllerCompat controllerCompat =
230 new RecentsAnimationControllerCompat(controller);
231 final RemoteAnimationTargetCompat[] appsCompat =
232 RemoteAnimationTargetCompat.wrap(apps);
Winson Chung584d6522018-02-07 23:57:38 +0000233 animationHandler.onAnimationStart(controllerCompat, appsCompat,
234 homeContentInsets, minimizedHomeBounds);
Winson Chungcbb15a92018-01-25 17:46:16 +0000235 }
236
lumark54284462019-03-05 20:44:27 +0800237 @Override
238 public void onAnimationCanceled(boolean deferredWithScreenshot) {
Tracy Zhouf36321fc2019-07-31 12:16:40 -0700239 animationHandler.onAnimationCanceled(
240 deferredWithScreenshot ? new ThumbnailData() : null);
Winson Chungcbb15a92018-01-25 17:46:16 +0000241 }
242 };
243 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700244 ActivityTaskManager.getService().startRecentsActivity(intent, receiver, runner);
Winson Chung2cf6ad82017-11-09 17:36:59 -0800245 if (resultCallback != null) {
246 resultCallbackHandler.post(new Runnable() {
247 @Override
248 public void run() {
249 resultCallback.accept(true);
250 }
251 });
252 }
253 } catch (Exception e) {
254 if (resultCallback != null) {
255 resultCallbackHandler.post(new Runnable() {
256 @Override
257 public void run() {
258 resultCallback.accept(false);
259 }
260 });
261 }
262 }
Winson Chung1c5aeff2017-11-08 17:32:28 -0800263 }
264
265 /**
Winson Chungddf62972018-02-12 11:10:04 -0800266 * Cancels the remote recents animation started from {@link #startRecentsActivity}.
267 */
Winson Chung6a38fca2018-03-28 17:57:09 -0700268 public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
Winson Chungddf62972018-02-12 11:10:04 -0800269 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700270 ActivityTaskManager.getService().cancelRecentsAnimation(restoreHomeStackPosition);
Winson Chungddf62972018-02-12 11:10:04 -0800271 } catch (RemoteException e) {
272 Log.e(TAG, "Failed to cancel recents animation", e);
273 }
274 }
275
276 /**
Winson Chungb05b3982017-11-01 18:02:43 -0700277 * Starts a task from Recents.
278 *
Winson Chung2cf6ad82017-11-09 17:36:59 -0800279 * @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
Winson Chungb05b3982017-11-01 18:02:43 -0700280 */
Winson Chung2cf6ad82017-11-09 17:36:59 -0800281 public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
Winson Chungb05b3982017-11-01 18:02:43 -0700282 Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
Winson Chung2cf6ad82017-11-09 17:36:59 -0800283 startActivityFromRecentsAsync(taskKey, options, WINDOWING_MODE_UNDEFINED,
Winson Chungb05b3982017-11-01 18:02:43 -0700284 ACTIVITY_TYPE_UNDEFINED, resultCallback, resultCallbackHandler);
285 }
286
287 /**
288 * Starts a task from Recents.
289 *
290 * @param resultCallback The result success callback
291 * @param resultCallbackHandler The handler to receive the result callback
292 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700293 public void startActivityFromRecentsAsync(final Task.TaskKey taskKey, ActivityOptions options,
294 int windowingMode, int activityType, final Consumer<Boolean> resultCallback,
295 final Handler resultCallbackHandler) {
Winson Chungb05b3982017-11-01 18:02:43 -0700296 if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
297 // We show non-visible docked tasks in Recents, but we always want to launch
298 // them in the fullscreen stack.
299 if (options == null) {
300 options = ActivityOptions.makeBasic();
301 }
302 options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
303 } else if (windowingMode != WINDOWING_MODE_UNDEFINED
304 || activityType != ACTIVITY_TYPE_UNDEFINED) {
305 if (options == null) {
306 options = ActivityOptions.makeBasic();
307 }
308 options.setLaunchWindowingMode(windowingMode);
309 options.setLaunchActivityType(activityType);
310 }
311 final ActivityOptions finalOptions = options;
312
Jorim Jaggid6f0a5c2019-07-08 16:53:08 +0200313
314 boolean result = false;
315 try {
316 result = startActivityFromRecents(taskKey.id, finalOptions);
317 } catch (Exception e) {
318 // Fall through
319 }
320 final boolean finalResult = result;
321 if (resultCallback != null) {
322 resultCallbackHandler.post(new Runnable() {
323 @Override
324 public void run() {
325 resultCallback.accept(finalResult);
Winson Chung42ce9002017-11-17 13:04:07 -0800326 }
Jorim Jaggid6f0a5c2019-07-08 16:53:08 +0200327 });
328 }
Winson Chungb05b3982017-11-01 18:02:43 -0700329 }
330
331 /**
Winson Chung42ce9002017-11-17 13:04:07 -0800332 * Starts a task from Recents synchronously.
333 */
334 public boolean startActivityFromRecents(int taskId, ActivityOptions options) {
335 try {
336 Bundle optsBundle = options == null ? null : options.toBundle();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700337 ActivityTaskManager.getService().startActivityFromRecents(taskId, optsBundle);
Winson Chung42ce9002017-11-17 13:04:07 -0800338 return true;
339 } catch (Exception e) {
340 return false;
341 }
342 }
343
344 /**
Winson Chung67f5c8b2018-09-24 12:09:19 -0700345 * Moves an already resumed task to the side of the screen to initiate split screen.
346 */
347 public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
348 Rect initialBounds) {
349 try {
350 return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId,
351 createMode, true /* onTop */, false /* animate */, initialBounds,
352 true /* showRecents */);
353 } catch (RemoteException e) {
354 return false;
355 }
356 }
357
358 /**
Winson Chung2cf6ad82017-11-09 17:36:59 -0800359 * Registers a task stack listener with the system.
360 * This should be called on the main thread.
361 */
362 public void registerTaskStackListener(TaskStackChangeListener listener) {
363 synchronized (mTaskStackChangeListeners) {
364 mTaskStackChangeListeners.addListener(ActivityManager.getService(), listener);
365 }
366 }
367
368 /**
369 * Unregisters a task stack listener with the system.
370 * This should be called on the main thread.
371 */
372 public void unregisterTaskStackListener(TaskStackChangeListener listener) {
373 synchronized (mTaskStackChangeListeners) {
374 mTaskStackChangeListeners.removeListener(listener);
375 }
376 }
377
378 /**
Winson Chungaa357452017-10-31 11:35:30 -0700379 * Requests that the system close any open system windows (including other SystemUI).
380 */
Matt Pietal777c82d2019-06-11 15:47:10 -0400381 public Future<?> closeSystemWindows(final String reason) {
382 return mBackgroundExecutor.submit(new Runnable() {
Winson Chung1c5aeff2017-11-08 17:32:28 -0800383 @Override
384 public void run() {
385 try {
386 ActivityManager.getService().closeSystemDialogs(reason);
387 } catch (RemoteException e) {
388 Log.w(TAG, "Failed to close system windows", e);
389 }
Winson Chungaa357452017-10-31 11:35:30 -0700390 }
391 });
392 }
393
394 /**
395 * Removes a task by id.
396 */
Sunny Goyalbba378e2018-08-22 12:50:26 -0700397 public void removeTask(final int taskId) {
Winson Chung1c5aeff2017-11-08 17:32:28 -0800398 mBackgroundExecutor.submit(new Runnable() {
399 @Override
400 public void run() {
401 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700402 ActivityTaskManager.getService().removeTask(taskId);
Winson Chung1c5aeff2017-11-08 17:32:28 -0800403 } catch (RemoteException e) {
404 Log.w(TAG, "Failed to remove task=" + taskId, e);
405 }
Winson Chungaa357452017-10-31 11:35:30 -0700406 }
407 });
408 }
409
410 /**
Winson Chunge6439102018-07-30 15:48:01 -0700411 * Removes all the recent tasks.
412 */
413 public void removeAllRecentTasks() {
414 mBackgroundExecutor.submit(new Runnable() {
415 @Override
416 public void run() {
417 try {
418 ActivityTaskManager.getService().removeAllVisibleRecentTasks();
419 } catch (RemoteException e) {
420 Log.w(TAG, "Failed to remove all tasks", e);
421 }
422 }
423 });
424 }
425
426 /**
Winson Chungaa357452017-10-31 11:35:30 -0700427 * Cancels the current window transtion to/from Recents for the given task id.
428 */
429 public void cancelWindowTransition(int taskId) {
430 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700431 ActivityTaskManager.getService().cancelTaskWindowTransition(taskId);
Winson Chungaa357452017-10-31 11:35:30 -0700432 } catch (RemoteException e) {
433 Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
434 }
435 }
Winson Chungb68213b2018-02-01 15:38:02 -0800436
437 /**
Matthew Ng6ff33b72018-02-27 13:47:38 -0800438 * @return whether screen pinning is active.
439 */
440 public boolean isScreenPinningActive() {
441 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700442 return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED;
Matthew Ng6ff33b72018-02-27 13:47:38 -0800443 } catch (RemoteException e) {
444 return false;
445 }
446 }
447
448 /**
449 * @return whether screen pinning is enabled.
450 */
451 public boolean isScreenPinningEnabled() {
452 final ContentResolver cr = AppGlobals.getInitialApplication().getContentResolver();
453 return Settings.System.getInt(cr, Settings.System.LOCK_TO_APP_ENABLED, 0) != 0;
454 }
455
456 /**
Winson Chungb68213b2018-02-01 15:38:02 -0800457 * @return whether there is currently a locked task (ie. in screen pinning).
458 */
459 public boolean isLockToAppActive() {
460 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700461 return ActivityTaskManager.getService().getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Winson Chungb68213b2018-02-01 15:38:02 -0800462 } catch (RemoteException e) {
463 return false;
464 }
465 }
Sunny Goyal50679092018-04-04 14:41:07 -0700466
467 /**
Gustav Sennton5a4fc212019-02-28 16:12:27 +0000468 * @return whether lock task mode is active in kiosk-mode (not screen pinning).
469 */
470 public boolean isLockTaskKioskModeActive() {
471 try {
472 return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_LOCKED;
473 } catch (RemoteException e) {
474 return false;
475 }
476 }
477
478 /**
Sunny Goyal50679092018-04-04 14:41:07 -0700479 * Shows a voice session identified by {@code token}
480 * @return true if the session was shown, false otherwise
481 */
482 public boolean showVoiceSession(IBinder token, Bundle args, int flags) {
483 IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface(
484 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
485 if (service == null) {
486 return false;
487 }
488 try {
489 return service.showSessionFromSession(token, args, flags);
490 } catch (RemoteException e) {
491 return false;
492 }
493 }
Evan Rosky575c68c2018-11-15 18:54:25 -0800494
495 /**
496 * Returns true if the system supports freeform multi-window.
497 */
498 public boolean supportsFreeformMultiWindow(Context context) {
499 final boolean freeformDevOption = Settings.Global.getInt(context.getContentResolver(),
500 Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
501 return ActivityTaskManager.supportsMultiWindow(context)
502 && (context.getPackageManager().hasSystemFeature(
503 PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
504 || freeformDevOption);
505 }
Sunny Goyalf5b03e02019-07-12 10:38:37 -0700506
507 /**
508 * Returns true if the running task represents the home task
509 */
510 public static boolean isHomeTask(RunningTaskInfo info) {
511 return info.configuration.windowConfiguration.getActivityType()
512 == WindowConfiguration.ACTIVITY_TYPE_HOME;
513 }
Winson Chung6519c1b2017-10-13 17:12:56 -0700514}