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 com.android.server.power; 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.PROTOCOL_TCP; 25 import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_UDP; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static junit.framework.Assert.assertFalse; 30 import static junit.framework.Assert.assertTrue; 31 32 import static org.mockito.ArgumentMatchers.any; 33 import static org.mockito.ArgumentMatchers.anyBoolean; 34 import static org.mockito.ArgumentMatchers.anyInt; 35 import static org.mockito.ArgumentMatchers.anyLong; 36 import static org.mockito.ArgumentMatchers.anyString; 37 import static org.mockito.ArgumentMatchers.eq; 38 import static org.mockito.Mockito.atLeast; 39 import static org.mockito.Mockito.inOrder; 40 import static org.mockito.Mockito.never; 41 import static org.mockito.Mockito.reset; 42 import static org.mockito.Mockito.spy; 43 import static org.mockito.Mockito.times; 44 import static org.mockito.Mockito.verify; 45 import static org.mockito.Mockito.verifyNoMoreInteractions; 46 import static org.mockito.Mockito.when; 47 48 import android.app.ActivityManagerInternal; 49 import android.app.AlarmManager; 50 import android.app.IActivityManager; 51 import android.app.IForegroundServiceObserver; 52 import android.content.Intent; 53 import android.content.IntentFilter; 54 import android.content.pm.PackageManager; 55 import android.content.pm.ServiceInfo; 56 import android.content.res.Resources; 57 import android.net.Uri; 58 import android.os.Binder; 59 import android.os.IPowerManager; 60 import android.os.PowerManager; 61 import android.os.PowerManager.LowPowerStandbyPolicy; 62 import android.os.PowerManager.LowPowerStandbyPortDescription; 63 import android.os.PowerManagerInternal; 64 import android.os.UserHandle; 65 import android.os.UserManager; 66 import android.os.test.TestLooper; 67 import android.provider.Settings; 68 import android.test.mock.MockContentResolver; 69 import android.util.ArraySet; 70 71 import androidx.test.InstrumentationRegistry; 72 73 import com.android.internal.util.test.BroadcastInterceptingContext; 74 import com.android.internal.util.test.FakeSettingsProvider; 75 import com.android.server.LocalServices; 76 import com.android.server.PowerAllowlistInternal; 77 import com.android.server.PowerAllowlistInternal.TempAllowlistChangeListener; 78 import com.android.server.net.NetworkPolicyManagerInternal; 79 import com.android.server.power.LowPowerStandbyController.DeviceConfigWrapper; 80 import com.android.server.testutils.OffsettableClock; 81 82 import org.junit.After; 83 import org.junit.Before; 84 import org.junit.Test; 85 import org.mockito.ArgumentCaptor; 86 import org.mockito.InOrder; 87 import org.mockito.Mock; 88 import org.mockito.MockitoAnnotations; 89 90 import java.io.File; 91 import java.util.Collections; 92 import java.util.List; 93 import java.util.concurrent.TimeUnit; 94 95 /** 96 * Tests for {@link com.android.server.power.LowPowerStandbyController}. 97 * 98 * Build/Install/Run: 99 * atest LowPowerStandbyControllerTest 100 */ 101 public class LowPowerStandbyControllerTest { 102 private static final int STANDBY_TIMEOUT = 5000; 103 private static final String TEST_PKG1 = "PKG1"; 104 private static final String TEST_PKG2 = "PKG2"; 105 private static final int TEST_PKG1_APP_ID = 123; 106 private static final int TEST_PKG2_APP_ID = 456; 107 private static final int USER_ID_1 = 0; 108 private static final int USER_ID_2 = 10; 109 private static final LowPowerStandbyPolicy EMPTY_POLICY = new LowPowerStandbyPolicy( 110 "Test policy", Collections.emptySet(), 0, Collections.emptySet()); 111 private static final LowPowerStandbyPortDescription PORT_DESC_1 = 112 new LowPowerStandbyPortDescription(PROTOCOL_UDP, MATCH_PORT_LOCAL, 5353); 113 private static final LowPowerStandbyPortDescription PORT_DESC_2 = 114 new LowPowerStandbyPortDescription(PROTOCOL_TCP, MATCH_PORT_LOCAL, 8008); 115 116 private LowPowerStandbyController mController; 117 private BroadcastInterceptingContext mContextSpy; 118 private Resources mResourcesSpy; 119 private OffsettableClock mClock; 120 private TestLooper mTestLooper; 121 private File mTestPolicyFile; 122 123 @Mock 124 private DeviceConfigWrapper mDeviceConfigWrapperMock; 125 @Mock 126 private IActivityManager mIActivityManagerMock; 127 @Mock 128 private AlarmManager mAlarmManagerMock; 129 @Mock 130 private PackageManager mPackageManagerMock; 131 @Mock 132 private UserManager mUserManagerMock; 133 @Mock 134 private IPowerManager mIPowerManagerMock; 135 @Mock 136 private PowerManagerInternal mPowerManagerInternalMock; 137 @Mock 138 private NetworkPolicyManagerInternal mNetworkPolicyManagerInternalMock; 139 @Mock 140 private PowerAllowlistInternal mPowerAllowlistInternalMock; 141 @Mock 142 private ActivityManagerInternal mActivityManagerInternalMock; 143 144 @Before setUp()145 public void setUp() throws Exception { 146 MockitoAnnotations.initMocks(this); 147 148 mContextSpy = spy(new BroadcastInterceptingContext(InstrumentationRegistry.getContext())); 149 when(mContextSpy.getPackageManager()).thenReturn(mPackageManagerMock); 150 when(mContextSpy.getSystemService(AlarmManager.class)).thenReturn(mAlarmManagerMock); 151 when(mContextSpy.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); 152 PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock, null, null); 153 when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager); 154 addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock); 155 addLocalServiceMock(NetworkPolicyManagerInternal.class, mNetworkPolicyManagerInternalMock); 156 addLocalServiceMock(PowerAllowlistInternal.class, mPowerAllowlistInternalMock); 157 addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock); 158 159 when(mIPowerManagerMock.isInteractive()).thenReturn(true); 160 161 when(mDeviceConfigWrapperMock.enableCustomPolicy()).thenReturn(true); 162 when(mDeviceConfigWrapperMock.enableStandbyPorts()).thenReturn(true); 163 mResourcesSpy = spy(mContextSpy.getResources()); 164 when(mContextSpy.getResources()).thenReturn(mResourcesSpy); 165 when(mResourcesSpy.getBoolean( 166 com.android.internal.R.bool.config_lowPowerStandbySupported)) 167 .thenReturn(true); 168 when(mResourcesSpy.getInteger( 169 com.android.internal.R.integer.config_lowPowerStandbyNonInteractiveTimeout)) 170 .thenReturn(STANDBY_TIMEOUT); 171 when(mResourcesSpy.getBoolean( 172 com.android.internal.R.bool.config_lowPowerStandbyEnabledByDefault)) 173 .thenReturn(false); 174 175 FakeSettingsProvider.clearSettingsProvider(); 176 MockContentResolver cr = new MockContentResolver(mContextSpy); 177 cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 178 when(mContextSpy.getContentResolver()).thenReturn(cr); 179 180 when(mUserManagerMock.getUserHandles(true)).thenReturn(List.of( 181 UserHandle.of(USER_ID_1), UserHandle.of(USER_ID_2))); 182 when(mPackageManagerMock.getPackageUid(eq(TEST_PKG1), any())).thenReturn(TEST_PKG1_APP_ID); 183 when(mPackageManagerMock.getPackageUid(eq(TEST_PKG2), any())).thenReturn(TEST_PKG2_APP_ID); 184 when(mPackageManagerMock.getPackageUidAsUser(eq(TEST_PKG1), eq(USER_ID_1))) 185 .thenReturn(TEST_PKG1_APP_ID); 186 when(mPackageManagerMock.getPackageUidAsUser(eq(TEST_PKG2), eq(USER_ID_1))) 187 .thenReturn(TEST_PKG2_APP_ID); 188 189 mClock = new OffsettableClock.Stopped(); 190 mTestLooper = new TestLooper(mClock::now); 191 192 mTestPolicyFile = new File(mContextSpy.getCacheDir(), "lps_policy.xml"); 193 mController = new LowPowerStandbyController(mContextSpy, mTestLooper.getLooper(), 194 () -> mClock.now(), mDeviceConfigWrapperMock, () -> mIActivityManagerMock, 195 mTestPolicyFile); 196 } 197 198 @After tearDown()199 public void tearDown() throws Exception { 200 LocalServices.removeServiceForTest(PowerManagerInternal.class); 201 LocalServices.removeServiceForTest(LowPowerStandbyControllerInternal.class); 202 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); 203 LocalServices.removeServiceForTest(PowerAllowlistInternal.class); 204 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 205 206 mTestPolicyFile.delete(); 207 } 208 209 @Test testOnSystemReady_isInactivate()210 public void testOnSystemReady_isInactivate() { 211 setLowPowerStandbySupportedConfig(true); 212 mController.systemReady(); 213 214 assertThat(mController.isActive()).isFalse(); 215 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 216 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 217 } 218 219 @Test testActivate()220 public void testActivate() throws Exception { 221 setLowPowerStandbySupportedConfig(true); 222 mController.systemReady(); 223 mController.setEnabled(true); 224 setNonInteractive(); 225 setDeviceIdleMode(true); 226 awaitStandbyTimeoutAlarm(); 227 assertThat(mController.isActive()).isTrue(); 228 verify(mPowerManagerInternalMock, times(1)).setLowPowerStandbyActive(true); 229 verify(mNetworkPolicyManagerInternalMock, times(1)).setLowPowerStandbyActive(true); 230 } 231 awaitStandbyTimeoutAlarm()232 private void awaitStandbyTimeoutAlarm() { 233 ArgumentCaptor<Long> timeArg = ArgumentCaptor.forClass(Long.class); 234 ArgumentCaptor<AlarmManager.OnAlarmListener> listenerArg = 235 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 236 verify(mAlarmManagerMock).setExact( 237 eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), 238 timeArg.capture(), anyString(), 239 listenerArg.capture(), any()); 240 mClock.reset(); 241 mClock.fastForward(timeArg.getValue()); 242 listenerArg.getValue().onAlarm(); 243 mTestLooper.dispatchAll(); 244 } 245 246 @Test testOnNonInteractive_notImmediatelyActive()247 public void testOnNonInteractive_notImmediatelyActive() throws Exception { 248 setLowPowerStandbySupportedConfig(true); 249 mController.systemReady(); 250 mController.setEnabled(true); 251 252 setNonInteractive(); 253 mTestLooper.dispatchAll(); 254 255 assertThat(mController.isActive()).isFalse(); 256 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 257 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 258 } 259 260 @Test testOnNonInteractive_activateAfterStandbyTimeout()261 public void testOnNonInteractive_activateAfterStandbyTimeout() throws Exception { 262 setLowPowerStandbySupportedConfig(true); 263 mController.systemReady(); 264 mController.setEnabled(true); 265 266 setNonInteractive(); 267 awaitStandbyTimeoutAlarm(); 268 269 assertThat(mController.isActive()).isTrue(); 270 verify(mPowerManagerInternalMock, times(1)).setLowPowerStandbyActive(true); 271 verify(mNetworkPolicyManagerInternalMock, times(1)).setLowPowerStandbyActive(true); 272 } 273 274 @Test testOnNonInteractive_doesNotActivateWhenBecomingInteractive()275 public void testOnNonInteractive_doesNotActivateWhenBecomingInteractive() throws Exception { 276 setLowPowerStandbySupportedConfig(true); 277 mController.systemReady(); 278 mController.setEnabled(true); 279 280 setNonInteractive(); 281 advanceTime(STANDBY_TIMEOUT / 2); 282 setInteractive(); 283 verifyStandbyAlarmCancelled(); 284 285 assertThat(mController.isActive()).isFalse(); 286 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 287 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 288 } 289 verifyStandbyAlarmCancelled()290 private void verifyStandbyAlarmCancelled() { 291 InOrder inOrder = inOrder(mAlarmManagerMock); 292 inOrder.verify(mAlarmManagerMock, atLeast(0)).setExact(anyInt(), anyLong(), anyString(), 293 any(), any()); 294 inOrder.verify(mAlarmManagerMock).cancel((AlarmManager.OnAlarmListener) any()); 295 inOrder.verifyNoMoreInteractions(); 296 } 297 298 @Test testOnInteractive_deactivate()299 public void testOnInteractive_deactivate() throws Exception { 300 setLowPowerStandbySupportedConfig(true); 301 mController.systemReady(); 302 mController.setEnabled(true); 303 setNonInteractive(); 304 setDeviceIdleMode(true); 305 awaitStandbyTimeoutAlarm(); 306 307 setInteractive(); 308 mTestLooper.dispatchAll(); 309 310 assertThat(mController.isActive()).isFalse(); 311 verify(mPowerManagerInternalMock, times(1)).setLowPowerStandbyActive(false); 312 verify(mNetworkPolicyManagerInternalMock, times(1)).setLowPowerStandbyActive(false); 313 } 314 315 @Test testOnDozeMaintenance_deactivate()316 public void testOnDozeMaintenance_deactivate() throws Exception { 317 setLowPowerStandbySupportedConfig(true); 318 mController.systemReady(); 319 mController.setEnabled(true); 320 mController.setActiveDuringMaintenance(false); 321 setNonInteractive(); 322 setDeviceIdleMode(true); 323 awaitStandbyTimeoutAlarm(); 324 325 setDeviceIdleMode(false); 326 mTestLooper.dispatchAll(); 327 328 assertThat(mController.isActive()).isFalse(); 329 verify(mPowerManagerInternalMock, times(1)).setLowPowerStandbyActive(false); 330 verify(mNetworkPolicyManagerInternalMock, times(1)).setLowPowerStandbyActive(false); 331 } 332 333 @Test testOnDozeMaintenance_activeDuringMaintenance_staysActive()334 public void testOnDozeMaintenance_activeDuringMaintenance_staysActive() throws Exception { 335 setLowPowerStandbySupportedConfig(true); 336 mController.systemReady(); 337 mController.setEnabled(true); 338 mController.setActiveDuringMaintenance(true); 339 setNonInteractive(); 340 setDeviceIdleMode(true); 341 awaitStandbyTimeoutAlarm(); 342 343 setDeviceIdleMode(false); 344 mTestLooper.dispatchAll(); 345 346 assertThat(mController.isActive()).isTrue(); 347 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyActive(false); 348 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyActive(false); 349 } 350 351 @Test testOnDozeMaintenanceEnds_activate()352 public void testOnDozeMaintenanceEnds_activate() throws Exception { 353 setLowPowerStandbySupportedConfig(true); 354 mController.systemReady(); 355 mController.setEnabled(true); 356 setNonInteractive(); 357 setDeviceIdleMode(true); 358 awaitStandbyTimeoutAlarm(); 359 360 setDeviceIdleMode(false); 361 advanceTime(1000); 362 setDeviceIdleMode(true); 363 mTestLooper.dispatchAll(); 364 365 assertThat(mController.isActive()).isTrue(); 366 verify(mPowerManagerInternalMock, times(2)).setLowPowerStandbyActive(true); 367 verify(mNetworkPolicyManagerInternalMock, times(2)).setLowPowerStandbyActive(true); 368 } 369 370 @Test testLowPowerStandbyDisabled_doesNotActivate()371 public void testLowPowerStandbyDisabled_doesNotActivate() throws Exception { 372 setLowPowerStandbySupportedConfig(true); 373 mController.systemReady(); 374 mController.setEnabled(false); 375 setNonInteractive(); 376 377 assertThat(mController.isActive()).isFalse(); 378 verify(mAlarmManagerMock, never()).setExact(anyInt(), anyLong(), anyString(), any(), any()); 379 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 380 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyActive(anyBoolean()); 381 } 382 383 @Test testLowPowerStandbyEnabled_EnabledChangedBroadcastsAreSent()384 public void testLowPowerStandbyEnabled_EnabledChangedBroadcastsAreSent() throws Exception { 385 setLowPowerStandbySupportedConfig(true); 386 mController.systemReady(); 387 388 BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent( 389 PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); 390 mController.setEnabled(false); 391 futureIntent.assertNotReceived(); 392 393 futureIntent = mContextSpy.nextBroadcastIntent( 394 PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); 395 mController.setEnabled(true); 396 assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); 397 398 futureIntent = mContextSpy.nextBroadcastIntent( 399 PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); 400 mController.setEnabled(true); 401 futureIntent.assertNotReceived(); 402 403 futureIntent = mContextSpy.nextBroadcastIntent( 404 PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); 405 406 mController.setEnabled(false); 407 assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); 408 } 409 410 @Test testSetEnabled_WhenNotSupported_DoesNotEnable()411 public void testSetEnabled_WhenNotSupported_DoesNotEnable() throws Exception { 412 setLowPowerStandbySupportedConfig(false); 413 mController.systemReady(); 414 415 mController.setEnabled(true); 416 417 assertThat(mController.isEnabled()).isFalse(); 418 } 419 420 @Test testIsSupported_WhenSupported()421 public void testIsSupported_WhenSupported() throws Exception { 422 setLowPowerStandbySupportedConfig(true); 423 mController.systemReady(); 424 425 assertThat(mController.isSupported()).isTrue(); 426 } 427 428 @Test testIsSupported_WhenNotSupported()429 public void testIsSupported_WhenNotSupported() throws Exception { 430 setLowPowerStandbySupportedConfig(false); 431 mController.systemReady(); 432 433 assertThat(mController.isSupported()).isFalse(); 434 } 435 436 @Test testForceActive()437 public void testForceActive() throws Exception { 438 setLowPowerStandbySupportedConfig(false); 439 mController.systemReady(); 440 441 mController.forceActive(true); 442 mTestLooper.dispatchAll(); 443 444 assertThat(mController.isActive()).isTrue(); 445 verify(mPowerManagerInternalMock).setLowPowerStandbyActive(true); 446 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyActive(true); 447 448 mController.forceActive(false); 449 mTestLooper.dispatchAll(); 450 451 assertThat(mController.isActive()).isFalse(); 452 verify(mPowerManagerInternalMock).setLowPowerStandbyActive(false); 453 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyActive(false); 454 } 455 setLowPowerStandbySupportedConfig(boolean supported)456 private void setLowPowerStandbySupportedConfig(boolean supported) { 457 when(mResourcesSpy.getBoolean( 458 com.android.internal.R.bool.config_lowPowerStandbySupported)) 459 .thenReturn(supported); 460 } 461 462 @Test testSetPolicy()463 public void testSetPolicy() throws Exception { 464 mController.systemReady(); 465 mController.setPolicy(EMPTY_POLICY); 466 assertThat(mController.getPolicy()).isEqualTo(EMPTY_POLICY); 467 } 468 469 @Test testSetDefaultPolicy()470 public void testSetDefaultPolicy() throws Exception { 471 mController.systemReady(); 472 mController.setPolicy(EMPTY_POLICY); 473 mController.setPolicy(null); 474 assertThat(mController.getPolicy()).isNotNull(); 475 assertThat(mController.getPolicy()).isEqualTo(LowPowerStandbyController.DEFAULT_POLICY); 476 } 477 478 @Test testAddToAllowlist_ReasonIsAllowed_servicesAreNotified()479 public void testAddToAllowlist_ReasonIsAllowed_servicesAreNotified() throws Exception { 480 mController.systemReady(); 481 mController.setPolicy( 482 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 483 484 LowPowerStandbyControllerInternal service = LocalServices.getService( 485 LowPowerStandbyControllerInternal.class); 486 service.addToAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 487 mTestLooper.dispatchAll(); 488 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{10}); 489 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{10}); 490 491 service.removeFromAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 492 mTestLooper.dispatchAll(); 493 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 494 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 495 } 496 497 @Test testRemoveFromAllowlist_ReasonIsAllowed_servicesAreNotified()498 public void testRemoveFromAllowlist_ReasonIsAllowed_servicesAreNotified() throws Exception { 499 mController.systemReady(); 500 mController.setPolicy( 501 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 502 503 LowPowerStandbyControllerInternal service = LocalServices.getService( 504 LowPowerStandbyControllerInternal.class); 505 service.addToAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 506 mTestLooper.dispatchAll(); 507 508 service.removeFromAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 509 mTestLooper.dispatchAll(); 510 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 511 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 512 } 513 514 @Test testSetAllowReasons_ActiveExemptionsNoLongerAllowed_servicesAreNotified()515 public void testSetAllowReasons_ActiveExemptionsNoLongerAllowed_servicesAreNotified() { 516 mController.systemReady(); 517 mController.setEnabled(true); 518 mController.setPolicy( 519 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 520 521 LowPowerStandbyControllerInternal service = LocalServices.getService( 522 LowPowerStandbyControllerInternal.class); 523 service.addToAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 524 mTestLooper.dispatchAll(); 525 526 mController.setPolicy(EMPTY_POLICY); 527 mTestLooper.dispatchAll(); 528 529 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 530 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{}); 531 } 532 533 @Test testSetAllowReasons_ReasonBecomesAllowed_servicesAreNotified()534 public void testSetAllowReasons_ReasonBecomesAllowed_servicesAreNotified() throws Exception { 535 mController.systemReady(); 536 mController.setEnabled(true); 537 mController.setPolicy(EMPTY_POLICY); 538 539 LowPowerStandbyControllerInternal service = LocalServices.getService( 540 LowPowerStandbyControllerInternal.class); 541 service.addToAllowlist(10, LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION); 542 mTestLooper.dispatchAll(); 543 544 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyAllowlist(any()); 545 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyAllowlist(any()); 546 547 mController.setPolicy( 548 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 549 mTestLooper.dispatchAll(); 550 551 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{10}); 552 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{10}); 553 } 554 555 @Test testSetAllowReasons_NoActiveExemptions_servicesAreNotNotified()556 public void testSetAllowReasons_NoActiveExemptions_servicesAreNotNotified() throws Exception { 557 mController.systemReady(); 558 mController.setEnabled(true); 559 mController.setPolicy( 560 policyWithAllowedReasons(LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION)); 561 mController.setPolicy(EMPTY_POLICY); 562 mTestLooper.dispatchAll(); 563 564 verify(mPowerManagerInternalMock, never()).setLowPowerStandbyAllowlist(any()); 565 verify(mNetworkPolicyManagerInternalMock, never()).setLowPowerStandbyAllowlist(any()); 566 } 567 568 @Test testSetAllowedFeatures_isAllowedIfDisabled()569 public void testSetAllowedFeatures_isAllowedIfDisabled() throws Exception { 570 mController.systemReady(); 571 mController.setEnabled(false); 572 mTestLooper.dispatchAll(); 573 574 assertTrue(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 575 } 576 577 @Test testSetAllowedFeatures_isAllowedWhenEnabled()578 public void testSetAllowedFeatures_isAllowedWhenEnabled() throws Exception { 579 mController.systemReady(); 580 mController.setEnabled(true); 581 mController.setPolicy(policyWithAllowedFeatures(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 582 mTestLooper.dispatchAll(); 583 584 assertTrue(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 585 } 586 587 @Test testSetAllowedFeatures_isNotAllowed()588 public void testSetAllowedFeatures_isNotAllowed() throws Exception { 589 mController.systemReady(); 590 mController.setEnabled(true); 591 mTestLooper.dispatchAll(); 592 593 assertFalse(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY)); 594 } 595 596 @Test testSetExemptPackages_uidPerUserIsExempt()597 public void testSetExemptPackages_uidPerUserIsExempt() throws Exception { 598 mController.systemReady(); 599 mController.setEnabled(true); 600 mController.setPolicy(policyWithExemptPackages(TEST_PKG1, TEST_PKG2)); 601 mTestLooper.dispatchAll(); 602 603 int[] expectedUidAllowlist = { 604 UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID), 605 UserHandle.getUid(USER_ID_1, TEST_PKG2_APP_ID), 606 UserHandle.getUid(USER_ID_2, TEST_PKG1_APP_ID), 607 UserHandle.getUid(USER_ID_2, TEST_PKG2_APP_ID) 608 }; 609 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(expectedUidAllowlist); 610 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(expectedUidAllowlist); 611 } 612 613 @Test testExemptPackageIsRemoved_servicesAreNotified()614 public void testExemptPackageIsRemoved_servicesAreNotified() throws Exception { 615 mController.systemReady(); 616 mController.setEnabled(true); 617 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 618 mTestLooper.dispatchAll(); 619 620 int[] expectedUidAllowlist = { 621 UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID), 622 UserHandle.getUid(USER_ID_2, TEST_PKG1_APP_ID), 623 }; 624 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(expectedUidAllowlist); 625 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(expectedUidAllowlist); 626 verifyNoMoreInteractions(mPowerManagerInternalMock, mNetworkPolicyManagerInternalMock); 627 628 reset(mPackageManagerMock); 629 when(mPackageManagerMock.getPackageUid(eq(TEST_PKG1), any())) 630 .thenThrow(PackageManager.NameNotFoundException.class); 631 632 Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); 633 intent.setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, TEST_PKG1, null)); 634 intent.putExtra(Intent.EXTRA_REPLACING, false); 635 mContextSpy.sendBroadcast(intent); 636 mTestLooper.dispatchAll(); 637 638 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]); 639 verify(mNetworkPolicyManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]); 640 } 641 642 @Test testUsersChanged_packagesExemptForNewUser()643 public void testUsersChanged_packagesExemptForNewUser() throws Exception { 644 mController.systemReady(); 645 mController.setEnabled(true); 646 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 647 mTestLooper.dispatchAll(); 648 649 InOrder inOrder = inOrder(mPowerManagerInternalMock); 650 651 inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{ 652 UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID), 653 UserHandle.getUid(USER_ID_2, TEST_PKG1_APP_ID), 654 }); 655 inOrder.verifyNoMoreInteractions(); 656 657 when(mUserManagerMock.getUserHandles(true)).thenReturn(List.of(UserHandle.of(USER_ID_1))); 658 Intent intent = new Intent(Intent.ACTION_USER_REMOVED); 659 intent.putExtra(Intent.EXTRA_USER, UserHandle.of(USER_ID_2)); 660 mContextSpy.sendBroadcast(intent); 661 mTestLooper.dispatchAll(); 662 663 inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{ 664 UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID) 665 }); 666 inOrder.verifyNoMoreInteractions(); 667 668 when(mUserManagerMock.getUserHandles(true)).thenReturn( 669 List.of(UserHandle.of(USER_ID_1), UserHandle.of(USER_ID_2))); 670 intent = new Intent(Intent.ACTION_USER_ADDED); 671 intent.putExtra(Intent.EXTRA_USER, UserHandle.of(USER_ID_2)); 672 mContextSpy.sendBroadcast(intent); 673 mTestLooper.dispatchAll(); 674 675 inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{ 676 UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID), 677 UserHandle.getUid(USER_ID_2, TEST_PKG1_APP_ID) 678 }); 679 inOrder.verifyNoMoreInteractions(); 680 } 681 682 @Test testIsExempt_exemptIfDisabled()683 public void testIsExempt_exemptIfDisabled() throws Exception { 684 mController.systemReady(); 685 mController.setEnabled(false); 686 mTestLooper.dispatchAll(); 687 688 assertTrue(mController.isPackageExempt(TEST_PKG1_APP_ID)); 689 } 690 691 @Test testIsExempt_notExemptIfEnabled()692 public void testIsExempt_notExemptIfEnabled() throws Exception { 693 mController.systemReady(); 694 mController.setEnabled(true); 695 mTestLooper.dispatchAll(); 696 697 assertFalse(mController.isPackageExempt(TEST_PKG1_APP_ID)); 698 } 699 700 @Test testAllowReason_tempPowerSaveAllowlist()701 public void testAllowReason_tempPowerSaveAllowlist() throws Exception { 702 mController.systemReady(); 703 mController.setEnabled(true); 704 mController.setPolicy(policyWithAllowedReasons( 705 LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST)); 706 mTestLooper.dispatchAll(); 707 708 ArgumentCaptor<TempAllowlistChangeListener> tempAllowlistChangeListenerArgumentCaptor = 709 ArgumentCaptor.forClass(TempAllowlistChangeListener.class); 710 verify(mPowerAllowlistInternalMock).registerTempAllowlistChangeListener( 711 tempAllowlistChangeListenerArgumentCaptor.capture()); 712 TempAllowlistChangeListener tempAllowlistChangeListener = 713 tempAllowlistChangeListenerArgumentCaptor.getValue(); 714 715 tempAllowlistChangeListener.onAppAdded(TEST_PKG1_APP_ID); 716 mTestLooper.dispatchAll(); 717 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG1_APP_ID}); 718 719 tempAllowlistChangeListener.onAppAdded(TEST_PKG2_APP_ID); 720 mTestLooper.dispatchAll(); 721 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist( 722 new int[]{TEST_PKG1_APP_ID, TEST_PKG2_APP_ID}); 723 724 tempAllowlistChangeListener.onAppRemoved(TEST_PKG1_APP_ID); 725 mTestLooper.dispatchAll(); 726 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG2_APP_ID}); 727 728 mController.setPolicy(EMPTY_POLICY); 729 mTestLooper.dispatchAll(); 730 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]); 731 } 732 733 @Test testAllowReason_ongoingPhoneCallService()734 public void testAllowReason_ongoingPhoneCallService() throws Exception { 735 mController.systemReady(); 736 mController.setEnabled(true); 737 mController.setPolicy(policyWithAllowedReasons( 738 LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL)); 739 mTestLooper.dispatchAll(); 740 741 ArgumentCaptor<IForegroundServiceObserver> fgsObserverCapt = 742 ArgumentCaptor.forClass(IForegroundServiceObserver.class); 743 verify(mIActivityManagerMock).registerForegroundServiceObserver(fgsObserverCapt.capture()); 744 IForegroundServiceObserver fgsObserver = fgsObserverCapt.getValue(); 745 746 when(mActivityManagerInternalMock.hasRunningForegroundService(eq(TEST_PKG1_APP_ID), 747 eq(ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL))).thenReturn(true); 748 fgsObserver.onForegroundStateChanged(null, TEST_PKG1, USER_ID_1, true); 749 mTestLooper.dispatchAll(); 750 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG1_APP_ID}); 751 752 when(mActivityManagerInternalMock.hasRunningForegroundService(eq(TEST_PKG2_APP_ID), 753 eq(ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL))).thenReturn(true); 754 fgsObserver.onForegroundStateChanged(null, TEST_PKG2, USER_ID_1, true); 755 mTestLooper.dispatchAll(); 756 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist( 757 new int[]{TEST_PKG1_APP_ID, TEST_PKG2_APP_ID}); 758 759 when(mActivityManagerInternalMock.hasRunningForegroundService(eq(TEST_PKG1_APP_ID), 760 eq(ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL))).thenReturn(false); 761 fgsObserver.onForegroundStateChanged(null, TEST_PKG1, USER_ID_1, false); 762 mTestLooper.dispatchAll(); 763 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG2_APP_ID}); 764 765 mController.setPolicy(EMPTY_POLICY); 766 mTestLooper.dispatchAll(); 767 verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]); 768 } 769 770 @Test testStandbyPorts_broadcastChangedIfPackageIsExempt()771 public void testStandbyPorts_broadcastChangedIfPackageIsExempt() throws Exception { 772 mController.systemReady(); 773 mController.setEnabled(true); 774 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 775 776 Binder token = new Binder(); 777 BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent( 778 PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED); 779 mController.acquireStandbyPorts(token, TEST_PKG1_APP_ID, List.of(PORT_DESC_1)); 780 mTestLooper.dispatchAll(); 781 assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); 782 783 futureIntent = mContextSpy.nextBroadcastIntent( 784 PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED); 785 mController.releaseStandbyPorts(token); 786 mTestLooper.dispatchAll(); 787 assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); 788 } 789 790 @Test testStandbyPorts_noBroadcastChangedIfPackageIsNotExempt()791 public void testStandbyPorts_noBroadcastChangedIfPackageIsNotExempt() throws Exception { 792 mController.systemReady(); 793 mController.setEnabled(true); 794 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 795 796 BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent( 797 PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED); 798 mController.acquireStandbyPorts(new Binder(), TEST_PKG2_APP_ID, List.of(PORT_DESC_1)); 799 mTestLooper.dispatchAll(); 800 futureIntent.assertNotReceived(); 801 } 802 803 @Test testActiveStandbyPorts_emptyIfDisabled()804 public void testActiveStandbyPorts_emptyIfDisabled() throws Exception { 805 mController.systemReady(); 806 mController.setEnabled(false); 807 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 808 809 mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1)); 810 assertThat(mController.getActiveStandbyPorts()).isEmpty(); 811 } 812 813 @Test testActiveStandbyPorts_emptyIfPackageNotExempt()814 public void testActiveStandbyPorts_emptyIfPackageNotExempt() throws Exception { 815 mController.systemReady(); 816 mController.setEnabled(true); 817 mController.setPolicy(policyWithExemptPackages(TEST_PKG2)); 818 819 mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1)); 820 assertThat(mController.getActiveStandbyPorts()).isEmpty(); 821 } 822 823 @Test testActiveStandbyPorts_activeIfPackageExempt()824 public void testActiveStandbyPorts_activeIfPackageExempt() throws Exception { 825 mController.systemReady(); 826 mController.setEnabled(true); 827 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 828 829 mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1)); 830 mController.acquireStandbyPorts(new Binder(), TEST_PKG2_APP_ID, List.of(PORT_DESC_2)); 831 assertThat(mController.getActiveStandbyPorts()).containsExactly(PORT_DESC_1); 832 } 833 834 @Test testActiveStandbyPorts_removedAfterRelease()835 public void testActiveStandbyPorts_removedAfterRelease() throws Exception { 836 mController.systemReady(); 837 mController.setEnabled(true); 838 mController.setPolicy(policyWithExemptPackages(TEST_PKG1)); 839 Binder token = new Binder(); 840 mController.acquireStandbyPorts(token, TEST_PKG1_APP_ID, List.of(PORT_DESC_1)); 841 mController.releaseStandbyPorts(token); 842 assertThat(mController.getActiveStandbyPorts()).isEmpty(); 843 } 844 setInteractive()845 private void setInteractive() throws Exception { 846 when(mIPowerManagerMock.isInteractive()).thenReturn(true); 847 mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON)); 848 } 849 setNonInteractive()850 private void setNonInteractive() throws Exception { 851 when(mIPowerManagerMock.isInteractive()).thenReturn(false); 852 mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF)); 853 } 854 setDeviceIdleMode(boolean idle)855 private void setDeviceIdleMode(boolean idle) throws Exception { 856 when(mIPowerManagerMock.isDeviceIdleMode()).thenReturn(idle); 857 mContextSpy.sendBroadcast(new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)); 858 } 859 policyWithAllowedReasons(int allowedReasons)860 private LowPowerStandbyPolicy policyWithAllowedReasons(int allowedReasons) { 861 return new LowPowerStandbyPolicy( 862 "Test policy", 863 Collections.emptySet(), 864 allowedReasons, 865 Collections.emptySet() 866 ); 867 } 868 policyWithAllowedFeatures(String... allowedFeatures)869 private LowPowerStandbyPolicy policyWithAllowedFeatures(String... allowedFeatures) { 870 return new LowPowerStandbyPolicy( 871 "Test policy", 872 Collections.emptySet(), 873 0, 874 new ArraySet<>(allowedFeatures) 875 ); 876 } 877 policyWithExemptPackages(String... exemptPackages)878 private LowPowerStandbyPolicy policyWithExemptPackages(String... exemptPackages) { 879 return new LowPowerStandbyPolicy( 880 "Test policy", 881 new ArraySet<>(exemptPackages), 882 0, 883 Collections.emptySet() 884 ); 885 } 886 advanceTime(long timeMs)887 private void advanceTime(long timeMs) { 888 mClock.fastForward(timeMs); 889 mTestLooper.dispatchAll(); 890 } 891 892 /** 893 * Creates a mock and registers it to {@link LocalServices}. 894 */ addLocalServiceMock(Class<T> clazz, T mock)895 private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { 896 LocalServices.removeServiceForTest(clazz); 897 LocalServices.addService(clazz, mock); 898 } 899 } 900