• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.car.cts.builtin.app;
18 
19 import static android.car.builtin.app.ActivityManagerHelper.ProcessObserverCallback;
20 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21 import static android.view.Display.DEFAULT_DISPLAY;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 import static com.google.common.truth.Truth.assertWithMessage;
25 
26 import static org.junit.Assume.assumeFalse;
27 
28 import android.app.Activity;
29 import android.app.ActivityManager;
30 import android.app.ActivityOptions;
31 import android.app.Instrumentation;
32 import android.app.TaskInfo;
33 import android.car.builtin.app.ActivityManagerHelper;
34 import android.car.cts.builtin.activity.ActivityManagerTestActivityBase;
35 import android.car.test.PermissionsCheckerRule;
36 import android.car.test.PermissionsCheckerRule.EnsureHasPermission;
37 import android.content.ComponentName;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.pm.PackageManager;
41 import android.graphics.Rect;
42 import android.os.Process;
43 import android.os.UserHandle;
44 import android.server.wm.ActivityManagerTestBase;
45 import android.server.wm.WindowManagerState;
46 import android.util.Log;
47 
48 import androidx.test.platform.app.InstrumentationRegistry;
49 import androidx.test.runner.AndroidJUnit4;
50 
51 import com.android.bedstead.nene.TestApis;
52 import com.android.bedstead.permissions.PermissionContext;
53 import com.android.compatibility.common.util.PollingCheck;
54 import com.android.compatibility.common.util.SystemUtil;
55 
56 import org.junit.Before;
57 import org.junit.Ignore;
58 import org.junit.Rule;
59 import org.junit.Test;
60 import org.junit.runner.RunWith;
61 
62 import java.util.List;
63 import java.util.concurrent.CountDownLatch;
64 import java.util.concurrent.TimeUnit;
65 import java.util.regex.Matcher;
66 import java.util.regex.Pattern;
67 
68 @RunWith(AndroidJUnit4.class)
69 public final class ActivityManagerHelperTest extends ActivityManagerTestBase {
70 
71     @Rule
72     public final PermissionsCheckerRule mPermissionsCheckerRule = new PermissionsCheckerRule();
73 
74     // type values from frameworks/base/core/java/android/app/WindowConfiguration
75     enum ActivityType {
76         ACTIVITY_TYPE_UNDEFINED,
77         ACTIVITY_TYPE_STANDARD
78     }
79 
80     private static final String TAG = ActivityManagerHelperTest.class.getSimpleName();
81 
82     private static final String PERMISSION_SET_ACTIVITY_WATCHER =
83             "android.permission.SET_ACTIVITY_WATCHER";
84     private static final String NOT_REQUESTED_PERMISSION_CAR_MILEAGE =
85             "android.car.permission.CAR_MILEAGE";
86     private static final String NOT_REQUESTED_PERMISSION_READ_CAR_POWER_POLICY =
87             "android.car.permission.READ_CAR_POWER_POLICY";
88 
89     private static final String GRANTED_PERMISSION_INTERACT_ACROSS_USERS =
90             "android.permission.INTERACT_ACROSS_USERS";
91 
92     // ActivityManagerHelper.removeTask needs this permission
93     private static final String PERMISSION_REMOVE_TASKS = "android.permission.REMOVE_TASKS";
94     // IActivityManager.getAllRootTaskInfos called in ActivityManagerHelper.stopAllTaskForUser
95     // needs this permission.
96     private static final String PERMISSION_MANAGE_ACTIVITY_TASKS =
97             "android.permission.MANAGE_ACTIVITY_TASKS";
98     // ActivityManager.getRunningAppProcess called in isAppRunning needs this permission
99     private static final String PERMISSION_INTERACT_ACROSS_USERS_FULL =
100             "android.permission.INTERACT_ACROSS_USERS_FULL";
101     private static final String PERMISSION_REAL_GET_TASKS =
102             "android.permission.REAL_GET_TASKS";
103 
104     private static final String SIMPLE_APP_PACKAGE_NAME = "android.car.cts.builtin.apps.simple";
105     private static final String SIMPLE_ACTIVITY_RELATIVE_NAME = ".SimpleActivity";
106     private static final String SIMPLE_ACTIVITY_NAME = SIMPLE_APP_PACKAGE_NAME
107             + SIMPLE_ACTIVITY_RELATIVE_NAME;
108     private static final String START_SIMPLE_ACTIVITY_COMMAND = "am start -W -n "
109             + SIMPLE_APP_PACKAGE_NAME + "/" + SIMPLE_ACTIVITY_RELATIVE_NAME;
110     private static final ComponentName SIMPLE_ACTIVITY_COMPONENT_NAME =
111             new ComponentName(SIMPLE_APP_PACKAGE_NAME, SIMPLE_ACTIVITY_RELATIVE_NAME);
112 
113     // TODO(b/230757942): replace following shell commands with direct API calls
114     private static final String CREATE_USER_COMMAND = "cmd car_service create-user ";
115     private static final String SWITCH_USER_COMMAND = "cmd car_service switch-user ";
116     private static final String REMOVE_USER_COMMAND = "cmd car_service remove-user ";
117     private static final String START_USER_COMMAND = "am start-user -w ";
118     private static final String GET_CURRENT_USER_COMMAND = "am get-current-user ";
119     private static final String CTS_CAR_TEST_USER_NAME = "CtsCarTestUser";
120     // the value from UserHandle.USER_NULL
121     private static final int INVALID_USER_ID = -10_000;
122 
123     private static final int OWNING_UID = UserHandle.ALL.getIdentifier();
124     private static final int MAX_NUM_TASKS = 1_000;
125     private static final int TIMEOUT_MS = 4_000;
126 
127     // x coordinate of the left boundary line of the animation rectangle
128     private static final int ANIMATION_RECT_LEFT = 0;
129     // y coordinate of the top boundary line of the animation rectangle
130     private static final int ANIMATION_RECT_TOP = 200;
131     // x coordinate of the right boundary line of the animation rectangle
132     private static final int ANIMATION_RECT_RIGHT = 400;
133     // y coordinate of the bottom boundary line of the animation rectangle
134     private static final int ANIMATION_RECT_BOTTOM = 0;
135 
136     private static final int RANDOM_NON_DEFAULT_DISPLAY_ID = 1;
137     private static final boolean NON_DEFAULT_LOCK_TASK_MODE = true;
138     private static final boolean
139             NON_DEFAULT_PENDING_INTENT_BACKGROUND_ACTIVITY_LAUNCH_ALLOWED = true;
140 
141 
142     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
143     private final Context mContext = mInstrumentation.getContext();
144 
145     @Before
setUp()146     public void setUp() throws Exception {
147         // Home was launched in ActivityManagerTestBase#setUp, wait until it is stable,
148         // in order not to mix the event of its TaskView Activity with the TestActivity.
149         mWmState.waitForHomeActivityVisible();
150     }
151 
152     @Test
153     @EnsureHasPermission(GRANTED_PERMISSION_INTERACT_ACROSS_USERS)
testCheckComponentPermission()154     public void testCheckComponentPermission() throws Exception {
155         // not requested from Manifest
156         assertComponentPermissionNotGranted(NOT_REQUESTED_PERMISSION_CAR_MILEAGE);
157         assertComponentPermissionNotGranted(NOT_REQUESTED_PERMISSION_READ_CAR_POWER_POLICY);
158 
159         // requested from Manifest and granted
160         assertComponentPermissionGranted(GRANTED_PERMISSION_INTERACT_ACROSS_USERS);
161     }
162 
163     @Test
testSetFocusedTask()164     public void testSetFocusedTask() throws Exception {
165         assumeFalse(hasAutomotiveSplitscreenMultitaskingFeature());
166         // setup
167         ActivityA task1BottomActivity = launchTestActivity(ActivityA.class);
168         ActivityB task1TopActivity = launchTestActivity(ActivityB.class);
169         ActivityC task2TopActivity = launchTestActivity(ActivityC.class);
170 
171         logActivityStack("amTestActivitys ",
172                 task1BottomActivity, task1TopActivity, task2TopActivity);
173 
174         assertWithMessage("bottom activity is the task root")
175                 .that(task1BottomActivity.isTaskRoot()).isTrue();
176         assertWithMessage("task id of the top activity in the task1")
177                 .that(task1TopActivity.getTaskId()).isEqualTo(task1BottomActivity.getTaskId());
178         assertWithMessage("task id of the top activity in the task2")
179                 .that(task2TopActivity.getTaskId()).isNotEqualTo(task1TopActivity.getTaskId());
180         assertWithMessage("task1 top activity is visible")
181                 .that(task1TopActivity.isVisible()).isFalse();
182         assertWithMessage("task2 top activity is visible")
183                 .that(task2TopActivity.isVisible()).isTrue();
184 
185         // execute
186         try {
187             mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
188                     PERMISSION_MANAGE_ACTIVITY_TASKS);
189 
190             ActivityManagerHelper.setFocusedTask(task1BottomActivity.getTaskId());
191         } finally {
192             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
193         }
194 
195 
196         // assert
197         ComponentName activityName = task1TopActivity.getComponentName();
198         waitAndAssertResumedAndFocusedActivityOnDisplay(activityName, DEFAULT_DISPLAY,
199                 "Activity must be resumed");
200         waitAndAssertFocusStatusChanged(task1TopActivity, true);
201         assertWithMessage("task1 top activity is visible")
202                 .that(task1TopActivity.isVisible()).isTrue();
203 
204         // teardown
205         task1TopActivity.finish();
206         task1BottomActivity.finish();
207         task2TopActivity.finish();
208     }
209 
210     @Test
testRemoveTask()211     public void testRemoveTask() throws Exception {
212         // setup
213         ActivityC testActivity = launchTestActivity(ActivityC.class);
214         int taskId = testActivity.getTaskId();
215         assertThat(doesTaskExist(taskId)).isTrue();
216 
217 
218         // execute
219         try (PermissionContext p = TestApis.permissions().withPermission(PERMISSION_REMOVE_TASKS)) {
220             ActivityManagerHelper.removeTask(taskId);
221         }
222 
223         // assert
224         PollingCheck.waitFor(TIMEOUT_MS, () -> testActivity.isDestroyed());
225         assertThat(doesTaskExist(taskId)).isFalse();
226     }
227 
228     @Test
testProcessObserverCallback()229     public void testProcessObserverCallback() throws Exception {
230         // setup
231         ProcessObserverCallbackTestImpl callbackImpl = new ProcessObserverCallbackTestImpl();
232 
233         // execute
234         try {
235             mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
236                     PERMISSION_SET_ACTIVITY_WATCHER);  // for registerProcessObserverCallback
237 
238             ActivityManagerHelper.registerProcessObserverCallback(callbackImpl);
239 
240             launchSimpleActivity();
241 
242             // assert
243             assertThat(callbackImpl.waitForForegroundActivitiesChanged()).isTrue();
244         } finally {
245             // teardown
246             ActivityManagerHelper.unregisterProcessObserverCallback(callbackImpl);
247             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
248         }
249     }
250 
251     @Test
testCreateActivityOptions()252     public void testCreateActivityOptions() {
253         Rect expectedRect = new Rect(ANIMATION_RECT_LEFT,
254                 ANIMATION_RECT_TOP,
255                 ANIMATION_RECT_RIGHT,
256                 ANIMATION_RECT_BOTTOM);
257         int expectedDisplayId = RANDOM_NON_DEFAULT_DISPLAY_ID;
258         boolean expectedLockTaskMode = NON_DEFAULT_LOCK_TASK_MODE;
259         boolean expectedLaunchAllowed =
260                 NON_DEFAULT_PENDING_INTENT_BACKGROUND_ACTIVITY_LAUNCH_ALLOWED;
261 
262         ActivityOptions originalOptions =
263                 ActivityOptions.makeCustomAnimation(mContext,
264                 /* entResId= */ android.R.anim.fade_in,
265                 /* exitResId= */ android.R.anim.fade_out);
266         originalOptions.setLaunchBounds(expectedRect);
267         originalOptions.setLaunchDisplayId(expectedDisplayId);
268         originalOptions.setLockTaskEnabled(expectedLockTaskMode);
269         originalOptions.setPendingIntentBackgroundActivityLaunchAllowed(expectedLaunchAllowed);
270 
271         ActivityOptions createdOptions =
272                 ActivityManagerHelper.createActivityOptions(originalOptions.toBundle());
273 
274         assertThat(createdOptions.getLaunchBounds()).isEqualTo(expectedRect);
275         assertThat(createdOptions.getLaunchDisplayId()).isEqualTo(expectedDisplayId);
276         assertThat(createdOptions.getLockTaskMode()).isEqualTo(expectedLockTaskMode);
277         assertThat(createdOptions.isPendingIntentBackgroundActivityLaunchAllowed())
278                 .isEqualTo(expectedLaunchAllowed);
279     }
280 
281     @Ignore("b/304870066")
282     @Test
testStopAllTasksForUser()283     public void testStopAllTasksForUser() throws Exception {
284         int initialCurrentUserId = getCurrentUserId();
285         int testUserId = INVALID_USER_ID;
286 
287         try {
288             mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
289                     PERMISSION_MANAGE_ACTIVITY_TASKS,
290                     PERMISSION_REMOVE_TASKS,
291                     PERMISSION_REAL_GET_TASKS,
292                     PERMISSION_INTERACT_ACROSS_USERS_FULL);
293 
294             testUserId = createUser(CTS_CAR_TEST_USER_NAME);
295             startUser(testUserId);
296 
297             switchUser(testUserId);
298             waitUntilUserCurrent(testUserId);
299 
300             installPackageForUser(testUserId);
301 
302             launchSimpleActivityInCurrentUser();
303             assertIsAppRunning(true, SIMPLE_APP_PACKAGE_NAME);
304 
305             switchUser(initialCurrentUserId);
306             waitUntilUserCurrent(initialCurrentUserId);
307 
308             stopAllTasksForUser(testUserId);
309             assertIsAppRunning(false, SIMPLE_APP_PACKAGE_NAME);
310 
311             removeUser(testUserId);
312             testUserId = INVALID_USER_ID;
313         } finally {
314             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
315 
316             deepCleanTestStopAllTasksForUser(testUserId, initialCurrentUserId);
317         }
318     }
319 
deepCleanTestStopAllTasksForUser(int testUserId, int initialCurrentUserId)320     private void deepCleanTestStopAllTasksForUser(int testUserId, int initialCurrentUserId)
321             throws Exception {
322         try {
323             if (initialCurrentUserId != getCurrentUserId()) {
324                 switchUser(initialCurrentUserId);
325                 waitUntilUserCurrent(initialCurrentUserId);
326             }
327         } finally {
328             if (testUserId != INVALID_USER_ID) {
329                 removeUser(testUserId);
330             }
331         }
332     }
333 
assertComponentPermissionGranted(String permission)334     private void assertComponentPermissionGranted(String permission) throws Exception {
335         assertThat(ActivityManagerHelper.checkComponentPermission(permission,
336                 Process.myUid(), /* owningUid= */ OWNING_UID, /* exported= */ true))
337                 .isEqualTo(PackageManager.PERMISSION_GRANTED);
338     }
339 
assertComponentPermissionNotGranted(String permission)340     private void assertComponentPermissionNotGranted(String permission) throws Exception {
341         assertThat(ActivityManagerHelper.checkComponentPermission(permission,
342                 Process.myUid(), /* owningUid= */ OWNING_UID, /* exported= */ true))
343                 .isEqualTo(PackageManager.PERMISSION_DENIED);
344     }
345 
346     private static final class ProcessObserverCallbackTestImpl extends ProcessObserverCallback {
347         private final CountDownLatch mLatch = new CountDownLatch(1);
348 
349         // Use onForegroundActivitiesChanged(), because onProcessDied() can be called
350         // in very long time later even if the task was removed.
351         @Override
onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities)352         public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
353             Log.d(TAG, "onForegroundActivitiesChanged: pid " + pid + " uid " + uid);
354             mLatch.countDown();
355         }
356 
waitForForegroundActivitiesChanged()357         public boolean waitForForegroundActivitiesChanged() throws Exception {
358             return mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
359         }
360     }
361 
launchSimpleActivity()362     private void launchSimpleActivity() {
363         ComponentName simpleActivity = new ComponentName(
364                 SIMPLE_APP_PACKAGE_NAME, SIMPLE_ACTIVITY_NAME);
365         Intent intent = new Intent()
366                 .setComponent(simpleActivity)
367                 .addFlags(FLAG_ACTIVITY_NEW_TASK);
368         mContext.startActivity(intent, /* options = */ null);
369         waitAndAssertResumedAndFocusedActivityOnDisplay(simpleActivity, DEFAULT_DISPLAY,
370                 "Activity isn't resumed");
371     }
372 
373     // launchSimpleActivity in the current user space via the car shell instead of the calling user.
374     // The calling user could be in the background.
launchSimpleActivityInCurrentUser()375     private static void launchSimpleActivityInCurrentUser() {
376         Log.d(TAG, "launchSimpleActivityInCurrentUser: " + START_SIMPLE_ACTIVITY_COMMAND);
377         String retStr = SystemUtil.runShellCommand(START_SIMPLE_ACTIVITY_COMMAND);
378         Log.d(TAG, "launchSimpleActivityInCurrentUser return: " + retStr);
379     }
380 
installPackageForUser(int userId)381     private static void installPackageForUser(int userId) {
382         String fullCommand = String.format("pm install-existing --user %d %s",
383                 userId, SIMPLE_APP_PACKAGE_NAME);
384         Log.d(TAG, "installPackageForUser: " + fullCommand);
385         String retStr = SystemUtil.runShellCommand(fullCommand);
386         Log.d(TAG, "installPackageForUser return: " + retStr);
387     }
388 
assertIsAppRunning(boolean isRunning, String pkgName)389     private void assertIsAppRunning(boolean isRunning, String pkgName) {
390         PollingCheck.waitFor(TIMEOUT_MS, () -> isAppRunning(pkgName) == isRunning);
391     }
392 
isAppRunning(String pkgName)393     private boolean isAppRunning(String pkgName) {
394         ActivityManager am = mContext.getSystemService(ActivityManager.class);
395 
396         List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(MAX_NUM_TASKS);
397 
398         for (ActivityManager.RunningTaskInfo taskInfo : runningTasks) {
399             if (pkgName.equals(taskInfo.baseActivity.getPackageName())) {
400                 return true;
401             }
402         }
403 
404         return false;
405     }
406 
launchTestActivity(Class<T> type)407     private <T> T launchTestActivity(Class<T> type) {
408         Intent startIntent = new Intent(mContext, type)
409                 .addFlags(FLAG_ACTIVITY_NEW_TASK);
410 
411         Activity testActivity = (Activity) mInstrumentation
412                 .startActivitySync(startIntent, /* options = */ null);
413 
414         ComponentName testActivityName = testActivity.getComponentName();
415         waitAndAssertResumedAndFocusedActivityOnDisplay(testActivityName, DEFAULT_DISPLAY,
416                 "Activity must be resumed");
417 
418         return type.cast(testActivity);
419     }
420 
421     // The logging order of the Activities follows the stack order. The first Activity
422     // in the parameter list is logged at last.
logActivityStack(String msg, Activity... activityStack)423     private static void logActivityStack(String msg, Activity... activityStack) {
424         for (int index = activityStack.length - 1; index >= 0; index--) {
425             String logMsg = String.format("%s\tindex=%d taskId=%d",
426                     msg, index, activityStack[index].getTaskId());
427             Log.d(TAG, logMsg);
428         }
429     }
430 
doesTaskExist(int taskId)431     private boolean doesTaskExist(int taskId) {
432         boolean retVal = false;
433         try {
434             mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
435                     PERMISSION_REMOVE_TASKS);
436             ActivityManager am = mContext.getSystemService(ActivityManager.class);
437             List<ActivityManager.RunningTaskInfo> taskList = am.getRunningTasks(MAX_NUM_TASKS);
438             for (TaskInfo taskInfo : taskList) {
439                 if (taskInfo.taskId == taskId) {
440                     retVal = true;
441                     break;
442                 }
443             }
444         } finally {
445             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
446         }
447         return retVal;
448     }
449 
450     public static final class ActivityA extends ActivityManagerTestActivityBase {
451     }
452 
453     public static final class ActivityB extends ActivityManagerTestActivityBase {
454     }
455 
456     public static final class ActivityC extends ActivityManagerTestActivityBase {
457     }
458 
waitAndAssertFocusStatusChanged(ActivityManagerTestActivityBase activity, boolean expectedStatus)459     private static void waitAndAssertFocusStatusChanged(ActivityManagerTestActivityBase activity,
460             boolean expectedStatus) throws Exception {
461         PollingCheck.waitFor(TIMEOUT_MS, () -> activity.hasFocus() == expectedStatus);
462     }
463 
createUser(String userName)464     private static int createUser(String userName) throws Exception {
465         Log.d(TAG, "createUser: " + userName);
466         String retStr = SystemUtil.runShellCommand(CREATE_USER_COMMAND + userName);
467         Pattern userIdPattern = Pattern.compile("id=(\\d+)");
468         Matcher matcher = userIdPattern.matcher(retStr);
469         if (!matcher.find()) {
470             throw new Exception("failed to create user: " + userName);
471         }
472         return Integer.parseInt(matcher.group(1));
473     }
474 
switchUser(int userId)475     private static void switchUser(int userId) throws Exception {
476         Log.d(TAG, "switchUser: " + userId);
477         String retStr = SystemUtil.runShellCommand(SWITCH_USER_COMMAND + userId);
478         if (!retStr.contains("STATUS_SUCCESSFUL")) {
479             throw new Exception("failed to switch to user: " + userId);
480         }
481         Log.d(TAG, "switchUser: " + retStr);
482     }
483 
removeUser(int userId)484     private static void removeUser(int userId) throws Exception {
485         Log.d(TAG, "removeUser: " + userId);
486         String retStr = SystemUtil.runShellCommand(REMOVE_USER_COMMAND + userId);
487         if (!retStr.contains("STATUS_SUCCESSFUL")) {
488             throw new Exception("failed to remove user: " + userId);
489         }
490         Log.d(TAG, "removeUser: " + retStr);
491     }
492 
startUser(int userId)493     private static void startUser(int userId) throws Exception {
494         String retStr = SystemUtil.runShellCommand(START_USER_COMMAND + userId);
495         if (!retStr.contains("Success: user started")) {
496             throw new Exception("failed to start user: " + userId + " with return: " + retStr);
497         }
498         Log.d(TAG, "startUser: " + retStr);
499     }
500 
getCurrentUserId()501     private static int getCurrentUserId() {
502         String retStr = SystemUtil.runShellCommand(GET_CURRENT_USER_COMMAND);
503         Log.d(TAG, "getCurrentUserId: " + retStr);
504         return Integer.parseInt(retStr.trim());
505     }
506 
waitUntilUserCurrent(int userId)507     private static void waitUntilUserCurrent(int userId) throws Exception {
508         PollingCheck.waitFor(TIMEOUT_MS, () -> userId == getCurrentUserId());
509     }
510 
511     // need to get the permission in the same user
stopAllTasksForUser(int userId)512     private static void stopAllTasksForUser(int userId) {
513         ActivityManagerHelper.stopAllTasksForUser(userId);
514     }
515 
checkSimpleActivityExistence()516     private static boolean checkSimpleActivityExistence() {
517         boolean foundSimpleActivity = false;
518 
519         Log.d(TAG, "checkSimpleActivityExistence --- Begin");
520         WindowManagerState wmState = new WindowManagerState();
521         wmState.computeState();
522         for (ActivityType activityType : ActivityType.values()) {
523             if (findSimpleActivityInType(activityType, wmState)) {
524                 foundSimpleActivity = true;
525                 break;
526             }
527         }
528         Log.d(TAG, "checkSimpleActivityExistence --- End with --- " + foundSimpleActivity);
529 
530         return foundSimpleActivity;
531     }
532 
findSimpleActivityInType(ActivityType activityType, WindowManagerState wmState)533     private static boolean findSimpleActivityInType(ActivityType activityType,
534             WindowManagerState wmState) {
535         boolean foundRootTask = false;
536         boolean foundSimpleActivity = false;
537 
538         WindowManagerState.Task rootTask =
539                 wmState.getRootTaskByActivityType(activityType.ordinal());
540         if (rootTask != null) {
541             foundRootTask = true;
542             List<WindowManagerState.Activity> allActivities = rootTask.getActivities();
543             if (rootTask.getActivity(SIMPLE_ACTIVITY_COMPONENT_NAME) != null) {
544                 foundSimpleActivity = true;
545             }
546 
547             // for debugging purpose only
548             for (WindowManagerState.Activity act : allActivities) {
549                 Log.d(TAG, activityType.name() + ": activity name -- " + act.getName());
550             }
551         }
552 
553         Log.d(TAG, activityType.name() + " has simple activity root task:" + foundRootTask);
554         Log.d(TAG, activityType.name() + " has simple activity: " + foundSimpleActivity);
555 
556         return foundSimpleActivity;
557     }
558 }
559