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