1 /* 2 * Copyright (C) 2019 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.PROCESS_CAPABILITY_ALL; 20 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; 21 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 22 import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK; 23 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; 24 import static android.app.stubs.LocalForegroundService.ACTION_START_FGS_RESULT; 25 import static android.app.stubs.LocalForegroundServiceLocation.ACTION_START_FGSL_RESULT; 26 import static android.os.PowerExemptionManager.REASON_PUSH_MESSAGING; 27 import static android.os.PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA; 28 import static android.os.PowerExemptionManager.REASON_UNKNOWN; 29 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 30 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; 31 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; 32 33 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 34 35 import static junit.framework.Assert.assertNotNull; 36 import static junit.framework.Assert.assertTrue; 37 import static junit.framework.Assert.fail; 38 39 import android.accessibilityservice.AccessibilityService; 40 import android.app.ActivityManager; 41 import android.app.BroadcastOptions; 42 import android.app.ForegroundServiceStartNotAllowedException; 43 import android.app.Instrumentation; 44 import android.app.cts.android.app.cts.tools.WaitForBroadcast; 45 import android.app.cts.android.app.cts.tools.WatchUidRunner; 46 import android.app.stubs.CommandReceiver; 47 import android.app.stubs.LocalForegroundService; 48 import android.app.stubs.LocalForegroundServiceLocation; 49 import android.content.ComponentName; 50 import android.content.Context; 51 import android.content.Intent; 52 import android.content.ServiceConnection; 53 import android.content.pm.ApplicationInfo; 54 import android.content.pm.ServiceInfo; 55 import android.os.Bundle; 56 import android.os.IBinder; 57 import android.os.PowerExemptionManager; 58 import android.os.SystemClock; 59 import android.permission.cts.PermissionUtils; 60 import android.platform.test.annotations.AsbSecurityTest; 61 import android.provider.DeviceConfig; 62 import android.provider.Settings; 63 import android.server.wm.settings.SettingsSession; 64 import android.support.test.uiautomator.UiDevice; 65 import android.util.Log; 66 67 import androidx.test.InstrumentationRegistry; 68 import androidx.test.ext.junit.runners.AndroidJUnit4; 69 import androidx.test.filters.LargeTest; 70 71 import com.android.compatibility.common.util.SystemUtil; 72 73 import org.junit.After; 74 import org.junit.Before; 75 import org.junit.Ignore; 76 import org.junit.Test; 77 import org.junit.runner.RunWith; 78 79 @RunWith(AndroidJUnit4.class) 80 public class ActivityManagerFgsBgStartTest { 81 private static final String TAG = ActivityManagerFgsBgStartTest.class.getName(); 82 83 static final String STUB_PACKAGE_NAME = "android.app.stubs"; 84 static final String PACKAGE_NAME_APP1 = "com.android.app1"; 85 static final String PACKAGE_NAME_APP2 = "com.android.app2"; 86 static final String PACKAGE_NAME_APP3 = "com.android.app3"; 87 88 private static final String KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED = 89 "default_fgs_starts_restriction_enabled"; 90 91 private static final String KEY_FGS_START_FOREGROUND_TIMEOUT = 92 "fgs_start_foreground_timeout"; 93 94 private static final String KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 95 "push_messaging_over_quota_behavior"; 96 97 private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000; 98 99 public static final Integer LOCAL_SERVICE_PROCESS_CAPABILITY = new Integer( 100 PROCESS_CAPABILITY_FOREGROUND_CAMERA 101 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE 102 | PROCESS_CAPABILITY_NETWORK); 103 104 static final int WAITFOR_MSEC = 10000; 105 106 private static final int TEMP_ALLOWLIST_DURATION_MS = 2000; 107 108 private static final String[] PACKAGE_NAMES = { 109 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3 110 }; 111 112 private Context mContext; 113 private Instrumentation mInstrumentation; 114 private Context mTargetContext; 115 116 private int mOrigDeviceDemoMode = 0; 117 118 @Before setUp()119 public void setUp() throws Exception { 120 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 121 mContext = mInstrumentation.getContext(); 122 mTargetContext = mInstrumentation.getTargetContext(); 123 for (int i = 0; i < PACKAGE_NAMES.length; ++i) { 124 CtsAppTestUtils.makeUidIdle(mInstrumentation, PACKAGE_NAMES[i]); 125 // The manifest file gives test app SYSTEM_ALERT_WINDOW permissions, which also exempt 126 // the app from BG-FGS-launch restriction. Remove SYSTEM_ALERT_WINDOW permission to test 127 // other BG-FGS-launch exemptions. 128 allowBgActivityStart(PACKAGE_NAMES[i], false); 129 } 130 CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext); 131 cleanupResiduals(); 132 enableFgsRestriction(true, true, null); 133 // Press home key to ensure stopAppSwitches is called so the grace period of 134 // the background start will be ignored if there's any. 135 UiDevice.getInstance(mInstrumentation).pressHome(); 136 } 137 138 @After tearDown()139 public void tearDown() throws Exception { 140 for (int i = 0; i < PACKAGE_NAMES.length; ++i) { 141 CtsAppTestUtils.makeUidIdle(mInstrumentation, PACKAGE_NAMES[i]); 142 allowBgActivityStart(PACKAGE_NAMES[i], true); 143 } 144 cleanupResiduals(); 145 enableFgsRestriction(true, true, null); 146 for (String packageName: PACKAGE_NAMES) { 147 resetFgsRestriction(packageName); 148 } 149 } 150 cleanupResiduals()151 private void cleanupResiduals() { 152 // Stop all the packages to avoid residual impact 153 final ActivityManager am = mContext.getSystemService(ActivityManager.class); 154 for (int i = 0; i < PACKAGE_NAMES.length; i++) { 155 final String pkgName = PACKAGE_NAMES[i]; 156 SystemUtil.runWithShellPermissionIdentity(() -> { 157 am.forceStopPackage(pkgName); 158 }); 159 } 160 // Make sure we are in Home screen 161 mInstrumentation.getUiAutomation().performGlobalAction( 162 AccessibilityService.GLOBAL_ACTION_HOME); 163 } 164 165 /** 166 * APP1 is in BG state, it can start FGSL, but it won't get location capability. 167 * APP1 is in TOP state, it gets location capability. 168 * @throws Exception 169 */ 170 @Test testFgsLocationStartFromBG()171 public void testFgsLocationStartFromBG() throws Exception { 172 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 173 PACKAGE_NAME_APP1, 0); 174 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 175 WAITFOR_MSEC); 176 177 try { 178 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 179 waiter.prepare(ACTION_START_FGSL_RESULT); 180 // APP1 is in BG state, Start FGSL in APP1, it won't get location capability. 181 Bundle bundle = new Bundle(); 182 bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, 183 ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 184 // start FGSL. 185 enableFgsRestriction(false, true, null); 186 CommandReceiver.sendCommand(mContext, 187 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 188 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 189 // APP1 is in FGS state, but won't get location capability. 190 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 191 WatchUidRunner.STATE_FG_SERVICE, 192 new Integer(PROCESS_CAPABILITY_NETWORK)); 193 waiter.doWait(WAITFOR_MSEC); 194 // stop FGSL 195 CommandReceiver.sendCommand(mContext, 196 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 197 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 198 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 199 WatchUidRunner.STATE_CACHED_EMPTY, 200 new Integer(PROCESS_CAPABILITY_NONE)); 201 202 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 203 waiter.prepare(ACTION_START_FGS_RESULT); 204 // APP1 is in FGS state, 205 CommandReceiver.sendCommand(mContext, 206 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 207 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 208 // start FGSL in app1, it won't get location capability. 209 CommandReceiver.sendCommand(mContext, 210 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 211 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 212 // APP1 is in STATE_FG_SERVICE, but won't get location capability. 213 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 214 WatchUidRunner.STATE_FG_SERVICE, 215 new Integer(PROCESS_CAPABILITY_NETWORK)); 216 waiter.doWait(WAITFOR_MSEC); 217 // stop FGS. 218 CommandReceiver.sendCommand(mContext, 219 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 220 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 221 // stop FGSL. 222 CommandReceiver.sendCommand(mContext, 223 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 224 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 225 226 // Put APP1 in TOP state, now it gets location capability (because the TOP process 227 // gets all while-in-use permission (not from FGSL). 228 allowBgActivityStart(PACKAGE_NAME_APP1, true); 229 CommandReceiver.sendCommand(mContext, 230 CommandReceiver.COMMAND_START_ACTIVITY, 231 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 232 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 233 WatchUidRunner.STATE_TOP, 234 new Integer(PROCESS_CAPABILITY_ALL)); 235 236 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 237 waiter.prepare(ACTION_START_FGSL_RESULT); 238 // APP1 is in TOP state, start the FGSL in APP1, it will get location capability. 239 CommandReceiver.sendCommand(mContext, 240 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 241 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 242 // Stop the activity. 243 CommandReceiver.sendCommand(mContext, 244 CommandReceiver.COMMAND_STOP_ACTIVITY, 245 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 246 // The FGSL still has location capability because it is started from TOP. 247 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 248 WatchUidRunner.STATE_FG_SERVICE, 249 new Integer(PROCESS_CAPABILITY_ALL)); 250 waiter.doWait(WAITFOR_MSEC); 251 // Stop FGSL. 252 CommandReceiver.sendCommand(mContext, 253 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 254 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 255 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 256 WatchUidRunner.STATE_CACHED_EMPTY, 257 new Integer(PROCESS_CAPABILITY_NONE)); 258 } finally { 259 uid1Watcher.finish(); 260 } 261 } 262 263 /** 264 * APP1 is in BG state, it can start FGSL in APP2, but the FGS won't get location 265 * capability. 266 * APP1 is in TOP state, it can start FGSL in APP2, FGSL gets location capability. 267 * @throws Exception 268 */ 269 @Test testFgsLocationStartFromBGTwoProcesses()270 public void testFgsLocationStartFromBGTwoProcesses() throws Exception { 271 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 272 PACKAGE_NAME_APP1, 0); 273 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 274 PACKAGE_NAME_APP2, 0); 275 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 276 WAITFOR_MSEC); 277 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 278 WAITFOR_MSEC); 279 280 try { 281 // APP1 is in BG state, start FGSL in APP2. 282 Bundle bundle = new Bundle(); 283 bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, 284 ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 285 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 286 waiter.prepare(ACTION_START_FGSL_RESULT); 287 enableFgsRestriction(false, true, null); 288 CommandReceiver.sendCommand(mContext, 289 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 290 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, bundle); 291 // APP2 won't have location capability because APP1 is not in TOP state. 292 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 293 WatchUidRunner.STATE_FG_SERVICE, 294 new Integer(PROCESS_CAPABILITY_NETWORK)); 295 waiter.doWait(WAITFOR_MSEC); 296 297 CommandReceiver.sendCommand(mContext, 298 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 299 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 300 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 301 WatchUidRunner.STATE_CACHED_EMPTY, 302 new Integer(PROCESS_CAPABILITY_NONE)); 303 304 // Put APP1 in TOP state 305 allowBgActivityStart(PACKAGE_NAME_APP1, true); 306 CommandReceiver.sendCommand(mContext, 307 CommandReceiver.COMMAND_START_ACTIVITY, 308 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 309 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 310 WatchUidRunner.STATE_TOP, 311 new Integer(PROCESS_CAPABILITY_ALL)); 312 313 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 314 waiter.prepare(ACTION_START_FGSL_RESULT); 315 // From APP1, start FGSL in APP2. 316 CommandReceiver.sendCommand(mContext, 317 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 318 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, bundle); 319 // Now APP2 gets location capability. 320 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 321 WatchUidRunner.STATE_FG_SERVICE, 322 new Integer(PROCESS_CAPABILITY_ALL)); 323 waiter.doWait(WAITFOR_MSEC); 324 325 CommandReceiver.sendCommand(mContext, 326 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 327 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 328 329 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 330 WatchUidRunner.STATE_CACHED_EMPTY, 331 new Integer(PROCESS_CAPABILITY_NONE)); 332 333 CommandReceiver.sendCommand(mContext, 334 CommandReceiver.COMMAND_STOP_ACTIVITY, 335 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 336 337 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 338 WatchUidRunner.STATE_CACHED_EMPTY, 339 new Integer(PROCESS_CAPABILITY_NONE)); 340 } finally { 341 uid1Watcher.finish(); 342 uid2Watcher.finish(); 343 } 344 } 345 346 /** 347 * APP1 is in BG state, by a PendingIntent, it can start FGSL in APP2, 348 * but the FGS won't get location capability. 349 * APP1 is in TOP state, by a PendingIntent, it can start FGSL in APP2, 350 * FGSL gets location capability. 351 * @throws Exception 352 */ 353 @Test testFgsLocationPendingIntent()354 public void testFgsLocationPendingIntent() throws Exception { 355 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 356 PACKAGE_NAME_APP1, 0); 357 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 358 PACKAGE_NAME_APP2, 0); 359 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 360 WAITFOR_MSEC); 361 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 362 WAITFOR_MSEC); 363 364 try { 365 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 366 waiter.prepare(ACTION_START_FGSL_RESULT); 367 // APP1 is in BG state, start FGSL in APP2. 368 enableFgsRestriction(false, true, null); 369 CommandReceiver.sendCommand(mContext, 370 CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT, 371 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 372 CommandReceiver.sendCommand(mContext, 373 CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT, 374 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 375 // APP2 won't have location capability. 376 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 377 WatchUidRunner.STATE_FG_SERVICE, 378 new Integer(PROCESS_CAPABILITY_NETWORK)); 379 waiter.doWait(WAITFOR_MSEC); 380 // Stop FGSL in APP2. 381 CommandReceiver.sendCommand(mContext, 382 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 383 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 384 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 385 WatchUidRunner.STATE_CACHED_EMPTY, 386 new Integer(PROCESS_CAPABILITY_NONE)); 387 388 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 389 waiter.prepare(ACTION_START_FGS_RESULT); 390 // Put APP1 in FGS state, start FGSL in APP2. 391 CommandReceiver.sendCommand(mContext, 392 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 393 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 394 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 395 WatchUidRunner.STATE_FG_SERVICE, 396 new Integer(PROCESS_CAPABILITY_NETWORK)); 397 waiter.doWait(WAITFOR_MSEC); 398 CommandReceiver.sendCommand(mContext, 399 CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT, 400 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 401 402 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 403 waiter.prepare(ACTION_START_FGSL_RESULT); 404 CommandReceiver.sendCommand(mContext, 405 CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT, 406 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 407 // APP2 won't have location capability. 408 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 409 WatchUidRunner.STATE_FG_SERVICE, 410 new Integer(PROCESS_CAPABILITY_NETWORK)); 411 waiter.doWait(WAITFOR_MSEC); 412 // stop FGSL in APP2. 413 CommandReceiver.sendCommand(mContext, 414 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 415 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 416 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 417 WatchUidRunner.STATE_CACHED_EMPTY, 418 new Integer(PROCESS_CAPABILITY_NONE)); 419 420 // put APP1 in TOP state, start FGSL in APP2. 421 allowBgActivityStart(PACKAGE_NAME_APP1, true); 422 CommandReceiver.sendCommand(mContext, 423 CommandReceiver.COMMAND_START_ACTIVITY, 424 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 425 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 426 WatchUidRunner.STATE_TOP, 427 new Integer(PROCESS_CAPABILITY_ALL)); 428 CommandReceiver.sendCommand(mContext, 429 CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT, 430 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 431 432 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 433 waiter.prepare(ACTION_START_FGSL_RESULT); 434 CommandReceiver.sendCommand(mContext, 435 CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT, 436 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 437 // APP2 now have location capability (because APP1 is TOP) 438 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 439 WatchUidRunner.STATE_FG_SERVICE, 440 new Integer(PROCESS_CAPABILITY_ALL)); 441 waiter.doWait(WAITFOR_MSEC); 442 443 // stop FGSL in APP2. 444 CommandReceiver.sendCommand(mContext, 445 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 446 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 447 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 448 WatchUidRunner.STATE_CACHED_EMPTY, 449 new Integer(PROCESS_CAPABILITY_NONE)); 450 451 // stop FGS in APP1, 452 CommandReceiver.sendCommand(mContext, 453 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 454 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 455 // stop TOP activity in APP1. 456 CommandReceiver.sendCommand(mContext, 457 CommandReceiver.COMMAND_STOP_ACTIVITY, 458 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 459 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 460 WatchUidRunner.STATE_CACHED_EMPTY, 461 new Integer(PROCESS_CAPABILITY_NONE)); 462 } finally { 463 uid1Watcher.finish(); 464 uid2Watcher.finish(); 465 } 466 } 467 468 /** 469 * Test a FGS start by bind from BG does not get get while-in-use capability. 470 * @throws Exception 471 */ 472 @Test 473 @AsbSecurityTest(cveBugId = 173516292) testFgsLocationStartFromBGWithBind()474 public void testFgsLocationStartFromBGWithBind() throws Exception { 475 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 476 PACKAGE_NAME_APP1, 0); 477 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 478 WAITFOR_MSEC); 479 480 try { 481 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 482 waiter.prepare(ACTION_START_FGSL_RESULT); 483 // APP1 is in BG state, bind FGSL in APP1 first. 484 enableFgsRestriction(false, true, null); 485 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE, 486 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 487 Bundle bundle = new Bundle(); 488 bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE, 489 ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 490 // Then start FGSL in APP1, it won't get location capability. 491 CommandReceiver.sendCommand(mContext, 492 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 493 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle); 494 495 // APP1 is in FGS state, but won't get location capability. 496 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 497 WatchUidRunner.STATE_FG_SERVICE, 498 new Integer(PROCESS_CAPABILITY_NETWORK)); 499 waiter.doWait(WAITFOR_MSEC); 500 501 // unbind service. 502 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 503 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 504 // stop FGSL 505 CommandReceiver.sendCommand(mContext, 506 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 507 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 508 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 509 WatchUidRunner.STATE_CACHED_EMPTY, 510 new Integer(PROCESS_CAPABILITY_NONE)); 511 } finally { 512 uid1Watcher.finish(); 513 } 514 } 515 516 @Test testUpdateUidProcState()517 public void testUpdateUidProcState() throws Exception { 518 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 519 PACKAGE_NAME_APP1, 0); 520 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 521 WAITFOR_MSEC); 522 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 523 PACKAGE_NAME_APP2, 0); 524 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 525 WAITFOR_MSEC); 526 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 527 PACKAGE_NAME_APP3, 0); 528 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 529 WAITFOR_MSEC); 530 531 try { 532 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 533 waiter.prepare(ACTION_START_FGS_RESULT); 534 535 enableFgsRestriction(false, true, null); 536 537 // START FGS in APP2. 538 CommandReceiver.sendCommand(mContext, 539 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 540 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 541 // APP2 proc state is 4. 542 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 543 WatchUidRunner.STATE_FG_SERVICE); 544 waiter.doWait(WAITFOR_MSEC); 545 546 // APP2 binds to APP1. 547 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 548 PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, Context.BIND_INCLUDE_CAPABILITIES, null); 549 // APP1 gets proc state 4. 550 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 551 WatchUidRunner.STATE_FG_SERVICE); 552 553 // Start activity in APP3, this put APP3 in TOP state. 554 allowBgActivityStart(PACKAGE_NAME_APP3, true); 555 CommandReceiver.sendCommand(mContext, 556 CommandReceiver.COMMAND_START_ACTIVITY, 557 PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null); 558 // APP3 gets proc state 2. 559 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 560 561 // APP3 repeatedly bind/unbind with APP2, observer APP1 proc state change. 562 // Observe updateUidProcState() call latency. 563 for (int i = 0; i < 10; ++i) { 564 // APP3 bind to APP2 565 CommandReceiver.sendCommand(mContext, 566 CommandReceiver.COMMAND_BIND_SERVICE, 567 PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, Context.BIND_INCLUDE_CAPABILITIES, 568 null); 569 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP); 570 571 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 572 PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null); 573 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 574 } 575 576 // unbind service. 577 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY, 578 PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null); 579 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 580 PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null); 581 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 582 PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, null); 583 CommandReceiver.sendCommand(mContext, 584 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 585 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 586 587 } finally { 588 uid1Watcher.finish(); 589 uid2Watcher.finish(); 590 uid3Watcher.finish(); 591 allowBgActivityStart(PACKAGE_NAME_APP3, false); 592 } 593 } 594 595 /** 596 * Test FGS background startForeground() restriction, use DeviceConfig to turn on restriction. 597 * @throws Exception 598 */ 599 @Test testFgsStartFromBG1()600 public void testFgsStartFromBG1() throws Exception { 601 testFgsStartFromBG(true); 602 } 603 604 /** 605 * Test FGS background startForeground() restriction, use AppCompat CHANGE ID to turn on 606 * restriction. 607 * @throws Exception 608 */ 609 @Test testFgsStartFromBG2()610 public void testFgsStartFromBG2() throws Exception { 611 testFgsStartFromBG(false); 612 } 613 testFgsStartFromBG(boolean useDeviceConfig)614 private void testFgsStartFromBG(boolean useDeviceConfig) throws Exception { 615 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 616 PACKAGE_NAME_APP1, 0); 617 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 618 WAITFOR_MSEC); 619 try { 620 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 621 waiter.prepare(ACTION_START_FGS_RESULT); 622 // disable the FGS background startForeground() restriction. 623 enableFgsRestriction(false, true, null); 624 enableFgsRestriction(false, useDeviceConfig, PACKAGE_NAME_APP1); 625 // APP1 is in BG state, Start FGS in APP1. 626 CommandReceiver.sendCommand(mContext, 627 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 628 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 629 // APP1 is in STATE_FG_SERVICE. 630 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 631 waiter.doWait(WAITFOR_MSEC); 632 // stop FGS. 633 CommandReceiver.sendCommand(mContext, 634 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 635 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 636 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 637 638 // Enable the FGS background startForeground() restriction. 639 allowBgActivityStart(PACKAGE_NAME_APP1, false); 640 enableFgsRestriction(true, true, null); 641 enableFgsRestriction(true, useDeviceConfig, PACKAGE_NAME_APP1); 642 // Start FGS in BG state. 643 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 644 waiter.prepare(ACTION_START_FGS_RESULT); 645 CommandReceiver.sendCommand(mContext, 646 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 647 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 648 // APP1 does not enter FGS state 649 try { 650 waiter.doWait(WAITFOR_MSEC); 651 fail("Service should not enter foreground service state"); 652 } catch (Exception e) { 653 } 654 655 // Put APP1 in TOP state. 656 allowBgActivityStart(PACKAGE_NAME_APP1, true); 657 CommandReceiver.sendCommand(mContext, 658 CommandReceiver.COMMAND_START_ACTIVITY, 659 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 660 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 661 allowBgActivityStart(PACKAGE_NAME_APP1, false); 662 663 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 664 waiter.prepare(ACTION_START_FGS_RESULT); 665 // Now it can start FGS. 666 CommandReceiver.sendCommand(mContext, 667 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 668 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 669 // Stop activity. 670 CommandReceiver.sendCommand(mContext, 671 CommandReceiver.COMMAND_STOP_ACTIVITY, 672 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 673 // FGS is still running. 674 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 675 waiter.doWait(WAITFOR_MSEC); 676 // Stop the FGS. 677 CommandReceiver.sendCommand(mContext, 678 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 679 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 680 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 681 } finally { 682 uid1Watcher.finish(); 683 } 684 } 685 686 /** 687 * Test a FGS can start from a process that is at BOUND_TOP state. 688 * @throws Exception 689 */ 690 @Test testFgsStartFromBoundTopState()691 public void testFgsStartFromBoundTopState() throws Exception { 692 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 693 PACKAGE_NAME_APP1, 0); 694 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 695 PACKAGE_NAME_APP2, 0); 696 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 697 PACKAGE_NAME_APP3, 0); 698 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 699 WAITFOR_MSEC); 700 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 701 WAITFOR_MSEC); 702 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 703 WAITFOR_MSEC); 704 try { 705 // Enable the FGS background startForeground() restriction. 706 enableFgsRestriction(true, true, null); 707 708 // Put APP1 in TOP state. 709 allowBgActivityStart(PACKAGE_NAME_APP1, true); 710 CommandReceiver.sendCommand(mContext, 711 CommandReceiver.COMMAND_START_ACTIVITY, 712 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 713 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 714 715 // APP1 bound to service in APP2, APP2 get BOUND_TOP state. 716 CommandReceiver.sendCommand(mContext, 717 CommandReceiver.COMMAND_BIND_SERVICE, 718 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 719 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP); 720 721 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 722 waiter.prepare(ACTION_START_FGS_RESULT); 723 // APP2 can start FGS in APP3. 724 CommandReceiver.sendCommand(mContext, 725 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 726 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 727 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 728 waiter.doWait(WAITFOR_MSEC); 729 730 // Stop activity. 731 CommandReceiver.sendCommand(mContext, 732 CommandReceiver.COMMAND_STOP_ACTIVITY, 733 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 734 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 735 // unbind service. 736 CommandReceiver.sendCommand(mContext, 737 CommandReceiver.COMMAND_UNBIND_SERVICE, 738 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 739 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 740 // Stop the FGS. 741 CommandReceiver.sendCommand(mContext, 742 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 743 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 744 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 745 } finally { 746 uid1Watcher.finish(); 747 uid2Watcher.finish(); 748 uid3Watcher.finish(); 749 } 750 } 751 752 /** 753 * Test a FGS can start from a process that is at FOREGROUND_SERVICE state. 754 * @throws Exception 755 */ 756 @Test testFgsStartFromFgsState()757 public void testFgsStartFromFgsState() throws Exception { 758 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 759 PACKAGE_NAME_APP1, 0); 760 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 761 PACKAGE_NAME_APP2, 0); 762 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 763 PACKAGE_NAME_APP3, 0); 764 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 765 WAITFOR_MSEC); 766 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 767 WAITFOR_MSEC); 768 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 769 WAITFOR_MSEC); 770 try { 771 // Enable the FGS background startForeground() restriction. 772 enableFgsRestriction(true, true, null); 773 774 // Put APP1 in TOP state. 775 allowBgActivityStart(PACKAGE_NAME_APP1, true); 776 CommandReceiver.sendCommand(mContext, 777 CommandReceiver.COMMAND_START_ACTIVITY, 778 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 779 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 780 781 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 782 waiter.prepare(ACTION_START_FGS_RESULT); 783 // APP1 can start FGS in APP2, APP2 gets FOREGROUND_SERVICE state. 784 CommandReceiver.sendCommand(mContext, 785 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 786 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 787 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 788 waiter.doWait(WAITFOR_MSEC); 789 790 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 791 waiter.prepare(ACTION_START_FGS_RESULT); 792 // APP2 can start FGS in APP3. 793 CommandReceiver.sendCommand(mContext, 794 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 795 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 796 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 797 waiter.doWait(WAITFOR_MSEC); 798 799 // Stop activity in APP1. 800 CommandReceiver.sendCommand(mContext, 801 CommandReceiver.COMMAND_STOP_ACTIVITY, 802 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 803 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 804 // Stop FGS in APP2. 805 CommandReceiver.sendCommand(mContext, 806 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 807 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 808 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 809 // Stop FGS in APP3. 810 CommandReceiver.sendCommand(mContext, 811 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 812 PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null); 813 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 814 } finally { 815 uid1Watcher.finish(); 816 uid2Watcher.finish(); 817 uid3Watcher.finish(); 818 } 819 } 820 821 /** 822 * When the service is started by bindService() command, test when BG-FGS-launch 823 * restriction is disabled, FGS can start from background. 824 * @throws Exception 825 */ 826 @Test testFgsStartFromBGWithBind()827 public void testFgsStartFromBGWithBind() throws Exception { 828 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 829 PACKAGE_NAME_APP1, 0); 830 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 831 WAITFOR_MSEC); 832 833 try { 834 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 835 waiter.prepare(ACTION_START_FGSL_RESULT); 836 // APP1 is in BG state, bind FGSL in APP1 first. 837 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE, 838 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 839 // Then start FGSL in APP1 840 enableFgsRestriction(false, true, null); 841 CommandReceiver.sendCommand(mContext, 842 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION, 843 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 844 // APP1 is in FGS state 845 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 846 waiter.doWait(WAITFOR_MSEC); 847 848 // stop FGS 849 CommandReceiver.sendCommand(mContext, 850 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION, 851 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 852 // unbind service. 853 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 854 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 855 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 856 } finally { 857 uid1Watcher.finish(); 858 } 859 } 860 861 /** 862 * When the service is started by bindService() command, test when BG-FGS-launch 863 * restriction is enabled, FGS can NOT start from background. 864 * @throws Exception 865 */ 866 @Test testFgsStartFromBGWithBindWithRestriction()867 public void testFgsStartFromBGWithBindWithRestriction() throws Exception { 868 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 869 PACKAGE_NAME_APP1, 0); 870 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 871 WAITFOR_MSEC); 872 873 try { 874 enableFgsRestriction(true, true, null); 875 // APP1 is in BG state, bind FGSL in APP1 first. 876 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE, 877 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 878 // Then start FGS in APP1 879 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 880 waiter.prepare(ACTION_START_FGS_RESULT); 881 CommandReceiver.sendCommand(mContext, 882 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 883 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 884 // APP1 does not enter FGS state 885 try { 886 waiter.doWait(WAITFOR_MSEC); 887 fail("Service should not enter foreground service state"); 888 } catch (Exception e) { 889 } 890 891 // stop FGS 892 CommandReceiver.sendCommand(mContext, 893 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 894 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 895 // unbind service. 896 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE, 897 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 898 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 899 } finally { 900 uid1Watcher.finish(); 901 } 902 } 903 904 /** 905 * Test BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag. 906 * Shell has START_ACTIVITIES_FROM_BACKGROUND permission, it can use this bind flag to 907 * pass BG-Activity-launch ability to APP2, then APP2 can start APP2 FGS from background. 908 */ 909 @Test testFgsBindingFlagActivity()910 public void testFgsBindingFlagActivity() throws Exception { 911 testFgsBindingFlag(Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS); 912 } 913 914 /** 915 * Test BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND flag. 916 * Shell has START_FOREGROUND_SERVICES_FROM_BACKGROUND permission, it can use this bind flag to 917 * pass BG-FGS-launch ability to APP2, then APP2 can start APP3 FGS from background. 918 */ 919 @Test testFgsBindingFlagFGS()920 public void testFgsBindingFlagFGS() throws Exception { 921 testFgsBindingFlag(Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND); 922 } 923 924 /** 925 * Test no binding flag. 926 * Shell has START_FOREGROUND_SERVICES_FROM_BACKGROUND permission, without any bind flag, 927 * the BG-FGS-launch ability can be passed to APP2 by service binding, then APP2 can start 928 * APP3 FGS from background. 929 */ 930 @Test testFgsBindingFlagNone()931 public void testFgsBindingFlagNone() throws Exception { 932 testFgsBindingFlag(0); 933 } 934 testFgsBindingFlag(int bindingFlag)935 private void testFgsBindingFlag(int bindingFlag) throws Exception { 936 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 937 PACKAGE_NAME_APP1, 0); 938 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 939 PACKAGE_NAME_APP2, 0); 940 ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo( 941 PACKAGE_NAME_APP3, 0); 942 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 943 WAITFOR_MSEC); 944 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 945 WAITFOR_MSEC); 946 WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid, 947 WAITFOR_MSEC); 948 try { 949 // Enable the FGS background startForeground() restriction. 950 enableFgsRestriction(true, true, null); 951 952 // testapp is in background. 953 // testapp binds to service in APP2, APP2 still in background state. 954 final Intent intent = new Intent().setClassName( 955 PACKAGE_NAME_APP2, "android.app.stubs.LocalService"); 956 957 /* 958 final ServiceConnection connection = new ServiceConnection() { 959 @Override 960 public void onServiceConnected(ComponentName name, IBinder service) { 961 } 962 @Override 963 public void onServiceDisconnected(ComponentName name) { 964 } 965 }; 966 runWithShellPermissionIdentity(() -> { 967 mTargetContext.bindService(intent, connection, 968 Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY); 969 }); 970 971 // APP2 can not start FGS in APP3. 972 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 973 waiter.prepare(ACTION_START_FGS_RESULT); 974 CommandReceiver.sendCommand(mContext, 975 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 976 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 977 try { 978 waiter.doWait(WAITFOR_MSEC); 979 fail("Service should not enter foreground service state"); 980 } catch (Exception e) { 981 } 982 983 // testapp unbind service in APP2. 984 runWithShellPermissionIdentity(() -> mTargetContext.unbindService(connection)); 985 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 986 */ 987 988 // testapp is in background. 989 // testapp binds to service in APP2 using the binding flag. 990 // APP2 still in background state. 991 final ServiceConnection connection2 = new ServiceConnection() { 992 @Override 993 public void onServiceConnected(ComponentName name, IBinder service) { 994 } 995 @Override 996 public void onServiceDisconnected(ComponentName name) { 997 } 998 }; 999 runWithShellPermissionIdentity(() -> mTargetContext.bindService(intent, connection2, 1000 Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY 1001 | bindingFlag)); 1002 1003 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1004 waiter.prepare(ACTION_START_FGS_RESULT); 1005 // Because the binding flag, 1006 // APP2 can start FGS from background. 1007 CommandReceiver.sendCommand(mContext, 1008 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1009 PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null); 1010 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1011 waiter.doWait(WAITFOR_MSEC); 1012 1013 // testapp unbind service in APP2. 1014 runWithShellPermissionIdentity(() -> mTargetContext.unbindService(connection2)); 1015 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1016 // Stop the FGS in APP3. 1017 CommandReceiver.sendCommand(mContext, 1018 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1019 PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null); 1020 uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1021 } finally { 1022 uid1Watcher.finish(); 1023 uid2Watcher.finish(); 1024 uid3Watcher.finish(); 1025 } 1026 } 1027 1028 /** 1029 * Test a FGS can start from BG if the app has SYSTEM_ALERT_WINDOW permission. 1030 */ 1031 @Test testFgsStartSystemAlertWindow()1032 public void testFgsStartSystemAlertWindow() throws Exception { 1033 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1034 PACKAGE_NAME_APP1, 0); 1035 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1036 WAITFOR_MSEC); 1037 try { 1038 // Enable the FGS background startForeground() restriction. 1039 enableFgsRestriction(true, true, null); 1040 // Start FGS in BG state. 1041 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1042 waiter.prepare(ACTION_START_FGS_RESULT); 1043 CommandReceiver.sendCommand(mContext, 1044 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1045 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1046 // APP1 does not enter FGS state 1047 try { 1048 waiter.doWait(WAITFOR_MSEC); 1049 fail("Service should not enter foreground service state"); 1050 } catch (Exception e) { 1051 } 1052 1053 PermissionUtils.grantPermission( 1054 PACKAGE_NAME_APP1, android.Manifest.permission.SYSTEM_ALERT_WINDOW); 1055 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1056 waiter.prepare(ACTION_START_FGS_RESULT); 1057 // Now it can start FGS. 1058 CommandReceiver.sendCommand(mContext, 1059 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1060 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1061 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1062 waiter.doWait(WAITFOR_MSEC); 1063 // Stop the FGS. 1064 CommandReceiver.sendCommand(mContext, 1065 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1066 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1067 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1068 } finally { 1069 uid1Watcher.finish(); 1070 } 1071 } 1072 1073 /** 1074 * Test a FGS can start from BG if the device is in retail demo mode. 1075 */ 1076 @Test 1077 // Change Settings.Global.DEVICE_DEMO_MODE on device may trigger other listener and put 1078 // the device in undesired state, for example, the battery charge level is set to 35% 1079 // permanently, ignore this test for now. 1080 @Ignore testFgsStartRetailDemoMode()1081 public void testFgsStartRetailDemoMode() throws Exception { 1082 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1083 PACKAGE_NAME_APP1, 0); 1084 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1085 WAITFOR_MSEC); 1086 runWithShellPermissionIdentity(()-> { 1087 mOrigDeviceDemoMode = Settings.Global.getInt(mContext.getContentResolver(), 1088 Settings.Global.DEVICE_DEMO_MODE, 0); }); 1089 1090 try { 1091 // Enable the FGS background startForeground() restriction. 1092 enableFgsRestriction(true, true, null); 1093 // Start FGS in BG state. 1094 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1095 waiter.prepare(ACTION_START_FGS_RESULT); 1096 CommandReceiver.sendCommand(mContext, 1097 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1098 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1099 // APP1 does not enter FGS state 1100 try { 1101 waiter.doWait(WAITFOR_MSEC); 1102 fail("Service should not enter foreground service state"); 1103 } catch (Exception e) { 1104 } 1105 1106 runWithShellPermissionIdentity(()-> { 1107 Settings.Global.putInt(mContext.getContentResolver(), 1108 Settings.Global.DEVICE_DEMO_MODE, 1); }); 1109 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1110 waiter.prepare(ACTION_START_FGS_RESULT); 1111 // Now it can start FGS. 1112 CommandReceiver.sendCommand(mContext, 1113 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1114 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1115 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1116 waiter.doWait(WAITFOR_MSEC); 1117 // Stop the FGS. 1118 CommandReceiver.sendCommand(mContext, 1119 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1120 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1121 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1122 } finally { 1123 uid1Watcher.finish(); 1124 runWithShellPermissionIdentity(()-> { 1125 Settings.Global.putInt(mContext.getContentResolver(), 1126 Settings.Global.DEVICE_DEMO_MODE, mOrigDeviceDemoMode); }); 1127 } 1128 } 1129 1130 // At Context.startForegroundService() or Service.startForeground() calls, if the FGS is 1131 // restricted by background restriction and the app's targetSdkVersion is at least S, the 1132 // framework throws a ForegroundServiceStartNotAllowedException with error message. 1133 @Test 1134 @Ignore("The instrumentation is allowed to star FGS, it does not throw the exception") testFgsStartFromBGException()1135 public void testFgsStartFromBGException() throws Exception { 1136 ForegroundServiceStartNotAllowedException expectedException = null; 1137 final Intent intent = new Intent().setClassName( 1138 PACKAGE_NAME_APP1, "android.app.stubs.LocalForegroundService"); 1139 try { 1140 allowBgActivityStart("android.app.stubs", false); 1141 enableFgsRestriction(true, true, null); 1142 mContext.startForegroundService(intent); 1143 } catch (ForegroundServiceStartNotAllowedException e) { 1144 expectedException = e; 1145 } finally { 1146 mContext.stopService(intent); 1147 allowBgActivityStart("android.app.stubs", true); 1148 } 1149 String expectedMessage = "mAllowStartForeground false"; 1150 assertNotNull(expectedException); 1151 assertTrue(expectedException.getMessage().contains(expectedMessage)); 1152 } 1153 1154 /** 1155 * Test a FGS can start from BG if the app is in the DeviceIdleController's AllowList. 1156 */ 1157 @Test testFgsStartAllowList()1158 public void testFgsStartAllowList() throws Exception { 1159 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1160 PACKAGE_NAME_APP1, 0); 1161 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1162 WAITFOR_MSEC); 1163 try { 1164 // Enable the FGS background startForeground() restriction. 1165 enableFgsRestriction(true, true, null); 1166 // Start FGS in BG state. 1167 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1168 waiter.prepare(ACTION_START_FGS_RESULT); 1169 CommandReceiver.sendCommand(mContext, 1170 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1171 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1172 // APP1 does not enter FGS state 1173 try { 1174 waiter.doWait(WAITFOR_MSEC); 1175 fail("Service should not enter foreground service state"); 1176 } catch (Exception e) { 1177 } 1178 1179 // Add package to AllowList. 1180 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1181 "dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1); 1182 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1183 waiter.prepare(ACTION_START_FGS_RESULT); 1184 // Now it can start FGS. 1185 CommandReceiver.sendCommand(mContext, 1186 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1187 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1188 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1189 waiter.doWait(WAITFOR_MSEC); 1190 // Stop the FGS. 1191 CommandReceiver.sendCommand(mContext, 1192 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1193 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1194 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1195 } finally { 1196 uid1Watcher.finish(); 1197 // Remove package from AllowList. 1198 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1199 "dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1); 1200 } 1201 } 1202 1203 /** 1204 * Test temp allowlist types in BroadcastOptions. 1205 */ 1206 @Test testTempAllowListType()1207 public void testTempAllowListType() throws Exception { 1208 testTempAllowListTypeInternal(TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED); 1209 testTempAllowListTypeInternal(TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED); 1210 } 1211 testTempAllowListTypeInternal(int type)1212 private void testTempAllowListTypeInternal(int type) throws Exception { 1213 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1214 PACKAGE_NAME_APP1, 0); 1215 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1216 PACKAGE_NAME_APP2, 0); 1217 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1218 WAITFOR_MSEC); 1219 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1220 WAITFOR_MSEC); 1221 try { 1222 // Enable the FGS background startForeground() restriction. 1223 enableFgsRestriction(true, true, null); 1224 // Start FGS in BG state. 1225 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1226 waiter.prepare(ACTION_START_FGS_RESULT); 1227 CommandReceiver.sendCommand(mContext, 1228 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1229 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1230 // APP1 does not enter FGS state 1231 try { 1232 waiter.doWait(WAITFOR_MSEC); 1233 fail("Service should not enter foreground service state"); 1234 } catch (Exception e) { 1235 } 1236 1237 // Now it can start FGS. 1238 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1239 waiter.prepare(ACTION_START_FGS_RESULT); 1240 runWithShellPermissionIdentity(()-> { 1241 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1242 // setTemporaryAppAllowlist API requires 1243 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission. 1244 options.setTemporaryAppAllowlist(TEMP_ALLOWLIST_DURATION_MS, type, REASON_UNKNOWN, 1245 ""); 1246 // Must use Shell to issue this command because Shell has 1247 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission. 1248 CommandReceiver.sendCommandWithBroadcastOptions(mContext, 1249 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1250 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null, 1251 options.toBundle()); 1252 }); 1253 if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { 1254 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1255 waiter.doWait(WAITFOR_MSEC); 1256 // Stop the FGS. 1257 CommandReceiver.sendCommand(mContext, 1258 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1259 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1260 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1261 WatchUidRunner.STATE_CACHED_EMPTY); 1262 } else if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED) { 1263 // APP1 does not enter FGS state 1264 try { 1265 waiter.doWait(WAITFOR_MSEC); 1266 fail("Service should not enter foreground service state"); 1267 } catch (Exception e) { 1268 } 1269 } 1270 } finally { 1271 uid1Watcher.finish(); 1272 uid2Watcher.finish(); 1273 // Sleep 10 seconds to let the temp allowlist expire so it won't affect next test case. 1274 SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS); 1275 } 1276 1277 } 1278 1279 /** 1280 * Test a FGS can start from BG if the process had a visible activity recently. 1281 */ 1282 @LargeTest 1283 @Test testVisibleActivityGracePeriod()1284 public void testVisibleActivityGracePeriod() throws Exception { 1285 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1286 PACKAGE_NAME_APP2, 0); 1287 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1288 WAITFOR_MSEC); 1289 final String namespaceActivityManager = "activity_manager"; 1290 final String keyFgToBgFgsGraceDuration = "fg_to_bg_fgs_grace_duration"; 1291 final long[] curFgToBgFgsGraceDuration = {-1}; 1292 try { 1293 // Enable the FGS background startForeground() restriction. 1294 enableFgsRestriction(true, true, null); 1295 // Allow bg actvity start from APP1. 1296 allowBgActivityStart(PACKAGE_NAME_APP1, true); 1297 1298 SystemUtil.runWithShellPermissionIdentity(() -> { 1299 curFgToBgFgsGraceDuration[0] = DeviceConfig.getInt( 1300 namespaceActivityManager, 1301 keyFgToBgFgsGraceDuration, -1); 1302 DeviceConfig.setProperty(namespaceActivityManager, 1303 keyFgToBgFgsGraceDuration, 1304 Long.toString(WAITFOR_MSEC), false); 1305 }); 1306 1307 testVisibleActivityGracePeriodInternal(uid2Watcher, "KEYCODE_HOME"); 1308 testVisibleActivityGracePeriodInternal(uid2Watcher, "KEYCODE_BACK"); 1309 } finally { 1310 uid2Watcher.finish(); 1311 // Remove package from AllowList. 1312 allowBgActivityStart(PACKAGE_NAME_APP1, false); 1313 if (curFgToBgFgsGraceDuration[0] >= 0) { 1314 SystemUtil.runWithShellPermissionIdentity(() -> { 1315 DeviceConfig.setProperty(namespaceActivityManager, 1316 keyFgToBgFgsGraceDuration, 1317 Long.toString(curFgToBgFgsGraceDuration[0]), false); 1318 }); 1319 } else { 1320 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1321 "device_config delete " + namespaceActivityManager 1322 + " " + keyFgToBgFgsGraceDuration); 1323 } 1324 } 1325 } 1326 testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode)1327 private void testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode) 1328 throws Exception { 1329 testVisibleActivityGracePeriodInternal(uidWatcher, keyCode, null, 1330 () -> uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1331 WatchUidRunner.STATE_FG_SERVICE), true); 1332 1333 testVisibleActivityGracePeriodInternal(uidWatcher, keyCode, 1334 () -> SystemClock.sleep(WAITFOR_MSEC + 2000), // Wait for the grace period to expire 1335 () -> { 1336 try { 1337 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1338 WatchUidRunner.STATE_FG_SERVICE); 1339 fail("Service should not enter foreground service state"); 1340 } catch (Exception e) { 1341 // Expected. 1342 } 1343 }, false); 1344 } 1345 testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode, Runnable prep, Runnable verifier, boolean stopFgs)1346 private void testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, 1347 String keyCode, Runnable prep, Runnable verifier, boolean stopFgs) throws Exception { 1348 // Put APP2 in TOP state. 1349 CommandReceiver.sendCommand(mContext, 1350 CommandReceiver.COMMAND_START_ACTIVITY, 1351 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1352 uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1353 1354 // Take a nap to wait for the UI to settle down. 1355 SystemClock.sleep(2000); 1356 1357 // Now inject key event. 1358 CtsAppTestUtils.executeShellCmd(mInstrumentation, "input keyevent " + keyCode); 1359 1360 // It should go to the cached state. 1361 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1362 1363 if (prep != null) { 1364 prep.run(); 1365 } 1366 1367 // Start FGS from APP2. 1368 CommandReceiver.sendCommand(mContext, 1369 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1370 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 1371 1372 if (verifier != null) { 1373 verifier.run(); 1374 } 1375 1376 if (stopFgs) { 1377 // Stop the FGS. 1378 CommandReceiver.sendCommand(mContext, 1379 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1380 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 1381 uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null); 1382 } 1383 } 1384 1385 /** 1386 * After background service is started, after 10 seconds timeout, the startForeground() can 1387 * succeed or not depends on the service's app proc state. 1388 * Test starService() -> startForeground() 1389 */ 1390 @Test testStartForegroundTimeout()1391 public void testStartForegroundTimeout() throws Exception { 1392 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1393 PACKAGE_NAME_APP1, 0); 1394 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1395 WAITFOR_MSEC); 1396 try { 1397 // Enable the FGS background startForeground() restriction. 1398 enableFgsRestriction(true, true, null); 1399 setFgsStartForegroundTimeout(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS); 1400 1401 // Put app to a TOP proc state. 1402 allowBgActivityStart(PACKAGE_NAME_APP1, true); 1403 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY, 1404 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1405 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP); 1406 allowBgActivityStart(PACKAGE_NAME_APP1, false); 1407 1408 // start background service. 1409 Bundle extras = LocalForegroundService.newCommand( 1410 LocalForegroundService.COMMAND_START_NO_FOREGROUND); 1411 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1412 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras); 1413 1414 // stop the activity. 1415 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY, 1416 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1417 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE); 1418 1419 // Sleep after the timeout DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS 1420 SystemClock.sleep(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS + 1000); 1421 1422 extras = LocalForegroundService.newCommand( 1423 LocalForegroundService.COMMAND_START_FOREGROUND); 1424 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1425 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras); 1426 // APP1 does not enter FGS state 1427 // startForeground() is called after 10 seconds FgsStartForegroundTimeout. 1428 try { 1429 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1430 fail("Service should not enter foreground service state"); 1431 } catch (Exception e) { 1432 } 1433 1434 // Put app to a TOP proc state. 1435 allowBgActivityStart(PACKAGE_NAME_APP1, true); 1436 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY, 1437 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1438 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1439 WatchUidRunner.STATE_TOP, new Integer(PROCESS_CAPABILITY_ALL)); 1440 allowBgActivityStart(PACKAGE_NAME_APP1, false); 1441 1442 // Call startForeground(). 1443 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1444 waiter.prepare(ACTION_START_FGS_RESULT); 1445 extras = LocalForegroundService.newCommand( 1446 LocalForegroundService.COMMAND_START_FOREGROUND); 1447 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1448 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras); 1449 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY, 1450 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1451 1452 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1453 waiter.doWait(WAITFOR_MSEC); 1454 1455 // Stop the FGS. 1456 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_SERVICE, 1457 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1458 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, 1459 new Integer(PROCESS_CAPABILITY_NONE)); 1460 } finally { 1461 uid1Watcher.finish(); 1462 setFgsStartForegroundTimeout(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS); 1463 } 1464 } 1465 1466 /** 1467 * After startForeground() and stopForeground(), the second startForeground() can succeed or not 1468 * depends on the service's app proc state. 1469 * Test startForegroundService() -> startForeground() -> stopForeground() -> startForeground() 1470 * -> startForeground(). 1471 */ 1472 @Test testSecondStartForeground()1473 public void testSecondStartForeground() throws Exception { 1474 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1475 PACKAGE_NAME_APP1, 0); 1476 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1477 WAITFOR_MSEC); 1478 try { 1479 // Enable the FGS background startForeground() restriction. 1480 enableFgsRestriction(true, true, null); 1481 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1482 waiter.prepare(ACTION_START_FGS_RESULT); 1483 // Bypass bg-service-start restriction. 1484 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1485 "dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1); 1486 // Start foreground service from APP1, the service can enter FGS. 1487 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1488 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1489 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1490 waiter.doWait(WAITFOR_MSEC); 1491 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1492 "dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1); 1493 1494 // stopForeground(), the service exits FGS, become a background service. 1495 Bundle extras = LocalForegroundService.newCommand( 1496 LocalForegroundService.COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION); 1497 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1498 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras); 1499 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE, 1500 new Integer(PROCESS_CAPABILITY_NONE)); 1501 1502 // APP2 is in the background, from APP2, call startForeground(). 1503 // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called, 1504 // because APP2 is in the background, mAllowStartForeground is set to false. 1505 // When Service.startForeground() is called, setFgsRestrictionLocked() is called again, 1506 // APP1's proc state is in the background and mAllowStartForeground is set to false. 1507 extras = LocalForegroundService.newCommand( 1508 LocalForegroundService.COMMAND_START_FOREGROUND); 1509 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1510 PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras); 1511 try { 1512 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1513 fail("Service should not enter foreground service state"); 1514 } catch (Exception e) { 1515 } 1516 1517 // Put APP1 to a TOP proc state. 1518 allowBgActivityStart(PACKAGE_NAME_APP1, true); 1519 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY, 1520 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1521 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, 1522 new Integer(PROCESS_CAPABILITY_ALL)); 1523 allowBgActivityStart(PACKAGE_NAME_APP1, false); 1524 1525 // APP2 is in the background, from APP2, call startForeground() second time. 1526 // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called, 1527 // because APP2 is in the background, mAllowStartForeground is set to false. 1528 // When Service.startForeground() is called, setFgsRestrictionLocked() is called again, 1529 // because APP1's proc state is in the foreground and mAllowStartForeground is set to 1530 // true. 1531 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1532 waiter.prepare(ACTION_START_FGS_RESULT); 1533 extras = LocalForegroundService.newCommand( 1534 LocalForegroundService.COMMAND_START_FOREGROUND); 1535 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE, 1536 PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras); 1537 waiter.doWait(WAITFOR_MSEC); 1538 // Stop app1's activity. 1539 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY, 1540 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1541 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE, 1542 LOCAL_SERVICE_PROCESS_CAPABILITY); 1543 1544 // Stop the FGS. 1545 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1546 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1547 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, 1548 new Integer(PROCESS_CAPABILITY_NONE)); 1549 } finally { 1550 uid1Watcher.finish(); 1551 } 1552 } 1553 1554 /** 1555 * Test OP_ACTIVATE_VPN and OP_ACTIVATE_PLATFORM_VPN are exempted from BG-FGS-launch 1556 * restriction. 1557 * @throws Exception 1558 */ 1559 @Test testFgsStartVpn()1560 public void testFgsStartVpn() throws Exception { 1561 testFgsStartVpnInternal("ACTIVATE_VPN"); 1562 testFgsStartVpnInternal("ACTIVATE_PLATFORM_VPN"); 1563 } 1564 testFgsStartVpnInternal(String vpnAppOp)1565 private void testFgsStartVpnInternal(String vpnAppOp) throws Exception { 1566 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1567 PACKAGE_NAME_APP1, 0); 1568 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1569 WAITFOR_MSEC); 1570 try { 1571 // Enable the FGS background startForeground() restriction. 1572 enableFgsRestriction(true, true, null); 1573 // Start FGS in BG state. 1574 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1575 waiter.prepare(ACTION_START_FGS_RESULT); 1576 CommandReceiver.sendCommand(mContext, 1577 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1578 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1579 // APP1 does not enter FGS state 1580 try { 1581 waiter.doWait(WAITFOR_MSEC); 1582 fail("Service should not enter foreground service state"); 1583 } catch (Exception e) { 1584 } 1585 1586 setAppOp(PACKAGE_NAME_APP1, vpnAppOp, true); 1587 1588 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1589 waiter.prepare(ACTION_START_FGS_RESULT); 1590 // Now it can start FGS. 1591 CommandReceiver.sendCommand(mContext, 1592 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1593 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1594 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1595 waiter.doWait(WAITFOR_MSEC); 1596 // Stop the FGS. 1597 CommandReceiver.sendCommand(mContext, 1598 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1599 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1600 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1601 } finally { 1602 uid1Watcher.finish(); 1603 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1604 "appops reset " + PACKAGE_NAME_APP1); 1605 } 1606 } 1607 1608 /** 1609 * The default behavior for temp allowlist reasonCode REASON_PUSH_MESSAGING_OVER_QUOTA 1610 * is TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED (not allowed to start FGS). But 1611 * the behavior can be changed by device config command. There are three possible values: 1612 * {@link TEMPORARY_ALLOW_LIST_TYPE_NONE} (-1): 1613 * not temp allowlisted. 1614 * {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} (0): 1615 * temp allowlisted and allow FGS. 1616 * {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} (1): 1617 * temp allowlisted, not allow FGS. 1618 * @throws Exception 1619 */ 1620 @Test testPushMessagingOverQuota()1621 public void testPushMessagingOverQuota() throws Exception { 1622 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1623 PACKAGE_NAME_APP1, 0); 1624 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1625 WAITFOR_MSEC); 1626 final int defaultBehavior = getPushMessagingOverQuotaBehavior(); 1627 try { 1628 // Enable the FGS background startForeground() restriction. 1629 enableFgsRestriction(true, true, null); 1630 // Default behavior is TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED. 1631 setPushMessagingOverQuotaBehavior( 1632 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED); 1633 // Start FGS in BG state. 1634 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1635 waiter.prepare(ACTION_START_FGS_RESULT); 1636 CommandReceiver.sendCommand(mContext, 1637 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1638 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1639 // APP1 does not enter FGS state 1640 try { 1641 waiter.doWait(WAITFOR_MSEC); 1642 fail("Service should not enter foreground service state"); 1643 } catch (Exception e) { 1644 } 1645 1646 setPushMessagingOverQuotaBehavior(TEMPORARY_ALLOW_LIST_TYPE_NONE); 1647 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1648 waiter.prepare(ACTION_START_FGS_RESULT); 1649 runWithShellPermissionIdentity(() -> { 1650 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList( 1651 PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA, 1652 "", TEMP_ALLOWLIST_DURATION_MS); 1653 }); 1654 CommandReceiver.sendCommand(mContext, 1655 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1656 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1657 // APP1 does not enter FGS state 1658 try { 1659 waiter.doWait(WAITFOR_MSEC); 1660 fail("Service should not enter foreground service state"); 1661 } catch (Exception e) { 1662 } 1663 1664 // Change behavior to TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED. 1665 setPushMessagingOverQuotaBehavior( 1666 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED); 1667 runWithShellPermissionIdentity(() -> { 1668 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList( 1669 PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA, 1670 "", TEMP_ALLOWLIST_DURATION_MS); 1671 }); 1672 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1673 waiter.prepare(ACTION_START_FGS_RESULT); 1674 // Now it can start FGS. 1675 CommandReceiver.sendCommand(mContext, 1676 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1677 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1678 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1679 waiter.doWait(WAITFOR_MSEC); 1680 // Stop the FGS. 1681 CommandReceiver.sendCommand(mContext, 1682 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1683 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1684 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1685 } finally { 1686 uid1Watcher.finish(); 1687 // Change back to default behavior. 1688 setPushMessagingOverQuotaBehavior(defaultBehavior); 1689 // allow temp allowlist to expire. 1690 SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS); 1691 } 1692 } 1693 1694 /** 1695 * Test temp allowlist reasonCode in BroadcastOptions. 1696 * When REASON_PUSH_MESSAGING_OVER_QUOTA, DeviceIdleController changes temp allowlist type to 1697 * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED so FGS start is not allowed. 1698 * When REASON_DENIED (-1), DeviceIdleController changes temp allowlist type to 1699 * TEMPORARY_ALLOWLIST_TYPE_NONE, the temp allowlist itself is not allowed. 1700 * All other reason codes, DeviceIdleController does not change temp allowlist type. 1701 */ 1702 @Test testTempAllowListReasonCode()1703 public void testTempAllowListReasonCode() throws Exception { 1704 // FGS start is temp allowed. 1705 testTempAllowListReasonCodeInternal(REASON_PUSH_MESSAGING); 1706 // FGS start is not allowed. 1707 testTempAllowListReasonCodeInternal(REASON_PUSH_MESSAGING_OVER_QUOTA); 1708 // Temp allowlist itself is not allowed. REASON_DENIED is not exposed in 1709 // PowerExemptionManager, just use its value "-1" here. 1710 testTempAllowListReasonCodeInternal(-1); 1711 } 1712 testTempAllowListReasonCodeInternal(int reasonCode)1713 private void testTempAllowListReasonCodeInternal(int reasonCode) throws Exception { 1714 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1715 PACKAGE_NAME_APP1, 0); 1716 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1717 PACKAGE_NAME_APP2, 0); 1718 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1719 WAITFOR_MSEC); 1720 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1721 WAITFOR_MSEC); 1722 final int defaultBehavior = getPushMessagingOverQuotaBehavior(); 1723 try { 1724 setPushMessagingOverQuotaBehavior( 1725 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED); 1726 // Enable the FGS background startForeground() restriction. 1727 enableFgsRestriction(true, true, null); 1728 // Now it can start FGS. 1729 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1730 waiter.prepare(ACTION_START_FGS_RESULT); 1731 runWithShellPermissionIdentity(()-> { 1732 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1733 // setTemporaryAppAllowlist API requires 1734 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission. 1735 options.setTemporaryAppAllowlist(TEMP_ALLOWLIST_DURATION_MS, 1736 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, reasonCode, 1737 ""); 1738 // Must use Shell to issue this command because Shell has 1739 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission. 1740 CommandReceiver.sendCommandWithBroadcastOptions(mContext, 1741 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1742 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null, 1743 options.toBundle()); 1744 }); 1745 if (reasonCode == REASON_PUSH_MESSAGING) { 1746 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1747 waiter.doWait(WAITFOR_MSEC); 1748 // Stop the FGS. 1749 CommandReceiver.sendCommand(mContext, 1750 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1751 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null); 1752 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1753 WatchUidRunner.STATE_CACHED_EMPTY); 1754 } else if (reasonCode == REASON_PUSH_MESSAGING_OVER_QUOTA) { 1755 // APP1 does not enter FGS state 1756 try { 1757 waiter.doWait(WAITFOR_MSEC); 1758 fail("Service should not enter foreground service state"); 1759 } catch (Exception e) { 1760 } 1761 } 1762 } finally { 1763 uid1Watcher.finish(); 1764 uid2Watcher.finish(); 1765 setPushMessagingOverQuotaBehavior(defaultBehavior); 1766 // Sleep to let the temp allowlist expire so it won't affect next test case. 1767 SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS); 1768 } 1769 } 1770 1771 /** 1772 * Test default_input_method is exempted from BG-FGS-start restriction. 1773 * @throws Exception 1774 */ 1775 @Test testFgsStartInputMethod()1776 public void testFgsStartInputMethod() throws Exception { 1777 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1778 PACKAGE_NAME_APP1, 0); 1779 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1780 WAITFOR_MSEC); 1781 final String defaultInputMethod = CtsAppTestUtils.executeShellCmd(mInstrumentation, 1782 "settings get --user current secure default_input_method"); 1783 try { 1784 // Enable the FGS background startForeground() restriction. 1785 enableFgsRestriction(true, true, null); 1786 // Start FGS in BG state. 1787 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1788 waiter.prepare(ACTION_START_FGS_RESULT); 1789 CommandReceiver.sendCommand(mContext, 1790 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1791 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1792 // APP1 does not enter FGS state 1793 try { 1794 waiter.doWait(WAITFOR_MSEC); 1795 fail("Service should not enter foreground service state"); 1796 } catch (Exception e) { 1797 } 1798 1799 // Change default_input_method to PACKAGE_NAME_APP1. 1800 final ComponentName cn = new ComponentName(PACKAGE_NAME_APP1, "xxx"); 1801 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1802 "settings put --user current secure default_input_method " 1803 + cn.flattenToShortString()); 1804 1805 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1806 waiter.prepare(ACTION_START_FGS_RESULT); 1807 // Now it can start FGS. 1808 CommandReceiver.sendCommand(mContext, 1809 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1810 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1811 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 1812 waiter.doWait(WAITFOR_MSEC); 1813 // Stop the FGS. 1814 CommandReceiver.sendCommand(mContext, 1815 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 1816 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1817 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 1818 } finally { 1819 uid1Watcher.finish(); 1820 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1821 "settings put --user current secure default_input_method " 1822 + defaultInputMethod); 1823 } 1824 } 1825 1826 @Test testFgsStartInBackgroundRestrictions()1827 public void testFgsStartInBackgroundRestrictions() throws Exception { 1828 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1829 PACKAGE_NAME_APP1, 0); 1830 ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo( 1831 PACKAGE_NAME_APP2, 0); 1832 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1833 WAITFOR_MSEC); 1834 WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid, 1835 WAITFOR_MSEC); 1836 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1837 final String dumpCommand = "dumpsys activity services " + PACKAGE_NAME_APP2 1838 + "/android.app.stubs.LocalForegroundService"; 1839 final long shortWaitMsec = 5_000; 1840 try { 1841 // Enable the FGS background startForeground() restriction. 1842 enableFgsRestriction(true, true, null); 1843 1844 // Set background restriction for APP2 1845 setAppOp(PACKAGE_NAME_APP2, "RUN_ANY_IN_BACKGROUND", false); 1846 1847 // Start the APP1 into the TOP state. 1848 allowBgActivityStart(PACKAGE_NAME_APP1, true); 1849 CommandReceiver.sendCommand(mContext, 1850 CommandReceiver.COMMAND_START_ACTIVITY, 1851 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1852 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1853 WatchUidRunner.STATE_TOP); 1854 1855 // APP1 binds to APP2. 1856 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE, 1857 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, Context.BIND_INCLUDE_CAPABILITIES, null); 1858 1859 // APP2 gets proc state BOUND_TOP. 1860 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1861 WatchUidRunner.STATE_BOUND_TOP); 1862 1863 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1864 waiter.prepare(ACTION_START_FGS_RESULT); 1865 1866 // START FGS in APP2. 1867 CommandReceiver.sendCommand(mContext, 1868 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1869 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 1870 waiter.doWait(WAITFOR_MSEC); 1871 1872 SystemClock.sleep(shortWaitMsec); 1873 1874 String[] dumpLines = CtsAppTestUtils.executeShellCmd( 1875 mInstrumentation, dumpCommand).split("\n"); 1876 assertNotNull(findLine(dumpLines, "isForeground=true")); 1877 1878 // Finish the activity in APP1 1879 CommandReceiver.sendCommand(mContext, 1880 CommandReceiver.COMMAND_STOP_ACTIVITY, 1881 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1882 mInstrumentation.getUiAutomation().performGlobalAction( 1883 AccessibilityService.GLOBAL_ACTION_HOME); 1884 1885 // APP1 should have been cached state now. 1886 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1887 WatchUidRunner.STATE_CACHED_EMPTY); 1888 1889 // Th FGS in APP2 should have been normal service state now. 1890 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1891 WatchUidRunner.STATE_SERVICE); 1892 1893 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1894 waiter.prepare(ACTION_START_FGS_RESULT); 1895 1896 // START FGS in APP1 1897 CommandReceiver.sendCommand(mContext, 1898 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1899 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1900 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1901 WatchUidRunner.STATE_FG_SERVICE); 1902 waiter.doWait(WAITFOR_MSEC); 1903 1904 // APP2 should be in FGS state too now. 1905 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1906 WatchUidRunner.STATE_FG_SERVICE); 1907 1908 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1909 waiter.prepare(ACTION_START_FGS_RESULT); 1910 1911 // START FGS in APP2. 1912 CommandReceiver.sendCommand(mContext, 1913 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1914 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null); 1915 waiter.doWait(WAITFOR_MSEC); 1916 1917 SystemClock.sleep(shortWaitMsec); 1918 1919 dumpLines = CtsAppTestUtils.executeShellCmd( 1920 mInstrumentation, dumpCommand).split("\n"); 1921 assertNotNull(findLine(dumpLines, "isForeground=true")); 1922 1923 // Set background restriction for APP1. 1924 setAppOp(PACKAGE_NAME_APP1, "RUN_ANY_IN_BACKGROUND", false); 1925 1926 // Both of them should have normal service state now. 1927 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1928 WatchUidRunner.STATE_SERVICE); 1929 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, 1930 WatchUidRunner.STATE_SERVICE); 1931 } finally { 1932 uid1Watcher.finish(); 1933 uid2Watcher.finish(); 1934 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1935 "appops reset " + PACKAGE_NAME_APP1); 1936 CtsAppTestUtils.executeShellCmd(mInstrumentation, 1937 "appops reset " + PACKAGE_NAME_APP2); 1938 } 1939 } 1940 1941 /** 1942 * Find a line containing {@code label} in {@code lines}. 1943 */ findLine(String[] lines, CharSequence label)1944 private String findLine(String[] lines, CharSequence label) { 1945 for (String line: lines) { 1946 if (line.contains(label)) { 1947 return line; 1948 } 1949 } 1950 return null; 1951 } 1952 1953 /** 1954 * When PowerExemptionManager.addToTemporaryAllowList() is called more than one time, the second 1955 * call can extend the duration of the first call if the first call has not expired yet. 1956 * @throws Exception 1957 */ 1958 @Test testOverlappedTempAllowList()1959 public void testOverlappedTempAllowList() throws Exception { 1960 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 1961 PACKAGE_NAME_APP1, 0); 1962 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 1963 WAITFOR_MSEC); 1964 try { 1965 // Enable the FGS background startForeground() restriction. 1966 enableFgsRestriction(true, true, null); 1967 // Start FGS in BG state. 1968 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1969 waiter.prepare(ACTION_START_FGS_RESULT); 1970 CommandReceiver.sendCommand(mContext, 1971 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 1972 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 1973 // APP1 does not enter FGS state 1974 try { 1975 waiter.doWait(WAITFOR_MSEC); 1976 fail("Service should not enter foreground service state"); 1977 } catch (Exception e) { 1978 } 1979 1980 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1981 waiter.prepare(ACTION_START_FGS_RESULT); 1982 runWithShellPermissionIdentity(() -> { 1983 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList( 1984 PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING, 1985 "", 10000); 1986 }); 1987 1988 SystemClock.sleep(5000); 1989 runWithShellPermissionIdentity(() -> { 1990 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList( 1991 PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING, 1992 "", 10000); 1993 }); 1994 SystemClock.sleep(5000); 1995 1996 // The first addToTemporaryAllowList()'s 10000ms duration has expired. 1997 // Now FGS start is allowed by second addToTemporaryAllowList()'s 10000ms duration. 1998 waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 1999 waiter.prepare(ACTION_START_FGS_RESULT); 2000 // Now it can start FGS. 2001 CommandReceiver.sendCommand(mContext, 2002 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, 2003 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 2004 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE); 2005 waiter.doWait(WAITFOR_MSEC); 2006 // Stop the FGS. 2007 CommandReceiver.sendCommand(mContext, 2008 CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE, 2009 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 2010 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY); 2011 } finally { 2012 uid1Watcher.finish(); 2013 // allow temp allowlist to expire. 2014 SystemClock.sleep(5000); 2015 } 2016 } 2017 2018 /** 2019 * IActivityManager.startService() is called directly (does not go through 2020 * {@link Context#startForegroundService(Intent)}, a spoofed packageName "com.google.android.as" 2021 * is used as callingPackage. Although "com.google.android.as" is allowlisted to start 2022 * foreground service from the background, but framework will detect this is a spoofed 2023 * packageName and disallow foreground service start from the background. 2024 * @throws Exception 2025 */ 2026 @Test testSpoofPackageName()2027 public void testSpoofPackageName() throws Exception { 2028 ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo( 2029 PACKAGE_NAME_APP1, 0); 2030 WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid, 2031 WAITFOR_MSEC); 2032 // CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME needs access 2033 // to hidden API PackageManager.getAttentionServicePackageName() and 2034 // PackageManager.getSystemCaptionsServicePackageName(), so we need to call 2035 // hddenApiSettings.set("*") to exempt the hidden APIs. 2036 SettingsSession<String> hiddenApiSettings = new SettingsSession<>( 2037 Settings.Global.getUriFor( 2038 Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS), 2039 Settings.Global::getString, Settings.Global::putString); 2040 hiddenApiSettings.set("*"); 2041 try { 2042 // Enable the FGS background startForeground() restriction. 2043 enableFgsRestriction(true, true, null); 2044 // Start FGS in BG state. 2045 WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext()); 2046 waiter.prepare(ACTION_START_FGS_RESULT); 2047 CommandReceiver.sendCommand(mContext, 2048 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME, 2049 PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null); 2050 // APP1 does not enter FGS state 2051 try { 2052 waiter.doWait(WAITFOR_MSEC); 2053 fail("Service should not enter foreground service state"); 2054 } catch (Exception e) { 2055 } 2056 } finally { 2057 uid1Watcher.finish(); 2058 if (hiddenApiSettings != null) { 2059 hiddenApiSettings.close(); 2060 } 2061 } 2062 } 2063 2064 /** 2065 * Turn on the FGS BG-launch restriction. DeviceConfig can turn on restriction on the whole 2066 * device (across all apps). AppCompat can turn on restriction on a single app package. 2067 * @param enable true to turn on restriction, false to turn off. 2068 * @param useDeviceConfig true to use DeviceConfig, false to use AppCompat CHANGE ID. 2069 * @param packageName the packageName if using AppCompat CHANGE ID. 2070 * @throws Exception 2071 */ enableFgsRestriction(boolean enable, boolean useDeviceConfig, String packageName)2072 private void enableFgsRestriction(boolean enable, boolean useDeviceConfig, String packageName) 2073 throws Exception { 2074 if (useDeviceConfig) { 2075 runWithShellPermissionIdentity(() -> { 2076 DeviceConfig.setProperty("activity_manager", 2077 KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED, 2078 Boolean.toString(enable), false); 2079 } 2080 ); 2081 } else { 2082 CtsAppTestUtils.executeShellCmd(mInstrumentation, 2083 "am compat " + (enable ? "enable" : "disable") 2084 + " FGS_BG_START_RESTRICTION_CHANGE_ID " + packageName); 2085 } 2086 } 2087 2088 /** 2089 * Clean up the FGS BG-launch restriction. 2090 * @param packageName the packageName that will have its changeid override reset. 2091 * @throws Exception 2092 */ resetFgsRestriction(String packageName)2093 private void resetFgsRestriction(String packageName) 2094 throws Exception { 2095 CtsAppTestUtils.executeShellCmd(mInstrumentation, 2096 "am compat reset FGS_BG_START_RESTRICTION_CHANGE_ID " + packageName); 2097 } 2098 2099 /** 2100 * SYSTEM_ALERT_WINDOW permission will allow both BG-activity start and BG-FGS start. 2101 * Some cases we want to grant this permission to allow activity start to bring the app up to 2102 * TOP state. 2103 * Some cases we want to revoke this permission to test other BG-FGS-launch exemptions. 2104 * @param packageName 2105 * @param allow 2106 * @throws Exception 2107 */ allowBgActivityStart(String packageName, boolean allow)2108 private void allowBgActivityStart(String packageName, boolean allow) throws Exception { 2109 if (allow) { 2110 PermissionUtils.grantPermission( 2111 packageName, android.Manifest.permission.SYSTEM_ALERT_WINDOW); 2112 } else { 2113 PermissionUtils.revokePermission( 2114 packageName, android.Manifest.permission.SYSTEM_ALERT_WINDOW); 2115 } 2116 } 2117 setFgsStartForegroundTimeout(int timeoutMs)2118 private void setFgsStartForegroundTimeout(int timeoutMs) throws Exception { 2119 runWithShellPermissionIdentity(() -> { 2120 DeviceConfig.setProperty("activity_manager", 2121 KEY_FGS_START_FOREGROUND_TIMEOUT, 2122 Integer.toString(timeoutMs), false); 2123 } 2124 ); 2125 } 2126 setAppOp(String packageName, String opStr, boolean allow)2127 private void setAppOp(String packageName, String opStr, boolean allow) throws Exception { 2128 CtsAppTestUtils.executeShellCmd(mInstrumentation, 2129 "appops set " + packageName + " " + opStr + " " 2130 + (allow ? "allow" : "deny")); 2131 } 2132 setPushMessagingOverQuotaBehavior( int type)2133 private void setPushMessagingOverQuotaBehavior( 2134 /* @PowerExemptionManager.TempAllowListType */ int type) throws Exception { 2135 runWithShellPermissionIdentity(() -> { 2136 DeviceConfig.setProperty("activity_manager", 2137 KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR, 2138 Integer.toString(type), false); 2139 } 2140 ); 2141 // Sleep 2 seconds to allow the device config change to be applied. 2142 SystemClock.sleep(2000); 2143 } 2144 getPushMessagingOverQuotaBehavior()2145 private int getPushMessagingOverQuotaBehavior() throws Exception { 2146 final String defaultBehaviorStr = CtsAppTestUtils.executeShellCmd(mInstrumentation, 2147 "device_config get activity_manager " 2148 + KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR).trim(); 2149 int defaultBehavior = TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; 2150 if (!defaultBehaviorStr.equals("null")) { 2151 try { 2152 defaultBehavior = Integer.parseInt(defaultBehaviorStr); 2153 } catch (NumberFormatException e) { 2154 Log.e("ActivityManagerFgsBgStartTest", 2155 "getPushMessagingOverQuotaBehavior:", e); 2156 } 2157 } 2158 return defaultBehavior; 2159 } 2160 } 2161