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