1 /* 2 * Copyright (C) 2021 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.os.cts; 18 19 import static android.os.PowerManager.FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY; 20 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL; 21 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST; 22 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION; 23 import static android.os.PowerManager.LowPowerStandbyPortDescription.MATCH_PORT_LOCAL; 24 import static android.os.PowerManager.LowPowerStandbyPortDescription.MATCH_PORT_REMOTE; 25 import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_TCP; 26 import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_UDP; 27 import static android.os.PowerManager.PARTIAL_WAKE_LOCK; 28 import static android.os.PowerManager.SYSTEM_WAKELOCK; 29 30 import static com.google.common.truth.Truth.assertThat; 31 32 import static org.junit.Assert.assertEquals; 33 import static org.junit.Assert.assertFalse; 34 import static org.junit.Assert.assertNotEquals; 35 import static org.junit.Assert.assertTrue; 36 import static org.junit.Assert.fail; 37 import static org.junit.Assume.assumeTrue; 38 39 import android.Manifest; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.pm.ServiceInfo; 44 import android.net.ConnectivityManager; 45 import android.net.Network; 46 import android.os.PowerExemptionManager; 47 import android.os.PowerManager; 48 import android.os.PowerManager.LowPowerStandbyPolicy; 49 import android.os.PowerManager.LowPowerStandbyPortDescription; 50 import android.os.PowerManager.WakeLock; 51 import android.platform.test.annotations.AppModeFull; 52 import android.platform.test.annotations.AppModeSdkSandbox; 53 import android.util.ArraySet; 54 55 import androidx.annotation.NonNull; 56 import androidx.test.InstrumentationRegistry; 57 import androidx.test.uiautomator.UiDevice; 58 59 import com.android.bedstead.harrier.BedsteadJUnit4; 60 import com.android.bedstead.harrier.DeviceState; 61 import com.android.bedstead.permissions.annotations.EnsureHasPermission; 62 import com.android.bedstead.nene.TestApis; 63 import com.android.bedstead.permissions.PermissionContext; 64 import com.android.compatibility.common.util.ApiTest; 65 import com.android.compatibility.common.util.BlockingBroadcastReceiver; 66 import com.android.compatibility.common.util.CallbackAsserter; 67 import com.android.compatibility.common.util.PollingCheck; 68 import com.android.compatibility.common.util.ProtoUtils; 69 import com.android.server.power.nano.PowerManagerServiceDumpProto; 70 import com.android.server.power.nano.WakeLockProto; 71 72 import org.junit.After; 73 import org.junit.Before; 74 import org.junit.ClassRule; 75 import org.junit.Rule; 76 import org.junit.Test; 77 import org.junit.runner.RunWith; 78 79 import java.io.IOException; 80 import java.net.InetAddress; 81 import java.util.Collections; 82 import java.util.List; 83 import java.util.concurrent.TimeUnit; 84 85 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 86 @RunWith(BedsteadJUnit4.class) 87 public class LowPowerStandbyTest { 88 private static final int BROADCAST_TIMEOUT_SEC = 3; 89 private static final int WAKELOCK_STATE_TIMEOUT = 1000; 90 private static final long LOW_POWER_STANDBY_ACTIVATE_TIMEOUT = TimeUnit.MINUTES.toMillis(2); 91 92 private static final String SYSTEM_WAKE_LOCK_TAG = "LowPowerStandbyTest:KeepSystemAwake"; 93 public static final String TEST_WAKE_LOCK_TAG = "LowPowerStandbyTest:TestWakeLock"; 94 private static final LowPowerStandbyPortDescription PORT_DESC_1 = 95 new LowPowerStandbyPortDescription(PROTOCOL_UDP, MATCH_PORT_REMOTE, 1234); 96 97 @ClassRule 98 @Rule 99 public static final DeviceState sDeviceState = new DeviceState(); 100 101 private Context mContext; 102 private PowerManager mPowerManager; 103 private LowPowerStandbyPolicy mOriginalPolicy; 104 private boolean mOriginalEnabled; 105 private WakeLock mSystemWakeLock; 106 107 @Before setUp()108 public void setUp() throws Exception { 109 mContext = InstrumentationRegistry.getInstrumentation().getContext(); 110 mPowerManager = mContext.getSystemService(PowerManager.class); 111 mOriginalEnabled = mPowerManager.isLowPowerStandbyEnabled(); 112 mOriginalPolicy = null; 113 114 try (PermissionContext p = TestApis.permissions().withPermission( 115 Manifest.permission.MANAGE_LOW_POWER_STANDBY)) { 116 assumeTrue(mPowerManager.isLowPowerStandbySupported()); 117 mOriginalPolicy = mPowerManager.getLowPowerStandbyPolicy(); 118 119 // Reset to the default policy 120 mPowerManager.setLowPowerStandbyPolicy(null); 121 } 122 } 123 124 @After tearDown()125 public void tearDown() throws Exception { 126 if (mPowerManager != null) { 127 try (PermissionContext p = TestApis.permissions().withPermission( 128 Manifest.permission.MANAGE_LOW_POWER_STANDBY)) { 129 wakeUp(); 130 mPowerManager.setLowPowerStandbyEnabled(mOriginalEnabled); 131 mPowerManager.forceLowPowerStandbyActive(false); 132 mPowerManager.setLowPowerStandbyPolicy(mOriginalPolicy); 133 } 134 } 135 unforceDoze(); 136 137 if (mSystemWakeLock != null) { 138 mSystemWakeLock.release(); 139 } 140 } 141 142 @Test 143 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyEnabled") testSetLowPowerStandbyEnabled_withoutPermission_throwsSecurityException()144 public void testSetLowPowerStandbyEnabled_withoutPermission_throwsSecurityException() { 145 try { 146 mPowerManager.setLowPowerStandbyEnabled(false); 147 fail("PowerManager.setLowPowerStandbyEnabled() didn't throw SecurityException as " 148 + "expected"); 149 } catch (SecurityException e) { 150 // expected 151 } 152 } 153 154 @Test 155 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyEnabled") 156 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 157 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testSetLowPowerStandbyEnabled_withPermission_doesNotThrowsSecurityException()158 public void testSetLowPowerStandbyEnabled_withPermission_doesNotThrowsSecurityException() { 159 mPowerManager.setLowPowerStandbyEnabled(false); 160 } 161 162 @Test 163 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 164 "android.os.PowerManager#isLowPowerStandbyEnabled"}) 165 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 166 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testSetLowPowerStandbyEnabled_reflectedByIsLowPowerStandbyEnabled()167 public void testSetLowPowerStandbyEnabled_reflectedByIsLowPowerStandbyEnabled() { 168 mPowerManager.setLowPowerStandbyEnabled(true); 169 assertTrue(mPowerManager.isLowPowerStandbyEnabled()); 170 171 mPowerManager.setLowPowerStandbyEnabled(false); 172 assertFalse(mPowerManager.isLowPowerStandbyEnabled()); 173 } 174 175 @Test 176 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyEnabled") 177 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 178 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testSetLowPowerStandbyEnabled_sendsBroadcast()179 public void testSetLowPowerStandbyEnabled_sendsBroadcast() throws Exception { 180 mPowerManager.setLowPowerStandbyEnabled(false); 181 182 CallbackAsserter broadcastAsserter = CallbackAsserter.forBroadcast( 183 new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); 184 mPowerManager.setLowPowerStandbyEnabled(true); 185 broadcastAsserter.assertCalled( 186 "ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED broadcast not received", 187 BROADCAST_TIMEOUT_SEC); 188 189 broadcastAsserter = CallbackAsserter.forBroadcast( 190 new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); 191 mPowerManager.setLowPowerStandbyEnabled(false); 192 broadcastAsserter.assertCalled( 193 "ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED broadcast not received", 194 BROADCAST_TIMEOUT_SEC); 195 } 196 197 @Test 198 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyEnabled") 199 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 200 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 201 Manifest.permission.DEVICE_POWER}) testLowPowerStandby_wakelockIsDisabled()202 public void testLowPowerStandby_wakelockIsDisabled() throws Exception { 203 keepSystemAwake(); 204 205 // Acquire test wakelock, which should be disabled by LPS 206 WakeLock testWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, TEST_WAKE_LOCK_TAG); 207 testWakeLock.acquire(); 208 209 mPowerManager.setLowPowerStandbyEnabled(true); 210 goToSleep(); 211 mPowerManager.forceLowPowerStandbyActive(true); 212 213 PollingCheck.check("Test wakelock not disabled", WAKELOCK_STATE_TIMEOUT, 214 () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 215 PollingCheck.check("System wakelock is disabled", WAKELOCK_STATE_TIMEOUT, 216 () -> !isWakeLockDisabled(SYSTEM_WAKE_LOCK_TAG)); 217 218 testWakeLock.release(); 219 } 220 221 @Test 222 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 223 "android.os.PowerManager#setLowPowerStandbyActiveDuringMaintenance"}) 224 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 225 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 226 Manifest.permission.DEVICE_POWER}) testSetLowPowerStandbyActiveDuringMaintenance()227 public void testSetLowPowerStandbyActiveDuringMaintenance() throws Exception { 228 // Keep system awake with system wakelock 229 keepSystemAwake(); 230 231 // Acquire test wakelock, which should be disabled by LPS 232 WakeLock testWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, 233 TEST_WAKE_LOCK_TAG); 234 testWakeLock.acquire(); 235 236 mPowerManager.setLowPowerStandbyEnabled(true); 237 mPowerManager.setLowPowerStandbyActiveDuringMaintenance(true); 238 239 goToSleep(); 240 forceDoze(); 241 242 PollingCheck.check( 243 "Test wakelock still enabled, expected to be disabled by Low Power Standby", 244 LOW_POWER_STANDBY_ACTIVATE_TIMEOUT, () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 245 246 enterDozeMaintenance(); 247 248 assertTrue(isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 249 250 mPowerManager.setLowPowerStandbyActiveDuringMaintenance(false); 251 PollingCheck.check( 252 "Test wakelock disabled during doze maintenance, even though Low Power Standby " 253 + "should not be active during maintenance", 254 WAKELOCK_STATE_TIMEOUT, () -> !isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 255 256 mPowerManager.setLowPowerStandbyActiveDuringMaintenance(true); 257 258 PollingCheck.check( 259 "Test wakelock enabled during doze maintenance, even though Low Power Standby " 260 + "should be active during maintenance", 261 WAKELOCK_STATE_TIMEOUT, () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 262 263 testWakeLock.release(); 264 } 265 266 @Test 267 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyEnabled") 268 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 269 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 270 Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.DEVICE_POWER}) testLowPowerStandby_networkIsBlocked()271 public void testLowPowerStandby_networkIsBlocked() throws Exception { 272 keepSystemAwake(); 273 274 NetworkBlockedStateAsserter asserter = new NetworkBlockedStateAsserter(mContext); 275 asserter.register(); 276 277 try { 278 mPowerManager.setLowPowerStandbyEnabled(true); 279 goToSleep(); 280 mPowerManager.forceLowPowerStandbyActive(true); 281 282 asserter.assertNetworkBlocked("Network is not blocked", true); 283 284 wakeUp(); 285 mPowerManager.forceLowPowerStandbyActive(false); 286 287 asserter.assertNetworkBlocked("Network is blocked after waking up", false); 288 } finally { 289 asserter.unregister(); 290 } 291 } 292 293 @Test 294 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 295 "android.os.PowerManager#setLowPowerStandbyPolicy", 296 "android.os.PowerManager#isExemptFromLowPowerStandby"}) 297 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 298 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isExempt_whenEnabled()299 public void testLowPowerStandby_isExempt_whenEnabled() throws Exception { 300 mPowerManager.setLowPowerStandbyEnabled(true); 301 mPowerManager.setLowPowerStandbyPolicy(emptyPolicy()); 302 assertFalse(mPowerManager.isExemptFromLowPowerStandby()); 303 304 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 305 assertTrue(mPowerManager.isExemptFromLowPowerStandby()); 306 307 mPowerManager.setLowPowerStandbyPolicy(new LowPowerStandbyPolicy( 308 "testLowPowerStandby_isExempt", 309 new ArraySet<>(new String[]{"some.other.package"}), 310 0, 311 Collections.emptySet() 312 )); 313 assertFalse(mPowerManager.isExemptFromLowPowerStandby()); 314 } 315 316 @Test 317 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 318 "android.os.PowerManager#setLowPowerStandbyPolicy", 319 "android.os.PowerManager#isExemptFromLowPowerStandby"}) 320 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 321 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isExempt_whenDisabled()322 public void testLowPowerStandby_isExempt_whenDisabled() throws Exception { 323 mPowerManager.setLowPowerStandbyEnabled(false); 324 mPowerManager.setLowPowerStandbyPolicy(emptyPolicy()); 325 assertTrue(mPowerManager.isExemptFromLowPowerStandby()); 326 } 327 328 @Test 329 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 330 "android.os.PowerManager#setLowPowerStandbyPolicy", 331 "android.os.PowerManager#getLowPowerStandbyPolicy"}) 332 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 333 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_getPolicy()334 public void testLowPowerStandby_getPolicy() throws Exception { 335 LowPowerStandbyPolicy policy = new LowPowerStandbyPolicy( 336 "testLowPowerStandby_getPolicy", 337 new ArraySet<>(new String[]{"package1", "package2"}), 338 123, 339 new ArraySet<>(new String[]{"feature1", "feature2"}) 340 ); 341 mPowerManager.setLowPowerStandbyPolicy(policy); 342 assertEquals(policy, mPowerManager.getLowPowerStandbyPolicy()); 343 344 mPowerManager.setLowPowerStandbyPolicy(null); 345 assertNotEquals(policy, mPowerManager.getLowPowerStandbyPolicy()); 346 } 347 348 @Test 349 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyPolicy") 350 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 351 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_setPolicy_changeBroadcastIsSent()352 public void testLowPowerStandby_setPolicy_changeBroadcastIsSent() throws Exception { 353 CallbackAsserter broadcastAsserter = CallbackAsserter.forBroadcast( 354 new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_POLICY_CHANGED)); 355 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 356 broadcastAsserter.assertCalled( 357 "ACTION_LOW_POWER_STANDBY_POLICY_CHANGED broadcast not received", 358 BROADCAST_TIMEOUT_SEC); 359 } 360 361 @Test 362 @ApiTest(apis = "android.os.PowerManager#setLowPowerStandbyPolicy") 363 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 364 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_setPolicy_exemptPackageIsNotRestricted()365 public void testLowPowerStandby_setPolicy_exemptPackageIsNotRestricted() throws Exception { 366 WakeLock testWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, TEST_WAKE_LOCK_TAG); 367 testWakeLock.acquire(); 368 369 mPowerManager.forceLowPowerStandbyActive(true); 370 PollingCheck.check("Test wakelock not disabled", 371 WAKELOCK_STATE_TIMEOUT, () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 372 373 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 374 PollingCheck.check("Test wakelock disabled, though package should be exempt", 375 WAKELOCK_STATE_TIMEOUT, () -> !isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 376 377 testWakeLock.release(); 378 } 379 380 @Test 381 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyPolicy", 382 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 383 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 384 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedReason_trueIfDisabled()385 public void testLowPowerStandby_isAllowedReason_trueIfDisabled() throws Exception { 386 mPowerManager.setLowPowerStandbyEnabled(false); 387 assertTrue(mPowerManager.isAllowedInLowPowerStandby( 388 LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 389 } 390 391 @Test 392 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 393 "android.os.PowerManager#setLowPowerStandbyPolicy", 394 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 395 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 396 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedReason_falseIfNotAllowed()397 public void testLowPowerStandby_isAllowedReason_falseIfNotAllowed() throws Exception { 398 mPowerManager.setLowPowerStandbyPolicy(emptyPolicy()); 399 mPowerManager.setLowPowerStandbyEnabled(true); 400 assertFalse(mPowerManager.isAllowedInLowPowerStandby( 401 LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 402 } 403 404 @Test 405 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 406 "android.os.PowerManager#setLowPowerStandbyPolicy", 407 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 408 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 409 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedReason_trueIfAllowed()410 public void testLowPowerStandby_isAllowedReason_trueIfAllowed() throws Exception { 411 mPowerManager.setLowPowerStandbyPolicy(policyWithAllowedReasons( 412 LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 413 mPowerManager.setLowPowerStandbyEnabled(true); 414 assertTrue(mPowerManager.isAllowedInLowPowerStandby( 415 LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 416 } 417 418 @Test 419 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 420 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 421 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 422 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedFeature_trueIfDisabled()423 public void testLowPowerStandby_isAllowedFeature_trueIfDisabled() throws Exception { 424 mPowerManager.setLowPowerStandbyEnabled(false); 425 assertTrue( 426 mPowerManager.isAllowedInLowPowerStandby(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 427 } 428 429 @Test 430 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 431 "android.os.PowerManager#setLowPowerStandbyPolicy", 432 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 433 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 434 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedFeature_falseIfNotAllowed()435 public void testLowPowerStandby_isAllowedFeature_falseIfNotAllowed() throws Exception { 436 mPowerManager.setLowPowerStandbyPolicy(emptyPolicy()); 437 mPowerManager.setLowPowerStandbyEnabled(true); 438 assertFalse(mPowerManager.isAllowedInLowPowerStandby( 439 FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 440 } 441 442 @Test 443 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 444 "android.os.PowerManager#setLowPowerStandbyPolicy", 445 "android.os.PowerManager#isAllowedInLowPowerStandby"}) 446 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 447 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_isAllowedFeature_trueIfAllowed()448 public void testLowPowerStandby_isAllowedFeature_trueIfAllowed() throws Exception { 449 mPowerManager.setLowPowerStandbyPolicy(policyWithAllowedFeatures( 450 FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 451 mPowerManager.setLowPowerStandbyEnabled(true); 452 assertTrue( 453 mPowerManager.isAllowedInLowPowerStandby(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 454 } 455 456 @Test 457 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyPolicy", 458 "android.os.PowerManager#LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST"}) 459 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 460 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_allowedReason_tempPowerSaveAllowlist()461 public void testLowPowerStandby_allowedReason_tempPowerSaveAllowlist() throws Exception { 462 WakeLock testWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, TEST_WAKE_LOCK_TAG); 463 testWakeLock.acquire(); 464 PollingCheck.check("Test wakelock disabled", WAKELOCK_STATE_TIMEOUT, 465 () -> !isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 466 467 mPowerManager.forceLowPowerStandbyActive(true); 468 PollingCheck.check("Test wakelock not disabled", WAKELOCK_STATE_TIMEOUT, 469 () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 470 471 mPowerManager.setLowPowerStandbyPolicy(policyWithAllowedReasons( 472 LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST)); 473 assertTrue("Test wakelock not disabled", isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 474 475 PowerExemptionManager powerExemptionManager = 476 mContext.getSystemService(PowerExemptionManager.class); 477 try (PermissionContext p = TestApis.permissions().withPermission( 478 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)) { 479 powerExemptionManager.addToTemporaryAllowList(mContext.getPackageName(), 480 PowerExemptionManager.REASON_OTHER, "", 5000); 481 } 482 PollingCheck.check("Test wakelock disabled, though UID should be exempt", 483 WAKELOCK_STATE_TIMEOUT, () -> !isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 484 485 testWakeLock.release(); 486 } 487 488 @Test 489 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyPolicy", 490 "android.os.PowerManager#LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL"}) 491 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 492 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_allowedReason_ongoingCall_phoneCallServiceExempt()493 public void testLowPowerStandby_allowedReason_ongoingCall_phoneCallServiceExempt() 494 throws Exception { 495 Intent intent = LowPowerStandbyForegroundService.createIntentWithForegroundServiceType( 496 mContext, ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL); 497 mContext.startForegroundService(intent); 498 499 mPowerManager.forceLowPowerStandbyActive(true); 500 PollingCheck.check("Test wakelock not disabled", WAKELOCK_STATE_TIMEOUT, 501 () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 502 503 mPowerManager.setLowPowerStandbyPolicy( 504 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL)); 505 PollingCheck.check("Test wakelock disabled, though UID should be exempt", 506 WAKELOCK_STATE_TIMEOUT, () -> !isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 507 508 mContext.stopService(intent); 509 } 510 511 @Test 512 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyPolicy", 513 "android.os.PowerManager#LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL"}) 514 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 515 @EnsureHasPermission(Manifest.permission.MANAGE_LOW_POWER_STANDBY) testLowPowerStandby_allowedReason_ongoingCall_otherFgsServiceNotExempt()516 public void testLowPowerStandby_allowedReason_ongoingCall_otherFgsServiceNotExempt() 517 throws Exception { 518 Intent intent = LowPowerStandbyForegroundService.createIntentWithForegroundServiceType( 519 mContext, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK); 520 mContext.startForegroundService(intent); 521 mPowerManager.setLowPowerStandbyPolicy( 522 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL)); 523 mPowerManager.forceLowPowerStandbyActive(true); 524 525 PollingCheck.check("Test wakelock not disabled", WAKELOCK_STATE_TIMEOUT, 526 () -> isWakeLockDisabled(TEST_WAKE_LOCK_TAG)); 527 528 mContext.stopService(intent); 529 } 530 531 @Test 532 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 533 "android.os.PowerManager#setLowPowerStandbyPolicy", 534 "android.os.PowerManager#newLowPowerStandbyPortsLock", 535 "android.os.PowerManager#getActiveLowPowerStandbyPorts"}) 536 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 537 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 538 Manifest.permission.SET_LOW_POWER_STANDBY_PORTS}) testActiveStandbyPorts_disabled()539 public void testActiveStandbyPorts_disabled() throws Exception { 540 mPowerManager.setLowPowerStandbyEnabled(false); 541 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 542 PowerManager.LowPowerStandbyPortsLock standbyPorts = 543 mPowerManager.newLowPowerStandbyPortsLock(List.of(PORT_DESC_1)); 544 standbyPorts.acquire(); 545 546 assertThat(mPowerManager.getActiveLowPowerStandbyPorts()).doesNotContain(PORT_DESC_1); 547 standbyPorts.release(); 548 } 549 550 @Test 551 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 552 "android.os.PowerManager#newLowPowerStandbyPortsLock", 553 "android.os.PowerManager#getActiveLowPowerStandbyPorts"}) 554 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 555 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 556 Manifest.permission.SET_LOW_POWER_STANDBY_PORTS}) testActiveStandbyPorts_notExempt()557 public void testActiveStandbyPorts_notExempt() throws Exception { 558 mPowerManager.setLowPowerStandbyEnabled(true); 559 560 PowerManager.LowPowerStandbyPortsLock standbyPorts = 561 mPowerManager.newLowPowerStandbyPortsLock(List.of(PORT_DESC_1)); 562 standbyPorts.acquire(); 563 564 assertThat(mPowerManager.getActiveLowPowerStandbyPorts()).doesNotContain(PORT_DESC_1); 565 standbyPorts.release(); 566 } 567 568 @Test 569 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 570 "android.os.PowerManager#setLowPowerStandbyPolicy", 571 "android.os.PowerManager#newLowPowerStandbyPortsLock", 572 "android.os.PowerManager#getActiveLowPowerStandbyPorts"}) 573 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 574 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 575 Manifest.permission.SET_LOW_POWER_STANDBY_PORTS}) testActiveStandbyPorts_exempt()576 public void testActiveStandbyPorts_exempt() throws Exception { 577 mPowerManager.setLowPowerStandbyEnabled(true); 578 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 579 PowerManager.LowPowerStandbyPortsLock standbyPorts = 580 mPowerManager.newLowPowerStandbyPortsLock(List.of(PORT_DESC_1)); 581 standbyPorts.acquire(); 582 583 assertThat(mPowerManager.getActiveLowPowerStandbyPorts()).contains(PORT_DESC_1); 584 standbyPorts.release(); 585 } 586 587 @Test 588 @ApiTest(apis = { 589 "android.os.PowerManager.LowPowerStandbyPortDescription#getProtocol", 590 "android.os.PowerManager.LowPowerStandbyPortDescription#getPortMatcher", 591 "android.os.PowerManager.LowPowerStandbyPortDescription#getPortNumber", 592 "android.os.PowerManager.LowPowerStandbyPortDescription#getLocalAddress" 593 }) testPortDescriptionGetters()594 public void testPortDescriptionGetters() throws Exception { 595 int protocol = PROTOCOL_UDP; 596 int portMatcher = MATCH_PORT_LOCAL; 597 int portNumber = 5555; 598 LowPowerStandbyPortDescription portDesc = 599 new LowPowerStandbyPortDescription(protocol, portMatcher, portNumber); 600 601 assertThat(portDesc.getProtocol()).isEqualTo(protocol); 602 assertThat(portDesc.getPortMatcher()).isEqualTo(portMatcher); 603 assertThat(portDesc.getPortNumber()).isEqualTo(portNumber); 604 assertThat(portDesc.getLocalAddress()).isEqualTo(null); 605 606 protocol = PROTOCOL_TCP; 607 portMatcher = MATCH_PORT_REMOTE; 608 portNumber = 433; 609 InetAddress localAddress = InetAddress.getByName("192.168.5.5"); 610 portDesc = 611 new LowPowerStandbyPortDescription(protocol, portMatcher, portNumber, localAddress); 612 613 assertThat(portDesc.getProtocol()).isEqualTo(protocol); 614 assertThat(portDesc.getPortMatcher()).isEqualTo(portMatcher); 615 assertThat(portDesc.getPortNumber()).isEqualTo(portNumber); 616 assertThat(portDesc.getLocalAddress()).isEqualTo(localAddress); 617 } 618 619 @Test 620 @ApiTest(apis = {"android.os.PowerManager#setLowPowerStandbyEnabled", 621 "android.os.PowerManager#setLowPowerStandbyPolicy", 622 "android.os.PowerManager#newLowPowerStandbyPortsLock", 623 "android.os.PowerManager#getActiveLowPowerStandbyPorts"}) 624 @AppModeFull(reason = "Instant apps cannot hold MANAGE_LOW_POWER_STANDBY permission") 625 @EnsureHasPermission({Manifest.permission.MANAGE_LOW_POWER_STANDBY, 626 Manifest.permission.SET_LOW_POWER_STANDBY_PORTS}) testActiveStandbyPorts_becomesActiveOnceExempt()627 public void testActiveStandbyPorts_becomesActiveOnceExempt() throws Exception { 628 mPowerManager.setLowPowerStandbyEnabled(true); 629 PowerManager.LowPowerStandbyPortsLock standbyPorts = 630 mPowerManager.newLowPowerStandbyPortsLock(List.of(PORT_DESC_1)); 631 standbyPorts.acquire(); 632 633 mPowerManager.setLowPowerStandbyPolicy(ownPackageExemptPolicy()); 634 assertThat(mPowerManager.getActiveLowPowerStandbyPorts()).contains(PORT_DESC_1); 635 standbyPorts.release(); 636 } 637 emptyPolicy()638 private LowPowerStandbyPolicy emptyPolicy() { 639 return new LowPowerStandbyPolicy( 640 "CTS: LowPowerStandbyTest empty policy", 641 Collections.emptySet(), 642 0, 643 Collections.emptySet() 644 ); 645 } 646 ownPackageExemptPolicy()647 private LowPowerStandbyPolicy ownPackageExemptPolicy() { 648 return new LowPowerStandbyPolicy( 649 "CTS: LowPowerStandbyTest own package exempt policy", 650 new ArraySet<>(new String[]{mContext.getPackageName()}), 651 0, 652 Collections.emptySet() 653 ); 654 } 655 policyWithAllowedReasons(int allowedReasons)656 private LowPowerStandbyPolicy policyWithAllowedReasons(int allowedReasons) { 657 return new LowPowerStandbyPolicy( 658 "CTS: LowPowerStandbyTest policy", 659 Collections.emptySet(), 660 allowedReasons, 661 Collections.emptySet() 662 ); 663 } 664 policyWithAllowedFeatures(String... allowedFeatures)665 private LowPowerStandbyPolicy policyWithAllowedFeatures(String... allowedFeatures) { 666 return new LowPowerStandbyPolicy( 667 "CTS: LowPowerStandbyTest policy", 668 Collections.emptySet(), 669 0, 670 new ArraySet<>(allowedFeatures) 671 ); 672 } 673 goToSleep()674 private void goToSleep() throws Exception { 675 if (!mPowerManager.isInteractive()) { 676 return; 677 } 678 679 final BlockingBroadcastReceiver screenOffReceiver = new BlockingBroadcastReceiver(mContext, 680 Intent.ACTION_SCREEN_OFF); 681 screenOffReceiver.register(); 682 683 executeShellCommand("input keyevent SLEEP"); 684 685 screenOffReceiver.awaitForBroadcast(1000); 686 screenOffReceiver.unregisterQuietly(); 687 } 688 wakeUp()689 private void wakeUp() throws Exception { 690 if (mPowerManager.isInteractive()) { 691 return; 692 } 693 694 final BlockingBroadcastReceiver screenOnReceiver = new BlockingBroadcastReceiver(mContext, 695 Intent.ACTION_SCREEN_ON); 696 screenOnReceiver.register(); 697 698 executeShellCommand("input keyevent WAKEUP"); 699 700 screenOnReceiver.awaitForBroadcast(1000); 701 screenOnReceiver.unregisterQuietly(); 702 } 703 forceDoze()704 private void forceDoze() throws Exception { 705 executeShellCommand("dumpsys deviceidle force-idle deep"); 706 } 707 unforceDoze()708 private void unforceDoze() throws Exception { 709 executeShellCommand("dumpsys deviceidle unforce"); 710 } 711 enterDozeMaintenance()712 private void enterDozeMaintenance() throws Exception { 713 executeShellCommand("dumpsys deviceidle force-idle deep"); 714 715 for (int i = 0; i < 4; i++) { 716 String stepResult = executeShellCommand("dumpsys deviceidle step deep"); 717 if (stepResult != null && stepResult.contains("IDLE_MAINTENANCE")) { 718 return; 719 } 720 } 721 722 fail("Failed to enter doze maintenance mode"); 723 } 724 isWakeLockDisabled(@onNull String tag)725 private boolean isWakeLockDisabled(@NonNull String tag) throws Exception { 726 final PowerManagerServiceDumpProto powerManagerServiceDump = getPowerManagerDump(); 727 for (WakeLockProto wakelock : powerManagerServiceDump.wakeLocks) { 728 if (tag.equals(wakelock.tag)) { 729 return wakelock.isDisabled; 730 } 731 } 732 throw new IllegalStateException("WakeLock " + tag + " is not held"); 733 } 734 getPowerManagerDump()735 private static PowerManagerServiceDumpProto getPowerManagerDump() throws Exception { 736 return ProtoUtils.getProto(InstrumentationRegistry.getInstrumentation().getUiAutomation(), 737 PowerManagerServiceDumpProto.class, "dumpsys power --proto"); 738 } 739 keepSystemAwake()740 private void keepSystemAwake() { 741 mSystemWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK | SYSTEM_WAKELOCK, 742 SYSTEM_WAKE_LOCK_TAG); 743 mSystemWakeLock.acquire(); 744 } 745 executeShellCommand(String command)746 private String executeShellCommand(String command) throws IOException { 747 UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 748 return uiDevice.executeShellCommand(command); 749 } 750 751 private static class NetworkBlockedStateAsserter { 752 private final ConnectivityManager mConnectivityManager; 753 private final ConnectivityManager.NetworkCallback mNetworkCallback; 754 755 private final Object mLock = new Object(); 756 private boolean mIsBlocked = false; 757 NetworkBlockedStateAsserter(Context context)758 NetworkBlockedStateAsserter(Context context) { 759 mConnectivityManager = context.getSystemService(ConnectivityManager.class); 760 mNetworkCallback = 761 new ConnectivityManager.NetworkCallback() { 762 @Override 763 public void onBlockedStatusChanged(Network network, boolean blocked) { 764 synchronized (mLock) { 765 if (mIsBlocked != blocked) { 766 mIsBlocked = blocked; 767 mLock.notify(); 768 } 769 } 770 } 771 }; 772 } 773 register()774 private void register() { 775 mConnectivityManager.registerDefaultNetworkCallback(mNetworkCallback); 776 } 777 assertNetworkBlocked(String message, boolean expected)778 private void assertNetworkBlocked(String message, boolean expected) throws Exception { 779 synchronized (mLock) { 780 if (mIsBlocked == expected) { 781 return; 782 } 783 mLock.wait(5000); 784 assertEquals(message, expected, mIsBlocked); 785 } 786 } 787 unregister()788 private void unregister() { 789 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 790 } 791 } 792 } 793