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