1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.cts; 18 19 import android.Manifest; 20 import android.accessibilityservice.AccessibilityService; 21 import android.app.Activity; 22 import android.app.ActivityManager; 23 import android.app.AppOpsManager; 24 import android.app.Instrumentation; 25 import android.app.KeyguardManager; 26 import android.app.cts.android.app.cts.tools.ServiceConnectionHandler; 27 import android.app.cts.android.app.cts.tools.ServiceProcessController; 28 import android.app.cts.android.app.cts.tools.SyncOrderedBroadcast; 29 import android.app.cts.android.app.cts.tools.UidImportanceListener; 30 import android.app.cts.android.app.cts.tools.WaitForBroadcast; 31 import android.app.cts.android.app.cts.tools.WatchUidRunner; 32 import android.content.ComponentName; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.pm.ApplicationInfo; 36 import android.content.pm.PackageManager; 37 import android.content.res.Configuration; 38 import android.os.IBinder; 39 import android.os.Parcel; 40 import android.os.PowerManager; 41 import android.os.RemoteException; 42 import android.os.SystemClock; 43 import android.server.am.WindowManagerState; 44 import android.support.test.InstrumentationRegistry; 45 import android.support.test.uiautomator.BySelector; 46 import android.support.test.uiautomator.UiDevice; 47 import android.support.test.uiautomator.UiSelector; 48 import android.test.InstrumentationTestCase; 49 import android.util.Log; 50 import android.view.accessibility.AccessibilityEvent; 51 52 import com.android.compatibility.common.util.SystemUtil; 53 54 public class ActivityManagerProcessStateTest extends InstrumentationTestCase { 55 private static final String TAG = ActivityManagerProcessStateTest.class.getName(); 56 57 private static final String STUB_PACKAGE_NAME = "android.app.stubs"; 58 private static final int WAIT_TIME = 2000; 59 // A secondary test activity from another APK. 60 static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp"; 61 static final String SIMPLE_SERVICE = ".SimpleService"; 62 static final String SIMPLE_SERVICE2 = ".SimpleService2"; 63 static final String SIMPLE_RECEIVER_START_SERVICE = ".SimpleReceiverStartService"; 64 static final String SIMPLE_ACTIVITY_START_SERVICE = ".SimpleActivityStartService"; 65 public static String ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT = 66 "com.android.cts.launcherapps.simpleapp.SimpleActivityStartService.RESULT"; 67 68 // APKs for testing heavy weight app interactions. 69 static final String CANT_SAVE_STATE_1_PACKAGE_NAME = "com.android.test.cantsavestate1"; 70 static final String CANT_SAVE_STATE_2_PACKAGE_NAME = "com.android.test.cantsavestate2"; 71 72 // Actions 73 static final String ACTION_START_FOREGROUND = "com.android.test.action.START_FOREGROUND"; 74 static final String ACTION_STOP_FOREGROUND = "com.android.test.action.STOP_FOREGROUND"; 75 76 private static final int TEMP_WHITELIST_DURATION_MS = 2000; 77 78 private Context mContext; 79 private Instrumentation mInstrumentation; 80 private Intent mServiceIntent; 81 private Intent mServiceStartForegroundIntent; 82 private Intent mServiceStopForegroundIntent; 83 private Intent mService2Intent; 84 private Intent mMainProcess[]; 85 private Intent mAllProcesses[]; 86 87 @Override setUp()88 protected void setUp() throws Exception { 89 super.setUp(); 90 mInstrumentation = getInstrumentation(); 91 mContext = mInstrumentation.getContext(); 92 mServiceIntent = new Intent(); 93 mServiceIntent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE); 94 mServiceStartForegroundIntent = new Intent(mServiceIntent); 95 mServiceStartForegroundIntent.setAction(ACTION_START_FOREGROUND); 96 mServiceStopForegroundIntent = new Intent(mServiceIntent); 97 mServiceStopForegroundIntent.setAction(ACTION_STOP_FOREGROUND); 98 mService2Intent = new Intent(); 99 mService2Intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE2); 100 mMainProcess = new Intent[1]; 101 mMainProcess[0] = mServiceIntent; 102 mAllProcesses = new Intent[2]; 103 mAllProcesses[0] = mServiceIntent; 104 mAllProcesses[1] = mService2Intent; 105 mContext.stopService(mServiceIntent); 106 mContext.stopService(mService2Intent); 107 removeTestAppFromWhitelists(); 108 } 109 removeTestAppFromWhitelists()110 private void removeTestAppFromWhitelists() throws Exception { 111 executeShellCmd("cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME); 112 executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME); 113 } 114 executeShellCmd(String cmd)115 private String executeShellCmd(String cmd) throws Exception { 116 final String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 117 Log.d(TAG, String.format("Output for '%s': %s", cmd, result)); 118 return result; 119 } 120 isScreenInteractive()121 private boolean isScreenInteractive() { 122 final PowerManager powerManager = 123 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 124 return powerManager.isInteractive(); 125 } 126 isKeyguardLocked()127 private boolean isKeyguardLocked() { 128 final KeyguardManager keyguardManager = 129 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 130 return keyguardManager.isKeyguardLocked(); 131 } 132 waitForAppFocus(String waitForApp, long waitTime)133 private void waitForAppFocus(String waitForApp, long waitTime) { 134 long waitUntil = SystemClock.elapsedRealtime() + waitTime; 135 while (true) { 136 WindowManagerState wms = new WindowManagerState(); 137 wms.computeState(); 138 String appName = wms.getFocusedApp(); 139 if (appName != null) { 140 ComponentName comp = ComponentName.unflattenFromString(appName); 141 if (waitForApp.equals(comp.getPackageName())) { 142 break; 143 } 144 } 145 if (SystemClock.elapsedRealtime() > waitUntil) { 146 throw new IllegalStateException("Timed out waiting for focus on app " 147 + waitForApp + ", last was " + appName); 148 } 149 Log.i(TAG, "Waiting for app focus, current: " + appName); 150 try { 151 Thread.sleep(100); 152 } catch (InterruptedException e) { 153 } 154 }; 155 } 156 startActivityAndWaitForShow(final Intent intent)157 private void startActivityAndWaitForShow(final Intent intent) throws Exception { 158 getInstrumentation().getUiAutomation().executeAndWaitForEvent( 159 () -> { 160 try { 161 mContext.startActivity(intent); 162 } catch (Exception e) { 163 fail("Cannot start activity: " + intent); 164 } 165 }, (AccessibilityEvent event) -> event.getEventType() 166 == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 167 , WAIT_TIME); 168 } 169 maybeClick(UiDevice device, UiSelector sel)170 private void maybeClick(UiDevice device, UiSelector sel) { 171 try { device.findObject(sel).click(); } catch (Throwable ignored) { } 172 } 173 maybeClick(UiDevice device, BySelector sel)174 private void maybeClick(UiDevice device, BySelector sel) { 175 try { device.findObject(sel).click(); } catch (Throwable ignored) { } 176 } 177 178 /** 179 * Test basic state changes as processes go up and down due to services running in them. 180 */ testUidImportanceListener()181 public void testUidImportanceListener() throws Exception { 182 final Parcel data = Parcel.obtain(); 183 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent, 184 WAIT_TIME); 185 ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent, 186 WAIT_TIME); 187 188 ActivityManager am = mContext.getSystemService(ActivityManager.class); 189 190 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 191 SIMPLE_PACKAGE_NAME, 0); 192 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 193 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 194 195 InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission( 196 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 197 boolean gotException = false; 198 try { 199 uidForegroundListener.register(); 200 } catch (SecurityException e) { 201 gotException = true; 202 } 203 assertTrue("Expected SecurityException thrown", gotException); 204 205 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 206 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 207 /* 208 Log.d("XXXX", "Invoke: " + cmd); 209 Log.d("XXXX", "Result: " + result); 210 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 211 + STUB_PACKAGE_NAME)); 212 */ 213 uidForegroundListener.register(); 214 215 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 216 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, WAIT_TIME); 217 uidGoneListener.register(); 218 219 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 220 WAIT_TIME); 221 222 try { 223 // First kill the processes to start out in a stable state. 224 conn.bind(); 225 conn2.bind(); 226 IBinder service1 = conn.getServiceIBinder(); 227 IBinder service2 = conn2.getServiceIBinder(); 228 conn.unbind(); 229 conn2.unbind(); 230 try { 231 service1.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 232 } catch (RemoteException e) { 233 } 234 try { 235 service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 236 } catch (RemoteException e) { 237 } 238 service1 = service2 = null; 239 240 // Wait for uid's processes to go away. 241 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 242 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 243 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 244 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 245 246 // And wait for the uid report to be gone. 247 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null); 248 249 // Now bind and see if we get told about the uid coming in to the foreground. 250 conn.bind(); 251 uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 252 ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE); 253 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 254 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 255 256 // Also make sure the uid state reports are as expected. Wait for active because 257 // there may be some intermediate states as the process comes up. 258 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 259 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 260 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 261 262 // Pull out the service IBinder for a kludy hack... 263 IBinder service = conn.getServiceIBinder(); 264 265 // Now unbind and see if we get told about it going to the background. 266 conn.unbind(); 267 uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 268 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 269 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 270 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 271 272 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 273 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 274 275 // Now kill the process and see if we are told about it being gone. 276 try { 277 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 278 } catch (RemoteException e) { 279 // It is okay if it is already gone for some reason. 280 } 281 282 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 283 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 284 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 285 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 286 287 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 288 uidWatcher.expect(WatchUidRunner.CMD_GONE, null); 289 290 // Now we are going to try different combinations of binding to two processes to 291 // see if they are correctly combined together for the app. 292 293 // Bring up both services. 294 conn.bind(); 295 conn2.bind(); 296 uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 297 ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE); 298 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 299 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 300 301 // Also make sure the uid state reports are as expected. 302 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 303 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 304 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 305 306 // Bring down one service, app state should remain foreground. 307 conn2.unbind(); 308 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 309 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 310 311 // Bring down other service, app state should now be cached. (If the processes both 312 // actually get killed immediately, this is also not a correctly behaving system.) 313 conn.unbind(); 314 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 315 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 316 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 317 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 318 319 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 320 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 321 322 // Bring up one service, this should be sufficient to become foreground. 323 conn2.bind(); 324 uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 325 ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE); 326 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 327 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 328 329 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 330 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 331 332 // Bring up other service, should remain foreground. 333 conn.bind(); 334 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 335 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 336 337 // Bring down one service, should remain foreground. 338 conn.unbind(); 339 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 340 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 341 342 // And bringing down other service should put us back to cached. 343 conn2.unbind(); 344 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 345 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 346 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 347 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 348 349 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 350 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 351 } finally { 352 data.recycle(); 353 uidWatcher.finish(); 354 uidForegroundListener.unregister(); 355 uidGoneListener.unregister(); 356 } 357 } 358 359 /** 360 * Test that background check correctly prevents idle services from running but allows 361 * whitelisted apps to bypass the check. 362 */ testBackgroundCheckService()363 public void testBackgroundCheckService() throws Exception { 364 final Parcel data = Parcel.obtain(); 365 Intent serviceIntent = new Intent(); 366 serviceIntent.setClassName(SIMPLE_PACKAGE_NAME, 367 SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE); 368 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, serviceIntent, 369 WAIT_TIME); 370 371 ActivityManager am = mContext.getSystemService(ActivityManager.class); 372 373 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 374 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 375 /* 376 Log.d("XXXX", "Invoke: " + cmd); 377 Log.d("XXXX", "Result: " + result); 378 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 379 + STUB_PACKAGE_NAME)); 380 */ 381 382 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 383 SIMPLE_PACKAGE_NAME, 0); 384 385 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 386 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 387 uidForegroundListener.register(); 388 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 389 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY, WAIT_TIME); 390 uidGoneListener.register(); 391 392 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 393 WAIT_TIME); 394 395 // First kill the process to start out in a stable state. 396 mContext.stopService(serviceIntent); 397 conn.bind(); 398 IBinder service = conn.getServiceIBinder(); 399 conn.unbind(); 400 try { 401 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 402 } catch (RemoteException e) { 403 } 404 service = null; 405 406 // Wait for uid's process to go away. 407 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 408 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 409 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 410 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 411 412 // And wait for the uid report to be gone. 413 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null); 414 415 String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny"; 416 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 417 418 // This is a side-effect of the app op command. 419 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 420 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "NONE"); 421 422 // We don't want to wait for the uid to actually go idle, we can force it now. 423 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 424 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 425 426 // Make sure app is not yet on whitelist 427 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 428 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 429 430 // We will use this to monitor when the service is running. 431 conn.startMonitoring(); 432 433 try { 434 // Try starting the service. Should fail! 435 boolean failed = false; 436 try { 437 mContext.startService(serviceIntent); 438 } catch (IllegalStateException e) { 439 failed = true; 440 } 441 if (!failed) { 442 fail("Service was allowed to start while in the background"); 443 } 444 445 // Put app on temporary whitelist to see if this allows the service start. 446 cmd = String.format("cmd deviceidle tempwhitelist -d %d %s", 447 TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME); 448 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 449 450 // Try starting the service now that the app is whitelisted... should work! 451 mContext.startService(serviceIntent); 452 conn.waitForConnect(); 453 454 // Also make sure the uid state reports are as expected. 455 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 456 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 457 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 458 459 // Good, now stop the service and give enough time to get off the temp whitelist. 460 mContext.stopService(serviceIntent); 461 conn.waitForDisconnect(); 462 463 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 464 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 465 466 executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME); 467 468 // Going off the temp whitelist causes a spurious proc state report... that's 469 // not ideal, but okay. 470 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 471 472 // We don't want to wait for the uid to actually go idle, we can force it now. 473 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 474 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 475 476 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 477 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 478 479 // Now that we should be off the temp whitelist, make sure we again can't start. 480 failed = false; 481 try { 482 mContext.startService(serviceIntent); 483 } catch (IllegalStateException e) { 484 failed = true; 485 } 486 if (!failed) { 487 fail("Service was allowed to start while in the background"); 488 } 489 490 // Now put app on whitelist, should allow service to run. 491 cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME; 492 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 493 494 // Try starting the service now that the app is whitelisted... should work! 495 mContext.startService(serviceIntent); 496 conn.waitForConnect(); 497 498 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 499 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 500 501 // Okay, bring down the service. 502 mContext.stopService(serviceIntent); 503 conn.waitForDisconnect(); 504 505 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 506 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 507 508 } finally { 509 mContext.stopService(serviceIntent); 510 conn.stopMonitoring(); 511 512 uidWatcher.finish(); 513 514 cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow"; 515 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 516 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 517 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 518 519 uidGoneListener.unregister(); 520 uidForegroundListener.unregister(); 521 522 data.recycle(); 523 } 524 } 525 526 /** 527 * Test that background check behaves correctly after a process is no longer foreground: 528 * first allowing a service to be started, then stopped by the system when idle. 529 */ testBackgroundCheckStopsService()530 public void testBackgroundCheckStopsService() throws Exception { 531 final Parcel data = Parcel.obtain(); 532 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent, 533 WAIT_TIME); 534 ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent, 535 WAIT_TIME); 536 537 ActivityManager am = mContext.getSystemService(ActivityManager.class); 538 539 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 540 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 541 /* 542 Log.d("XXXX", "Invoke: " + cmd); 543 Log.d("XXXX", "Result: " + result); 544 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 545 + STUB_PACKAGE_NAME)); 546 */ 547 548 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 549 SIMPLE_PACKAGE_NAME, 0); 550 551 UidImportanceListener uidServiceListener = new UidImportanceListener(mContext, 552 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 553 uidServiceListener.register(); 554 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 555 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, WAIT_TIME); 556 uidGoneListener.register(); 557 558 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 559 WAIT_TIME); 560 561 // First kill the process to start out in a stable state. 562 mContext.stopService(mServiceIntent); 563 mContext.stopService(mService2Intent); 564 conn.bind(); 565 conn2.bind(); 566 IBinder service = conn.getServiceIBinder(); 567 IBinder service2 = conn2.getServiceIBinder(); 568 conn.unbind(); 569 conn2.unbind(); 570 try { 571 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 572 } catch (RemoteException e) { 573 } 574 try { 575 service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 576 } catch (RemoteException e) { 577 } 578 service = service2 = null; 579 580 // Wait for uid's process to go away. 581 uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 582 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 583 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, 584 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 585 586 // And wait for the uid report to be gone. 587 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, WAIT_TIME); 588 589 String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny"; 590 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 591 592 // This is a side-effect of the app op command. 593 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 594 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_NONEXISTENT); 595 596 // We don't want to wait for the uid to actually go idle, we can force it now. 597 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 598 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 599 600 // Make sure app is not yet on whitelist 601 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 602 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 603 604 // We will use this to monitor when the service is running. 605 conn.startMonitoring(); 606 607 try { 608 // Try starting the service. Should fail! 609 boolean failed = false; 610 try { 611 mContext.startService(mServiceIntent); 612 } catch (IllegalStateException e) { 613 failed = true; 614 } 615 if (!failed) { 616 fail("Service was allowed to start while in the background"); 617 } 618 619 // First poke the process into the foreground, so we can avoid background check. 620 conn2.bind(); 621 conn2.waitForConnect(); 622 623 // Wait for process state to reflect running service. 624 uidServiceListener.waitForValue( 625 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 626 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE); 627 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, 628 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 629 630 // Also make sure the uid state reports are as expected. 631 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 632 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 633 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 634 635 conn2.unbind(); 636 637 // Wait for process to recover back down to being cached. 638 uidServiceListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 639 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 640 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 641 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 642 643 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 644 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 645 646 // Try starting the service now that the app is waiting to idle... should work! 647 mContext.startService(mServiceIntent); 648 conn.waitForConnect(); 649 650 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 651 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 652 653 // And also start the second service. 654 conn2.startMonitoring(); 655 mContext.startService(mService2Intent); 656 conn2.waitForConnect(); 657 658 // Force app to go idle now 659 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 660 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 661 662 // Wait for services to be stopped by system. 663 uidServiceListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 664 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); 665 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 666 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 667 668 // And service should be stopped by system, so just make sure it is disconnected. 669 conn.waitForDisconnect(); 670 conn2.waitForDisconnect(); 671 672 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 673 // There may be a transient 'SVC' proc state here. 674 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 675 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 676 677 } finally { 678 mContext.stopService(mServiceIntent); 679 mContext.stopService(mService2Intent); 680 conn.cleanup(); 681 conn2.cleanup(); 682 683 uidWatcher.finish(); 684 685 cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow"; 686 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 687 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 688 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 689 690 uidGoneListener.unregister(); 691 uidServiceListener.unregister(); 692 693 data.recycle(); 694 } 695 } 696 697 /** 698 * Test the background check doesn't allow services to be started from broadcasts except 699 * when in the correct states. 700 */ testBackgroundCheckBroadcastService()701 public void testBackgroundCheckBroadcastService() throws Exception { 702 final Intent broadcastIntent = new Intent(); 703 broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 704 broadcastIntent.setClassName(SIMPLE_PACKAGE_NAME, 705 SIMPLE_PACKAGE_NAME + SIMPLE_RECEIVER_START_SERVICE); 706 707 final ServiceProcessController controller = new ServiceProcessController(mContext, 708 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME); 709 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 710 mServiceIntent, WAIT_TIME); 711 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 712 713 try { 714 // First kill the process to start out in a stable state. 715 controller.ensureProcessGone(); 716 717 // Do initial setup. 718 controller.denyBackgroundOp(); 719 controller.makeUidIdle(); 720 controller.removeFromWhitelist(); 721 722 // We will use this to monitor when the service is running. 723 conn.startMonitoring(); 724 725 // Try sending broadcast to start the service. Should fail! 726 SyncOrderedBroadcast br = new SyncOrderedBroadcast(); 727 broadcastIntent.putExtra("service", mServiceIntent); 728 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 729 int brCode = br.getReceivedCode(); 730 if (brCode != Activity.RESULT_CANCELED) { 731 fail("Didn't fail starting service, result=" + brCode); 732 } 733 734 // Track the uid proc state changes from the broadcast (but not service execution) 735 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null, WAIT_TIME); 736 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME); 737 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER, WAIT_TIME); 738 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME); 739 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME); 740 741 // Put app on temporary whitelist to see if this allows the service start. 742 controller.tempWhitelist(TEMP_WHITELIST_DURATION_MS); 743 744 // Being on the whitelist means the uid is now active. 745 uidWatcher.expect(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME); 746 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME); 747 748 // Try starting the service now that the app is whitelisted... should work! 749 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 750 brCode = br.getReceivedCode(); 751 if (brCode != Activity.RESULT_FIRST_USER) { 752 fail("Failed starting service, result=" + brCode); 753 } 754 conn.waitForConnect(); 755 756 // Also make sure the uid state reports are as expected. 757 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 758 // We are going to wait until 'SVC', because we may see an intermediate 'RCVR' 759 // proc state depending on timing. 760 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 761 762 // Good, now stop the service and give enough time to get off the temp whitelist. 763 mContext.stopService(mServiceIntent); 764 conn.waitForDisconnect(); 765 766 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 767 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 768 769 controller.removeFromTempWhitelist(); 770 771 // Going off the temp whitelist causes a spurious proc state report... that's 772 // not ideal, but okay. 773 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 774 775 // We don't want to wait for the uid to actually go idle, we can force it now. 776 controller.makeUidIdle(); 777 778 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 779 780 // Make sure the process is gone so we start over fresh. 781 controller.ensureProcessGone(); 782 783 // Now that we should be off the temp whitelist, make sure we again can't start. 784 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 785 brCode = br.getReceivedCode(); 786 if (brCode != Activity.RESULT_CANCELED) { 787 fail("Didn't fail starting service, result=" + brCode); 788 } 789 790 // Track the uid proc state changes from the broadcast (but not service execution) 791 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null); 792 // There could be a transient 'cached' state here before 'uncached' if uid state 793 // changes are dispatched before receiver is started. 794 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 795 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER); 796 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 797 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 798 799 // Now put app on whitelist, should allow service to run. 800 controller.addToWhitelist(); 801 802 // Try starting the service now that the app is whitelisted... should work! 803 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 804 brCode = br.getReceivedCode(); 805 if (brCode != Activity.RESULT_FIRST_USER) { 806 fail("Failed starting service, result=" + brCode); 807 } 808 conn.waitForConnect(); 809 810 // Also make sure the uid state reports are as expected. 811 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 812 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 813 814 // Okay, bring down the service. 815 mContext.stopService(mServiceIntent); 816 conn.waitForDisconnect(); 817 818 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 819 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 820 821 } finally { 822 mContext.stopService(mServiceIntent); 823 conn.stopMonitoringIfNeeded(); 824 controller.cleanup(); 825 } 826 } 827 828 /** 829 * Test that background check does allow services to be started from activities. 830 */ testBackgroundCheckActivityService()831 public void testBackgroundCheckActivityService() throws Exception { 832 final Intent activityIntent = new Intent(); 833 activityIntent.setClassName(SIMPLE_PACKAGE_NAME, 834 SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_START_SERVICE); 835 activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 836 837 final ServiceProcessController controller = new ServiceProcessController(mContext, 838 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME); 839 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 840 mServiceIntent, WAIT_TIME); 841 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 842 843 try { 844 // First kill the process to start out in a stable state. 845 controller.ensureProcessGone(); 846 847 // Do initial setup. 848 controller.denyBackgroundOp(); 849 controller.makeUidIdle(); 850 controller.removeFromWhitelist(); 851 852 // We will use this to monitor when the service is running. 853 conn.startMonitoring(); 854 855 // Try starting activity that will start the service. This should be okay. 856 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 857 waiter.prepare(ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT); 858 activityIntent.putExtra("service", mServiceIntent); 859 mContext.startActivity(activityIntent); 860 Intent resultIntent = waiter.doWait(WAIT_TIME); 861 int brCode = resultIntent.getIntExtra("result", Activity.RESULT_CANCELED); 862 if (brCode != Activity.RESULT_FIRST_USER) { 863 fail("Failed starting service, result=" + brCode); 864 } 865 conn.waitForConnect(); 866 867 final String expectedActivityState = (isScreenInteractive() && !isKeyguardLocked()) 868 ? WatchUidRunner.STATE_TOP : WatchUidRunner.STATE_TOP_SLEEPING; 869 // Also make sure the uid state reports are as expected. 870 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 871 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 872 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, expectedActivityState); 873 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 874 875 // Okay, bring down the service. 876 mContext.stopService(mServiceIntent); 877 conn.waitForDisconnect(); 878 879 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 880 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 881 882 // App isn't yet idle, so we should be able to start the service again. 883 mContext.startService(mServiceIntent); 884 conn.waitForConnect(); 885 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 886 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 887 888 // And now fast-forward to the app going idle, service should be stopped. 889 controller.makeUidIdle(); 890 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null); 891 892 conn.waitForDisconnect(); 893 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 894 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 895 896 // No longer should be able to start service. 897 boolean failed = false; 898 try { 899 mContext.startService(mServiceIntent); 900 } catch (IllegalStateException e) { 901 failed = true; 902 } 903 if (!failed) { 904 fail("Service was allowed to start while in the background"); 905 } 906 907 } finally { 908 mContext.stopService(mServiceIntent); 909 conn.stopMonitoringIfNeeded(); 910 controller.cleanup(); 911 } 912 } 913 914 /** 915 * Test that the foreground service app op does prevent the foreground state. 916 */ testForegroundServiceAppOp()917 public void testForegroundServiceAppOp() throws Exception { 918 final ServiceProcessController controller = new ServiceProcessController(mContext, 919 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME); 920 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 921 mServiceIntent, WAIT_TIME); 922 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 923 924 try { 925 // First kill the process to start out in a stable state. 926 controller.ensureProcessGone(); 927 928 // Do initial setup. 929 controller.makeUidIdle(); 930 controller.removeFromWhitelist(); 931 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 932 933 // Put app on whitelist, to allow service to run. 934 controller.addToWhitelist(); 935 936 // We will use this to monitor when the service is running. 937 conn.startMonitoring(); 938 939 // -------- START SERVICE AND THEN SUCCESSFULLY GO TO FOREGROUND 940 941 // Now start the service and wait for it to come up. 942 mContext.startService(mServiceStartForegroundIntent); 943 conn.waitForConnect(); 944 945 // Also make sure the uid state reports are as expected. 946 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 947 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 948 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 949 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 950 951 // Now take it out of foreground and confirm. 952 mContext.startService(mServiceStopForegroundIntent); 953 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 954 955 // Good, now stop the service and wait for it to go away. 956 mContext.stopService(mServiceStartForegroundIntent); 957 conn.waitForDisconnect(); 958 959 // There may be a transient STATE_SERVICE we don't care about, so waitFor. 960 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 961 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 962 963 // We don't want to wait for the uid to actually go idle, we can force it now. 964 controller.makeUidIdle(); 965 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 966 967 // Make sure the process is gone so we start over fresh. 968 controller.ensureProcessGone(); 969 970 // -------- START SERVICE AND BLOCK GOING TO FOREGROUND 971 972 // Now we will deny the app op and ensure the service can't become foreground. 973 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore"); 974 975 // Now start the service and wait for it to come up. 976 mContext.startService(mServiceStartForegroundIntent); 977 conn.waitForConnect(); 978 979 // Also make sure the uid state reports are as expected. 980 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 981 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 982 983 // Good, now stop the service and wait for it to go away. 984 mContext.stopService(mServiceStartForegroundIntent); 985 conn.waitForDisconnect(); 986 987 // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE. 988 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 989 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 990 991 // Make sure the uid is idle (it should be anyway, it never went active here). 992 controller.makeUidIdle(); 993 994 // Make sure the process is gone so we start over fresh. 995 controller.ensureProcessGone(); 996 997 // -------- DIRECT START FOREGROUND SERVICE SUCCESSFULLY 998 999 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 1000 1001 // Now start the service and wait for it to come up. 1002 mContext.startForegroundService(mServiceStartForegroundIntent); 1003 conn.waitForConnect(); 1004 1005 // Make sure it becomes a foreground service. The process state changes here 1006 // are weird looking because we first need to force the app out of idle to allow 1007 // it to start the service. 1008 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1009 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1010 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1011 1012 // Good, now stop the service and wait for it to go away. 1013 mContext.stopService(mServiceStartForegroundIntent); 1014 conn.waitForDisconnect(); 1015 1016 // There may be a transient STATE_SERVICE we don't care about, so waitFor. 1017 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1018 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1019 1020 // We don't want to wait for the uid to actually go idle, we can force it now. 1021 controller.makeUidIdle(); 1022 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1023 1024 // Make sure the process is gone so we start over fresh. 1025 controller.ensureProcessGone(); 1026 1027 // -------- DIRECT START FOREGROUND SERVICE BLOCKED 1028 1029 // Now we will deny the app op and ensure the service can't become foreground. 1030 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore"); 1031 1032 // But we will put it on the whitelist so the service is still allowed to start. 1033 controller.addToWhitelist(); 1034 1035 // Now start the service and wait for it to come up. 1036 mContext.startForegroundService(mServiceStartForegroundIntent); 1037 conn.waitForConnect(); 1038 1039 // In this case we only get to run it as a regular service. 1040 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1041 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 1042 1043 // Good, now stop the service and wait for it to go away. 1044 mContext.stopService(mServiceStartForegroundIntent); 1045 conn.waitForDisconnect(); 1046 1047 // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE. 1048 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1049 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1050 1051 // Make sure the uid is idle (it should be anyway, it never went active here). 1052 controller.makeUidIdle(); 1053 1054 // Make sure the process is gone so we start over fresh. 1055 controller.ensureProcessGone(); 1056 1057 // -------- XXX NEED TO TEST NON-WHITELIST CASE WHERE NOTHING HAPPENS 1058 1059 } finally { 1060 mContext.stopService(mServiceStartForegroundIntent); 1061 conn.stopMonitoringIfNeeded(); 1062 controller.cleanup(); 1063 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 1064 controller.removeFromWhitelist(); 1065 } 1066 } 1067 supportsCantSaveState()1068 private boolean supportsCantSaveState() { 1069 if (mContext.getPackageManager().hasSystemFeature( 1070 PackageManager.FEATURE_CANT_SAVE_STATE)) { 1071 return true; 1072 } 1073 1074 // Most types of devices need to support this. 1075 int mode = mContext.getResources().getConfiguration().uiMode 1076 & Configuration.UI_MODE_TYPE_MASK; 1077 if (mode != Configuration.UI_MODE_TYPE_WATCH 1078 && mode != Configuration.UI_MODE_TYPE_APPLIANCE) { 1079 // Most devices must support the can't save state feature. 1080 throw new IllegalStateException("Devices that are not watches or appliances must " 1081 + "support FEATURE_CANT_SAVE_STATE"); 1082 } 1083 return false; 1084 } 1085 1086 /** 1087 * Test that a single "can't save state" app has the proper process management 1088 * semantics. 1089 */ testCantSaveStateLaunchAndBackground()1090 public void testCantSaveStateLaunchAndBackground() throws Exception { 1091 if (!supportsCantSaveState()) { 1092 return; 1093 } 1094 1095 final Intent activityIntent = new Intent(); 1096 activityIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME); 1097 activityIntent.setAction(Intent.ACTION_MAIN); 1098 activityIntent.addCategory(Intent.CATEGORY_LAUNCHER); 1099 activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1100 1101 final Intent homeIntent = new Intent(); 1102 homeIntent.setAction(Intent.ACTION_MAIN); 1103 homeIntent.addCategory(Intent.CATEGORY_HOME); 1104 homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1105 1106 ActivityManager am = mContext.getSystemService(ActivityManager.class); 1107 1108 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 1109 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 1110 1111 // We don't want to wait for the uid to actually go idle, we can force it now. 1112 String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1113 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1114 1115 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 1116 CANT_SAVE_STATE_1_PACKAGE_NAME, 0); 1117 1118 // This test is also using UidImportanceListener to make sure the correct 1119 // heavy-weight state is reported there. 1120 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 1121 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 1122 WAIT_TIME); 1123 uidForegroundListener.register(); 1124 UidImportanceListener uidBackgroundListener = new UidImportanceListener(mContext, 1125 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE-1, 1126 WAIT_TIME); 1127 uidBackgroundListener.register(); 1128 1129 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 1130 WAIT_TIME); 1131 1132 try { 1133 // Start the heavy-weight app, should launch like a normal app. 1134 mContext.startActivity(activityIntent); 1135 1136 // Wait for process state to reflect running activity. 1137 uidForegroundListener.waitForValue( 1138 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 1139 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); 1140 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 1141 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1142 1143 // Also make sure the uid state reports are as expected. 1144 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1145 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1146 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1147 1148 // Now go to home, leaving the app. It should be put in the heavy weight state. 1149 mContext.startActivity(homeIntent); 1150 1151 // Wait for process to go down to background heavy-weight. 1152 uidBackgroundListener.waitForValue( 1153 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE, 1154 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE); 1155 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE, 1156 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1157 1158 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1159 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1160 1161 // While in background, should go in to normal idle state. 1162 // Force app to go idle now 1163 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1164 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1165 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1166 1167 // Switch back to heavy-weight app to see if it correctly returns to foreground. 1168 mContext.startActivity(activityIntent); 1169 1170 // Wait for process state to reflect running activity. 1171 uidForegroundListener.waitForValue( 1172 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 1173 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); 1174 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND, 1175 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1176 1177 // Also make sure the uid state reports are as expected. 1178 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1179 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1180 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1181 1182 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1183 1184 // Exit activity, check to see if we are now cached. 1185 getInstrumentation().getUiAutomation().performGlobalAction( 1186 AccessibilityService.GLOBAL_ACTION_BACK); 1187 1188 // Wait for process to become cached 1189 uidBackgroundListener.waitForValue( 1190 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 1191 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 1192 assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, 1193 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1194 1195 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1196 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1197 1198 // While in background, should go in to normal idle state. 1199 // Force app to go idle now 1200 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1201 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1202 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1203 1204 } finally { 1205 uidWatcher.finish(); 1206 uidForegroundListener.unregister(); 1207 uidBackgroundListener.unregister(); 1208 } 1209 } 1210 1211 /** 1212 * Test that switching between two "can't save state" apps is handled properly. 1213 */ testCantSaveStateLaunchAndSwitch()1214 public void testCantSaveStateLaunchAndSwitch() throws Exception { 1215 if (!supportsCantSaveState()) { 1216 return; 1217 } 1218 1219 final Intent activity1Intent = new Intent(); 1220 activity1Intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME); 1221 activity1Intent.setAction(Intent.ACTION_MAIN); 1222 activity1Intent.addCategory(Intent.CATEGORY_LAUNCHER); 1223 activity1Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1224 1225 final Intent activity2Intent = new Intent(); 1226 activity2Intent.setPackage(CANT_SAVE_STATE_2_PACKAGE_NAME); 1227 activity2Intent.setAction(Intent.ACTION_MAIN); 1228 activity2Intent.addCategory(Intent.CATEGORY_LAUNCHER); 1229 activity2Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1230 1231 final Intent homeIntent = new Intent(); 1232 homeIntent.setAction(Intent.ACTION_MAIN); 1233 homeIntent.addCategory(Intent.CATEGORY_HOME); 1234 homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1235 1236 ActivityManager am = mContext.getSystemService(ActivityManager.class); 1237 UiDevice device = UiDevice.getInstance(getInstrumentation()); 1238 1239 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 1240 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 1241 1242 // We don't want to wait for the uid to actually go idle, we can force it now. 1243 String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1244 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1245 cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME; 1246 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1247 1248 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1249 CANT_SAVE_STATE_1_PACKAGE_NAME, 0); 1250 WatchUidRunner uid1Watcher = new WatchUidRunner(getInstrumentation(), app1Info.uid, 1251 WAIT_TIME); 1252 1253 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1254 CANT_SAVE_STATE_2_PACKAGE_NAME, 0); 1255 WatchUidRunner uid2Watcher = new WatchUidRunner(getInstrumentation(), app2Info.uid, 1256 WAIT_TIME); 1257 1258 try { 1259 // Start the first heavy-weight app, should launch like a normal app. 1260 mContext.startActivity(activity1Intent); 1261 1262 // Make sure the uid state reports are as expected. 1263 uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1264 uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1265 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1266 1267 // Now go to home, leaving the app. It should be put in the heavy weight state. 1268 mContext.startActivity(homeIntent); 1269 1270 // Wait for process to go down to background heavy-weight. 1271 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1272 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1273 1274 // Start the second heavy-weight app, should ask us what to do with the two apps 1275 startActivityAndWaitForShow(activity2Intent); 1276 1277 // First, let's try returning to the original app. 1278 maybeClick(device, new UiSelector().resourceId("android:id/switch_old")); 1279 device.waitForIdle(); 1280 1281 // App should now be back in foreground. 1282 uid1Watcher.expect(WatchUidRunner.CMD_UNCACHED, null); 1283 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1284 1285 // Return to home. 1286 mContext.startActivity(homeIntent); 1287 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1288 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1289 1290 // Again try starting second heavy-weight app to get prompt. 1291 startActivityAndWaitForShow(activity2Intent); 1292 1293 // Now we'll switch to the new app. 1294 maybeClick(device, new UiSelector().resourceId("android:id/switch_new")); 1295 device.waitForIdle(); 1296 1297 // The original app should now become cached. 1298 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1299 1300 // And the new app should start. 1301 uid2Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1302 uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1303 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1304 1305 // Make sure the original app is idle for cleanliness 1306 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1307 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1308 uid1Watcher.expect(WatchUidRunner.CMD_IDLE, null); 1309 1310 // Return to home. 1311 mContext.startActivity(homeIntent); 1312 uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1313 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1314 1315 // Try starting the first heavy weight app, but return to the existing second. 1316 startActivityAndWaitForShow(activity1Intent); 1317 maybeClick(device, new UiSelector().resourceId("android:id/switch_old")); 1318 device.waitForIdle(); 1319 uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1320 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1321 1322 // Return to home. 1323 mContext.startActivity(homeIntent); 1324 uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1325 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1326 1327 // Again start the first heavy weight app, this time actually switching to it 1328 startActivityAndWaitForShow(activity1Intent); 1329 maybeClick(device, new UiSelector().resourceId("android:id/switch_new")); 1330 device.waitForIdle(); 1331 1332 // The second app should now become cached. 1333 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1334 1335 // And the first app should start. 1336 uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1337 uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1338 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1339 1340 // Exit activity, check to see if we are now cached. 1341 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1342 getInstrumentation().getUiAutomation().performGlobalAction( 1343 AccessibilityService.GLOBAL_ACTION_BACK); 1344 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1345 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1346 1347 // Make both apps idle for cleanliness. 1348 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1349 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1350 cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME; 1351 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1352 1353 } finally { 1354 uid2Watcher.finish(); 1355 uid1Watcher.finish(); 1356 } 1357 } 1358 } 1359