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