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