• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 package android.app.cts;
17 
18 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
19 import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
20 import static android.content.ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
21 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
22 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
23 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
24 import static android.content.ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
25 import static android.content.Intent.ACTION_MAIN;
26 import static android.content.Intent.CATEGORY_HOME;
27 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
28 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
29 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
30 import static android.content.pm.PackageManager.DONT_KILL_APP;
31 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
32 
33 import static org.junit.Assert.assertEquals;
34 import static org.junit.Assert.assertFalse;
35 import static org.junit.Assert.assertNotEquals;
36 import static org.junit.Assert.assertNotNull;
37 import static org.junit.Assert.assertNull;
38 import static org.junit.Assert.assertThrows;
39 import static org.junit.Assert.assertTrue;
40 import static org.junit.Assert.fail;
41 import static org.junit.Assume.assumeFalse;
42 import static org.junit.Assume.assumeTrue;
43 
44 import android.app.Activity;
45 import android.app.ActivityManager;
46 import android.app.ActivityManager.RecentTaskInfo;
47 import android.app.ActivityManager.RunningAppProcessInfo;
48 import android.app.ActivityManager.RunningServiceInfo;
49 import android.app.ActivityManager.RunningTaskInfo;
50 import android.app.ActivityOptions;
51 import android.app.HomeVisibilityListener;
52 import android.app.Instrumentation;
53 import android.app.Instrumentation.ActivityMonitor;
54 import android.app.Instrumentation.ActivityResult;
55 import android.app.PendingIntent;
56 import android.app.TaskInfo;
57 import android.app.cts.android.app.cts.tools.WatchUidRunner;
58 import android.app.stubs.ActivityManagerRecentOneActivity;
59 import android.app.stubs.ActivityManagerRecentTwoActivity;
60 import android.app.stubs.CommandReceiver;
61 import android.app.stubs.LocalForegroundService;
62 import android.app.stubs.MockApplicationActivity;
63 import android.app.stubs.MockService;
64 import android.app.stubs.RemoteActivity;
65 import android.app.stubs.ScreenOnActivity;
66 import android.app.stubs.TestHomeActivity;
67 import android.app.stubs.TrimMemService;
68 import android.content.BroadcastReceiver;
69 import android.content.ComponentName;
70 import android.content.Context;
71 import android.content.Intent;
72 import android.content.IntentFilter;
73 import android.content.ServiceConnection;
74 import android.content.pm.ApplicationInfo;
75 import android.content.pm.ConfigurationInfo;
76 import android.content.pm.PackageManager;
77 import android.content.pm.ResolveInfo;
78 import android.content.res.Configuration;
79 import android.content.res.Resources;
80 import android.os.Binder;
81 import android.os.Bundle;
82 import android.os.Handler;
83 import android.os.HandlerThread;
84 import android.os.IBinder;
85 import android.os.Message;
86 import android.os.Messenger;
87 import android.os.NewUserRequest;
88 import android.os.Parcel;
89 import android.os.Process;
90 import android.os.RemoteException;
91 import android.os.SystemClock;
92 import android.os.UserHandle;
93 import android.os.UserManager;
94 import android.permission.cts.PermissionUtils;
95 import android.platform.test.annotations.RestrictedBuildTest;
96 import android.provider.DeviceConfig;
97 import android.provider.Settings;
98 import android.server.wm.settings.SettingsSession;
99 import android.support.test.uiautomator.UiDevice;
100 import android.util.ArrayMap;
101 import android.util.ArraySet;
102 import android.util.Log;
103 import android.util.Pair;
104 
105 import androidx.test.InstrumentationRegistry;
106 import androidx.test.filters.LargeTest;
107 import androidx.test.runner.AndroidJUnit4;
108 
109 import com.android.compatibility.common.util.AmMonitor;
110 import com.android.compatibility.common.util.AppStandbyUtils;
111 import com.android.compatibility.common.util.ShellIdentityUtils;
112 import com.android.compatibility.common.util.SystemUtil;
113 
114 import org.junit.After;
115 import org.junit.Before;
116 import org.junit.Test;
117 import org.junit.runner.RunWith;
118 
119 import java.io.IOException;
120 import java.util.ArrayList;
121 import java.util.List;
122 import java.util.concurrent.CountDownLatch;
123 import java.util.concurrent.LinkedBlockingQueue;
124 import java.util.concurrent.TimeUnit;
125 import java.util.function.BiPredicate;
126 import java.util.function.Consumer;
127 import java.util.function.Predicate;
128 import java.util.function.Supplier;
129 
130 @RunWith(AndroidJUnit4.class)
131 public class ActivityManagerTest {
132     private static final String TAG = ActivityManagerTest.class.getSimpleName();
133     private static final String STUB_PACKAGE_NAME = "android.app.stubs";
134     private static final long WAITFOR_MSEC = 5000;
135     private static final String SERVICE_NAME = "android.app.stubs.MockService";
136     private static final long WAIT_TIME = 2000;
137     private static final long WAITFOR_ORDERED_BROADCAST_DRAINED = 60000;
138     // A secondary test activity from another APK.
139     static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
140     static final String SIMPLE_ACTIVITY = ".SimpleActivity";
141     static final String SIMPLE_ACTIVITY_IMMEDIATE_EXIT = ".SimpleActivityImmediateExit";
142     static final String SIMPLE_ACTIVITY_CHAIN_EXIT = ".SimpleActivityChainExit";
143     static final String SIMPLE_RECEIVER = ".SimpleReceiver";
144     static final String SIMPLE_REMOTE_RECEIVER = ".SimpleRemoteReceiver";
145     // The action sent back by the SIMPLE_APP after a restart.
146     private static final String ACTIVITY_LAUNCHED_ACTION =
147             "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
148     // The action sent back by the SIMPLE_APP_IMMEDIATE_EXIT when it terminates.
149     private static final String ACTIVITY_EXIT_ACTION =
150             "com.android.cts.launchertests.LauncherAppsTests.EXIT_ACTION";
151     // The action sent back by the SIMPLE_APP_CHAIN_EXIT when the task chain ends.
152     private static final String ACTIVITY_CHAIN_EXIT_ACTION =
153             "com.android.cts.launchertests.LauncherAppsTests.CHAIN_EXIT_ACTION";
154     // The action sent to identify the time track info.
155     private static final String ACTIVITY_TIME_TRACK_INFO = "com.android.cts.TIME_TRACK_INFO";
156 
157     private static final String PACKAGE_NAME_APP1 = "com.android.app1";
158     private static final String PACKAGE_NAME_APP2 = "com.android.app2";
159     private static final String PACKAGE_NAME_APP3 = "com.android.app3";
160 
161     private static final String CANT_SAVE_STATE_1_PACKAGE_NAME = "com.android.test.cantsavestate1";
162     private static final String ACTION_FINISH = "com.android.test.action.FINISH";
163 
164     private static final String MCC_TO_UPDATE = "987";
165     private static final String MNC_TO_UPDATE = "654";
166 
167     // Return states of the ActivityReceiverFilter.
168     public static final int RESULT_PASS = 1;
169     public static final int RESULT_FAIL = 2;
170     public static final int RESULT_TIMEOUT = 3;
171 
172     private Context mTargetContext;
173     private ActivityManager mActivityManager;
174     private PackageManager mPackageManager;
175     private Intent mIntent;
176     private List<Activity> mStartedActivityList;
177     private int mErrorProcessID;
178     private Instrumentation mInstrumentation;
179     private HomeActivitySession mTestHomeSession;
180     private boolean mAppStandbyEnabled;
181     private boolean mAutomotiveDevice;
182     private boolean mLeanbackOnly;
183 
184     @Before
setUp()185     public void setUp() throws Exception {
186         mInstrumentation = InstrumentationRegistry.getInstrumentation();
187         mTargetContext = mInstrumentation.getTargetContext();
188         mActivityManager = (ActivityManager) mTargetContext
189                 .getSystemService(Context.ACTIVITY_SERVICE);
190         mPackageManager = mInstrumentation.getContext().getPackageManager();
191         mStartedActivityList = new ArrayList<Activity>();
192         mErrorProcessID = -1;
193         mAppStandbyEnabled = AppStandbyUtils.isAppStandbyEnabled();
194         mAutomotiveDevice = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
195         mLeanbackOnly = mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
196         toggleScreenOn(true);
197         startSubActivity(ScreenOnActivity.class);
198         drainOrderedBroadcastQueue(2);
199     }
200 
201     @After
tearDown()202     public void tearDown() throws Exception {
203         if (mTestHomeSession != null) {
204             mTestHomeSession.close();
205         }
206         if (mIntent != null) {
207             mInstrumentation.getContext().stopService(mIntent);
208         }
209         for (int i = 0; i < mStartedActivityList.size(); i++) {
210             mStartedActivityList.get(i).finish();
211         }
212         if (mErrorProcessID != -1) {
213             android.os.Process.killProcess(mErrorProcessID);
214         }
215     }
216 
217     /**
218      * Drain the ordered broadcast queue, it'll be useful when the test runs right after
219      * the device booted, the ordered broadcast queue could be clogged.
220      */
drainOrderedBroadcastQueue(int loopCount)221     private void drainOrderedBroadcastQueue(int loopCount) throws Exception {
222         for (int i = loopCount; i > 0; i--) {
223             final CountDownLatch latch = new CountDownLatch(1);
224             final BroadcastReceiver receiver = new BroadcastReceiver() {
225                 @Override
226                 public void onReceive(Context context, Intent intent) {
227                     latch.countDown();
228                 }
229             };
230             CommandReceiver.sendCommandWithResultReceiver(mTargetContext,
231                     CommandReceiver.COMMAND_EMPTY,
232                     STUB_PACKAGE_NAME, STUB_PACKAGE_NAME, 0, null, receiver);
233             latch.await(WAITFOR_ORDERED_BROADCAST_DRAINED, TimeUnit.MILLISECONDS);
234         }
235         Log.i(TAG, "Ordered broadcast queue drained");
236     }
237 
238     @Test
testGetRecentTasks()239     public void testGetRecentTasks() throws Exception {
240         int maxNum = 0;
241         int flags = 0;
242 
243         List<RecentTaskInfo> recentTaskList;
244         // Test parameter: maxNum is set to 0
245         recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
246         assertNotNull(recentTaskList);
247         assertTrue(recentTaskList.size() == 0);
248         // Test parameter: maxNum is set to 50
249         maxNum = 50;
250         recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
251         assertNotNull(recentTaskList);
252         // start recent1_activity.
253         startSubActivity(ActivityManagerRecentOneActivity.class);
254         Thread.sleep(WAIT_TIME);
255         // start recent2_activity
256         startSubActivity(ActivityManagerRecentTwoActivity.class);
257         Thread.sleep(WAIT_TIME);
258         /*
259          * assert both recent1_activity and recent2_activity exist in the recent
260          * tasks list. Moreover,the index of the recent2_activity is smaller
261          * than the index of recent1_activity
262          */
263         recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
264         int indexRecentOne = getTaskInfoIndex(recentTaskList,
265                 ActivityManagerRecentOneActivity.class);
266         int indexRecentTwo = getTaskInfoIndex(recentTaskList,
267                 ActivityManagerRecentTwoActivity.class);
268         assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
269         assertTrue(indexRecentTwo < indexRecentOne);
270 
271         try {
272             mActivityManager.getRecentTasks(-1, 0);
273             fail("Should throw IllegalArgumentException");
274         } catch (IllegalArgumentException e) {
275             // expected exception
276         }
277     }
278 
279     @Test
280     public void testGetRecentTasksLimitedToCurrentAPK() throws Exception {
281         int maxNum = 0;
282         int flags = 0;
283 
284         // Check the number of tasks at this time.
285         List<RecentTaskInfo>  recentTaskList;
286         recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
287         int numberOfEntriesFirstRun = recentTaskList.size();
288 
289         // Start another activity from another APK.
290         Intent intent = new Intent(Intent.ACTION_MAIN);
291         intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
292         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
293         ActivityReceiverFilter receiver = new ActivityReceiverFilter(ACTIVITY_LAUNCHED_ACTION);
294         mTargetContext.startActivity(intent);
295 
296         // Make sure the activity has really started.
297         assertEquals(RESULT_PASS, receiver.waitForActivity());
298         receiver.close();
299 
300         // There shouldn't be any more tasks in this list at this time.
301         recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
302         int numberOfEntriesSecondRun = recentTaskList.size();
303         assertTrue(numberOfEntriesSecondRun == numberOfEntriesFirstRun);
304 
305         // Tell the activity to finalize.
306         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
307         intent.putExtra("finish", true);
308         mTargetContext.startActivity(intent);
309     }
310 
311     // The receiver filter needs to be instantiated with the command to filter for before calling
312     // startActivity.
313     private class ActivityReceiverFilter extends BroadcastReceiver {
314         // The activity we want to filter for.
315         private String mActivityToFilter;
316         private int result = RESULT_TIMEOUT;
317         public long mTimeUsed = 0;
318         private static final int TIMEOUT_IN_MS = 5000;
319 
320         // Create the filter with the intent to look for.
321         public ActivityReceiverFilter(String activityToFilter) {
322             mActivityToFilter = activityToFilter;
323             IntentFilter filter = new IntentFilter();
324             filter.addAction(mActivityToFilter);
325             mInstrumentation.getTargetContext().registerReceiver(this, filter);
326         }
327 
328         // Turn off the filter.
329         public void close() {
330             mInstrumentation.getTargetContext().unregisterReceiver(this);
331         }
332 
333         @Override
334         public void onReceive(Context context, Intent intent) {
335             if (intent.getAction().equals(mActivityToFilter)) {
336                 synchronized(this) {
337                    result = RESULT_PASS;
338                    if (mActivityToFilter.equals(ACTIVITY_TIME_TRACK_INFO)) {
339                        mTimeUsed = intent.getExtras().getLong(
340                                ActivityOptions.EXTRA_USAGE_TIME_REPORT);
341                    }
342                    notifyAll();
343                 }
344             }
345         }
346 
347         public int waitForActivity() {
348             synchronized(this) {
349                 try {
350                     wait(TIMEOUT_IN_MS);
351                 } catch (InterruptedException e) {
352                 }
353             }
354             return result;
355         }
356     }
357 
358     private final <T extends Activity> void startSubActivity(Class<T> activityClass) {
359         startSubActivity(activityClass, null);
360     }
361 
362     private <T extends Activity> void startSubActivity(
363             Class<T> activityClass,
364             ActivityOptions activityOptions) {
365         final Instrumentation.ActivityResult result = new ActivityResult(0, new Intent());
366         final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), result, false);
367         mInstrumentation.addMonitor(monitor);
368         launchActivity(STUB_PACKAGE_NAME, activityClass, activityOptions);
369         mStartedActivityList.add(monitor.waitForActivity());
370     }
371 
372     private <T extends Activity> T launchActivity(
373             String pkg,
374             Class<T> activityCls,
375             ActivityOptions activityOptions) {
376         Intent intent = new Intent(Intent.ACTION_MAIN);
377         return launchActivityWithIntent(pkg, activityCls, intent, activityOptions);
378     }
379 
380     private <T extends Activity> T launchActivityWithIntent(
381             String pkg,
382             Class<T> activityCls,
383             Intent intent,
384             ActivityOptions activityOptions) {
385         intent.setClassName(pkg, activityCls.getName());
386         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
387         T activity = (T) mInstrumentation.startActivitySync(
388                 intent, activityOptions == null ? null : activityOptions.toBundle());
389         mInstrumentation.waitForIdleSync();
390         return activity;
391     }
392 
393     private <T extends TaskInfo, S extends Activity> int getTaskInfoIndex(List<T> taskList,
394             Class<S> activityClass) {
395         int i = 0;
396         for (TaskInfo ti : taskList) {
397             if (ti.baseActivity.getClassName().equals(activityClass.getName())) {
398                 return i;
399             }
400             i++;
401         }
402         return -1;
403     }
404 
405     @Test
406     public void testGetRunningTasks() {
407         // Test illegal parameter
408         List<RunningTaskInfo> runningTaskList;
409         runningTaskList = mActivityManager.getRunningTasks(-1);
410         assertTrue(runningTaskList.size() == 0);
411 
412         runningTaskList = mActivityManager.getRunningTasks(0);
413         assertTrue(runningTaskList.size() == 0);
414 
415         runningTaskList = mActivityManager.getRunningTasks(20);
416         int taskSize = runningTaskList.size();
417         assertTrue(taskSize >= 0 && taskSize <= 20);
418 
419         // start recent1_activity.
420         startSubActivity(ActivityManagerRecentOneActivity.class);
421 
422         runningTaskList = mActivityManager.getRunningTasks(20);
423 
424         // assert only recent1_activity exists and is visible.
425         int indexRecentOne = getTaskInfoIndex(runningTaskList,
426                 ActivityManagerRecentOneActivity.class);
427         int indexRecentTwo = getTaskInfoIndex(runningTaskList,
428                 ActivityManagerRecentTwoActivity.class);
429         assertTrue(indexRecentOne != -1 && indexRecentTwo == -1);
430         assertTrue(runningTaskList.get(indexRecentOne).isVisible());
431 
432         // start recent2_activity in fullscreen to hide the recent1_activity.
433         final ActivityOptions options = ActivityOptions.makeBasic();
434         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
435         startSubActivity(ActivityManagerRecentTwoActivity.class, options);
436 
437         /*
438          * assert both recent1_activity and recent2_activity exist in the
439          * running tasks list. Moreover,the index of the recent2_activity is
440          * smaller than the index of recent1_activity.
441          */
442         runningTaskList = mActivityManager.getRunningTasks(20);
443         indexRecentOne = getTaskInfoIndex(runningTaskList,
444                 ActivityManagerRecentOneActivity.class);
445         indexRecentTwo = getTaskInfoIndex(runningTaskList,
446                 ActivityManagerRecentTwoActivity.class);
447         assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
448         assertTrue(indexRecentTwo < indexRecentOne);
449 
450         // assert only recent2_activity is visible.
451         assertFalse(runningTaskList.get(indexRecentOne).isVisible());
452         assertTrue(runningTaskList.get(indexRecentTwo).isVisible());
453     }
454 
455     @Test
456     public void testGetRunningServices() throws Exception {
457         // Test illegal parameter
458         List<RunningServiceInfo> runningServiceInfo;
459         runningServiceInfo = mActivityManager.getRunningServices(-1);
460         assertTrue(runningServiceInfo.isEmpty());
461 
462         runningServiceInfo = mActivityManager.getRunningServices(0);
463         assertTrue(runningServiceInfo.isEmpty());
464 
465         runningServiceInfo = mActivityManager.getRunningServices(5);
466         assertTrue(runningServiceInfo.size() <= 5);
467 
468         Intent intent = new Intent();
469         intent.setClass(mInstrumentation.getTargetContext(), MockService.class);
470         intent.putExtra(MockService.EXTRA_NO_STOP, true);
471         mInstrumentation.getTargetContext().startService(intent);
472         MockService.waitForStart(WAIT_TIME);
473 
474         runningServiceInfo = mActivityManager.getRunningServices(Integer.MAX_VALUE);
475         boolean foundService = false;
476         for (RunningServiceInfo rs : runningServiceInfo) {
477             if (rs.service.getClassName().equals(SERVICE_NAME)) {
478                 foundService = true;
479                 break;
480             }
481         }
482         assertTrue(foundService);
483         MockService.prepareDestroy();
484         mTargetContext.stopService(intent);
485         boolean destroyed = MockService.waitForDestroy(WAIT_TIME);
486         assertTrue(destroyed);
487     }
488 
489     private void executeAndLogShellCommand(String cmd) throws IOException {
490         final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
491         final String output = uiDevice.executeShellCommand(cmd);
492         Log.d(TAG, "executed[" + cmd + "]; output[" + output.trim() + "]");
493     }
494 
495     private String executeShellCommand(String cmd) throws IOException {
496         final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
497         return uiDevice.executeShellCommand(cmd).trim();
498     }
499 
500     private void setForcedAppStandby(String packageName, boolean enabled) throws IOException {
501         final StringBuilder cmdBuilder = new StringBuilder("appops set ")
502                 .append(packageName)
503                 .append(" RUN_ANY_IN_BACKGROUND ")
504                 .append(enabled ? "ignore" : "allow");
505         executeAndLogShellCommand(cmdBuilder.toString());
506     }
507 
508     @Test
509     public void testIsBackgroundRestricted() throws IOException {
510         // This instrumentation runs in the target package's uid.
511         final Context targetContext = mInstrumentation.getTargetContext();
512         final String targetPackage = targetContext.getPackageName();
513         final ActivityManager am = targetContext.getSystemService(ActivityManager.class);
514         setForcedAppStandby(targetPackage, true);
515         assertTrue(am.isBackgroundRestricted());
516         setForcedAppStandby(targetPackage, false);
517         assertFalse(am.isBackgroundRestricted());
518     }
519 
520     @Test
521     public void testGetMemoryInfo() {
522         ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
523         mActivityManager.getMemoryInfo(outInfo);
524         assertTrue(outInfo.lowMemory == (outInfo.availMem <= outInfo.threshold));
525     }
526 
527     @Test
528     public void testGetRunningAppProcesses() throws Exception {
529         List<RunningAppProcessInfo> list = mActivityManager.getRunningAppProcesses();
530         assertNotNull(list);
531         final String SYSTEM_PROCESS = "system";
532         boolean hasSystemProcess = false;
533         // The package name is also the default name for the application process
534         final String TEST_PROCESS = STUB_PACKAGE_NAME;
535         boolean hasTestProcess = false;
536         for (RunningAppProcessInfo ra : list) {
537             if (ra.processName.equals(SYSTEM_PROCESS)) {
538                 hasSystemProcess = true;
539 
540                 // Make sure the importance is a sane value.
541                 assertTrue(ra.importance >= RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
542                 assertTrue(ra.importance < RunningAppProcessInfo.IMPORTANCE_GONE);
543             } else if (ra.processName.equals(TEST_PROCESS)) {
544                 hasTestProcess = true;
545             }
546         }
547 
548         // For security reasons the system process is not exposed.
549         assertFalse(hasSystemProcess);
550         assertTrue(hasTestProcess);
551 
552         for (RunningAppProcessInfo ra : list) {
553             if (ra.processName.equals("android.app.stubs:remote")) {
554                 fail("should be no process named android.app.stubs:remote");
555             }
556         }
557         // start a new process
558         // XXX would be a lot cleaner to bind instead of start.
559         mIntent = new Intent("android.app.REMOTESERVICE");
560         mIntent.setPackage("android.app.stubs");
561         mInstrumentation.getTargetContext().startService(mIntent);
562         Thread.sleep(WAITFOR_MSEC);
563 
564         List<RunningAppProcessInfo> listNew = mActivityManager.getRunningAppProcesses();
565         mInstrumentation.getTargetContext().stopService(mIntent);
566 
567         for (RunningAppProcessInfo ra : listNew) {
568             if (ra.processName.equals("android.app.stubs:remote")) {
569                 return;
570             }
571         }
572         fail("android.app.stubs:remote process should be available");
573     }
574 
575     @Test
576     public void testGetMyMemoryState() {
577         final RunningAppProcessInfo ra = new RunningAppProcessInfo();
578         ActivityManager.getMyMemoryState(ra);
579 
580         assertEquals(android.os.Process.myUid(), ra.uid);
581 
582         // When an instrumentation test is running, the importance is high.
583         assertEquals(RunningAppProcessInfo.IMPORTANCE_FOREGROUND, ra.importance);
584     }
585 
586     @Test
587     public void testGetProcessInErrorState() throws Exception {
588         List<ActivityManager.ProcessErrorStateInfo> errList = null;
589         errList = mActivityManager.getProcessesInErrorState();
590         assertNull(errList);
591 
592         // Setup the ANR monitor.
593         final AmMonitor monitor = new AmMonitor(mInstrumentation, null);
594         final ApplicationInfo app1Info = mTargetContext.getPackageManager().getApplicationInfo(
595                 PACKAGE_NAME_APP1, 0);
596         final ApplicationInfo stubInfo = mTargetContext.getPackageManager().getApplicationInfo(
597                 STUB_PACKAGE_NAME, 0);
598         final WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
599                 WAITFOR_MSEC);
600         final String crashActivityName = "ActivityManagerStubCrashActivity";
601 
602         final SettingsSession<Integer> showOnFirstCrash = new SettingsSession<>(
603                 Settings.Global.getUriFor(Settings.Global.SHOW_FIRST_CRASH_DIALOG),
604                 Settings.Global::getInt, Settings.Global::putInt);
605         final SettingsSession<Integer> showBackground = new SettingsSession<>(
606                 Settings.Secure.getUriFor(Settings.Secure.ANR_SHOW_BACKGROUND),
607                 Settings.Secure::getInt, Settings.Secure::putInt);
608         try {
609             SystemUtil.runWithShellPermissionIdentity(() -> {
610                 showOnFirstCrash.set(1);
611                 showBackground.set(1);
612             });
613 
614             CommandReceiver.sendCommand(mTargetContext,
615                     CommandReceiver.COMMAND_START_ACTIVITY,
616                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
617             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
618                     WatchUidRunner.STATE_TOP,
619                     new Integer(ActivityManager.PROCESS_CAPABILITY_ALL));
620 
621             // Sleep a while to let things go through.
622             Thread.sleep(WAIT_TIME);
623 
624             // Now tell it goto ANR.
625             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_SELF_INDUCED_ANR,
626                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
627 
628             // Verify we got the ANR.
629             assertTrue(monitor.waitFor(AmMonitor.WAIT_FOR_EARLY_ANR, WAITFOR_MSEC));
630 
631             // Let it continue.
632             monitor.sendCommand(AmMonitor.CMD_CONTINUE);
633 
634             // Now it should've reached the normal ANR process.
635             assertTrue(monitor.waitFor(AmMonitor.WAIT_FOR_ANR, WAITFOR_MSEC * 3));
636 
637             // Continue again, we need to see the ANR dialog in order to get the error report.
638             monitor.sendCommand(AmMonitor.CMD_CONTINUE);
639 
640             // Sleep a while to let things go through.
641             Thread.sleep(WAIT_TIME);
642 
643             // We shouldn't be able to read the error state info of that.
644             errList = mActivityManager.getProcessesInErrorState();
645             assertNull(errList);
646 
647             // Shell should have the access.
648             final List<ActivityManager.ProcessErrorStateInfo>[] holder = new List[1];
649             SystemUtil.runWithShellPermissionIdentity(() -> {
650                 holder[0] = mActivityManager.getProcessesInErrorState();
651             });
652             assertNotNull(holder[0]);
653             assertEquals(1, holder[0].size());
654             verifyProcessErrorStateInfo(holder[0].get(0),
655                     ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
656                     app1Info.uid,
657                     PACKAGE_NAME_APP1);
658 
659             // Start a crashing activity in remote process with the same UID.
660             final Intent intent = new Intent(Intent.ACTION_MAIN);
661             intent.setClassName(STUB_PACKAGE_NAME, STUB_PACKAGE_NAME + "." + crashActivityName);
662             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
663             mTargetContext.startActivity(intent);
664 
665             // Wait for the crash.
666             assertTrue(monitor.waitFor(AmMonitor.WAIT_FOR_CRASHED, WAITFOR_MSEC));
667 
668             // Let it continue, we need to see the crash dialog in order to get the error report.
669             monitor.sendCommand(AmMonitor.CMD_CONTINUE);
670 
671             // Sleep a while to let things go through.
672             Thread.sleep(WAIT_TIME);
673 
674             // We should be able to see this crash info.
675             errList = mActivityManager.getProcessesInErrorState();
676             assertNotNull(errList);
677             assertEquals(1, errList.size());
678 
679             verifyProcessErrorStateInfo(errList.get(0),
680                     ActivityManager.ProcessErrorStateInfo.CRASHED,
681                     stubInfo.uid,
682                     STUB_PACKAGE_NAME + ":" + crashActivityName);
683 
684             // Shell should have the access to all of the crash info here.
685             SystemUtil.runWithShellPermissionIdentity(() -> {
686                 holder[0] = mActivityManager.getProcessesInErrorState();
687             });
688             assertNotNull(holder[0]);
689             assertEquals(2, holder[0].size());
690             // The return result is not sorted.
691             final ActivityManager.ProcessErrorStateInfo t0 = holder[0].get(0);
692             final ActivityManager.ProcessErrorStateInfo t1 = holder[0].get(1);
693             final ActivityManager.ProcessErrorStateInfo info0 = t0.uid == stubInfo.uid ? t0 : t1;
694             final ActivityManager.ProcessErrorStateInfo info1 = t1.uid == app1Info.uid ? t1 : t0;
695 
696             verifyProcessErrorStateInfo(info0,
697                     ActivityManager.ProcessErrorStateInfo.CRASHED,
698                     stubInfo.uid,
699                     STUB_PACKAGE_NAME + ":" + crashActivityName);
700             verifyProcessErrorStateInfo(info1,
701                     ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
702                     app1Info.uid,
703                     PACKAGE_NAME_APP1);
704         } finally {
SystemUtil.runWithShellPermissionIdentity()705             SystemUtil.runWithShellPermissionIdentity(() -> {
706                 showOnFirstCrash.close();
707                 showBackground.close();
708             });
monitor.finish()709             monitor.finish();
uid1Watcher.finish()710             uid1Watcher.finish();
SystemUtil.runWithShellPermissionIdentity()711             SystemUtil.runWithShellPermissionIdentity(() -> {
712                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
713             });
714         }
715     }
716 
verifyProcessErrorStateInfo(ActivityManager.ProcessErrorStateInfo info, int condition, int uid, String processName)717     private void verifyProcessErrorStateInfo(ActivityManager.ProcessErrorStateInfo info,
718             int condition, int uid, String processName) throws Exception {
719         assertEquals(condition, info.condition);
720         assertEquals(uid, info.uid);
721         assertEquals(processName, info.processName);
722     }
723 
724     @Test
testGetDeviceConfigurationInfo()725     public void testGetDeviceConfigurationInfo() {
726         ConfigurationInfo conInf = mActivityManager.getDeviceConfigurationInfo();
727         assertNotNull(conInf);
728     }
729 
730     @Test
testUpdateMccMncConfiguration()731     public void testUpdateMccMncConfiguration() throws Exception {
732         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
733             Log.i(TAG, "testUpdateMccMncConfiguration skipped: no telephony available");
734             return;
735         }
736 
737         Configuration originalConfig = mTargetContext.getResources().getConfiguration();
738         String[] mccMncConfigToUpdate = new String[] {MCC_TO_UPDATE, MNC_TO_UPDATE};
739         boolean success = ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
740                 (am) -> am.updateMccMncConfiguration(mccMncConfigToUpdate[0],
741                         mccMncConfigToUpdate[1]));
742 
743         if (success) {
744             Configuration changedConfig = mTargetContext.getResources().getConfiguration();
745             assertEquals(MNC_TO_UPDATE, Integer.toString(changedConfig.mnc));
746             assertEquals(MCC_TO_UPDATE, Integer.toString(changedConfig.mcc));
747         }
748 
749         // Set mcc mnc configs back in the end of the test if they were set to something else.
750         ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
751                 (am) -> am.updateMccMncConfiguration(Integer.toString(originalConfig.mcc),
752                         Integer.toString(originalConfig.mnc)));
753     }
754 
755     /**
756      * Simple test for {@link ActivityManager#isUserAMonkey()} - verifies its false.
757      *
758      * TODO: test positive case
759      */
760     @Test
testIsUserAMonkey()761     public void testIsUserAMonkey() {
762         assertFalse(ActivityManager.isUserAMonkey());
763     }
764 
765     /**
766      * Verify that {@link ActivityManager#isRunningInTestHarness()} is false.
767      */
768     @RestrictedBuildTest
769     @Test
testIsRunningInTestHarness()770     public void testIsRunningInTestHarness() {
771         assertFalse("isRunningInTestHarness must be false in production builds",
772                 ActivityManager.isRunningInTestHarness());
773     }
774 
775     /**
776      * Go back to the home screen since running applications can interfere with application
777      * lifetime tests.
778      */
launchHome()779     private void launchHome() throws Exception {
780         if (!noHomeScreen()) {
781             Intent intent = new Intent(Intent.ACTION_MAIN);
782             intent.addCategory(Intent.CATEGORY_HOME);
783             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
784             mTargetContext.startActivity(intent);
785             Thread.sleep(WAIT_TIME);
786         }
787     }
788 
789     /**
790      * Gets the value of com.android.internal.R.bool.config_noHomeScreen.
791      * @return true if no home screen is supported, false otherwise.
792      */
noHomeScreen()793     private boolean noHomeScreen() {
794         try {
795             return mTargetContext.getResources().getBoolean(
796                     Resources.getSystem().getIdentifier("config_noHomeScreen", "bool", "android"));
797         } catch (Resources.NotFoundException e) {
798             // Assume there's a home screen.
799             return false;
800         }
801     }
802 
803     /**
804      * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
805      */
806     @Test
testTimeTrackingAPI_SimpleStartExit()807     public void testTimeTrackingAPI_SimpleStartExit() throws Exception {
808         createManagedHomeActivitySession();
809         launchHome();
810         // Prepare to start an activity from another APK.
811         Intent intent = new Intent(Intent.ACTION_MAIN);
812         intent.setClassName(SIMPLE_PACKAGE_NAME,
813                 SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_IMMEDIATE_EXIT);
814         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
815 
816         // Prepare the time receiver action.
817         Context context = mInstrumentation.getTargetContext();
818         ActivityOptions options = ActivityOptions.makeBasic();
819         Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
820         options.requestUsageTimeReport(PendingIntent.getBroadcast(context, 0, receiveIntent,
821                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE));
822 
823         // The application finished tracker.
824         ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(ACTIVITY_EXIT_ACTION);
825 
826         // The filter for the time event.
827         ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
828 
829         // Run the activity.
830         mTargetContext.startActivity(intent, options.toBundle());
831 
832         // Wait until it finishes and end the reciever then.
833         assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
834         appEndReceiver.close();
835 
836         if (!noHomeScreen()) {
837             // At this time the timerReceiver should not fire, even though the activity has shut
838             // down, because we are back to the home screen. Going to the home screen does not
839             // qualify as the user leaving the activity's flow. The time tracking is considered
840             // complete only when the user switches to another activity that is not part of the
841             // tracked flow.
842             assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
843             assertTrue(timeReceiver.mTimeUsed == 0);
844         } else {
845             // With platforms that have no home screen, focus is returned to something else that is
846             // considered a completion of the tracked activity flow, and hence time tracking is
847             // triggered.
848             assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
849         }
850 
851         // Issuing now another activity will trigger the timing information release.
852         final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
853         dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
854         final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
855 
856         // Wait until it finishes and end the reciever then.
857         assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
858         timeReceiver.close();
859         assertTrue(timeReceiver.mTimeUsed != 0);
860     }
861 
862     @Test
testHomeVisibilityListener()863     public void testHomeVisibilityListener() throws Exception {
864         assumeFalse("With platforms that have no home screen, no need to test", noHomeScreen());
865 
866         LinkedBlockingQueue<Boolean> currentHomeScreenVisibility = new LinkedBlockingQueue<>(2);
867         HomeVisibilityListener homeVisibilityListener = new HomeVisibilityListener() {
868             @Override
869             public void onHomeVisibilityChanged(boolean isHomeActivityVisible) {
870                 currentHomeScreenVisibility.offer(isHomeActivityVisible);
871             }
872         };
873         launchHome();
874         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mActivityManager,
875                 (am) -> am.addHomeVisibilityListener(Runnable::run, homeVisibilityListener));
876 
877         try {
878             // Make sure we got the first notification that the home screen is visible.
879             assertTrue(currentHomeScreenVisibility.poll(WAIT_TIME, TimeUnit.MILLISECONDS));
880             // Launch a basic activity to obscure the home screen.
881             Intent intent = new Intent(Intent.ACTION_MAIN);
882             intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
883             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
884             mTargetContext.startActivity(intent);
885 
886             // Make sure the observer reports the home screen as no longer visible
887             assertFalse(currentHomeScreenVisibility.poll(WAIT_TIME, TimeUnit.MILLISECONDS));
888         } finally {
889             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mActivityManager,
890                     (am) -> am.removeHomeVisibilityListener(homeVisibilityListener));
891         }
892     }
893 
894     /**
895      * Verify that the TimeTrackingAPI works properly when switching away from the monitored task.
896      */
897     @Test
testTimeTrackingAPI_SwitchAwayTriggers()898     public void testTimeTrackingAPI_SwitchAwayTriggers() throws Exception {
899         createManagedHomeActivitySession();
900         launchHome();
901 
902         // Prepare to start an activity from another APK.
903         Intent intent = new Intent(Intent.ACTION_MAIN);
904         intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
905         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
906 
907         // Prepare the time receiver action.
908         Context context = mInstrumentation.getTargetContext();
909         ActivityOptions options = ActivityOptions.makeBasic();
910         Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
911         options.requestUsageTimeReport(PendingIntent.getBroadcast(context, 0, receiveIntent,
912                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE));
913 
914         // The application started tracker.
915         ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
916                 ACTIVITY_LAUNCHED_ACTION);
917 
918         // The filter for the time event.
919         ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
920 
921         // Run the activity.
922         mTargetContext.startActivity(intent, options.toBundle());
923 
924         // Wait until it finishes and end the reciever then.
925         assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
926         appStartedReceiver.close();
927 
928         // At this time the timerReceiver should not fire since our app is running.
929         assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
930         assertTrue(timeReceiver.mTimeUsed == 0);
931 
932         // Starting now another activity will put ours into the back hence releasing the timing.
933         final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
934         dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
935         final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
936 
937         // Wait until it finishes and end the reciever then.
938         assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
939         timeReceiver.close();
940         assertTrue(timeReceiver.mTimeUsed != 0);
941     }
942 
943     /**
944      * Verify that the TimeTrackingAPI works properly when handling an activity chain gets started
945      * and ended.
946      */
947     @Test
testTimeTrackingAPI_ChainedActivityExit()948     public void testTimeTrackingAPI_ChainedActivityExit() throws Exception {
949         createManagedHomeActivitySession();
950         launchHome();
951         // Prepare to start an activity from another APK.
952         Intent intent = new Intent(Intent.ACTION_MAIN);
953         intent.setClassName(SIMPLE_PACKAGE_NAME,
954                 SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_CHAIN_EXIT);
955         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
956 
957         // Prepare the time receiver action.
958         Context context = mInstrumentation.getTargetContext();
959         ActivityOptions options = ActivityOptions.makeBasic();
960         Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
961         options.requestUsageTimeReport(PendingIntent.getBroadcast(context, 0, receiveIntent,
962                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE));
963 
964         // The application finished tracker.
965         ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(
966                 ACTIVITY_CHAIN_EXIT_ACTION);
967 
968         // The filter for the time event.
969         ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
970 
971         // Run the activity.
972         mTargetContext.startActivity(intent, options.toBundle());
973 
974         // Wait until it finishes and end the reciever then.
975         assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
976         appEndReceiver.close();
977 
978         if (!noHomeScreen()) {
979             // At this time the timerReceiver should not fire, even though the activity has shut
980             // down, because we are back to the home screen. Going to the home screen does not
981             // qualify as the user leaving the activity's flow. The time tracking is considered
982             // complete only when the user switches to another activity that is not part of the
983             // tracked flow.
984             assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
985             assertTrue(timeReceiver.mTimeUsed == 0);
986         } else {
987             // With platforms that have no home screen, focus is returned to something else that is
988             // considered a completion of the tracked activity flow, and hence time tracking is
989             // triggered.
990             assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
991         }
992 
993         // Issue another activity so that the timing information gets released.
994         final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
995         dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
996         final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
997 
998         // Wait until it finishes and end the reciever then.
999         assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
1000         timeReceiver.close();
1001         assertTrue(timeReceiver.mTimeUsed != 0);
1002     }
1003 
1004     /**
1005      * Verify that after force-stopping a package which has a foreground task contains multiple
1006      * activities, the process of the package should not be alive (restarted).
1007      */
1008     @Test
testForceStopPackageWontRestartProcess()1009     public void testForceStopPackageWontRestartProcess() throws Exception {
1010         // Ensure that there are no remaining component records of the test app package.
1011         SystemUtil.runWithShellPermissionIdentity(
1012                 () -> mActivityManager.forceStopPackage(SIMPLE_PACKAGE_NAME));
1013         ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
1014                 ACTIVITY_LAUNCHED_ACTION);
1015         // Start an activity of another APK.
1016         Intent intent = new Intent();
1017         intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
1018         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1019         mTargetContext.startActivity(intent);
1020         assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
1021 
1022         // Start a new activity in the same task. Here adds an action to make a different to intent
1023         // filter comparison so another same activity will be created.
1024         intent.setAction(Intent.ACTION_MAIN);
1025         mTargetContext.startActivity(intent);
1026         assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
1027         appStartedReceiver.close();
1028 
1029         // Wait for the first activity to stop so its ActivityRecord.haveState will be true. The
1030         // condition is required to keep the activity record when its process is died.
1031         Thread.sleep(WAIT_TIME);
1032 
1033         // The package name is also the default name for the activity process.
1034         final String testProcess = SIMPLE_PACKAGE_NAME;
1035         Predicate<RunningAppProcessInfo> processNamePredicate =
1036                 runningApp -> testProcess.equals(runningApp.processName);
1037 
1038         List<RunningAppProcessInfo> runningApps = SystemUtil.callWithShellPermissionIdentity(
1039                 () -> mActivityManager.getRunningAppProcesses());
1040         assertTrue("Process " + testProcess + " should be found in running process list",
1041                 runningApps.stream().anyMatch(processNamePredicate));
1042 
1043         runningApps = SystemUtil.callWithShellPermissionIdentity(() -> {
1044             mActivityManager.forceStopPackage(SIMPLE_PACKAGE_NAME);
1045             // Wait awhile (process starting may be asynchronous) to verify if the process is
1046             // started again unexpectedly.
1047             Thread.sleep(WAIT_TIME);
1048             return mActivityManager.getRunningAppProcesses();
1049         });
1050 
1051         assertFalse("Process " + testProcess + " should not be alive after force-stop",
1052                 runningApps.stream().anyMatch(processNamePredicate));
1053     }
1054 
1055     /**
1056      * This test is to verify that devices are patched with the fix in b/119327603 for b/115384617.
1057      */
1058     @Test
testIsAppForegroundRemoved()1059     public void testIsAppForegroundRemoved() throws ClassNotFoundException {
1060        try {
1061            Class.forName("android.app.IActivityManager").getDeclaredMethod(
1062                    "isAppForeground", int.class);
1063            fail("IActivityManager.isAppForeground() API should not be available.");
1064        } catch (NoSuchMethodException e) {
1065            // Patched devices should throw this exception since isAppForeground is removed.
1066        }
1067     }
1068 
1069     /**
1070      * This test verifies the self-induced ANR by ActivityManager.appNotResponding().
1071      */
1072     @Test
testAppNotResponding()1073     public void testAppNotResponding() throws Exception {
1074         // Setup the ANR monitor
1075         AmMonitor monitor = new AmMonitor(mInstrumentation,
1076                 new String[]{AmMonitor.WAIT_FOR_CRASHED});
1077 
1078         // Now tell it goto ANR
1079         CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_SELF_INDUCED_ANR,
1080                 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1081 
1082         try {
1083 
1084             // Verify we got the ANR
1085             assertTrue(monitor.waitFor(AmMonitor.WAIT_FOR_EARLY_ANR, WAITFOR_MSEC));
1086 
1087             // Just kill the test app
1088             monitor.sendCommand(AmMonitor.CMD_KILL);
1089         } finally {
1090             // clean up
1091             monitor.finish();
1092             SystemUtil.runWithShellPermissionIdentity(() -> {
1093                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
1094             });
1095         }
1096     }
1097 
1098     /*
1099      * Verifies the {@link android.app.ActivityManager#killProcessesWhenImperceptible}.
1100      */
1101     @Test
testKillingPidsOnImperceptible()1102     public void testKillingPidsOnImperceptible() throws Exception {
1103         // Start remote service process
1104         final String remoteProcessName = STUB_PACKAGE_NAME + ":remote";
1105         Intent remoteIntent = new Intent("android.app.REMOTESERVICE");
1106         remoteIntent.setPackage(STUB_PACKAGE_NAME);
1107         mTargetContext.startService(remoteIntent);
1108         Thread.sleep(WAITFOR_MSEC);
1109 
1110         RunningAppProcessInfo remote = getRunningAppProcessInfo(remoteProcessName);
1111         assertNotNull(remote);
1112 
1113         ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
1114                 ACTIVITY_LAUNCHED_ACTION);
1115         boolean disabled = "0".equals(executeShellCommand("cmd deviceidle enabled light"));
1116         try {
1117             if (disabled) {
1118                 executeAndLogShellCommand("cmd deviceidle enable light");
1119             }
1120             final Intent intent = new Intent(Intent.ACTION_MAIN);
1121             intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
1122             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1123             mTargetContext.startActivity(intent);
1124             assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
1125 
1126             RunningAppProcessInfo proc = getRunningAppProcessInfo(SIMPLE_PACKAGE_NAME);
1127             assertNotNull(proc);
1128 
1129             final String reason = "cts";
1130 
1131             try {
1132                 mActivityManager.killProcessesWhenImperceptible(new int[]{proc.pid}, reason);
1133                 fail("Shouldn't have the permission");
1134             } catch (SecurityException e) {
1135                 // expected
1136             }
1137 
1138             final long defaultWaitForKillTimeout = 5_000;
1139 
1140             // Keep the device awake
1141             toggleScreenOn(true);
1142 
1143             // Kill the remote process
1144             SystemUtil.runWithShellPermissionIdentity(() -> {
1145                 mActivityManager.killProcessesWhenImperceptible(new int[]{remote.pid}, reason);
1146             });
1147 
1148             // Kill the activity process
1149             SystemUtil.runWithShellPermissionIdentity(() -> {
1150                 mActivityManager.killProcessesWhenImperceptible(new int[]{proc.pid}, reason);
1151             });
1152 
1153             // The processes should be still alive because device isn't in idle
1154             assertFalse(waitUntilTrue(defaultWaitForKillTimeout, () -> isProcessGone(
1155                     remote.pid, remoteProcessName)));
1156             assertFalse(waitUntilTrue(defaultWaitForKillTimeout, () -> isProcessGone(
1157                     proc.pid, SIMPLE_PACKAGE_NAME)));
1158 
1159             if (isAtvDevice()) {
1160                 // On operator tier devices of AndroidTv, Activity is put behind TvLauncher
1161                 // after turnScreenOff by android.intent.category.HOME intent from
1162                 // TvRecommendation.
1163                 return;
1164             }
1165 
1166             // force device idle
1167             toggleScreenOn(false);
1168             triggerIdle(true);
1169 
1170             // Now the remote process should have been killed.
1171             assertTrue(waitUntilTrue(defaultWaitForKillTimeout, () -> isProcessGone(
1172                     remote.pid, remoteProcessName)));
1173 
1174             // The activity process should be still alive because it's is on the top (perceptible)
1175             assertFalse(waitUntilTrue(defaultWaitForKillTimeout, () -> isProcessGone(
1176                     proc.pid, SIMPLE_PACKAGE_NAME)));
1177 
1178             triggerIdle(false);
1179             // Toogle screen ON
1180             toggleScreenOn(true);
1181 
1182             // Now launch home
1183             executeAndLogShellCommand("input keyevent KEYCODE_HOME");
1184 
1185             // force device idle again
1186             toggleScreenOn(false);
1187             triggerIdle(true);
1188 
1189             // Now the activity process should be gone.
1190             assertTrue(waitUntilTrue(defaultWaitForKillTimeout, () -> isProcessGone(
1191                     proc.pid, SIMPLE_PACKAGE_NAME)));
1192 
1193         } finally {
1194             // Clean up code
1195             triggerIdle(false);
1196             toggleScreenOn(true);
1197             appStartedReceiver.close();
1198             mTargetContext.stopService(remoteIntent);
1199 
1200             if (disabled) {
1201                 executeAndLogShellCommand("cmd deviceidle disable light");
1202             }
1203             SystemUtil.runWithShellPermissionIdentity(() -> {
1204                 mActivityManager.forceStopPackage(SIMPLE_PACKAGE_NAME);
1205             });
1206             executeAndLogShellCommand("am kill " + STUB_PACKAGE_NAME);
1207         }
1208     }
1209 
1210     /**
1211      * Verifies the system will kill app's child processes if they are using excessive cpu
1212      */
1213     @LargeTest
1214     @Test
testKillingAppChildProcess()1215     public void testKillingAppChildProcess() throws Exception {
1216         final long powerCheckInterval = 5 * 1000;
1217         final long processGoneTimeout = powerCheckInterval * 4;
1218         final int waitForSec = 5 * 1000;
1219         final String activityManagerConstants = "activity_manager_constants";
1220 
1221         final SettingsSession<String> amSettings = new SettingsSession<>(
1222                 Settings.Global.getUriFor(activityManagerConstants),
1223                 Settings.Global::getString, Settings.Global::putString);
1224 
1225         final ApplicationInfo ai = mTargetContext.getPackageManager()
1226                 .getApplicationInfo(PACKAGE_NAME_APP1, 0);
1227         final WatchUidRunner watcher = new WatchUidRunner(mInstrumentation, ai.uid, waitForSec);
1228 
1229         try {
1230             // Shorten the power check intervals
1231             amSettings.set("power_check_interval=" + powerCheckInterval);
1232 
1233             // Make sure we could start activity from background
1234             SystemUtil.runShellCommand(mInstrumentation,
1235                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP1);
1236 
1237             // Keep the device awake
1238             toggleScreenOn(true);
1239 
1240             // Start an activity
1241             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1242                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1243 
1244             watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1245 
1246             // Spawn a light weight child process
1247             CountDownLatch startLatch = startChildProcessInPackage(PACKAGE_NAME_APP1,
1248                     new String[] {"/system/bin/sh", "-c",  "sleep 1000"});
1249 
1250             // Wait for the start of the child process
1251             assertTrue("Failed to spawn child process",
1252                     startLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1253 
1254             // Stop the activity
1255             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1256                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1257 
1258             watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1259 
1260             // Wait for the system to kill that light weight child (it won't happen actually)
1261             CountDownLatch stopLatch = initWaitingForChildProcessGone(
1262                     PACKAGE_NAME_APP1, processGoneTimeout);
1263 
1264             assertFalse("App's light weight child process shouldn't be gone",
1265                     stopLatch.await(processGoneTimeout, TimeUnit.MILLISECONDS));
1266 
1267             // Now kill the light weight child
1268             stopLatch = stopChildProcess(PACKAGE_NAME_APP1, waitForSec);
1269 
1270             assertTrue("Failed to kill app's light weight child process",
1271                     stopLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1272 
1273             // Start an activity again
1274             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1275                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1276 
1277             watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1278 
1279             // Spawn the cpu intensive child process
1280             startLatch = startChildProcessInPackage(PACKAGE_NAME_APP1,
1281                     new String[] {"/system/bin/sh", "-c",  "while true; do :; done"});
1282 
1283             // Wait for the start of the child process
1284             assertTrue("Failed to spawn child process",
1285                     startLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1286 
1287             // Stop the activity
1288             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1289                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1290 
1291             watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1292 
1293             // Wait for the system to kill that heavy child due to excessive cpu usage,
1294             // as well as the parent process.
1295             watcher.waitFor(WatchUidRunner.CMD_GONE, processGoneTimeout);
1296 
1297         } finally {
1298             amSettings.close();
1299 
1300             SystemUtil.runShellCommand(mInstrumentation,
1301                     "cmd deviceidle whitelist -" + PACKAGE_NAME_APP1);
1302 
1303             SystemUtil.runWithShellPermissionIdentity(() -> {
1304                 // force stop test package, where the whole test process group will be killed.
1305                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
1306             });
1307 
1308             watcher.finish();
1309         }
1310     }
1311 
1312 
1313     /**
1314      * Verifies the system will trim app's child processes if there are too many
1315      */
1316     @LargeTest
1317     @Test
testTrimAppChildProcess()1318     public void testTrimAppChildProcess() throws Exception {
1319         final long powerCheckInterval = 5 * 1000;
1320         final long processGoneTimeout = powerCheckInterval * 4;
1321         final int waitForSec = 5 * 1000;
1322         final int maxPhantomProcessesNum = 2;
1323         final String namespaceActivityManager = "activity_manager";
1324         final String activityManagerConstants = "activity_manager_constants";
1325         final String maxPhantomProcesses = "max_phantom_processes";
1326 
1327         final SettingsSession<String> amSettings = new SettingsSession<>(
1328                 Settings.Global.getUriFor(activityManagerConstants),
1329                 Settings.Global::getString, Settings.Global::putString);
1330         final Bundle currentMax = new Bundle();
1331         final String keyCurrent = "current";
1332 
1333         ApplicationInfo ai = mTargetContext.getPackageManager()
1334                 .getApplicationInfo(PACKAGE_NAME_APP1, 0);
1335         final WatchUidRunner watcher1 = new WatchUidRunner(mInstrumentation, ai.uid, waitForSec);
1336         ai = mTargetContext.getPackageManager().getApplicationInfo(PACKAGE_NAME_APP2, 0);
1337         final WatchUidRunner watcher2 = new WatchUidRunner(mInstrumentation, ai.uid, waitForSec);
1338         ai = mTargetContext.getPackageManager().getApplicationInfo(PACKAGE_NAME_APP3, 0);
1339         final WatchUidRunner watcher3 = new WatchUidRunner(mInstrumentation, ai.uid, waitForSec);
1340 
1341         try {
1342             // Shorten the power check intervals
1343             amSettings.set("power_check_interval=" + powerCheckInterval);
1344 
1345             // Reduce the maximum phantom processes allowance
1346             SystemUtil.runWithShellPermissionIdentity(() -> {
1347                 int current = DeviceConfig.getInt(namespaceActivityManager,
1348                         maxPhantomProcesses, -1);
1349                 currentMax.putInt(keyCurrent, current);
1350                 DeviceConfig.setProperty(namespaceActivityManager,
1351                         maxPhantomProcesses,
1352                         Integer.toString(maxPhantomProcessesNum), false);
1353             });
1354 
1355             // Make sure we could start activity from background
1356             SystemUtil.runShellCommand(mInstrumentation,
1357                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP1);
1358             SystemUtil.runShellCommand(mInstrumentation,
1359                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP2);
1360             SystemUtil.runShellCommand(mInstrumentation,
1361                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP3);
1362 
1363             // Keep the device awake
1364             toggleScreenOn(true);
1365 
1366             // Start an activity
1367             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1368                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1369 
1370             watcher1.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1371 
1372             // Spawn a light weight child process
1373             CountDownLatch startLatch = startChildProcessInPackage(PACKAGE_NAME_APP1,
1374                     new String[] {"/system/bin/sh", "-c",  "sleep 1000"});
1375 
1376             // Wait for the start of the child process
1377             assertTrue("Failed to spawn child process",
1378                     startLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1379 
1380             // Start an activity in another package
1381             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1382                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
1383 
1384             watcher2.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1385 
1386             // Spawn a light weight child process
1387             startLatch = startChildProcessInPackage(PACKAGE_NAME_APP2,
1388                     new String[] {"/system/bin/sh", "-c",  "sleep 1000"});
1389 
1390             // Wait for the start of the child process
1391             assertTrue("Failed to spawn child process",
1392                     startLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1393 
1394             // Finish the 1st activity
1395             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1396                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1397 
1398             watcher1.waitFor(WatchUidRunner.CMD_CACHED, null);
1399 
1400             // Wait for the system to kill that light weight child (it won't happen actually)
1401             CountDownLatch stopLatch = initWaitingForChildProcessGone(
1402                     PACKAGE_NAME_APP1, processGoneTimeout);
1403 
1404             assertFalse("App's light weight child process shouldn't be gone",
1405                     stopLatch.await(processGoneTimeout, TimeUnit.MILLISECONDS));
1406 
1407             // Sleep a while
1408             SystemClock.sleep(powerCheckInterval);
1409 
1410             // Now start an activity in the 3rd party
1411             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1412                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null);
1413 
1414             watcher3.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1415 
1416             // Spawn a light weight child process
1417             startLatch = startChildProcessInPackage(PACKAGE_NAME_APP3,
1418                     new String[] {"/system/bin/sh", "-c",  "sleep 1000"});
1419 
1420             // Wait for the start of the child process
1421             assertTrue("Failed to spawn child process",
1422                     startLatch.await(waitForSec, TimeUnit.MILLISECONDS));
1423 
1424             // Now the 1st child process should have been gone.
1425             stopLatch = initWaitingForChildProcessGone(
1426                     PACKAGE_NAME_APP1, processGoneTimeout);
1427 
1428             assertTrue("1st App's child process should have been gone",
1429                     stopLatch.await(processGoneTimeout, TimeUnit.MILLISECONDS));
1430 
1431         } finally {
1432             amSettings.close();
1433 
1434             SystemUtil.runWithShellPermissionIdentity(() -> {
1435                 final int current = currentMax.getInt(keyCurrent);
1436                 if (current < 0) {
1437                     // Hm, DeviceConfig doesn't have an API to delete a property,
1438                     // let's set it empty so the code will use the built-in default value.
1439                     DeviceConfig.setProperty(namespaceActivityManager,
1440                             maxPhantomProcesses, "", false);
1441                 } else {
1442                     DeviceConfig.setProperty(namespaceActivityManager,
1443                             maxPhantomProcesses, Integer.toString(current), false);
1444                 }
1445             });
1446 
1447             SystemUtil.runShellCommand(mInstrumentation,
1448                     "cmd deviceidle whitelist -" + PACKAGE_NAME_APP1);
1449             SystemUtil.runShellCommand(mInstrumentation,
1450                     "cmd deviceidle whitelist -" + PACKAGE_NAME_APP2);
1451             SystemUtil.runShellCommand(mInstrumentation,
1452                     "cmd deviceidle whitelist -" + PACKAGE_NAME_APP3);
1453 
1454             SystemUtil.runWithShellPermissionIdentity(() -> {
1455                 // force stop test package, where the whole test process group will be killed.
1456                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
1457                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP2);
1458                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP3);
1459             });
1460 
1461             watcher1.finish();
1462             watcher2.finish();
1463             watcher3.finish();
1464         }
1465     }
1466 
startChildProcessInPackage(String pkgName, String[] cmdline)1467     private CountDownLatch startChildProcessInPackage(String pkgName, String[] cmdline) {
1468         final CountDownLatch startLatch = new CountDownLatch(1);
1469 
1470         final IBinder binder = new Binder() {
1471             @Override
1472             protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1473                     throws RemoteException {
1474                 switch (code) {
1475                     case CommandReceiver.RESULT_CHILD_PROCESS_STARTED:
1476                         startLatch.countDown();
1477                         return true;
1478                     default:
1479                         return false;
1480                 }
1481             }
1482         };
1483         final Bundle extras = new Bundle();
1484         extras.putBinder(CommandReceiver.EXTRA_CALLBACK, binder);
1485         extras.putStringArray(CommandReceiver.EXTRA_CHILD_CMDLINE, cmdline);
1486 
1487         CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_CHILD_PROCESS,
1488                 pkgName, pkgName, 0, extras);
1489 
1490         return startLatch;
1491     }
1492 
stopChildProcess(String pkgName, long timeout)1493     final CountDownLatch stopChildProcess(String pkgName, long timeout) {
1494         final CountDownLatch stopLatch = new CountDownLatch(1);
1495 
1496         final IBinder binder = new Binder() {
1497             @Override
1498             protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1499                     throws RemoteException {
1500                 switch (code) {
1501                     case CommandReceiver.RESULT_CHILD_PROCESS_STOPPED:
1502                         stopLatch.countDown();
1503                         return true;
1504                     default:
1505                         return false;
1506                 }
1507             }
1508         };
1509         final Bundle extras = new Bundle();
1510         extras.putBinder(CommandReceiver.EXTRA_CALLBACK, binder);
1511         extras.putLong(CommandReceiver.EXTRA_TIMEOUT, timeout);
1512 
1513         CommandReceiver.sendCommand(mTargetContext,
1514                 CommandReceiver.COMMAND_STOP_CHILD_PROCESS, pkgName, pkgName, 0, extras);
1515 
1516         return stopLatch;
1517     }
1518 
initWaitingForChildProcessGone(String pkgName, long timeout)1519     final CountDownLatch initWaitingForChildProcessGone(String pkgName, long timeout) {
1520         final CountDownLatch stopLatch = new CountDownLatch(1);
1521 
1522         final IBinder binder = new Binder() {
1523             @Override
1524             protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1525                     throws RemoteException {
1526                 switch (code) {
1527                     case CommandReceiver.RESULT_CHILD_PROCESS_GONE:
1528                         stopLatch.countDown();
1529                         return true;
1530                     default:
1531                         return false;
1532                 }
1533             }
1534         };
1535         final Bundle extras = new Bundle();
1536         extras.putBinder(CommandReceiver.EXTRA_CALLBACK, binder);
1537         extras.putLong(CommandReceiver.EXTRA_TIMEOUT, timeout);
1538 
1539         CommandReceiver.sendCommand(mTargetContext,
1540                 CommandReceiver.COMMAND_WAIT_FOR_CHILD_PROCESS_GONE, pkgName, pkgName, 0, extras);
1541 
1542         return stopLatch;
1543     }
1544 
1545     @Test
testTrimMemActivityFg()1546     public void testTrimMemActivityFg() throws Exception {
1547         final int waitForSec = 5 * 1000;
1548         final ApplicationInfo ai1 = mTargetContext.getPackageManager()
1549                 .getApplicationInfo(PACKAGE_NAME_APP1, 0);
1550         final WatchUidRunner watcher1 = new WatchUidRunner(mInstrumentation, ai1.uid, waitForSec);
1551 
1552         final ApplicationInfo ai2 = mTargetContext.getPackageManager()
1553                 .getApplicationInfo(PACKAGE_NAME_APP2, 0);
1554         final WatchUidRunner watcher2 = new WatchUidRunner(mInstrumentation, ai2.uid, waitForSec);
1555 
1556         final ApplicationInfo ai3 = mTargetContext.getPackageManager()
1557                 .getApplicationInfo(CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
1558         final WatchUidRunner watcher3 = new WatchUidRunner(mInstrumentation, ai3.uid, waitForSec);
1559 
1560         final CountDownLatch[] latchHolder = new CountDownLatch[1];
1561         final int[] expectedLevel = new int[1];
1562         final Bundle extras = initWaitingForTrimLevel(level -> {
1563             if (level == expectedLevel[0]) {
1564                 latchHolder[0].countDown();
1565             }
1566         });
1567         try {
1568             // Make sure we could start activity from background
1569             SystemUtil.runShellCommand(mInstrumentation,
1570                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP1);
1571 
1572             // Override the memory pressure level, force it staying at normal.
1573             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set NORMAL");
1574 
1575             // Keep the device awake
1576             toggleScreenOn(true);
1577 
1578             latchHolder[0] = new CountDownLatch(1);
1579             expectedLevel[0] = TRIM_MEMORY_RUNNING_MODERATE;
1580 
1581             // Start an activity
1582             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1583                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1584 
1585             watcher1.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1586 
1587             // Force the memory pressure to moderate
1588             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set MODERATE");
1589             assertTrue("Failed to wait for the trim memory event",
1590                     latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1591 
1592             latchHolder[0] = new CountDownLatch(1);
1593             expectedLevel[0] = TRIM_MEMORY_RUNNING_LOW;
1594             // Force the memory pressure to low
1595             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set LOW");
1596             assertTrue("Failed to wait for the trim memory event",
1597                     latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1598 
1599             latchHolder[0] = new CountDownLatch(1);
1600             expectedLevel[0] = TRIM_MEMORY_RUNNING_CRITICAL;
1601             // Force the memory pressure to critical
1602             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set CRITICAL");
1603             assertTrue("Failed to wait for the trim memory event",
1604                     latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1605 
1606             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_SERVICE,
1607                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, LocalForegroundService.newCommand(
1608                     LocalForegroundService.COMMAND_START_NO_FOREGROUND));
1609 
1610             // Reset the memory pressure override
1611             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor reset");
1612 
1613             latchHolder[0] = new CountDownLatch(1);
1614             expectedLevel[0] = TRIM_MEMORY_UI_HIDDEN;
1615             // Start another activity in package2
1616             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1617                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
1618             watcher2.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1619             watcher1.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE, null);
1620             assertTrue("Failed to wait for the trim memory event",
1621                     latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1622 
1623             // Start the heavy weight activity
1624             final Intent intent = new Intent();
1625             final CountDownLatch[] heavyLatchHolder = new CountDownLatch[1];
1626             final Predicate[] testFunc = new Predicate[1];
1627 
1628             intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
1629             intent.setAction(Intent.ACTION_MAIN);
1630             intent.addCategory(Intent.CATEGORY_LAUNCHER);
1631             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1632             intent.putExtras(initWaitingForTrimLevel(level -> {
1633                 if (testFunc[0].test(level)) {
1634                     heavyLatchHolder[0].countDown();
1635                 }
1636             }));
1637 
1638             mTargetContext.startActivity(intent);
1639             watcher3.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1640 
1641             heavyLatchHolder[0] = new CountDownLatch(1);
1642             testFunc[0] = level -> TRIM_MEMORY_RUNNING_MODERATE <= (int) level
1643                     && TRIM_MEMORY_RUNNING_CRITICAL >= (int) level;
1644             // Force the memory pressure to moderate
1645             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set MODERATE");
1646             assertTrue("Failed to wait for the trim memory event",
1647                     heavyLatchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1648 
1649             // Now go home
1650             final Intent homeIntent = new Intent();
1651             homeIntent.setAction(Intent.ACTION_MAIN);
1652             homeIntent.addCategory(Intent.CATEGORY_HOME);
1653             homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1654 
1655             heavyLatchHolder[0] = new CountDownLatch(1);
1656             testFunc[0] = level -> TRIM_MEMORY_BACKGROUND == (int) level;
1657             mTargetContext.startActivity(homeIntent);
1658             assertTrue("Failed to wait for the trim memory event",
1659                     heavyLatchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1660 
1661         } finally {
1662             SystemUtil.runShellCommand(mInstrumentation,
1663                     "cmd deviceidle whitelist -" + PACKAGE_NAME_APP1);
1664 
1665             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor reset");
1666 
1667             SystemUtil.runWithShellPermissionIdentity(() -> {
1668                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
1669                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP2);
1670                 mActivityManager.forceStopPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
1671             });
1672 
1673             watcher1.finish();
1674             watcher2.finish();
1675             watcher3.finish();
1676         }
1677     }
1678 
1679     @Test
testTrimMemActivityBg()1680     public void testTrimMemActivityBg() throws Exception {
1681         final int minLru = 8;
1682         final int waitForSec = 30 * 1000;
1683         final String prefix = "trimmem_";
1684         final CountDownLatch[] latchHolder = new CountDownLatch[1];
1685         final String pkgName = PACKAGE_NAME_APP1;
1686         final ArrayMap<String, Pair<int[], ServiceConnection>> procName2Level = new ArrayMap<>();
1687         int startSeq = 0;
1688 
1689         try {
1690             // Kill all background processes
1691             SystemUtil.runShellCommand(mInstrumentation, "am kill-all");
1692 
1693             // Override the memory pressure level, force it staying at normal.
1694             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set NORMAL");
1695 
1696             List<String> lru;
1697             // Start a new isolated service once a time, and then check the lru list
1698             do {
1699                 final String instanceName = prefix + startSeq++;
1700                 final int[] levelHolder = new int[1];
1701 
1702                 // Spawn the new isolated service
1703                 final ServiceConnection conn = TrimMemService.bindToTrimMemService(
1704                         pkgName, instanceName, latchHolder, levelHolder, mTargetContext);
1705 
1706                 // Get the list of all cached apps
1707                 lru = getCachedAppsLru();
1708                 assertTrue(lru.size() > 0);
1709 
1710                 for (int i = lru.size() - 1; i >= 0; i--) {
1711                     String p = lru.get(i);
1712                     if (p.indexOf(instanceName) != -1) {
1713                         // This is the new one we just created
1714                         procName2Level.put(p, new Pair<>(levelHolder, conn));
1715                         break;
1716                     }
1717                 }
1718                 if (lru.size() < minLru) {
1719                     continue;
1720                 }
1721                 if (lru.get(0).indexOf(pkgName) != -1) {
1722                     // Okay now the very least recent used cached process is one of ours
1723                     break;
1724                 } else {
1725                     // Hm, someone dropped below us in the between, let's kill it
1726                     ArraySet<String> others = new ArraySet<>();
1727                     for (int i = 0, size = lru.size(); i < size; i++) {
1728                         final String name = lru.get(i);
1729                         if (name.indexOf(pkgName) != -1) {
1730                             break;
1731                         }
1732                         others.add(name);
1733                     }
1734                     SystemUtil.runWithShellPermissionIdentity(() -> {
1735                         final List<ActivityManager.RunningAppProcessInfo> procs = mActivityManager
1736                                 .getRunningAppProcesses();
1737                         for (ActivityManager.RunningAppProcessInfo info: procs) {
1738                             if (info.importance
1739                                     == ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED) {
1740                                 if (others.contains(info.processName)) {
1741                                     mActivityManager.killBackgroundProcesses(info.pkgList[0]);
1742                                 }
1743                             }
1744                         }
1745                     });
1746                 }
1747             } while (true);
1748 
1749             // Remove all other processes
1750             for (int i = lru.size() - 1; i >= 0; i--) {
1751                 if (lru.get(i).indexOf(pkgName) == -1) {
1752                     lru.remove(i);
1753                 }
1754             }
1755 
1756             latchHolder[0] = new CountDownLatch(lru.size());
1757             // Force the memory pressure to moderate
1758             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set MODERATE");
1759             assertTrue("Failed to wait for the trim memory event",
1760                     latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
1761 
1762             // Verify the trim levels among the LRU
1763             int level = TRIM_MEMORY_COMPLETE;
1764             assertEquals(level, procName2Level.get(lru.get(0)).first[0]);
1765             for (int i = 1, size = lru.size(); i < size; i++) {
1766                 int curLevel = procName2Level.get(lru.get(i)).first[0];
1767                 assertTrue(level >= curLevel);
1768                 level = curLevel;
1769             }
1770 
1771             // Cleanup: Unbind from them
1772             for (int i = procName2Level.size() - 1; i >= 0; i--) {
1773                 mTargetContext.unbindService(procName2Level.valueAt(i).second);
1774             }
1775         } finally {
1776             SystemUtil.runShellCommand(mInstrumentation, "am memory-factor reset");
1777 
1778             SystemUtil.runWithShellPermissionIdentity(() -> {
1779                 mActivityManager.forceStopPackage(PACKAGE_NAME_APP1);
1780             });
1781         }
1782     }
1783 
1784     @Test
testServiceDoneLRUPosition()1785     public void testServiceDoneLRUPosition() throws Exception {
1786         final String[] packageNames = {PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3};
1787         final WatchUidRunner[] watchers = initWatchUidRunners(packageNames, WAITFOR_MSEC);
1788         final HandlerThread handlerThread = new HandlerThread("worker");
1789         final Messenger[] controllerHolder = new Messenger[1];
1790         final CountDownLatch[] countDownLatchHolder = new CountDownLatch[1];
1791         handlerThread.start();
1792         final Messenger messenger = new Messenger(new Handler(handlerThread.getLooper(), msg -> {
1793             final Bundle bundle = (Bundle) msg.obj;
1794             final IBinder binder = bundle.getBinder(CommandReceiver.EXTRA_MESSENGER);
1795             if (binder != null) {
1796                 controllerHolder[0] = new Messenger(binder);
1797                 countDownLatchHolder[0].countDown();
1798             }
1799             return true;
1800         }));
1801 
1802         try {
1803             // Make sure we could start activity from background
1804             forEach(packageNames, packageName -> SystemUtil.runShellCommand(mInstrumentation,
1805                     "cmd deviceidle whitelist +" + packageName));
1806 
1807             // Keep the device awake
1808             toggleScreenOn(true);
1809 
1810             // Start a FGS in app1
1811             final Bundle extras = new Bundle();
1812             countDownLatchHolder[0] = new CountDownLatch(1);
1813             extras.putBinder(CommandReceiver.EXTRA_MESSENGER, messenger.getBinder());
1814             CommandReceiver.sendCommand(mTargetContext,
1815                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1816                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1817 
1818             watchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
1819                     null);
1820 
1821             assertTrue("Failed to get the controller interface",
1822                     countDownLatchHolder[0].await(WAITFOR_MSEC, TimeUnit.MILLISECONDS));
1823 
1824             final String[] otherPackages = {PACKAGE_NAME_APP2, PACKAGE_NAME_APP3};
1825             final WatchUidRunner[] otherWatchers = {watchers[1], watchers[2]};
1826             // Start an activity in another package
1827             forBiEach(otherPackages, otherWatchers, (packageName, watcher) -> {
1828                 CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1829                         packageName, packageName, 0, null);
1830                 watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1831             });
1832 
1833             // Stop both of these activities
1834             forBiEach(otherPackages, otherWatchers, (packageName, watcher) -> {
1835                 CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1836                         packageName, packageName, 0, null);
1837                 watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
1838                         null);
1839             });
1840 
1841             // Launch home so we'd have cleared these the above test activities from recents.
1842             launchHome();
1843 
1844             // Now stop the foreground service, we'd have to do via the controller interface
1845             final Message msg = Message.obtain();
1846             try {
1847                 msg.what = LocalForegroundService.COMMAND_STOP_SELF;
1848                 controllerHolder[0].send(msg);
1849             } catch (RemoteException e) {
1850                 fail("Unable to stop test package");
1851             }
1852             msg.recycle();
1853             watchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
1854                     null);
1855 
1856             verifyLruOrders(packageNames, 0, true, (a, b) -> a > b, "%s should be newer than %s");
1857         } finally {
1858             handlerThread.quitSafely();
1859 
1860             forEach(packageNames, packageName -> SystemUtil.runShellCommand(mInstrumentation,
1861                     "cmd deviceidle whitelist -" + packageName));
1862 
1863             // force stop test package, where the whole test process group will be killed.
1864             forEach(packageNames, packageName -> SystemUtil.runWithShellPermissionIdentity(
1865                     () -> mActivityManager.forceStopPackage(packageName)));
1866 
1867             forEach(watchers, watcher -> watcher.finish());
1868         }
1869     }
1870 
1871     @Test
testBroadcastReceiverLRUPosition()1872     public void testBroadcastReceiverLRUPosition() throws Exception {
1873         assumeTrue("app standby not enabled", mAppStandbyEnabled);
1874         assumeFalse("not testable in automotive device", mAutomotiveDevice);
1875         assumeFalse("not testable in leanback device", mLeanbackOnly);
1876 
1877         final String[] packageNames = {PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3};
1878         final WatchUidRunner[] watchers = initWatchUidRunners(packageNames, WAITFOR_MSEC * 2);
1879 
1880         try {
1881             // Set the PACKAGE_NAME_APP1 into rare bucket
1882             SystemUtil.runShellCommand(mInstrumentation, "am set-standby-bucket "
1883                     + PACKAGE_NAME_APP1 + " rare");
1884 
1885             // Make sure we could start activity from background
1886             forEach(packageNames, packageName -> SystemUtil.runShellCommand(mInstrumentation,
1887                     "cmd deviceidle whitelist +" + packageName));
1888 
1889             // Keep the device awake
1890             toggleScreenOn(true);
1891 
1892             // Start activities in these packages.
1893             forBiEach(packageNames, watchers, (packageName, watcher) -> {
1894                 CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
1895                         packageName, packageName, 0, null);
1896                 watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
1897             });
1898 
1899             // Stop all of these activities
1900             forBiEach(packageNames, watchers, (packageName, watcher) -> {
1901                 CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1902                         packageName, packageName, 0, null);
1903                 watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
1904                         null);
1905             });
1906 
1907             // Launch home so we'd have cleared these the above test activities from recents.
1908             launchHome();
1909 
1910             // Verify the LRU position.
1911             verifyLruOrders(packageNames, 0, false, (a, b) -> a < b, "%s should be older than %s");
1912 
1913             forEach(packageNames, packageName -> SystemUtil.runShellCommand(mInstrumentation,
1914                     "cmd deviceidle whitelist -" + packageName));
1915             // Restrict the PACKAGE_NAME_APP1
1916             SystemUtil.runShellCommand(mInstrumentation, "am set-standby-bucket "
1917                     + PACKAGE_NAME_APP1 + " restricted");
1918             // Sleep a while to let it take effect.
1919             Thread.sleep(WAITFOR_MSEC);
1920 
1921             final Intent intent = new Intent();
1922             final CountDownLatch[] latch = new CountDownLatch[] {new CountDownLatch(1)};
1923             final BroadcastReceiver receiver = new BroadcastReceiver() {
1924                 @Override
1925                 public void onReceive(Context context, Intent intent) {
1926                     latch[0].countDown();
1927                 }
1928             };
1929             // Send a broadcast to PACKAGE_NAME_APP1
1930             CommandReceiver.sendCommandWithResultReceiver(mTargetContext,
1931                     CommandReceiver.COMMAND_EMPTY, PACKAGE_NAME_APP1, PACKAGE_NAME_APP1,
1932                     0, null, receiver);
1933 
1934             assertTrue("Failed to get the broadcast",
1935                     latch[0].await(WAITFOR_MSEC * 2, TimeUnit.MILLISECONDS));
1936 
1937             // Now check the LRU position again, it should remain the same because it's restricted.
1938             verifyLruOrders(packageNames, 0, false, (a, b) -> a < b, "%s should be older than %s");
1939 
1940             // Set the PACKAGE_NAME_APP1 into rare bucket again.
1941             SystemUtil.runShellCommand(mInstrumentation, "am set-standby-bucket "
1942                     + PACKAGE_NAME_APP1 + " rare");
1943 
1944             latch[0] = new CountDownLatch(1);
1945             // Send a broadcast to PACKAGE_NAME_APP1 again.
1946             CommandReceiver.sendCommandWithResultReceiver(mTargetContext,
1947                     CommandReceiver.COMMAND_EMPTY, PACKAGE_NAME_APP1, PACKAGE_NAME_APP1,
1948                     0, null, receiver);
1949 
1950             // Now its LRU posistion should have been bumped.
1951             verifyLruOrders(packageNames, 0, true, (a, b) -> a > b, "%s should be newer than %s");
1952         } finally {
1953             forEach(packageNames, packageName -> SystemUtil.runShellCommand(mInstrumentation,
1954                     "cmd deviceidle whitelist -" + packageName));
1955 
1956             SystemUtil.runShellCommand(mInstrumentation, "am set-standby-bucket "
1957                     + PACKAGE_NAME_APP1 + " rare");
1958 
1959             // force stop test package, where the whole test process group will be killed.
1960             forEach(packageNames, packageName -> SystemUtil.runWithShellPermissionIdentity(
1961                     () -> mActivityManager.forceStopPackage(packageName)));
1962 
1963             forEach(watchers, watcher -> watcher.finish());
1964         }
1965     }
1966 
1967     @Test
testGetUidProcessState_checkAccess()1968     public void testGetUidProcessState_checkAccess() throws Exception {
1969         boolean hasPermissionGrantChanged = false;
1970         if (!PermissionUtils.isPermissionGranted(STUB_PACKAGE_NAME,
1971                 android.Manifest.permission.PACKAGE_USAGE_STATS)) {
1972             PermissionUtils.grantPermission(
1973                     STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
1974             hasPermissionGrantChanged = true;
1975         }
1976         int newUserId = UserHandle.USER_NULL;
1977         try {
1978             // Verify that calling the API doesn't trigger any exceptions.
1979             mActivityManager.getUidProcessState(Process.myUid());
1980 
1981             assumeTrue(UserManager.supportsMultipleUsers());
1982             newUserId = createNewUser();
1983             assertNotEquals(UserHandle.USER_NULL, newUserId);
1984             startUser(newUserId);
1985             installExistingPackageAsUser(STUB_PACKAGE_NAME, newUserId);
1986             final int uidFromNewUser = UserHandle.getUid(newUserId, Process.myUid());
1987             // Verify that calling the API for a uid on a different user results in an exception.
1988             assertThrows(SecurityException.class, () -> mActivityManager.getUidProcessState(
1989                     uidFromNewUser));
1990 
1991             // Verify that calling the API with shell identity (which has
1992             // INTERACT_ACROSS_USERS_FULL permission) for a uid on a different user works.
1993             SystemUtil.runWithShellPermissionIdentity(() -> mActivityManager.getUidProcessState(
1994                     uidFromNewUser));
1995         } finally {
1996             if (newUserId != UserHandle.USER_NULL) {
1997                 removeUser(newUserId);
1998             }
1999             if (hasPermissionGrantChanged) {
2000                 PermissionUtils.revokePermission(
2001                         STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
2002             }
2003         }
2004     }
2005 
2006     @Test
testGetUidProcessCapabilities_checkAccess()2007     public void testGetUidProcessCapabilities_checkAccess() throws Exception {
2008         boolean hasPermissionGrantChanged = false;
2009         if (!PermissionUtils.isPermissionGranted(STUB_PACKAGE_NAME,
2010                 android.Manifest.permission.PACKAGE_USAGE_STATS)) {
2011             PermissionUtils.grantPermission(
2012                     STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
2013             hasPermissionGrantChanged = true;
2014         }
2015         int newUserId = UserHandle.USER_NULL;
2016         try {
2017             // Verify that calling the API doesn't trigger any exceptions.
2018             mActivityManager.getUidProcessCapabilities(Process.myUid());
2019 
2020             assumeTrue(UserManager.supportsMultipleUsers());
2021             newUserId = createNewUser();
2022             assertNotEquals(UserHandle.USER_NULL, newUserId);
2023             startUser(newUserId);
2024             installExistingPackageAsUser(STUB_PACKAGE_NAME, newUserId);
2025             final int uidFromNewUser = UserHandle.getUid(newUserId, Process.myUid());
2026             // Verify that calling the API for a uid on a different user results in an exception.
2027             assertThrows(SecurityException.class, () -> mActivityManager.getUidProcessState(
2028                     uidFromNewUser));
2029 
2030             // Verify that calling the API with shell identity (which has
2031             // INTERACT_ACROSS_USERS_FULL permission) for a uid on a different user works.
2032             SystemUtil.runWithShellPermissionIdentity(() -> mActivityManager.getUidProcessState(
2033                     uidFromNewUser));
2034         } finally {
2035             if (newUserId != UserHandle.USER_NULL) {
2036                 removeUser(newUserId);
2037             }
2038             if (hasPermissionGrantChanged) {
2039                 PermissionUtils.revokePermission(
2040                         STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
2041             }
2042         }
2043     }
2044 
createNewUser()2045     private int createNewUser() throws Exception {
2046         final UserManager userManager = mTargetContext.getSystemService(UserManager.class);
2047         return SystemUtil.runWithShellPermissionIdentity(() -> {
2048             final NewUserRequest newUserRequest = new NewUserRequest.Builder()
2049                     .setName("test_user")
2050                     .setUserType(UserManager.USER_TYPE_FULL_SECONDARY)
2051                     .build();
2052             final UserHandle newUser = userManager.createUser(newUserRequest)
2053                     .getUser();
2054             return newUser == null ? UserHandle.USER_NULL : newUser.getIdentifier();
2055         });
2056     }
2057 
2058     private void startUser(int userId) throws Exception {
2059         final String cmd = "cmd activity start-user -w " + userId;
2060         final String output = executeShellCommand(cmd);
2061         if (output.startsWith("Error")) {
2062             fail("Error starting the new user u" + userId + ": " + output);
2063         }
2064         final String state = executeShellCommand("am get-started-user-state " + userId);
2065         if (!state.contains("RUNNING_UNLOCKED")) {
2066             fail("Unexpected state for the new user u" + userId + ": " + state);
2067         }
2068     }
2069 
2070     private void removeUser(int userId) throws Exception {
2071         final String cmd = "cmd package remove-user " + userId;
2072         final String output = executeShellCommand(cmd);
2073         if (output.startsWith("Error")) {
2074             fail("Error removing the user u" + userId + ": " + output);
2075         }
2076     }
2077 
2078     private void installExistingPackageAsUser(String packageName, int userId)
2079             throws Exception {
2080         final String cmd = String.format("cmd package install-existing --user %d --wait %s",
2081                 userId, packageName);
2082         executeShellCommand(cmd);
2083     }
2084 
2085     private int[] getLruPositions(String[] packageNames) throws Exception {
2086         final List<String> lru = getCachedAppsLru();
2087         assertTrue("Failed to get cached app list", lru.size() > 0);
2088         final int[] pos = new int[packageNames.length];
2089         for (int i = 0; i < packageNames.length; i++) {
2090             pos[i] = lru.indexOf(packageNames[i]);
2091         }
2092         return pos;
2093     }
2094 
2095     private void verifyLruOrders(String[] packageNames, int testIndex, boolean newest,
2096             BiPredicate<Integer, Integer> predicate, String msg) throws Exception {
2097         final List<String> lru = getCachedAppsLru();
2098 
2099         assertTrue("Failed to get cached app list", lru.size() > 0);
2100         final int[] pos = getLruPositions(packageNames);
2101         if (pos[testIndex] != -1) {
2102             for (int i = 0; i < pos.length; i++) {
2103                 if (i == testIndex || pos[i] == -1) {
2104                     continue;
2105                 }
2106                 assertTrue(String.format(msg, packageNames[testIndex], packageNames[i]),
2107                         predicate.test(pos[testIndex], pos[i]));
2108             }
2109         } else if (newest) {
2110             for (int i = 0; i < pos.length; i++) {
2111                 assertEquals(packageNames[i] + " should have gone", -1, pos[i]);
2112             }
2113         }
2114     }
2115 
2116     private WatchUidRunner[] initWatchUidRunners(String[] packageNames, long waitFormMs)
2117             throws Exception {
2118         final WatchUidRunner[] watchers = new WatchUidRunner[packageNames.length];
2119         for (int i = 0; i < packageNames.length; i++) {
2120             final ApplicationInfo ai = mTargetContext.getPackageManager()
2121                     .getApplicationInfo(packageNames[i], 0);
2122             watchers[i] = new WatchUidRunner(mInstrumentation, ai.uid, waitFormMs);
2123         }
2124         return watchers;
2125     }
2126 
2127     private interface ConsumerWithException<T> {
2128         void accept(T t) throws Exception;
2129     }
2130 
2131     private interface BiConsumerWithException<T, U> {
2132         void accept(T t, U u) throws Exception;
2133     }
2134 
2135     private <T> void forEach(T[] items, ConsumerWithException<T> consumer) throws Exception {
2136         for (T item: items) {
2137             consumer.accept(item);
2138         }
2139     }
2140 
2141     private <T, U> void forBiEach(T[] itemsA, U[] itemsB, BiConsumerWithException<T, U> consumer)
2142             throws Exception {
2143         for (int i = 0; i < itemsA.length; i++) {
2144             consumer.accept(itemsA[i], itemsB[i]);
2145         }
2146     }
2147 
2148     private List<String> getCachedAppsLru() throws Exception {
2149         final List<String> lru = new ArrayList<>();
2150         final String output = SystemUtil.runShellCommand(mInstrumentation, "dumpsys activity lru");
2151         final String[] lines = output.split("\n");
2152         for (String line: lines) {
2153             if (line == null || line.indexOf(" cch") == -1) {
2154                 continue;
2155             }
2156             final int slash = line.lastIndexOf('/');
2157             if (slash == -1) {
2158                 continue;
2159             }
2160             line = line.substring(0, slash);
2161             final int space = line.lastIndexOf(' ');
2162             if (space == -1) {
2163                 continue;
2164             }
2165             line = line.substring(space + 1);
2166             final int colon = line.indexOf(':');
2167             if (colon == -1) {
2168                 continue;
2169             }
2170             lru.add(0, line.substring(colon + 1));
2171         }
2172         return lru;
2173     }
2174 
2175     private Bundle initWaitingForTrimLevel(final Consumer<Integer> checker) {
2176         final IBinder binder = new Binder() {
2177             @Override
2178             protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
2179                     throws RemoteException {
2180                 switch (code) {
2181                     case IBinder.FIRST_CALL_TRANSACTION:
2182                         final int level = data.readInt();
2183                         checker.accept(level);
2184                         return true;
2185                     default:
2186                         return false;
2187                 }
2188             }
2189         };
2190         final Bundle extras = new Bundle();
2191         extras.putBinder(CommandReceiver.EXTRA_CALLBACK, binder);
2192         return extras;
2193     }
2194 
2195     private RunningAppProcessInfo getRunningAppProcessInfo(String processName) {
2196         try {
2197             return SystemUtil.callWithShellPermissionIdentity(()-> {
2198                 return mActivityManager.getRunningAppProcesses().stream().filter(
2199                         (ra) -> processName.equals(ra.processName)).findFirst().orElse(null);
2200             });
2201         } catch (Exception e) {
2202         }
2203         return null;
2204     }
2205 
2206     private boolean isProcessGone(int pid, String processName) {
2207         RunningAppProcessInfo info = getRunningAppProcessInfo(processName);
2208         return info == null || info.pid != pid;
2209     }
2210 
2211     // Copied from DeviceStatesTest
2212     /**
2213      * Make sure the screen state.
2214      */
2215     private void toggleScreenOn(final boolean screenon) throws Exception {
2216         if (screenon) {
2217             executeAndLogShellCommand("input keyevent KEYCODE_WAKEUP");
2218             executeAndLogShellCommand("wm dismiss-keyguard");
2219         } else {
2220             executeAndLogShellCommand("input keyevent KEYCODE_SLEEP");
2221         }
2222         // Since the screen on/off intent is ordered, they will not be sent right now.
2223         SystemClock.sleep(2_000);
2224     }
2225 
2226     /**
2227      * Simulated for idle, and then perform idle maintenance now.
2228      */
2229     private void triggerIdle(boolean idle) throws Exception {
2230         if (idle) {
2231             executeAndLogShellCommand("cmd deviceidle force-idle light");
2232         } else {
2233             executeAndLogShellCommand("cmd deviceidle unforce");
2234         }
2235         // Wait a moment to let that happen before proceeding.
2236         SystemClock.sleep(2_000);
2237     }
2238 
2239     /**
2240      * Return true if the given supplier says it's true
2241      */
2242     private boolean waitUntilTrue(long maxWait, Supplier<Boolean> supplier) throws Exception {
2243         final long deadLine = SystemClock.uptimeMillis() + maxWait;
2244         boolean result = false;
2245         do {
2246             Thread.sleep(500);
2247         } while (!(result = supplier.get()) && SystemClock.uptimeMillis() < deadLine);
2248         return result;
2249     }
2250 
2251     private void createManagedHomeActivitySession()
2252             throws Exception {
2253         if (noHomeScreen()) return;
2254         ComponentName homeActivity = new ComponentName(
2255                 STUB_PACKAGE_NAME, TestHomeActivity.class.getName());
2256         mTestHomeSession = new HomeActivitySession(homeActivity);
2257     }
2258 
2259     /**
2260      * HomeActivitySession is used to replace the default home component, so that you can use
2261      * your preferred home for testing within the session. The original default home will be
2262      * restored automatically afterward.
2263      */
2264     private class HomeActivitySession {
2265         private PackageManager mPackageManager;
2266         private ComponentName mOrigHome;
2267         private ComponentName mSessionHome;
2268 
2269         HomeActivitySession(ComponentName sessionHome) throws Exception {
2270             mSessionHome = sessionHome;
2271             mPackageManager = mInstrumentation.getContext().getPackageManager();
2272             mOrigHome = getDefaultHomeComponent();
2273 
2274             SystemUtil.runWithShellPermissionIdentity(
2275                     () -> mPackageManager.setComponentEnabledSetting(mSessionHome,
2276                             COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP));
2277             setDefaultHome(mSessionHome);
2278         }
2279 
2280         public void close() throws Exception {
2281             SystemUtil.runWithShellPermissionIdentity(
2282                     () -> mPackageManager.setComponentEnabledSetting(mSessionHome,
2283                             COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP));
2284             if (mOrigHome != null) {
2285                 setDefaultHome(mOrigHome);
2286                 mOrigHome = null;
2287             }
2288         }
2289 
2290         private void setDefaultHome(ComponentName componentName) throws Exception {
2291             executeShellCommand("cmd package set-home-activity --user "
2292                     + android.os.Process.myUserHandle().getIdentifier() + " "
2293                     + componentName.flattenToString());
2294         }
2295 
2296         private ComponentName getDefaultHomeComponent() {
2297             final Intent intent = new Intent(ACTION_MAIN);
2298             intent.addCategory(CATEGORY_HOME);
2299             intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
2300             final ResolveInfo resolveInfo = mInstrumentation.getContext()
2301                     .getPackageManager().resolveActivity(intent, MATCH_DEFAULT_ONLY);
2302             if (resolveInfo == null) {
2303                 throw new AssertionError("Home activity not found");
2304             }
2305             return new ComponentName(resolveInfo.activityInfo.packageName,
2306                     resolveInfo.activityInfo.name);
2307         }
2308     }
2309 
2310     private boolean isAtvDevice() {
2311         final Context context = mInstrumentation.getTargetContext();
2312         return context.getPackageManager()
2313                 .hasSystemFeature(PackageManager.FEATURE_TELEVISION);
2314     }
2315 
2316     @Test
2317     public void testKillBackgroundProcess() throws Exception {
2318         final String otherPackage = "com.android.app1";
2319         final ApplicationInfo ai1 = mTargetContext.getPackageManager()
2320                 .getApplicationInfo(otherPackage, 0);
2321         final WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, Process.myUid(),
2322                 WAITFOR_MSEC);
2323         final WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, ai1.uid,
2324                 WAITFOR_MSEC);
2325         try {
2326             launchHome();
2327 
2328             // Since we're running instrumentation, our proc state will stay above FGS.
2329             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
2330                     WatchUidRunner.STATE_FG_SERVICE);
2331 
2332             // Start an activity in another process in our package, our proc state will goto TOP.
2333             final CountDownLatch remoteBinderDeathLatch1 = startRemoteActivityAndLinkToDeath(
2334                     new ComponentName(mTargetContext, RemoteActivity.class),
2335                     uid1Watcher);
2336 
2337             final CountDownLatch remoteBinderDeathLatch2 = startRemoteActivityAndLinkToDeath(
2338                     new ComponentName(otherPackage, STUB_PACKAGE_NAME + ".RemoteActivity"),
2339                     uid2Watcher);
2340 
2341             // Launch home again so our activity will be backgrounded.
2342             launchHome();
2343 
2344             // The uid goes back to FGS state,
2345             // but the process with the remote activity should have been in the background.
2346             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
2347                     WatchUidRunner.STATE_FG_SERVICE);
2348 
2349             // And the test package should be in background too.
2350             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
2351                     WatchUidRunner.STATE_LAST);
2352 
2353             // Now, try to kill the background process of our own, it should succeed.
2354             mActivityManager.killBackgroundProcesses(mTargetContext.getPackageName());
2355 
2356             assertTrue("We should be able to kill our own process",
2357                     remoteBinderDeathLatch1.await(WAITFOR_MSEC, TimeUnit.MILLISECONDS));
2358 
2359             // Try to kill the background process of other app, it should fail.
2360             mActivityManager.killBackgroundProcesses(otherPackage);
2361 
2362             assertFalse("We should be able to kill the processes of other package",
2363                     remoteBinderDeathLatch2.await(WAITFOR_MSEC, TimeUnit.MILLISECONDS));
2364 
2365             // Adopt the permission, we should be able to kill it now.
2366             mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
2367                     android.Manifest.permission.FORCE_STOP_PACKAGES);
2368 
2369             mActivityManager.killBackgroundProcesses(otherPackage);
2370 
2371             assertTrue("We should be able to kill the processes of other package",
2372                     remoteBinderDeathLatch2.await(WAITFOR_MSEC, TimeUnit.MILLISECONDS));
2373         } finally {
2374             uid1Watcher.finish();
2375             uid2Watcher.finish();
2376             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
2377             finishAndRemoveTask(new ComponentName(mTargetContext, RemoteActivity.class));
2378         }
2379     }
2380 
2381     private void finishAndRemoveTask(ComponentName activity) {
2382         for (ActivityManager.AppTask task : mActivityManager.getAppTasks()) {
2383             final ActivityManager.RecentTaskInfo info = task.getTaskInfo();
2384             if (info != null && activity.equals(info.topActivity)) {
2385                 task.finishAndRemoveTask();
2386                 break;
2387             }
2388         }
2389     }
2390 
2391     private CountDownLatch startRemoteActivityAndLinkToDeath(ComponentName activity,
2392             WatchUidRunner uidWatcher) throws Exception {
2393         final IBinder[] remoteBinderHolder = new IBinder[1];
2394         final CountDownLatch remoteBinderLatch = new CountDownLatch(1);
2395         final IBinder binder = new Binder() {
2396             @Override
2397             protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
2398                     throws RemoteException {
2399                 switch (code) {
2400                     case IBinder.FIRST_CALL_TRANSACTION:
2401                         remoteBinderHolder[0] = data.readStrongBinder();
2402                         remoteBinderLatch.countDown();
2403                         return true;
2404                     default:
2405                         return false;
2406                 }
2407             }
2408         };
2409         final CountDownLatch remoteBinderDeathLatch = new CountDownLatch(1);
2410         final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
2411             @Override
2412             public void binderDied() {
2413                 remoteBinderDeathLatch.countDown();
2414             }
2415         };
2416         final Intent intent = new Intent();
2417         intent.setComponent(activity);
2418         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2419         final Bundle extras = new Bundle();
2420         extras.putBinder(RemoteActivity.EXTRA_CALLBACK, binder);
2421         intent.putExtras(extras);
2422         mTargetContext.startActivity(intent);
2423 
2424         uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
2425         assertTrue("Failed to receive the callback from remote activity",
2426                 remoteBinderLatch.await(WAITFOR_MSEC, TimeUnit.MILLISECONDS));
2427         assertNotNull(remoteBinderHolder[0]);
2428         remoteBinderHolder[0].linkToDeath(recipient, 0);
2429 
2430         // Sleep a while to let things go through.
2431         Thread.sleep(WAIT_TIME);
2432         return remoteBinderDeathLatch;
2433     }
2434 }
2435