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