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 static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; 20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; 21 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 22 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; 23 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; 24 25 import android.accessibilityservice.AccessibilityService; 26 import android.app.Activity; 27 import android.app.ActivityManager; 28 import android.app.AppOpsManager; 29 import android.app.Instrumentation; 30 import android.app.KeyguardManager; 31 import android.app.cts.android.app.cts.tools.ServiceConnectionHandler; 32 import android.app.cts.android.app.cts.tools.ServiceProcessController; 33 import android.app.cts.android.app.cts.tools.SyncOrderedBroadcast; 34 import android.app.cts.android.app.cts.tools.UidImportanceListener; 35 import android.app.cts.android.app.cts.tools.WaitForBroadcast; 36 import android.app.cts.android.app.cts.tools.WatchUidRunner; 37 import android.app.stubs.CommandReceiver; 38 import android.app.stubs.LocalForegroundServiceLocation; 39 import android.app.stubs.ScreenOnActivity; 40 import android.content.ComponentName; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.content.pm.ApplicationInfo; 44 import android.content.pm.PackageManager; 45 import android.content.pm.ServiceInfo; 46 import android.content.res.Configuration; 47 import android.os.Build; 48 import android.os.Bundle; 49 import android.os.IBinder; 50 import android.os.Parcel; 51 import android.os.PowerManager; 52 import android.os.RemoteException; 53 import android.os.SystemClock; 54 import android.server.wm.WindowManagerState; 55 import android.support.test.uiautomator.BySelector; 56 import android.support.test.uiautomator.UiDevice; 57 import android.support.test.uiautomator.UiSelector; 58 import android.test.InstrumentationTestCase; 59 import android.util.Log; 60 import android.view.accessibility.AccessibilityEvent; 61 62 import androidx.test.InstrumentationRegistry; 63 64 import com.android.compatibility.common.util.SystemUtil; 65 66 public class ActivityManagerProcessStateTest extends InstrumentationTestCase { 67 private static final String TAG = ActivityManagerProcessStateTest.class.getName(); 68 69 private static final String STUB_PACKAGE_NAME = "android.app.stubs"; 70 private static final String PACKAGE_NAME_APP1 = "com.android.app1"; 71 private static final String PACKAGE_NAME_APP2 = "com.android.app2"; 72 private static final String PACKAGE_NAME_APP3 = "com.android.app3"; 73 74 private static final String[] PACKAGE_NAMES = { 75 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3 76 }; 77 78 private static final int WAIT_TIME = 2000; 79 private static final int WAITFOR_MSEC = 5000; 80 // A secondary test activity from another APK. 81 static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp"; 82 static final String SIMPLE_SERVICE = ".SimpleService"; 83 static final String SIMPLE_SERVICE2 = ".SimpleService2"; 84 static final String SIMPLE_RECEIVER_START_SERVICE = ".SimpleReceiverStartService"; 85 static final String SIMPLE_ACTIVITY_START_SERVICE = ".SimpleActivityStartService"; 86 public static String ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT = 87 "com.android.cts.launcherapps.simpleapp.SimpleActivityStartService.RESULT"; 88 89 // APKs for testing heavy weight app interactions. 90 static final String CANT_SAVE_STATE_1_PACKAGE_NAME = "com.android.test.cantsavestate1"; 91 static final String CANT_SAVE_STATE_2_PACKAGE_NAME = "com.android.test.cantsavestate2"; 92 93 // Actions 94 static final String ACTION_START_FOREGROUND = "com.android.test.action.START_FOREGROUND"; 95 static final String ACTION_STOP_FOREGROUND = "com.android.test.action.STOP_FOREGROUND"; 96 97 private static final int TEMP_WHITELIST_DURATION_MS = 2000; 98 99 private Context mContext; 100 private Instrumentation mInstrumentation; 101 private Intent mServiceIntent; 102 private Intent mServiceStartForegroundIntent; 103 private Intent mServiceStopForegroundIntent; 104 private Intent mService2Intent; 105 private Intent mMainProcess[]; 106 private Intent mAllProcesses[]; 107 108 private int mAppCount; 109 private ApplicationInfo [] mAppInfo; 110 private WatchUidRunner [] mWatchers; 111 112 113 @Override 114 protected void setUp() throws Exception { 115 super.setUp(); 116 mInstrumentation = getInstrumentation(); 117 mContext = mInstrumentation.getContext(); 118 mServiceIntent = new Intent(); 119 mServiceIntent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE); 120 mServiceStartForegroundIntent = new Intent(mServiceIntent); 121 mServiceStartForegroundIntent.setAction(ACTION_START_FOREGROUND); 122 mServiceStopForegroundIntent = new Intent(mServiceIntent); 123 mServiceStopForegroundIntent.setAction(ACTION_STOP_FOREGROUND); 124 mService2Intent = new Intent(); 125 mService2Intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE2); 126 mMainProcess = new Intent[1]; 127 mMainProcess[0] = mServiceIntent; 128 mAllProcesses = new Intent[2]; 129 mAllProcesses[0] = mServiceIntent; 130 mAllProcesses[1] = mService2Intent; 131 mContext.stopService(mServiceIntent); 132 mContext.stopService(mService2Intent); 133 turnScreenOn(); 134 removeTestAppFromWhitelists(); 135 mAppCount = 0; 136 } 137 138 /** Set up count app info objects and WatchUidRunners. */ 139 private void setupWatchers(int count) throws Exception { 140 mAppCount = count; 141 mAppInfo = new ApplicationInfo[count]; 142 mWatchers = new WatchUidRunner[count]; 143 for (int i = 0; i < count; i++) { 144 mAppInfo[i] = mContext.getPackageManager().getApplicationInfo( 145 PACKAGE_NAMES[i], 0); 146 mWatchers[i] = new WatchUidRunner(mInstrumentation, mAppInfo[i].uid, 147 WAITFOR_MSEC); 148 } 149 } 150 151 /** Finish all started WatchUidRunners. */ 152 private void shutdownWatchers() throws Exception { 153 for (int i = 0; i < mAppCount; i++) { 154 mWatchers[i].finish(); 155 } 156 } 157 158 private void turnScreenOn() throws Exception { 159 executeShellCmd("input keyevent KEYCODE_WAKEUP"); 160 executeShellCmd("wm dismiss-keyguard"); 161 } 162 163 private void removeTestAppFromWhitelists() throws Exception { 164 executeShellCmd("cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME); 165 executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME); 166 } 167 168 private String executeShellCmd(String cmd) throws Exception { 169 final String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 170 Log.d(TAG, String.format("Output for '%s': %s", cmd, result)); 171 return result; 172 } 173 174 private boolean isScreenInteractive() { 175 final PowerManager powerManager = 176 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 177 return powerManager.isInteractive(); 178 } 179 180 private boolean isKeyguardLocked() { 181 final KeyguardManager keyguardManager = 182 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 183 return keyguardManager.isKeyguardLocked(); 184 } 185 186 private void waitForAppFocus(String waitForApp, long waitTime) { 187 long waitUntil = SystemClock.elapsedRealtime() + waitTime; 188 while (true) { 189 WindowManagerState wms = new WindowManagerState(); 190 wms.computeState(); 191 String appName = wms.getFocusedApp(); 192 if (appName != null) { 193 ComponentName comp = ComponentName.unflattenFromString(appName); 194 if (waitForApp.equals(comp.getPackageName())) { 195 break; 196 } 197 } 198 if (SystemClock.elapsedRealtime() > waitUntil) { 199 throw new IllegalStateException("Timed out waiting for focus on app " 200 + waitForApp + ", last was " + appName); 201 } 202 Log.i(TAG, "Waiting for app focus, current: " + appName); 203 try { 204 Thread.sleep(100); 205 } catch (InterruptedException e) { 206 } 207 }; 208 } 209 210 private void startActivityAndWaitForShow(final Intent intent) throws Exception { 211 getInstrumentation().getUiAutomation().executeAndWaitForEvent( 212 () -> { 213 try { 214 mContext.startActivity(intent); 215 } catch (Exception e) { 216 fail("Cannot start activity: " + intent); 217 } 218 }, (AccessibilityEvent event) -> event.getEventType() 219 == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 220 , WAIT_TIME); 221 } 222 223 private void maybeClick(UiDevice device, UiSelector sel) { 224 try { device.findObject(sel).click(); } catch (Throwable ignored) { } 225 } 226 227 private void maybeClick(UiDevice device, BySelector sel) { 228 try { device.findObject(sel).click(); } catch (Throwable ignored) { } 229 } 230 231 /** 232 * Test basic state changes as processes go up and down due to services running in them. 233 */ 234 public void testUidImportanceListener() throws Exception { 235 final Parcel data = Parcel.obtain(); 236 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent, 237 WAIT_TIME); 238 ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent, 239 WAIT_TIME); 240 241 ActivityManager am = mContext.getSystemService(ActivityManager.class); 242 243 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 244 SIMPLE_PACKAGE_NAME, 0); 245 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 246 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 247 248 InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission( 249 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 250 boolean gotException = false; 251 try { 252 uidForegroundListener.register(); 253 } catch (SecurityException e) { 254 gotException = true; 255 } 256 assertTrue("Expected SecurityException thrown", gotException); 257 258 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 259 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 260 /* 261 Log.d("XXXX", "Invoke: " + cmd); 262 Log.d("XXXX", "Result: " + result); 263 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 264 + STUB_PACKAGE_NAME)); 265 */ 266 uidForegroundListener.register(); 267 268 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 269 appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME); 270 uidGoneListener.register(); 271 272 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 273 WAIT_TIME); 274 275 try { 276 // First kill the processes to start out in a stable state. 277 conn.bind(); 278 conn2.bind(); 279 IBinder service1 = conn.getServiceIBinder(); 280 IBinder service2 = conn2.getServiceIBinder(); 281 conn.unbind(); 282 conn2.unbind(); 283 try { 284 service1.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 285 } catch (RemoteException e) { 286 } 287 try { 288 service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 289 } catch (RemoteException e) { 290 } 291 service1 = service2 = null; 292 293 // Wait for uid's processes to go away. 294 uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE); 295 assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 296 297 // And wait for the uid report to be gone. 298 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null); 299 300 // Now bind and see if we get told about the uid coming in to the foreground. 301 conn.bind(); 302 uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE); 303 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 304 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 305 306 // Also make sure the uid state reports are as expected. Wait for active because 307 // there may be some intermediate states as the process comes up. 308 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 309 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 310 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 311 312 // Pull out the service IBinder for a kludy hack... 313 IBinder service = conn.getServiceIBinder(); 314 315 // Now unbind and see if we get told about it going to the background. 316 conn.unbind(); 317 uidForegroundListener.waitForValue(IMPORTANCE_CACHED, IMPORTANCE_CACHED); 318 assertEquals(IMPORTANCE_CACHED, am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 319 320 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 321 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 322 323 // Now kill the process and see if we are told about it being gone. 324 try { 325 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 326 } catch (RemoteException e) { 327 // It is okay if it is already gone for some reason. 328 } 329 330 uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE); 331 assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 332 333 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 334 uidWatcher.expect(WatchUidRunner.CMD_GONE, null); 335 336 // Now we are going to try different combinations of binding to two processes to 337 // see if they are correctly combined together for the app. 338 339 // Bring up both services. 340 conn.bind(); 341 conn2.bind(); 342 uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE); 343 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 344 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 345 346 // Also make sure the uid state reports are as expected. 347 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 348 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 349 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 350 351 // Bring down one service, app state should remain foreground. 352 conn2.unbind(); 353 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 354 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 355 356 // Bring down other service, app state should now be cached. (If the processes both 357 // actually get killed immediately, this is also not a correctly behaving system.) 358 conn.unbind(); 359 uidGoneListener.waitForValue(IMPORTANCE_CACHED, IMPORTANCE_CACHED); 360 assertEquals(IMPORTANCE_CACHED, 361 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 362 363 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 364 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 365 366 // Bring up one service, this should be sufficient to become foreground. 367 conn2.bind(); 368 uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE); 369 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 370 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 371 372 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 373 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 374 375 // Bring up other service, should remain foreground. 376 conn.bind(); 377 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 378 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 379 380 // Bring down one service, should remain foreground. 381 conn.unbind(); 382 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 383 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 384 385 // And bringing down other service should put us back to cached. 386 conn2.unbind(); 387 uidGoneListener.waitForValue(IMPORTANCE_CACHED, 388 IMPORTANCE_CACHED); 389 assertEquals(IMPORTANCE_CACHED, 390 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 391 392 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 393 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 394 } finally { 395 data.recycle(); 396 uidWatcher.finish(); 397 uidForegroundListener.unregister(); 398 uidGoneListener.unregister(); 399 } 400 } 401 402 /** 403 * Test that background check correctly prevents idle services from running but allows 404 * whitelisted apps to bypass the check. 405 */ 406 public void testBackgroundCheckService() throws Exception { 407 final Parcel data = Parcel.obtain(); 408 Intent serviceIntent = new Intent(); 409 serviceIntent.setClassName(SIMPLE_PACKAGE_NAME, 410 SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE); 411 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, serviceIntent, 412 WAIT_TIME); 413 414 ActivityManager am = mContext.getSystemService(ActivityManager.class); 415 416 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 417 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 418 /* 419 Log.d("XXXX", "Invoke: " + cmd); 420 Log.d("XXXX", "Result: " + result); 421 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 422 + STUB_PACKAGE_NAME)); 423 */ 424 425 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 426 SIMPLE_PACKAGE_NAME, 0); 427 428 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 429 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 430 uidForegroundListener.register(); 431 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 432 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY, WAIT_TIME); 433 uidGoneListener.register(); 434 435 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 436 WAIT_TIME); 437 438 // First kill the process to start out in a stable state. 439 mContext.stopService(serviceIntent); 440 conn.bind(); 441 IBinder service = conn.getServiceIBinder(); 442 conn.unbind(); 443 try { 444 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 445 } catch (RemoteException e) { 446 } 447 service = null; 448 449 // Wait for uid's process to go away. 450 uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE); 451 assertEquals(IMPORTANCE_GONE, 452 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 453 454 // And wait for the uid report to be gone. 455 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null); 456 457 String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny"; 458 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 459 460 // This is a side-effect of the app op command. 461 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 462 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "NONE"); 463 464 // We don't want to wait for the uid to actually go idle, we can force it now. 465 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 466 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 467 468 // Make sure app is not yet on whitelist 469 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 470 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 471 472 // We will use this to monitor when the service is running. 473 conn.startMonitoring(); 474 475 try { 476 // Try starting the service. Should fail! 477 boolean failed = false; 478 try { 479 mContext.startService(serviceIntent); 480 } catch (IllegalStateException e) { 481 failed = true; 482 } 483 if (!failed) { 484 fail("Service was allowed to start while in the background"); 485 } 486 487 // Put app on temporary whitelist to see if this allows the service start. 488 cmd = String.format("cmd deviceidle tempwhitelist -d %d %s", 489 TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME); 490 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 491 492 // Try starting the service now that the app is whitelisted... should work! 493 mContext.startService(serviceIntent); 494 conn.waitForConnect(); 495 496 // Also make sure the uid state reports are as expected. 497 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 498 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 499 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 500 501 // Good, now stop the service and give enough time to get off the temp whitelist. 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 executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME); 509 510 // Going off the temp whitelist causes a spurious proc state report... that's 511 // not ideal, but okay. 512 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 513 514 // We don't want to wait for the uid to actually go idle, we can force it now. 515 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 516 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 517 518 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 519 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 520 521 // Now that we should be off the temp whitelist, make sure we again can't start. 522 failed = false; 523 try { 524 mContext.startService(serviceIntent); 525 } catch (IllegalStateException e) { 526 failed = true; 527 } 528 if (!failed) { 529 fail("Service was allowed to start while in the background"); 530 } 531 532 // Now put app on whitelist, should allow service to run. 533 cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME; 534 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 535 536 // Try starting the service now that the app is whitelisted... should work! 537 mContext.startService(serviceIntent); 538 conn.waitForConnect(); 539 540 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 541 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 542 543 // Okay, bring down the service. 544 mContext.stopService(serviceIntent); 545 conn.waitForDisconnect(); 546 547 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 548 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 549 550 } finally { 551 mContext.stopService(serviceIntent); 552 conn.stopMonitoring(); 553 554 uidWatcher.finish(); 555 556 cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow"; 557 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 558 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 559 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 560 561 uidGoneListener.unregister(); 562 uidForegroundListener.unregister(); 563 564 data.recycle(); 565 } 566 } 567 568 /** 569 * Test that background check behaves correctly after a process is no longer foreground: 570 * first allowing a service to be started, then stopped by the system when idle. 571 */ 572 public void testBackgroundCheckStopsService() throws Exception { 573 final Parcel data = Parcel.obtain(); 574 ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent, 575 WAIT_TIME); 576 ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent, 577 WAIT_TIME); 578 579 ActivityManager am = mContext.getSystemService(ActivityManager.class); 580 581 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 582 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 583 /* 584 Log.d("XXXX", "Invoke: " + cmd); 585 Log.d("XXXX", "Result: " + result); 586 Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package " 587 + STUB_PACKAGE_NAME)); 588 */ 589 590 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 591 SIMPLE_PACKAGE_NAME, 0); 592 593 UidImportanceListener uidServiceListener = new UidImportanceListener(mContext, 594 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME); 595 uidServiceListener.register(); 596 UidImportanceListener uidGoneListener = new UidImportanceListener(mContext, 597 appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME); 598 uidGoneListener.register(); 599 600 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 601 WAIT_TIME); 602 603 // First kill the process to start out in a stable state. 604 mContext.stopService(mServiceIntent); 605 mContext.stopService(mService2Intent); 606 conn.bind(); 607 conn2.bind(); 608 IBinder service = conn.getServiceIBinder(); 609 IBinder service2 = conn2.getServiceIBinder(); 610 conn.unbind(); 611 conn2.unbind(); 612 try { 613 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 614 } catch (RemoteException e) { 615 } 616 try { 617 service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); 618 } catch (RemoteException e) { 619 } 620 service = service2 = null; 621 622 // Wait for uid's process to go away. 623 uidGoneListener.waitForValue(IMPORTANCE_GONE, 624 IMPORTANCE_GONE); 625 assertEquals(IMPORTANCE_GONE, 626 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 627 628 // And wait for the uid report to be gone. 629 uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, WAIT_TIME); 630 631 String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny"; 632 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 633 634 // This is a side-effect of the app op command. 635 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 636 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_NONEXISTENT); 637 638 // We don't want to wait for the uid to actually go idle, we can force it now. 639 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 640 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 641 642 // Make sure app is not yet on whitelist 643 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 644 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 645 646 // We will use this to monitor when the service is running. 647 conn.startMonitoring(); 648 649 try { 650 // Try starting the service. Should fail! 651 boolean failed = false; 652 try { 653 mContext.startService(mServiceIntent); 654 } catch (IllegalStateException e) { 655 failed = true; 656 } 657 if (!failed) { 658 fail("Service was allowed to start while in the background"); 659 } 660 661 // First poke the process into the foreground, so we can avoid background check. 662 conn2.bind(); 663 conn2.waitForConnect(); 664 665 // Wait for process state to reflect running service. 666 uidServiceListener.waitForValue( 667 IMPORTANCE_FOREGROUND_SERVICE, 668 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE); 669 assertEquals(IMPORTANCE_FOREGROUND_SERVICE, 670 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 671 672 // Also make sure the uid state reports are as expected. 673 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 674 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 675 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 676 677 conn2.unbind(); 678 679 // Wait for process to recover back down to being cached. 680 uidServiceListener.waitForValue(IMPORTANCE_CACHED, 681 IMPORTANCE_GONE); 682 assertEquals(IMPORTANCE_CACHED, 683 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 684 685 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 686 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 687 688 // Try starting the service now that the app is waiting to idle... should work! 689 mContext.startService(mServiceIntent); 690 conn.waitForConnect(); 691 692 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 693 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 694 695 // And also start the second service. 696 conn2.startMonitoring(); 697 mContext.startService(mService2Intent); 698 conn2.waitForConnect(); 699 700 // Force app to go idle now 701 cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME; 702 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 703 704 // Wait for services to be stopped by system. 705 uidServiceListener.waitForValue(IMPORTANCE_CACHED, 706 IMPORTANCE_GONE); 707 assertEquals(IMPORTANCE_CACHED, 708 am.getPackageImportance(SIMPLE_PACKAGE_NAME)); 709 710 // And service should be stopped by system, so just make sure it is disconnected. 711 conn.waitForDisconnect(); 712 conn2.waitForDisconnect(); 713 714 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 715 // There may be a transient 'SVC' proc state here. 716 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 717 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 718 719 } finally { 720 mContext.stopService(mServiceIntent); 721 mContext.stopService(mService2Intent); 722 conn.cleanup(); 723 conn2.cleanup(); 724 725 uidWatcher.finish(); 726 727 cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow"; 728 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 729 cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME; 730 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 731 732 uidGoneListener.unregister(); 733 uidServiceListener.unregister(); 734 735 data.recycle(); 736 } 737 } 738 739 /** 740 * Test the background check doesn't allow services to be started from broadcasts except 741 * when in the correct states. 742 */ 743 public void testBackgroundCheckBroadcastService() throws Exception { 744 final Intent broadcastIntent = new Intent(); 745 broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 746 broadcastIntent.setClassName(SIMPLE_PACKAGE_NAME, 747 SIMPLE_PACKAGE_NAME + SIMPLE_RECEIVER_START_SERVICE); 748 749 final ServiceProcessController controller = new ServiceProcessController(mContext, 750 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME); 751 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 752 mServiceIntent, WAIT_TIME); 753 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 754 755 try { 756 // First kill the process to start out in a stable state. 757 controller.ensureProcessGone(); 758 759 // Do initial setup. 760 controller.denyBackgroundOp(); 761 controller.makeUidIdle(); 762 controller.removeFromWhitelist(); 763 764 // We will use this to monitor when the service is running. 765 conn.startMonitoring(); 766 767 // Try sending broadcast to start the service. Should fail! 768 SyncOrderedBroadcast br = new SyncOrderedBroadcast(); 769 broadcastIntent.putExtra("service", mServiceIntent); 770 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 771 int brCode = br.getReceivedCode(); 772 if (brCode != Activity.RESULT_CANCELED) { 773 fail("Didn't fail starting service, result=" + brCode); 774 } 775 776 // Track the uid proc state changes from the broadcast (but not service execution) 777 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null, WAIT_TIME); 778 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME); 779 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER, WAIT_TIME); 780 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME); 781 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME); 782 783 // Put app on temporary whitelist to see if this allows the service start. 784 controller.tempWhitelist(TEMP_WHITELIST_DURATION_MS); 785 786 // Being on the whitelist means the uid is now active. 787 uidWatcher.expect(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME); 788 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME); 789 790 // Try starting the service now that the app is whitelisted... should work! 791 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 792 brCode = br.getReceivedCode(); 793 if (brCode != Activity.RESULT_FIRST_USER) { 794 fail("Failed starting service, result=" + brCode); 795 } 796 conn.waitForConnect(); 797 798 // Also make sure the uid state reports are as expected. 799 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 800 // We are going to wait until 'SVC', because we may see an intermediate 'RCVR' 801 // proc state depending on timing. 802 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 803 804 // Good, now stop the service and give enough time to get off the temp whitelist. 805 mContext.stopService(mServiceIntent); 806 conn.waitForDisconnect(); 807 808 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 809 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 810 811 controller.removeFromTempWhitelist(); 812 813 // Going off the temp whitelist causes a spurious proc state report... that's 814 // not ideal, but okay. 815 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 816 817 // We don't want to wait for the uid to actually go idle, we can force it now. 818 controller.makeUidIdle(); 819 820 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 821 822 // Make sure the process is gone so we start over fresh. 823 controller.ensureProcessGone(); 824 825 // Now that we should be off the temp whitelist, make sure we again can't start. 826 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 827 brCode = br.getReceivedCode(); 828 if (brCode != Activity.RESULT_CANCELED) { 829 fail("Didn't fail starting service, result=" + brCode); 830 } 831 832 // Track the uid proc state changes from the broadcast (but not service execution) 833 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null); 834 // There could be a transient 'cached' state here before 'uncached' if uid state 835 // changes are dispatched before receiver is started. 836 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 837 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER); 838 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 839 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 840 841 // Now put app on whitelist, should allow service to run. 842 controller.addToWhitelist(); 843 844 // Try starting the service now that the app is whitelisted... should work! 845 br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME); 846 brCode = br.getReceivedCode(); 847 if (brCode != Activity.RESULT_FIRST_USER) { 848 fail("Failed starting service, result=" + brCode); 849 } 850 conn.waitForConnect(); 851 852 // Also make sure the uid state reports are as expected. 853 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 854 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 855 856 // Okay, bring down the service. 857 mContext.stopService(mServiceIntent); 858 conn.waitForDisconnect(); 859 860 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 861 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 862 863 } finally { 864 mContext.stopService(mServiceIntent); 865 conn.stopMonitoringIfNeeded(); 866 controller.cleanup(); 867 } 868 } 869 870 /** 871 * Test that background check does allow services to be started from activities. 872 */ 873 public void testBackgroundCheckActivityService() throws Exception { 874 final Intent activityIntent = new Intent(); 875 activityIntent.setClassName(SIMPLE_PACKAGE_NAME, 876 SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_START_SERVICE); 877 activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 878 879 final ServiceProcessController controller = new ServiceProcessController(mContext, 880 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME); 881 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 882 mServiceIntent, WAIT_TIME); 883 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 884 885 try { 886 // First kill the process to start out in a stable state. 887 controller.ensureProcessGone(); 888 889 // Do initial setup. 890 controller.denyBackgroundOp(); 891 controller.makeUidIdle(); 892 controller.removeFromWhitelist(); 893 894 // We will use this to monitor when the service is running. 895 conn.startMonitoring(); 896 897 // Try starting activity that will start the service. This should be okay. 898 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 899 waiter.prepare(ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT); 900 activityIntent.putExtra("service", mServiceIntent); 901 mContext.startActivity(activityIntent); 902 Intent resultIntent = waiter.doWait(WAIT_TIME); 903 int brCode = resultIntent.getIntExtra("result", Activity.RESULT_CANCELED); 904 if (brCode != Activity.RESULT_FIRST_USER) { 905 fail("Failed starting service, result=" + brCode); 906 } 907 conn.waitForConnect(); 908 909 final String expectedActivityState = (isScreenInteractive() && !isKeyguardLocked()) 910 ? WatchUidRunner.STATE_TOP : WatchUidRunner.STATE_TOP_SLEEPING; 911 // Also make sure the uid state reports are as expected. 912 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 913 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 914 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, expectedActivityState); 915 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 916 917 // Okay, bring down the service. 918 mContext.stopService(mServiceIntent); 919 conn.waitForDisconnect(); 920 921 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 922 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 923 924 // App isn't yet idle, so we should be able to start the service again. 925 mContext.startService(mServiceIntent); 926 conn.waitForConnect(); 927 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 928 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 929 930 // And now fast-forward to the app going idle, service should be stopped. 931 controller.makeUidIdle(); 932 uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null); 933 934 conn.waitForDisconnect(); 935 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 936 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 937 938 // No longer should be able to start service. 939 boolean failed = false; 940 try { 941 mContext.startService(mServiceIntent); 942 } catch (IllegalStateException e) { 943 failed = true; 944 } 945 if (!failed) { 946 fail("Service was allowed to start while in the background"); 947 } 948 949 } finally { 950 mContext.stopService(mServiceIntent); 951 conn.stopMonitoringIfNeeded(); 952 controller.cleanup(); 953 } 954 } 955 956 /** 957 * Test that the foreground service app op does prevent the foreground state. 958 */ 959 public void testForegroundServiceAppOp() throws Exception { 960 // Use default timeout value 5000 961 final ServiceProcessController controller = new ServiceProcessController(mContext, 962 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses); 963 // Use default timeout value 5000 964 final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, 965 mServiceIntent); 966 final WatchUidRunner uidWatcher = controller.getUidWatcher(); 967 968 try { 969 // First kill the process to start out in a stable state. 970 controller.ensureProcessGone(); 971 972 // Do initial setup. 973 controller.makeUidIdle(); 974 controller.removeFromWhitelist(); 975 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 976 977 // Put app on whitelist, to allow service to run. 978 controller.addToWhitelist(); 979 980 // We will use this to monitor when the service is running. 981 conn.startMonitoring(); 982 983 // -------- START SERVICE AND THEN SUCCESSFULLY GO TO FOREGROUND 984 985 // Now start the service and wait for it to come up. 986 mContext.startService(mServiceStartForegroundIntent); 987 conn.waitForConnect(); 988 989 // Also make sure the uid state reports are as expected. 990 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 991 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 992 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 993 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 994 995 // Now take it out of foreground and confirm. 996 mContext.startService(mServiceStopForegroundIntent); 997 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 998 999 // Good, now stop the service and wait for it to go away. 1000 mContext.stopService(mServiceStartForegroundIntent); 1001 conn.waitForDisconnect(); 1002 1003 // There may be a transient STATE_SERVICE we don't care about, so waitFor. 1004 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1005 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1006 1007 // We don't want to wait for the uid to actually go idle, we can force it now. 1008 controller.makeUidIdle(); 1009 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1010 1011 // Make sure the process is gone so we start over fresh. 1012 controller.ensureProcessGone(); 1013 1014 // -------- START SERVICE AND BLOCK GOING TO FOREGROUND 1015 1016 // Now we will deny the app op and ensure the service can't become foreground. 1017 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore"); 1018 1019 // Now start the service and wait for it to come up. 1020 mContext.startService(mServiceStartForegroundIntent); 1021 conn.waitForConnect(); 1022 1023 // Also make sure the uid state reports are as expected. 1024 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1025 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 1026 1027 // Good, now stop the service and wait for it to go away. 1028 mContext.stopService(mServiceStartForegroundIntent); 1029 conn.waitForDisconnect(); 1030 1031 // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE. 1032 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1033 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1034 1035 // Make sure the uid is idle (it should be anyway, it never went active here). 1036 controller.makeUidIdle(); 1037 1038 // Make sure the process is gone so we start over fresh. 1039 controller.ensureProcessGone(); 1040 1041 // -------- DIRECT START FOREGROUND SERVICE SUCCESSFULLY 1042 1043 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 1044 1045 // Now start the service and wait for it to come up. 1046 mContext.startForegroundService(mServiceStartForegroundIntent); 1047 conn.waitForConnect(); 1048 1049 // Make sure it becomes a foreground service. The process state changes here 1050 // are weird looking because we first need to force the app out of idle to allow 1051 // it to start the service. 1052 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1053 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1054 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1055 // Remove tempwhitelist avoid temp white list block idle command and app crash occur. 1056 executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME); 1057 // Good, now stop the service and wait for it to go away. 1058 mContext.stopService(mServiceStartForegroundIntent); 1059 conn.waitForDisconnect(); 1060 1061 // There may be a transient STATE_SERVICE we don't care about, so waitFor. 1062 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1063 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1064 1065 // We don't want to wait for the uid to actually go idle, we can force it now. 1066 controller.makeUidIdle(); 1067 1068 // Make sure the process is gone so we start over fresh. 1069 controller.ensureProcessGone(); 1070 1071 // -------- DIRECT START FOREGROUND SERVICE BLOCKED 1072 1073 // Now we will deny the app op and ensure the service can't become foreground. 1074 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore"); 1075 1076 // But we will put it on the whitelist so the service is still allowed to start. 1077 controller.addToWhitelist(); 1078 1079 // Now start the service and wait for it to come up. 1080 mContext.startForegroundService(mServiceStartForegroundIntent); 1081 conn.waitForConnect(); 1082 1083 // In this case we only get to run it as a regular service. 1084 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1085 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 1086 1087 // Good, now stop the service and wait for it to go away. 1088 mContext.stopService(mServiceStartForegroundIntent); 1089 conn.waitForDisconnect(); 1090 1091 // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE. 1092 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1093 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1094 1095 // Make sure the uid is idle (it should be anyway, it never went active here). 1096 controller.makeUidIdle(); 1097 1098 // Make sure the process is gone so we start over fresh. 1099 controller.ensureProcessGone(); 1100 1101 // -------- XXX NEED TO TEST NON-WHITELIST CASE WHERE NOTHING HAPPENS 1102 1103 } finally { 1104 mContext.stopService(mServiceStartForegroundIntent); 1105 conn.stopMonitoringIfNeeded(); 1106 controller.cleanup(); 1107 controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow"); 1108 controller.removeFromWhitelist(); 1109 } 1110 } 1111 1112 private boolean supportsCantSaveState() { 1113 if (mContext.getPackageManager().hasSystemFeature( 1114 PackageManager.FEATURE_CANT_SAVE_STATE)) { 1115 return true; 1116 } 1117 1118 // Most types of devices need to support this. 1119 int mode = mContext.getResources().getConfiguration().uiMode 1120 & Configuration.UI_MODE_TYPE_MASK; 1121 if (mode != Configuration.UI_MODE_TYPE_WATCH 1122 && mode != Configuration.UI_MODE_TYPE_APPLIANCE) { 1123 // Most devices must support the can't save state feature. 1124 throw new IllegalStateException("Devices that are not watches or appliances must " 1125 + "support FEATURE_CANT_SAVE_STATE"); 1126 } 1127 return false; 1128 } 1129 1130 /** 1131 * Test that a single "can't save state" app has the proper process management 1132 * semantics. 1133 */ 1134 public void testCantSaveStateLaunchAndBackground() throws Exception { 1135 if (!supportsCantSaveState()) { 1136 return; 1137 } 1138 1139 final Intent activityIntent = new Intent(); 1140 activityIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME); 1141 activityIntent.setAction(Intent.ACTION_MAIN); 1142 activityIntent.addCategory(Intent.CATEGORY_LAUNCHER); 1143 activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1144 1145 final Intent homeIntent = new Intent(); 1146 homeIntent.setAction(Intent.ACTION_MAIN); 1147 homeIntent.addCategory(Intent.CATEGORY_HOME); 1148 homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1149 1150 ActivityManager am = mContext.getSystemService(ActivityManager.class); 1151 1152 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 1153 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 1154 1155 // We don't want to wait for the uid to actually go idle, we can force it now. 1156 String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1157 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1158 1159 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( 1160 CANT_SAVE_STATE_1_PACKAGE_NAME, 0); 1161 1162 // This test is also using UidImportanceListener to make sure the correct 1163 // heavy-weight state is reported there. 1164 UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext, 1165 appInfo.uid, IMPORTANCE_FOREGROUND, 1166 WAIT_TIME); 1167 uidForegroundListener.register(); 1168 UidImportanceListener uidBackgroundListener = new UidImportanceListener(mContext, 1169 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE-1, 1170 WAIT_TIME); 1171 uidBackgroundListener.register(); 1172 1173 WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid, 1174 WAIT_TIME); 1175 1176 UiDevice device = UiDevice.getInstance(getInstrumentation()); 1177 1178 try { 1179 // Start the heavy-weight app, should launch like a normal app. 1180 mContext.startActivity(activityIntent); 1181 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1182 device.waitForIdle(); 1183 1184 // Wait for process state to reflect running activity. 1185 uidForegroundListener.waitForValue( 1186 IMPORTANCE_FOREGROUND, 1187 IMPORTANCE_FOREGROUND); 1188 assertEquals(IMPORTANCE_FOREGROUND, 1189 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1190 1191 // Also make sure the uid state reports are as expected. 1192 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1193 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1194 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1195 1196 // Now go to home, leaving the app. It should be put in the heavy weight state. 1197 mContext.startActivity(homeIntent); 1198 1199 final int expectedImportance = 1200 (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) 1201 ? ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE 1202 : ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE_PRE_26; 1203 // Wait for process to go down to background heavy-weight. 1204 uidBackgroundListener.waitForValue(expectedImportance, expectedImportance); 1205 assertEquals(expectedImportance, 1206 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1207 1208 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1209 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1210 1211 // While in background, should go in to normal idle state. 1212 // Force app to go idle now 1213 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1214 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1215 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1216 1217 // Switch back to heavy-weight app to see if it correctly returns to foreground. 1218 mContext.startActivity(activityIntent); 1219 1220 // Wait for process state to reflect running activity. 1221 uidForegroundListener.waitForValue( 1222 IMPORTANCE_FOREGROUND, 1223 IMPORTANCE_FOREGROUND); 1224 assertEquals(IMPORTANCE_FOREGROUND, 1225 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1226 1227 // Also make sure the uid state reports are as expected. 1228 uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1229 uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1230 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1231 1232 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1233 device.waitForIdle(); 1234 1235 // Exit activity, check to see if we are now cached. 1236 getInstrumentation().getUiAutomation().performGlobalAction( 1237 AccessibilityService.GLOBAL_ACTION_BACK); 1238 1239 // Wait for process to become cached 1240 uidBackgroundListener.waitForValue( 1241 IMPORTANCE_CACHED, 1242 IMPORTANCE_CACHED); 1243 assertEquals(IMPORTANCE_CACHED, 1244 am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME)); 1245 1246 uidWatcher.expect(WatchUidRunner.CMD_CACHED, null); 1247 uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1248 1249 // While in background, should go in to normal idle state. 1250 // Force app to go idle now 1251 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1252 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1253 uidWatcher.expect(WatchUidRunner.CMD_IDLE, null); 1254 1255 } finally { 1256 uidWatcher.finish(); 1257 uidForegroundListener.unregister(); 1258 uidBackgroundListener.unregister(); 1259 } 1260 } 1261 1262 /** 1263 * Test that switching between two "can't save state" apps is handled properly. 1264 */ 1265 public void testCantSaveStateLaunchAndSwitch() throws Exception { 1266 if (!supportsCantSaveState()) { 1267 return; 1268 } 1269 1270 final Intent activity1Intent = new Intent(); 1271 activity1Intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME); 1272 activity1Intent.setAction(Intent.ACTION_MAIN); 1273 activity1Intent.addCategory(Intent.CATEGORY_LAUNCHER); 1274 activity1Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1275 1276 final Intent activity2Intent = new Intent(); 1277 activity2Intent.setPackage(CANT_SAVE_STATE_2_PACKAGE_NAME); 1278 activity2Intent.setAction(Intent.ACTION_MAIN); 1279 activity2Intent.addCategory(Intent.CATEGORY_LAUNCHER); 1280 activity2Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1281 1282 final Intent homeIntent = new Intent(); 1283 homeIntent.setAction(Intent.ACTION_MAIN); 1284 homeIntent.addCategory(Intent.CATEGORY_HOME); 1285 homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1286 1287 ActivityManager am = mContext.getSystemService(ActivityManager.class); 1288 UiDevice device = UiDevice.getInstance(getInstrumentation()); 1289 1290 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 1291 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS); 1292 1293 // We don't want to wait for the uid to actually go idle, we can force it now. 1294 String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1295 String result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1296 cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME; 1297 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1298 1299 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1300 CANT_SAVE_STATE_1_PACKAGE_NAME, 0); 1301 WatchUidRunner uid1Watcher = new WatchUidRunner(getInstrumentation(), app1Info.uid, 1302 WAIT_TIME); 1303 1304 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1305 CANT_SAVE_STATE_2_PACKAGE_NAME, 0); 1306 WatchUidRunner uid2Watcher = new WatchUidRunner(getInstrumentation(), app2Info.uid, 1307 WAIT_TIME); 1308 1309 try { 1310 // Start the first heavy-weight app, should launch like a normal app. 1311 mContext.startActivity(activity1Intent); 1312 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1313 device.waitForIdle(); 1314 1315 // Make sure the uid state reports are as expected. 1316 uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1317 uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1318 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1319 1320 // Now go to home, leaving the app. It should be put in the heavy weight state. 1321 mContext.startActivity(homeIntent); 1322 1323 // Wait for process to go down to background heavy-weight. 1324 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1325 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1326 1327 // Start the second heavy-weight app, should ask us what to do with the two apps 1328 startActivityAndWaitForShow(activity2Intent); 1329 1330 // First, let's try returning to the original app. 1331 maybeClick(device, new UiSelector().resourceId("android:id/switch_old")); 1332 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1333 device.waitForIdle(); 1334 1335 // App should now be back in foreground. 1336 uid1Watcher.expect(WatchUidRunner.CMD_UNCACHED, null); 1337 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1338 1339 // Return to home. 1340 mContext.startActivity(homeIntent); 1341 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1342 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1343 1344 // Again try starting second heavy-weight app to get prompt. 1345 startActivityAndWaitForShow(activity2Intent); 1346 1347 // Now we'll switch to the new app. 1348 maybeClick(device, new UiSelector().resourceId("android:id/switch_new")); 1349 waitForAppFocus(CANT_SAVE_STATE_2_PACKAGE_NAME, WAIT_TIME); 1350 device.waitForIdle(); 1351 1352 // The original app should now become cached. 1353 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1354 1355 // And the new app should start. 1356 uid2Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1357 uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1358 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1359 1360 // Make sure the original app is idle for cleanliness 1361 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1362 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1363 uid1Watcher.expect(WatchUidRunner.CMD_IDLE, null); 1364 1365 // Return to home. 1366 mContext.startActivity(homeIntent); 1367 uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1368 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1369 1370 // Try starting the first heavy weight app, but return to the existing second. 1371 startActivityAndWaitForShow(activity1Intent); 1372 maybeClick(device, new UiSelector().resourceId("android:id/switch_old")); 1373 waitForAppFocus(CANT_SAVE_STATE_2_PACKAGE_NAME, WAIT_TIME); 1374 device.waitForIdle(); 1375 uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1376 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1377 1378 // Return to home. 1379 mContext.startActivity(homeIntent); 1380 uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1381 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT); 1382 1383 // Again start the first heavy weight app, this time actually switching to it 1384 startActivityAndWaitForShow(activity1Intent); 1385 maybeClick(device, new UiSelector().resourceId("android:id/switch_new")); 1386 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1387 device.waitForIdle(); 1388 1389 // The second app should now become cached. 1390 uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1391 1392 // And the first app should start. 1393 uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null); 1394 uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null); 1395 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1396 1397 // Exit activity, check to see if we are now cached. 1398 waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME); 1399 device.waitForIdle(); 1400 getInstrumentation().getUiAutomation().performGlobalAction( 1401 AccessibilityService.GLOBAL_ACTION_BACK); 1402 uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null); 1403 uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT); 1404 1405 // Make both apps idle for cleanliness. 1406 cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME; 1407 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1408 cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME; 1409 result = SystemUtil.runShellCommand(getInstrumentation(), cmd); 1410 1411 } finally { 1412 uid2Watcher.finish(); 1413 uid1Watcher.finish(); 1414 } 1415 } 1416 1417 /** 1418 * Test a service binding cycle between two apps, with one of them also running a 1419 * foreground service. The other app should also get an FGS proc state. On stopping the 1420 * foreground service, app should go back to cached state. 1421 * @throws Exception 1422 */ 1423 public void testCycleFgs() throws Exception { 1424 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1425 PACKAGE_NAME_APP1, 0); 1426 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 1427 PACKAGE_NAME_APP3, 0); 1428 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1429 WAITFOR_MSEC); 1430 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 1431 WAITFOR_MSEC); 1432 1433 try { 1434 CommandReceiver.sendCommand(mContext, 1435 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1436 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1437 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1438 1439 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1440 PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null); 1441 1442 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1443 1444 // Create a cycle 1445 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1446 PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null); 1447 1448 try { 1449 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1450 WatchUidRunner.STATE_CACHED_EMPTY); 1451 fail("App3 should not be demoted to cached"); 1452 } catch (IllegalStateException ise) { 1453 // Didn't go to cached in spite of cycle. Good! 1454 } 1455 1456 // Stop the foreground service 1457 CommandReceiver.sendCommand(mContext, CommandReceiver 1458 .COMMAND_STOP_FOREGROUND_SERVICE, 1459 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1460 1461 // Check that the app's proc state has fallen 1462 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1463 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1464 } finally { 1465 uid1Watcher.finish(); 1466 uid3Watcher.finish(); 1467 } 1468 } 1469 1470 /** 1471 * Test a service binding cycle between three apps, with one of them also running a 1472 * foreground service. The other apps should also get an FGS proc state. On stopping the 1473 * foreground service, app should go back to cached state. 1474 * @throws Exception 1475 */ 1476 public void testCycleFgsTriangle() throws Exception { 1477 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1478 PACKAGE_NAME_APP1, 0); 1479 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1480 PACKAGE_NAME_APP2, 0); 1481 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 1482 PACKAGE_NAME_APP3, 0); 1483 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1484 WAITFOR_MSEC); 1485 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1486 WAITFOR_MSEC); 1487 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 1488 WAITFOR_MSEC); 1489 1490 try { 1491 CommandReceiver.sendCommand(mContext, 1492 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1493 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1494 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1495 1496 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1497 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1498 1499 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1500 1501 // Bind from 2 to 3 1502 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1503 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 1504 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1505 1506 // Create a cycle 1507 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1508 PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null); 1509 1510 try { 1511 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1512 WatchUidRunner.STATE_CACHED_EMPTY); 1513 fail("App3 should not be demoted to cached"); 1514 } catch (IllegalStateException ise) { 1515 // Didn't go to cached in spite of cycle. Good! 1516 } 1517 1518 try { 1519 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1520 WatchUidRunner.STATE_CACHED_EMPTY); 1521 fail("App2 should not be demoted to cached"); 1522 } catch (IllegalStateException ise) { 1523 // Didn't go to cached in spite of cycle. Good! 1524 } 1525 1526 try { 1527 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1528 WatchUidRunner.STATE_CACHED_EMPTY); 1529 fail("App1 should not be demoted to cached"); 1530 } catch (IllegalStateException ise) { 1531 // Didn't go to cached in spite of cycle. Good! 1532 } 1533 1534 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 1535 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1536 1537 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1538 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1539 } finally { 1540 uid1Watcher.finish(); 1541 uid2Watcher.finish(); 1542 uid3Watcher.finish(); 1543 } 1544 } 1545 1546 /** 1547 * Test a service binding cycle between three apps, with one of them also running a 1548 * foreground service. The other apps should also get an FGS proc state. On stopping the 1549 * foreground service, app should go back to cached state. 1550 * @throws Exception 1551 */ 1552 public void testCycleFgsTriangleBiDi() throws Exception { 1553 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1554 PACKAGE_NAME_APP1, 0); 1555 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1556 PACKAGE_NAME_APP2, 0); 1557 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 1558 PACKAGE_NAME_APP3, 0); 1559 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1560 WAITFOR_MSEC); 1561 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1562 WAITFOR_MSEC); 1563 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 1564 WAITFOR_MSEC); 1565 1566 try { 1567 CommandReceiver.sendCommand(mContext, 1568 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1569 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1570 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1571 1572 // Bind from 1 to 2, 1 to 3 1573 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1574 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1575 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1576 PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null); 1577 1578 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1579 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1580 1581 // Bind from 2 to 3, 3 to 2, 3 to 1 1582 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1583 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 1584 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1585 PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null); 1586 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1587 PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null); 1588 1589 try { 1590 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1591 WatchUidRunner.STATE_CACHED_EMPTY); 1592 fail("App3 should not be demoted to cached"); 1593 } catch (IllegalStateException ise) { 1594 // Didn't go to cached in spite of cycle. Good! 1595 } 1596 1597 // Stop the foreground service 1598 CommandReceiver.sendCommand(mContext, CommandReceiver 1599 .COMMAND_STOP_FOREGROUND_SERVICE, 1600 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1601 1602 // Check that the apps' proc state has fallen 1603 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1604 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1605 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1606 } finally { 1607 uid1Watcher.finish(); 1608 uid2Watcher.finish(); 1609 uid3Watcher.finish(); 1610 } 1611 } 1612 1613 /** 1614 * Test process states for foreground service with and without location type in the manifest. 1615 * When running a foreground service with location type, the process should go to 1616 * PROCESS_STATE_FOREGROUND_SERVICE_LOCATION. 1617 * @throws Exception 1618 */ 1619 public void testFgsLocation() throws Exception { 1620 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1621 PACKAGE_NAME_APP1, 0); 1622 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1623 WAITFOR_MSEC); 1624 1625 try { 1626 // First start a foreground service 1627 CommandReceiver.sendCommand(mContext, 1628 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1629 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1630 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1631 1632 // Try to elevate to foreground service location 1633 Bundle bundle = new Bundle(); 1634 bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, 1635 ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 1636 CommandReceiver.sendCommand(mContext, 1637 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 1638 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 1639 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1640 WatchUidRunner.STATE_FG_SERVICE_LOCATION); 1641 1642 // Back down to foreground service 1643 CommandReceiver.sendCommand(mContext, 1644 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 1645 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1646 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1647 1648 try { 1649 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1650 WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME); 1651 fail("App1 should not be demoted to cached"); 1652 } catch (IllegalStateException ise) { 1653 } 1654 1655 // Remove foreground service as well 1656 CommandReceiver.sendCommand(mContext, 1657 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1658 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1659 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1660 1661 } finally { 1662 uid1Watcher.finish(); 1663 } 1664 } 1665 1666 /** 1667 * Test process states for foreground service binding to another app, with and without 1668 * BIND_INCLUDE_CAPABILITIES. Bound app should either go to FGS or FGSL, depending on the 1669 * flag. 1670 * @throws Exception 1671 */ 1672 public void testFgsLocationBind() throws Exception { 1673 setupWatchers(3); 1674 1675 try { 1676 // First start a foreground service 1677 CommandReceiver.sendCommand(mContext, 1678 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1679 mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null); 1680 mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1681 1682 // Try to elevate to foreground service location 1683 Bundle bundle = new Bundle(); 1684 bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, 1685 ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 1686 CommandReceiver.sendCommand(mContext, 1687 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 1688 mAppInfo[0].packageName, mAppInfo[0].packageName, 0, bundle); 1689 // Verify moved to FGSL 1690 mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, 1691 WatchUidRunner.STATE_FG_SERVICE_LOCATION); 1692 1693 // Bind App 0 -> App 1, verify doesn't include capabilities (only FGS, not FGSL) 1694 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1695 mAppInfo[0].packageName, mAppInfo[1].packageName, 0, null); 1696 mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1697 1698 // Bind App 0 -> App 2, include capabilities (FGSL) 1699 bundle = new Bundle(); 1700 bundle.putInt(CommandReceiver.EXTRA_FLAGS, Context.BIND_INCLUDE_CAPABILITIES); 1701 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1702 mAppInfo[0].packageName, mAppInfo[2].packageName, 0, bundle); 1703 mWatchers[2].waitFor(WatchUidRunner.CMD_PROCSTATE, 1704 WatchUidRunner.STATE_FG_SERVICE_LOCATION); 1705 1706 // Back down to foreground service 1707 CommandReceiver.sendCommand(mContext, 1708 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 1709 mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null); 1710 mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1711 1712 // Remove foreground service as well 1713 CommandReceiver.sendCommand(mContext, 1714 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1715 mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null); 1716 mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1717 1718 } finally { 1719 shutdownWatchers(); 1720 } 1721 } 1722 1723 /** 1724 * Test process states for top app binding with and without BIND_INCLUDE_CAPABILITIES flag. 1725 * Bound app should be TOP w/flag and BTOP without flag. 1726 * @throws Exception 1727 */ 1728 public void testTopBind() throws Exception { 1729 setupWatchers(2); 1730 1731 Activity activity = null; 1732 1733 try { 1734 // This will start an activity in App0 1735 activity = startSubActivity(ScreenOnActivity.class); 1736 1737 // Bind Stub -> App 0, verify doesn't include capabilities (only BTOP, not TOP) 1738 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1739 STUB_PACKAGE_NAME, mAppInfo[0].packageName, 0, null); 1740 mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP); 1741 1742 // Bind Stub -> App 1, include capabilities (TOP) 1743 Bundle bundle = new Bundle(); 1744 bundle.putInt(CommandReceiver.EXTRA_FLAGS, Context.BIND_INCLUDE_CAPABILITIES); 1745 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1746 STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, bundle); 1747 mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, 1748 WatchUidRunner.STATE_TOP); 1749 } finally { 1750 shutdownWatchers(); 1751 if (activity != null) { 1752 activity.finish(); 1753 } 1754 } 1755 } 1756 1757 private final <T extends Activity> Activity startSubActivity(Class<T> activityClass) { 1758 final Instrumentation.ActivityResult result = new Instrumentation.ActivityResult( 1759 0, new Intent()); 1760 final Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor( 1761 activityClass.getName(), result, false); 1762 mInstrumentation.addMonitor(monitor); 1763 launchActivity(STUB_PACKAGE_NAME, activityClass, null); 1764 return monitor.waitForActivity(); 1765 } 1766 1767 public void testCycleTop() throws Exception { 1768 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1769 PACKAGE_NAME_APP1, 0); 1770 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1771 PACKAGE_NAME_APP2, 0); 1772 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 1773 PACKAGE_NAME_APP3, 0); 1774 1775 UidImportanceListener uid1Listener = new UidImportanceListener(mContext, 1776 app1Info.uid, IMPORTANCE_VISIBLE, 1777 WAITFOR_MSEC); 1778 uid1Listener.register(); 1779 1780 UidImportanceListener uid1ServiceListener = new UidImportanceListener(mContext, 1781 app1Info.uid, IMPORTANCE_CACHED, 1782 WAITFOR_MSEC); 1783 uid1ServiceListener.register(); 1784 1785 UidImportanceListener uid2Listener = new UidImportanceListener(mContext, 1786 app2Info.uid, IMPORTANCE_VISIBLE, 1787 WAITFOR_MSEC); 1788 uid2Listener.register(); 1789 1790 UidImportanceListener uid2ServiceListener = new UidImportanceListener(mContext, 1791 app2Info.uid, IMPORTANCE_CACHED, 1792 WAITFOR_MSEC); 1793 uid2ServiceListener.register(); 1794 1795 UidImportanceListener uid3Listener = new UidImportanceListener(mContext, 1796 app3Info.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, 1797 WAITFOR_MSEC); 1798 uid3Listener.register(); 1799 1800 Activity activity = null; 1801 1802 try { 1803 // Start an activity 1804 activity = startSubActivity(ScreenOnActivity.class); 1805 1806 // Start a FGS in app2 1807 CommandReceiver.sendCommand(mContext, 1808 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, PACKAGE_NAME_APP2, 1809 PACKAGE_NAME_APP2, 0, null); 1810 1811 uid2Listener.waitForValue( 1812 IMPORTANCE_FOREGROUND_SERVICE, 1813 IMPORTANCE_FOREGROUND_SERVICE); 1814 1815 // Bind from TOP to the service in app1 1816 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1817 STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null); 1818 1819 uid1Listener.waitForValue(IMPORTANCE_FOREGROUND, 1820 IMPORTANCE_FOREGROUND_SERVICE); 1821 1822 // Bind from app1 to a service in app2 1823 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1824 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1825 1826 // Bind from app2 to a service in app3 1827 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1828 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 1829 1830 uid3Listener.waitForValue(IMPORTANCE_FOREGROUND, 1831 IMPORTANCE_FOREGROUND_SERVICE); 1832 1833 // Create a cycle 1834 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1835 PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null); 1836 1837 try { 1838 uid3Listener.waitForValue(IMPORTANCE_CACHED, 1839 IMPORTANCE_CACHED); 1840 fail("App3 should not be demoted to cached, expecting FGS"); 1841 } catch (IllegalStateException e) { 1842 // Didn't go to cached in spite of cycle. Good! 1843 } 1844 1845 // Unbind from the TOP app 1846 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 1847 STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null); 1848 1849 // Check that the apps' proc state is FOREGROUND_SERVICE 1850 uid2Listener.waitForValue( 1851 IMPORTANCE_FOREGROUND_SERVICE, 1852 IMPORTANCE_FOREGROUND_SERVICE); 1853 1854 // Stop the foreground service 1855 CommandReceiver.sendCommand(mContext, CommandReceiver 1856 .COMMAND_STOP_FOREGROUND_SERVICE, 1857 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 1858 1859 // Check that the apps fall down to cached state 1860 uid1ServiceListener.waitForValue( 1861 IMPORTANCE_CACHED, 1862 IMPORTANCE_CACHED); 1863 1864 uid2ServiceListener.waitForValue( 1865 IMPORTANCE_CACHED, 1866 IMPORTANCE_CACHED); 1867 uid3Listener.waitForValue( 1868 IMPORTANCE_CACHED, 1869 IMPORTANCE_CACHED); 1870 } finally { 1871 uid1Listener.unregister(); 1872 uid1ServiceListener.unregister(); 1873 uid2Listener.unregister(); 1874 uid2ServiceListener.unregister(); 1875 uid3Listener.unregister(); 1876 if (activity != null) { 1877 activity.finish(); 1878 } 1879 } 1880 } 1881 } 1882