1 /* 2 * Copyright (C) 20019 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; 18 19 import static android.Manifest.permission.MODIFY_DAY_NIGHT_MODE; 20 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_DAY; 21 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT; 22 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_OFF; 23 import static android.app.UiModeManager.MODE_NIGHT_AUTO; 24 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM; 25 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME; 26 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE; 27 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN; 28 import static android.app.UiModeManager.MODE_NIGHT_NO; 29 import static android.app.UiModeManager.MODE_NIGHT_YES; 30 import static android.app.UiModeManager.PROJECTION_TYPE_ALL; 31 import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE; 32 import static android.app.UiModeManager.PROJECTION_TYPE_NONE; 33 34 import static com.android.server.UiModeManagerService.SUPPORTED_NIGHT_MODE_CUSTOM_TYPES; 35 36 import static com.google.common.truth.Truth.assertThat; 37 38 import static junit.framework.Assert.fail; 39 import static junit.framework.TestCase.assertFalse; 40 import static junit.framework.TestCase.assertTrue; 41 42 import static org.hamcrest.Matchers.contains; 43 import static org.hamcrest.Matchers.empty; 44 import static org.junit.Assert.assertEquals; 45 import static org.junit.Assert.assertThat; 46 import static org.mockito.ArgumentMatchers.any; 47 import static org.mockito.ArgumentMatchers.anyInt; 48 import static org.mockito.ArgumentMatchers.anyLong; 49 import static org.mockito.ArgumentMatchers.anyString; 50 import static org.mockito.ArgumentMatchers.eq; 51 import static org.mockito.ArgumentMatchers.notNull; 52 import static org.mockito.ArgumentMatchers.nullable; 53 import static org.mockito.BDDMockito.given; 54 import static org.mockito.Mockito.atLeast; 55 import static org.mockito.Mockito.atLeastOnce; 56 import static org.mockito.Mockito.doAnswer; 57 import static org.mockito.Mockito.doReturn; 58 import static org.mockito.Mockito.doThrow; 59 import static org.mockito.Mockito.mock; 60 import static org.mockito.Mockito.never; 61 import static org.mockito.Mockito.spy; 62 import static org.mockito.Mockito.times; 63 import static org.mockito.Mockito.verify; 64 import static org.mockito.Mockito.verifyNoMoreInteractions; 65 import static org.mockito.Mockito.verifyZeroInteractions; 66 import static org.mockito.Mockito.when; 67 import static org.testng.Assert.assertThrows; 68 69 import android.Manifest; 70 import android.app.Activity; 71 import android.app.AlarmManager; 72 import android.app.Flags; 73 import android.app.IOnProjectionStateChangedListener; 74 import android.app.IUiModeManager; 75 import android.content.BroadcastReceiver; 76 import android.content.Context; 77 import android.content.Intent; 78 import android.content.IntentFilter; 79 import android.content.pm.PackageManager; 80 import android.content.res.Configuration; 81 import android.content.res.Resources; 82 import android.os.Bundle; 83 import android.os.Handler; 84 import android.os.IBinder; 85 import android.os.IpcDataCache; 86 import android.os.PowerManager; 87 import android.os.PowerManagerInternal; 88 import android.os.PowerSaveState; 89 import android.os.Process; 90 import android.os.RemoteException; 91 import android.os.UserHandle; 92 import android.os.test.FakePermissionEnforcer; 93 import android.platform.test.annotations.EnableFlags; 94 import android.platform.test.flag.junit.SetFlagsRule; 95 import android.provider.Settings; 96 import android.service.dreams.DreamManagerInternal; 97 import android.test.mock.MockContentResolver; 98 import android.testing.AndroidTestingRunner; 99 import android.testing.TestableLooper; 100 101 import com.android.internal.util.test.FakeSettingsProvider; 102 import com.android.server.twilight.TwilightListener; 103 import com.android.server.twilight.TwilightManager; 104 import com.android.server.twilight.TwilightState; 105 import com.android.server.wm.WindowManagerInternal; 106 107 import org.junit.Before; 108 import org.junit.Ignore; 109 import org.junit.Rule; 110 import org.junit.Test; 111 import org.junit.runner.RunWith; 112 import org.mockito.ArgumentCaptor; 113 import org.mockito.Captor; 114 import org.mockito.Mock; 115 import org.mockito.Spy; 116 117 import java.time.LocalDateTime; 118 import java.time.LocalTime; 119 import java.time.ZoneId; 120 import java.util.List; 121 import java.util.Map; 122 import java.util.function.Consumer; 123 124 @RunWith(AndroidTestingRunner.class) 125 @TestableLooper.RunWithLooper 126 public class UiModeManagerServiceTest extends UiServiceTestCase { 127 private static final String PACKAGE_NAME = "Diane Coffee"; 128 private UiModeManagerService mUiManagerService; 129 private IUiModeManager mService; 130 private MockContentResolver mContentResolver; 131 @Mock 132 private WindowManagerInternal mWindowManager; 133 @Mock 134 private Context mContext; 135 @Mock 136 private Resources mResources; 137 @Mock 138 private TwilightManager mTwilightManager; 139 @Mock 140 private PowerManager.WakeLock mWakeLock; 141 @Mock 142 private AlarmManager mAlarmManager; 143 @Mock 144 private PowerManager mPowerManager; 145 @Mock 146 private TwilightState mTwilightState; 147 @Mock 148 PowerManagerInternal mLocalPowerManager; 149 150 @Mock 151 DreamManagerInternal mDreamManagerInternal; 152 @Mock 153 private PackageManager mPackageManager; 154 @Mock 155 private IBinder mBinder; 156 @Spy 157 private TestInjector mInjector; 158 @Captor 159 private ArgumentCaptor<Intent> mOrderedBroadcastIntent; 160 @Captor 161 private ArgumentCaptor<BroadcastReceiver> mOrderedBroadcastReceiver; 162 163 private BroadcastReceiver mScreenOffCallback; 164 private BroadcastReceiver mDreamingStartedCallback; 165 private BroadcastReceiver mTimeChangedCallback; 166 private BroadcastReceiver mDockStateChangedCallback; 167 private AlarmManager.OnAlarmListener mCustomListener; 168 private Consumer<PowerSaveState> mPowerSaveConsumer; 169 private TwilightListener mTwilightListener; 170 private FakePermissionEnforcer mPermissionEnforcer; 171 172 @Rule 173 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule( 174 SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT); 175 176 177 @Before disableProcessCaches()178 public void disableProcessCaches() { 179 IpcDataCache.disableForTestMode(); 180 } 181 182 @Before setUp()183 public void setUp() { 184 // The AIDL stub will use PermissionEnforcer to check permission from the caller. 185 mPermissionEnforcer = new FakePermissionEnforcer(); 186 mPermissionEnforcer.grant(Manifest.permission.MODIFY_DAY_NIGHT_MODE); 187 mPermissionEnforcer.grant(Manifest.permission.READ_PROJECTION_STATE); 188 doReturn(mPermissionEnforcer).when(mContext).getSystemService( 189 eq(Context.PERMISSION_ENFORCER_SERVICE)); 190 doAnswer(inv -> { 191 mTwilightListener = (TwilightListener) inv.getArgument(0); 192 return null; 193 }).when(mTwilightManager).registerListener(any(), any()); 194 doAnswer(inv -> { 195 mPowerSaveConsumer = (Consumer<PowerSaveState>) inv.getArgument(1); 196 return null; 197 }).when(mLocalPowerManager).registerLowPowerModeObserver(anyInt(), any()); 198 when(mLocalPowerManager.getLowPowerState(anyInt())) 199 .thenReturn(new PowerSaveState.Builder().setBatterySaverEnabled(false).build()); 200 when(mContext.getResources()).thenReturn(mResources); 201 when(mResources.getString(com.android.internal.R.string.config_somnambulatorComponent)) 202 .thenReturn("somnambulator"); 203 mContentResolver = new MockContentResolver(); 204 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 205 when(mContext.getContentResolver()).thenReturn(mContentResolver); 206 when(mContext.getPackageManager()).thenReturn(mPackageManager); 207 when(mPowerManager.isInteractive()).thenReturn(true); 208 when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock); 209 when(mTwilightManager.getLastTwilightState()).thenReturn(mTwilightState); 210 when(mTwilightState.isNight()).thenReturn(true); 211 when(mContext.registerReceiver(notNull(), notNull())).then(inv -> { 212 IntentFilter filter = inv.getArgument(1); 213 if (filter.hasAction(Intent.ACTION_TIMEZONE_CHANGED)) { 214 mTimeChangedCallback = inv.getArgument(0); 215 } 216 if (filter.hasAction(Intent.ACTION_SCREEN_OFF)) { 217 mScreenOffCallback = inv.getArgument(0); 218 } 219 if (filter.hasAction(Intent.ACTION_DREAMING_STARTED)) { 220 mDreamingStartedCallback = inv.getArgument(0); 221 } 222 if (filter.hasAction(Intent.ACTION_DOCK_EVENT)) { 223 mDockStateChangedCallback = inv.getArgument(0); 224 } 225 return null; 226 }); 227 doAnswer(inv -> { 228 mCustomListener = inv.getArgument(3); 229 return null; 230 }).when(mAlarmManager).setExact(anyInt(), anyLong(), anyString(), 231 any(AlarmManager.OnAlarmListener.class), any(Handler.class)); 232 233 doAnswer(inv -> { 234 mCustomListener = () -> {}; 235 return null; 236 }).when(mAlarmManager).cancel(eq(mCustomListener)); 237 when(mContext.getSystemService(eq(Context.POWER_SERVICE))) 238 .thenReturn(mPowerManager); 239 when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 240 when(mContext.getSystemService(eq(Context.ALARM_SERVICE))) 241 .thenReturn(mAlarmManager); 242 addLocalService(WindowManagerInternal.class, mWindowManager); 243 addLocalService(PowerManagerInternal.class, mLocalPowerManager); 244 addLocalService(TwilightManager.class, mTwilightManager); 245 addLocalService(DreamManagerInternal.class, mDreamManagerInternal); 246 247 mInjector = spy(new TestInjector()); 248 mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true, 249 mTwilightManager, mInjector); 250 try { 251 mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 252 } catch (SecurityException e) {/* ignore for permission denial */} 253 mService = mUiManagerService.getService(); 254 } 255 addLocalService(Class<T> clazz, T service)256 private <T> void addLocalService(Class<T> clazz, T service) { 257 LocalServices.removeServiceForTest(clazz); 258 LocalServices.addService(clazz, service); 259 } 260 261 @Ignore // b/152719290 - Fails on stage-aosp-master 262 @Test setNightModeActivated_overridesFunctionCorrectly()263 public void setNightModeActivated_overridesFunctionCorrectly() throws RemoteException { 264 // set up 265 when(mPowerManager.isInteractive()).thenReturn(false); 266 mService.setNightMode(MODE_NIGHT_NO); 267 assertFalse(mUiManagerService.getConfiguration().isNightModeActive()); 268 269 // assume it is day time 270 doReturn(false).when(mTwilightState).isNight(); 271 272 // set mode to auto 273 mService.setNightMode(MODE_NIGHT_AUTO); 274 275 // set night mode on overriding current config 276 mService.setNightModeActivated(true); 277 278 assertTrue(mUiManagerService.getConfiguration().isNightModeActive()); 279 280 // now it is night time 281 doReturn(true).when(mTwilightState).isNight(); 282 mTwilightListener.onTwilightStateChanged(mTwilightState); 283 284 assertTrue(mUiManagerService.getConfiguration().isNightModeActive()); 285 286 // now it is next day mid day 287 doReturn(false).when(mTwilightState).isNight(); 288 mTwilightListener.onTwilightStateChanged(mTwilightState); 289 290 assertFalse(mUiManagerService.getConfiguration().isNightModeActive()); 291 } 292 293 @Test setNightModeActivated_true_withCustomModeBedtime_shouldOverrideNightModeCorrectly()294 public void setNightModeActivated_true_withCustomModeBedtime_shouldOverrideNightModeCorrectly() 295 throws RemoteException { 296 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 297 assertFalse(mUiManagerService.getConfiguration().isNightModeActive()); 298 299 mService.setNightModeActivated(true); 300 301 assertThat(mUiManagerService.getConfiguration().isNightModeActive()).isTrue(); 302 } 303 304 @Test setNightModeActivated_false_withCustomModeBedtime_shouldOverrideNightModeCorrectly()305 public void setNightModeActivated_false_withCustomModeBedtime_shouldOverrideNightModeCorrectly() 306 throws RemoteException { 307 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 308 assertFalse(mUiManagerService.getConfiguration().isNightModeActive()); 309 310 mService.setNightModeActivated(true); 311 mService.setNightModeActivated(false); 312 313 assertThat(mUiManagerService.getConfiguration().isNightModeActive()).isFalse(); 314 } 315 316 @Test setAutoMode_deviceInactiveRegistered()317 public void setAutoMode_deviceInactiveRegistered() throws RemoteException { 318 try { 319 mService.setNightMode(MODE_NIGHT_NO); 320 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 321 mService.setNightMode(MODE_NIGHT_AUTO); 322 verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class), any()); 323 } 324 325 @Ignore // b/152719290 - Fails on stage-aosp-master 326 @Test setAutoMode_deviceInactiveUnRegistered()327 public void setAutoMode_deviceInactiveUnRegistered() throws RemoteException { 328 try { 329 mService.setNightMode(MODE_NIGHT_AUTO); 330 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 331 try { 332 mService.setNightMode(MODE_NIGHT_NO); 333 } catch (SecurityException e) { /*we should ignore this update config exception*/ } 334 given(mContext.registerReceiver(any(), any())).willThrow(SecurityException.class); 335 verify(mContext, atLeastOnce()).unregisterReceiver(any(BroadcastReceiver.class)); 336 } 337 338 @Test setNightModeCustomType_bedtime_shouldNotActivateNightMode()339 public void setNightModeCustomType_bedtime_shouldNotActivateNightMode() throws RemoteException { 340 try { 341 mService.setNightMode(MODE_NIGHT_NO); 342 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 343 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 344 345 assertThat(isNightModeActivated()).isFalse(); 346 } 347 348 @Test setNightModeCustomType_noPermission_shouldThrow()349 public void setNightModeCustomType_noPermission_shouldThrow() throws RemoteException { 350 mPermissionEnforcer.revoke(MODIFY_DAY_NIGHT_MODE); 351 352 assertThrows(SecurityException.class, 353 () -> mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME)); 354 } 355 356 @Test setNightModeCustomType_customTypeUnknown_shouldThrow()357 public void setNightModeCustomType_customTypeUnknown_shouldThrow() throws RemoteException { 358 assertThrows(IllegalArgumentException.class, 359 () -> mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN)); 360 } 361 362 @Test setNightModeCustomType_customTypeUnsupported_shouldThrow()363 public void setNightModeCustomType_customTypeUnsupported_shouldThrow() throws RemoteException { 364 assertThrows(IllegalArgumentException.class, 365 () -> { 366 int maxSupportedCustomType = 0; 367 for (Integer supportedType : SUPPORTED_NIGHT_MODE_CUSTOM_TYPES) { 368 maxSupportedCustomType = Math.max(maxSupportedCustomType, supportedType); 369 } 370 mService.setNightModeCustomType(maxSupportedCustomType + 1); 371 }); 372 } 373 374 @Test setNightModeCustomType_bedtime_shouldHaveNoScreenOffRegistered()375 public void setNightModeCustomType_bedtime_shouldHaveNoScreenOffRegistered() 376 throws RemoteException { 377 try { 378 mService.setNightMode(MODE_NIGHT_NO); 379 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 380 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 381 ArgumentCaptor<IntentFilter> intentFiltersCaptor = ArgumentCaptor.forClass( 382 IntentFilter.class); 383 verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class), 384 intentFiltersCaptor.capture()); 385 386 List<IntentFilter> intentFilters = intentFiltersCaptor.getAllValues(); 387 for (IntentFilter intentFilter : intentFilters) { 388 assertThat(intentFilter.hasAction(Intent.ACTION_SCREEN_OFF)).isFalse(); 389 } 390 } 391 392 @Test setNightModeActivated_fromNoToYesAndBack()393 public void setNightModeActivated_fromNoToYesAndBack() throws RemoteException { 394 mService.setNightMode(MODE_NIGHT_NO); 395 mService.setNightModeActivated(true); 396 assertTrue(isNightModeActivated()); 397 mService.setNightModeActivated(false); 398 assertFalse(isNightModeActivated()); 399 } 400 401 @Test setNightModeActivated_permissionToChangeOtherUsers()402 public void setNightModeActivated_permissionToChangeOtherUsers() throws RemoteException { 403 SystemService.TargetUser user = mock(SystemService.TargetUser.class); 404 doReturn(9).when(user).getUserIdentifier(); 405 mUiManagerService.onUserSwitching(user, user); 406 when(mContext.checkCallingOrSelfPermission( 407 eq(Manifest.permission.INTERACT_ACROSS_USERS))) 408 .thenReturn(PackageManager.PERMISSION_DENIED); 409 assertFalse(mService.setNightModeActivated(true)); 410 } 411 412 @Test setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_shouldActivate()413 public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_shouldActivate() 414 throws RemoteException { 415 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 416 mService.setNightModeActivatedForCustomMode( 417 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 418 419 assertThat(isNightModeActivated()).isTrue(); 420 } 421 422 @Test setNightModeActivatedForCustomMode_customTypeBedtime_withParamOffAndBedtime_shouldDeactivate()423 public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOffAndBedtime_shouldDeactivate() 424 throws RemoteException { 425 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 426 mService.setNightModeActivatedForCustomMode( 427 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */); 428 429 assertThat(isNightModeActivated()).isFalse(); 430 } 431 432 @Test setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndSchedule_shouldNotActivate()433 public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndSchedule_shouldNotActivate() 434 throws RemoteException { 435 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 436 mService.setNightModeActivatedForCustomMode( 437 MODE_NIGHT_CUSTOM_TYPE_SCHEDULE, true /* active */); 438 439 assertThat(isNightModeActivated()).isFalse(); 440 } 441 442 @Test setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_shouldNotActivate()443 public void setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_shouldNotActivate() 444 throws RemoteException { 445 mService.setNightMode(MODE_NIGHT_CUSTOM); 446 mService.setNightModeActivatedForCustomMode( 447 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 448 449 assertThat(isNightModeActivated()).isFalse(); 450 } 451 452 @Test setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_thenCustomTypeBedtime_shouldActivate()453 public void setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_thenCustomTypeBedtime_shouldActivate() 454 throws RemoteException { 455 mService.setNightMode(MODE_NIGHT_CUSTOM); 456 mService.setNightModeActivatedForCustomMode( 457 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 458 459 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 460 461 assertThat(isNightModeActivated()).isTrue(); 462 } 463 464 @Test setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeSchedule_shouldKeepNightModeActivate()465 public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeSchedule_shouldKeepNightModeActivate() 466 throws RemoteException { 467 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 468 mService.setNightModeActivatedForCustomMode( 469 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 470 471 mService.setNightMode(MODE_NIGHT_CUSTOM); 472 LocalTime now = LocalTime.now(); 473 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 474 mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000); 475 476 assertThat(isNightModeActivated()).isTrue(); 477 } 478 479 @Test setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeScheduleAndScreenOff_shouldDeactivateNightMode()480 public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeScheduleAndScreenOff_shouldDeactivateNightMode() 481 throws RemoteException { 482 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 483 mService.setNightModeActivatedForCustomMode( 484 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 485 486 mService.setNightMode(MODE_NIGHT_CUSTOM); 487 LocalTime now = LocalTime.now(); 488 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 489 mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000); 490 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 491 492 assertThat(isNightModeActivated()).isFalse(); 493 } 494 495 @Test autoNightModeSwitch_batterySaverOn()496 public void autoNightModeSwitch_batterySaverOn() throws RemoteException { 497 mService.setNightMode(MODE_NIGHT_NO); 498 when(mTwilightState.isNight()).thenReturn(false); 499 mService.setNightMode(MODE_NIGHT_AUTO); 500 501 // night NO 502 assertFalse(isNightModeActivated()); 503 504 mPowerSaveConsumer.accept( 505 new PowerSaveState.Builder().setBatterySaverEnabled(true).build()); 506 507 // night YES 508 assertTrue(isNightModeActivated()); 509 } 510 511 @Test nightModeCustomBedtime_batterySaverOn_notInBedtime_shouldActivateNightMode()512 public void nightModeCustomBedtime_batterySaverOn_notInBedtime_shouldActivateNightMode() 513 throws RemoteException { 514 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 515 516 mPowerSaveConsumer.accept( 517 new PowerSaveState.Builder().setBatterySaverEnabled(true).build()); 518 519 assertThat(isNightModeActivated()).isTrue(); 520 } 521 522 @Test nightModeCustomBedtime_batterySaverOn_afterBedtime_shouldKeepNightModeActivated()523 public void nightModeCustomBedtime_batterySaverOn_afterBedtime_shouldKeepNightModeActivated() 524 throws RemoteException { 525 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 526 mPowerSaveConsumer.accept( 527 new PowerSaveState.Builder().setBatterySaverEnabled(true).build()); 528 529 mService.setNightModeActivatedForCustomMode( 530 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */); 531 532 assertThat(isNightModeActivated()).isTrue(); 533 } 534 535 @Test nightModeBedtime_duringBedtime_batterySaverOnThenOff_shouldKeepNightModeActivated()536 public void nightModeBedtime_duringBedtime_batterySaverOnThenOff_shouldKeepNightModeActivated() 537 throws RemoteException { 538 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 539 mService.setNightModeActivatedForCustomMode( 540 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 541 542 mPowerSaveConsumer.accept( 543 new PowerSaveState.Builder().setBatterySaverEnabled(true).build()); 544 mPowerSaveConsumer.accept( 545 new PowerSaveState.Builder().setBatterySaverEnabled(false).build()); 546 547 assertThat(isNightModeActivated()).isTrue(); 548 } 549 550 @Test nightModeCustomBedtime_duringBedtime_batterySaverOnThenOff_finallyAfterBedtime_shouldDeactivateNightMode()551 public void nightModeCustomBedtime_duringBedtime_batterySaverOnThenOff_finallyAfterBedtime_shouldDeactivateNightMode() 552 throws RemoteException { 553 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 554 mService.setNightModeActivatedForCustomMode( 555 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 556 mPowerSaveConsumer.accept( 557 new PowerSaveState.Builder().setBatterySaverEnabled(true).build()); 558 mPowerSaveConsumer.accept( 559 new PowerSaveState.Builder().setBatterySaverEnabled(false).build()); 560 561 mService.setNightModeActivatedForCustomMode( 562 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */); 563 564 assertThat(isNightModeActivated()).isFalse(); 565 } 566 567 @Test nightModeCustomBedtime_duringBedtime_changeModeToNo_shouldDeactivateNightMode()568 public void nightModeCustomBedtime_duringBedtime_changeModeToNo_shouldDeactivateNightMode() 569 throws RemoteException { 570 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 571 mService.setNightModeActivatedForCustomMode( 572 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 573 574 mService.setNightMode(MODE_NIGHT_NO); 575 576 assertThat(isNightModeActivated()).isFalse(); 577 } 578 579 @Test nightModeCustomBedtime_duringBedtime_changeModeToNoAndThenExitBedtime_shouldKeepNightModeDeactivated()580 public void nightModeCustomBedtime_duringBedtime_changeModeToNoAndThenExitBedtime_shouldKeepNightModeDeactivated() 581 throws RemoteException { 582 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 583 mService.setNightModeActivatedForCustomMode( 584 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 585 mService.setNightMode(MODE_NIGHT_NO); 586 587 mService.setNightModeActivatedForCustomMode( 588 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */); 589 590 assertThat(isNightModeActivated()).isFalse(); 591 } 592 593 @Test nightModeCustomBedtime_duringBedtime_changeModeToYes_shouldKeepNightModeActivated()594 public void nightModeCustomBedtime_duringBedtime_changeModeToYes_shouldKeepNightModeActivated() 595 throws RemoteException { 596 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 597 mService.setNightModeActivatedForCustomMode( 598 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 599 600 mService.setNightMode(MODE_NIGHT_YES); 601 602 assertThat(isNightModeActivated()).isTrue(); 603 } 604 605 @Test nightModeCustomBedtime_duringBedtime_changeModeToYesAndThenExitBedtime_shouldKeepNightModeActivated()606 public void nightModeCustomBedtime_duringBedtime_changeModeToYesAndThenExitBedtime_shouldKeepNightModeActivated() 607 throws RemoteException { 608 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 609 mService.setNightModeActivatedForCustomMode( 610 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 611 612 mService.setNightMode(MODE_NIGHT_YES); 613 mService.setNightModeActivatedForCustomMode( 614 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */); 615 616 assertThat(isNightModeActivated()).isTrue(); 617 } 618 619 @Test nightModeNo_duringBedtime_shouldKeepNightModeDeactivated()620 public void nightModeNo_duringBedtime_shouldKeepNightModeDeactivated() 621 throws RemoteException { 622 mService.setNightMode(MODE_NIGHT_NO); 623 624 mService.setNightModeActivatedForCustomMode( 625 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 626 627 assertThat(isNightModeActivated()).isFalse(); 628 } 629 630 @Test nightModeNo_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode()631 public void nightModeNo_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode() 632 throws RemoteException { 633 mService.setNightMode(MODE_NIGHT_NO); 634 635 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 636 mService.setNightModeActivatedForCustomMode( 637 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 638 639 assertThat(isNightModeActivated()).isTrue(); 640 } 641 642 @Test nightModeYes_thenChangeToCustomTypeBedtime_shouldDeactivateNightMode()643 public void nightModeYes_thenChangeToCustomTypeBedtime_shouldDeactivateNightMode() 644 throws RemoteException { 645 mService.setNightMode(MODE_NIGHT_YES); 646 647 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 648 649 assertThat(isNightModeActivated()).isFalse(); 650 } 651 652 @Test nightModeYes_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode()653 public void nightModeYes_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode() 654 throws RemoteException { 655 mService.setNightMode(MODE_NIGHT_YES); 656 657 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 658 mService.setNightModeActivatedForCustomMode( 659 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 660 661 assertThat(isNightModeActivated()).isTrue(); 662 } 663 664 @Test nightModeAuto_thenChangeToCustomTypeBedtime_notInBedtime_shouldDeactivateNightMode()665 public void nightModeAuto_thenChangeToCustomTypeBedtime_notInBedtime_shouldDeactivateNightMode() 666 throws RemoteException { 667 // set mode to auto 668 mService.setNightMode(MODE_NIGHT_AUTO); 669 mService.setNightModeActivated(true); 670 // now it is night time 671 doReturn(true).when(mTwilightState).isNight(); 672 mTwilightListener.onTwilightStateChanged(mTwilightState); 673 674 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 675 676 assertThat(isNightModeActivated()).isFalse(); 677 } 678 679 @Test nightModeAuto_thenChangeToCustomTypeBedtime_duringBedtime_shouldActivateNightMode()680 public void nightModeAuto_thenChangeToCustomTypeBedtime_duringBedtime_shouldActivateNightMode() 681 throws RemoteException { 682 // set mode to auto 683 mService.setNightMode(MODE_NIGHT_AUTO); 684 mService.setNightModeActivated(true); 685 // now it is night time 686 doReturn(true).when(mTwilightState).isNight(); 687 mTwilightListener.onTwilightStateChanged(mTwilightState); 688 689 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 690 mService.setNightModeActivatedForCustomMode( 691 MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */); 692 693 assertThat(isNightModeActivated()).isTrue(); 694 } 695 696 @Test setAutoMode_clearCache()697 public void setAutoMode_clearCache() throws RemoteException { 698 try { 699 mService.setNightMode(MODE_NIGHT_AUTO); 700 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 701 try { 702 mService.setNightMode(MODE_NIGHT_NO); 703 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 704 verify(mWindowManager).clearSnapshotCache(); 705 } 706 707 @Test setNightModeActive_fromNightModeYesToNoWhenFalse()708 public void setNightModeActive_fromNightModeYesToNoWhenFalse() throws RemoteException { 709 try { 710 mService.setNightMode(MODE_NIGHT_YES); 711 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 712 try { 713 mService.setNightModeActivated(false); 714 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 715 assertEquals(MODE_NIGHT_NO, mService.getNightMode()); 716 } 717 718 @Test setNightModeActive_fromNightModeNoToYesWhenTrue()719 public void setNightModeActive_fromNightModeNoToYesWhenTrue() throws RemoteException { 720 try { 721 mService.setNightMode(MODE_NIGHT_NO); 722 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 723 try { 724 mService.setNightModeActivated(true); 725 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 726 assertEquals(MODE_NIGHT_YES, mService.getNightMode()); 727 } 728 729 @Test setNightModeActive_autoNightModeNoChanges()730 public void setNightModeActive_autoNightModeNoChanges() throws RemoteException { 731 try { 732 mService.setNightMode(MODE_NIGHT_AUTO); 733 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 734 try { 735 mService.setNightModeActivated(true); 736 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 737 assertEquals(MODE_NIGHT_AUTO, mService.getNightMode()); 738 } 739 740 @Test getNightModeCustomType_nightModeNo_shouldReturnUnknown()741 public void getNightModeCustomType_nightModeNo_shouldReturnUnknown() throws RemoteException { 742 try { 743 mService.setNightMode(MODE_NIGHT_NO); 744 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 745 746 assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN); 747 } 748 749 @Test getNightModeCustomType_nightModeYes_shouldReturnUnknown()750 public void getNightModeCustomType_nightModeYes_shouldReturnUnknown() throws RemoteException { 751 try { 752 mService.setNightMode(MODE_NIGHT_YES); 753 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 754 755 assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN); 756 } 757 758 @Test getNightModeCustomType_nightModeAuto_shouldReturnUnknown()759 public void getNightModeCustomType_nightModeAuto_shouldReturnUnknown() throws RemoteException { 760 try { 761 mService.setNightMode(MODE_NIGHT_AUTO); 762 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 763 764 assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN); 765 } 766 767 @Test getNightModeCustomType_nightModeCustom_shouldReturnSchedule()768 public void getNightModeCustomType_nightModeCustom_shouldReturnSchedule() 769 throws RemoteException { 770 try { 771 mService.setNightMode(MODE_NIGHT_CUSTOM); 772 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 773 774 assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_SCHEDULE); 775 } 776 777 @Test getNightModeCustomType_nightModeCustomBedtime_shouldReturnBedtime()778 public void getNightModeCustomType_nightModeCustomBedtime_shouldReturnBedtime() 779 throws RemoteException { 780 try { 781 mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 782 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 783 784 assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_BEDTIME); 785 } 786 787 @Test getNightModeCustomType_permissionNotGranted_shouldThrow()788 public void getNightModeCustomType_permissionNotGranted_shouldThrow() 789 throws RemoteException { 790 mPermissionEnforcer.revoke(MODIFY_DAY_NIGHT_MODE); 791 792 assertThrows(SecurityException.class, () -> mService.getNightModeCustomType()); 793 } 794 795 @Test isNightModeActive_nightModeYes()796 public void isNightModeActive_nightModeYes() throws RemoteException { 797 try { 798 mService.setNightMode(MODE_NIGHT_YES); 799 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 800 assertTrue(isNightModeActivated()); 801 } 802 803 @Test isNightModeActive_nightModeNo()804 public void isNightModeActive_nightModeNo() throws RemoteException { 805 try { 806 mService.setNightMode(MODE_NIGHT_NO); 807 } catch (SecurityException e) { /* we should ignore this update config exception*/ } 808 assertFalse(isNightModeActivated()); 809 } 810 811 @Test customTime_darkThemeOn_afterScreenOff()812 public void customTime_darkThemeOn_afterScreenOff() throws RemoteException { 813 LocalTime now = LocalTime.now(); 814 mService.setNightMode(MODE_NIGHT_NO); 815 mService.setCustomNightModeStart(now.minusHours(1L).toNanoOfDay() / 1000); 816 mService.setCustomNightModeEnd(now.plusHours(1L).toNanoOfDay() / 1000); 817 mService.setNightMode(MODE_NIGHT_CUSTOM); 818 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 819 assertTrue(isNightModeActivated()); 820 } 821 822 @Test customTime_darkThemeOff_afterScreenOff()823 public void customTime_darkThemeOff_afterScreenOff() throws RemoteException { 824 LocalTime now = LocalTime.now(); 825 mService.setNightMode(MODE_NIGHT_YES); 826 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 827 mService.setCustomNightModeEnd(now.minusHours(1L).toNanoOfDay() / 1000); 828 mService.setNightMode(MODE_NIGHT_CUSTOM); 829 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 830 assertFalse(isNightModeActivated()); 831 } 832 833 @Test customTime_darkThemeOn_afterDreamingStarted()834 public void customTime_darkThemeOn_afterDreamingStarted() throws RemoteException { 835 LocalTime now = LocalTime.now(); 836 mService.setNightMode(MODE_NIGHT_NO); 837 mService.setCustomNightModeStart(now.minusHours(1L).toNanoOfDay() / 1000); 838 mService.setCustomNightModeEnd(now.plusHours(1L).toNanoOfDay() / 1000); 839 mService.setNightMode(MODE_NIGHT_CUSTOM); 840 mDreamingStartedCallback.onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STARTED)); 841 assertTrue(isNightModeActivated()); 842 } 843 844 @Test customTime_darkThemeOff_afterDreamingStarted()845 public void customTime_darkThemeOff_afterDreamingStarted() throws RemoteException { 846 LocalTime now = LocalTime.now(); 847 mService.setNightMode(MODE_NIGHT_YES); 848 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 849 mService.setCustomNightModeEnd(now.minusHours(1L).toNanoOfDay() / 1000); 850 mService.setNightMode(MODE_NIGHT_CUSTOM); 851 mDreamingStartedCallback.onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STARTED)); 852 assertFalse(isNightModeActivated()); 853 } 854 855 @Test customTime_darkThemeOff_afterStartEnd()856 public void customTime_darkThemeOff_afterStartEnd() throws RemoteException { 857 LocalTime now = LocalTime.now(); 858 mService.setNightMode(MODE_NIGHT_YES); 859 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 860 mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000); 861 mService.setNightMode(MODE_NIGHT_CUSTOM); 862 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 863 assertFalse(isNightModeActivated()); 864 } 865 866 @Test customTime_darkThemeOn_afterStartEnd()867 public void customTime_darkThemeOn_afterStartEnd() throws RemoteException { 868 LocalTime now = LocalTime.now(); 869 mService.setNightMode(MODE_NIGHT_YES); 870 mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000); 871 mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000); 872 mService.setNightMode(MODE_NIGHT_CUSTOM); 873 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 874 assertFalse(isNightModeActivated()); 875 } 876 877 878 @Test customTime_darkThemeOn_beforeStartEnd()879 public void customTime_darkThemeOn_beforeStartEnd() throws RemoteException { 880 LocalTime now = LocalTime.now(); 881 mService.setNightMode(MODE_NIGHT_YES); 882 mService.setCustomNightModeStart(now.minusHours(1L).toNanoOfDay() / 1000); 883 mService.setCustomNightModeEnd(now.minusHours(2L).toNanoOfDay() / 1000); 884 mService.setNightMode(MODE_NIGHT_CUSTOM); 885 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 886 assertTrue(isNightModeActivated()); 887 } 888 889 @Test customTime_darkThemeOff_beforeStartEnd()890 public void customTime_darkThemeOff_beforeStartEnd() throws RemoteException { 891 LocalTime now = LocalTime.now(); 892 mService.setNightMode(MODE_NIGHT_YES); 893 mService.setCustomNightModeStart(now.minusHours(2L).toNanoOfDay() / 1000); 894 mService.setCustomNightModeEnd(now.minusHours(1L).toNanoOfDay() / 1000); 895 mService.setNightMode(MODE_NIGHT_CUSTOM); 896 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 897 assertFalse(isNightModeActivated()); 898 } 899 900 @Test customTIme_customAlarmSetWhenScreenTimeChanges()901 public void customTIme_customAlarmSetWhenScreenTimeChanges() throws RemoteException { 902 when(mPowerManager.isInteractive()).thenReturn(false); 903 mService.setNightMode(MODE_NIGHT_CUSTOM); 904 verify(mAlarmManager, times(1)) 905 .setExact(anyInt(), anyLong(), anyString(), any(), any()); 906 mTimeChangedCallback.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED)); 907 verify(mAlarmManager, atLeast(2)) 908 .setExact(anyInt(), anyLong(), anyString(), any(), any()); 909 } 910 911 @Test customTime_alarmSetInTheFutureWhenOn()912 public void customTime_alarmSetInTheFutureWhenOn() throws RemoteException { 913 LocalDateTime now = LocalDateTime.now(); 914 when(mPowerManager.isInteractive()).thenReturn(false); 915 mService.setNightMode(MODE_NIGHT_YES); 916 mService.setCustomNightModeStart(now.toLocalTime().minusHours(1L).toNanoOfDay() / 1000); 917 mService.setCustomNightModeEnd(now.toLocalTime().plusHours(1L).toNanoOfDay() / 1000); 918 LocalDateTime next = now.plusHours(1L); 919 final long millis = next.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); 920 mService.setNightMode(MODE_NIGHT_CUSTOM); 921 verify(mAlarmManager) 922 .setExact(anyInt(), eq(millis), anyString(), any(), any()); 923 } 924 925 @Test customTime_appliesImmediatelyWhenScreenOff()926 public void customTime_appliesImmediatelyWhenScreenOff() throws RemoteException { 927 when(mPowerManager.isInteractive()).thenReturn(false); 928 LocalTime now = LocalTime.now(); 929 mService.setNightMode(MODE_NIGHT_NO); 930 mService.setCustomNightModeStart(now.minusHours(1L).toNanoOfDay() / 1000); 931 mService.setCustomNightModeEnd(now.plusHours(1L).toNanoOfDay() / 1000); 932 mService.setNightMode(MODE_NIGHT_CUSTOM); 933 assertTrue(isNightModeActivated()); 934 } 935 936 @Test customTime_appliesOnlyWhenScreenOff()937 public void customTime_appliesOnlyWhenScreenOff() throws RemoteException { 938 LocalTime now = LocalTime.now(); 939 mService.setNightMode(MODE_NIGHT_NO); 940 mService.setCustomNightModeStart(now.minusHours(1L).toNanoOfDay() / 1000); 941 mService.setCustomNightModeEnd(now.plusHours(1L).toNanoOfDay() / 1000); 942 mService.setNightMode(MODE_NIGHT_CUSTOM); 943 assertFalse(isNightModeActivated()); 944 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 945 assertTrue(isNightModeActivated()); 946 } 947 948 @Test nightAuto_appliesOnlyWhenScreenOff()949 public void nightAuto_appliesOnlyWhenScreenOff() throws RemoteException { 950 when(mTwilightState.isNight()).thenReturn(true); 951 mService.setNightMode(MODE_NIGHT_NO); 952 mService.setNightMode(MODE_NIGHT_AUTO); 953 assertFalse(isNightModeActivated()); 954 mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 955 assertTrue(isNightModeActivated()); 956 } 957 isNightModeActivated()958 private boolean isNightModeActivated() { 959 return (mUiManagerService.getConfiguration().uiMode 960 & Configuration.UI_MODE_NIGHT_YES) != 0; 961 } 962 963 @Test requestProjection_failsForBogusPackageName()964 public void requestProjection_failsForBogusPackageName() throws Exception { 965 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 966 .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1); 967 968 assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder, 969 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 970 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 971 } 972 973 @Test requestProjection_failsIfNameNotFound()974 public void requestProjection_failsIfNameNotFound() throws Exception { 975 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 976 .thenThrow(new PackageManager.NameNotFoundException()); 977 978 assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder, 979 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 980 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 981 } 982 983 @Test requestProjection_failsIfNoProjectionTypes()984 public void requestProjection_failsIfNoProjectionTypes() throws Exception { 985 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 986 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 987 988 assertThrows(IllegalArgumentException.class, 989 () -> mService.requestProjection(mBinder, PROJECTION_TYPE_NONE, PACKAGE_NAME)); 990 verify(mContext, never()).enforceCallingPermission( 991 eq(Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION), any()); 992 verifyZeroInteractions(mBinder); 993 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 994 } 995 996 @Test requestProjection_failsIfMultipleProjectionTypes()997 public void requestProjection_failsIfMultipleProjectionTypes() throws Exception { 998 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 999 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1000 1001 // Don't use PROJECTION_TYPE_ALL because that's actually == -1 and will fail the > 0 check. 1002 int multipleProjectionTypes = PROJECTION_TYPE_AUTOMOTIVE | 0x0002 | 0x0004; 1003 1004 assertThrows(IllegalArgumentException.class, 1005 () -> mService.requestProjection(mBinder, multipleProjectionTypes, PACKAGE_NAME)); 1006 verify(mContext, never()).enforceCallingPermission( 1007 eq(Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION), any()); 1008 verifyZeroInteractions(mBinder); 1009 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1010 } 1011 1012 @Test requestProjection_enforcesToggleAutomotiveProjectionPermission()1013 public void requestProjection_enforcesToggleAutomotiveProjectionPermission() throws Exception { 1014 doThrow(new SecurityException()) 1015 .when(mPackageManager).getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()); 1016 1017 assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder, 1018 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1019 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1020 } 1021 1022 @Test requestProjection_automotive_failsIfAlreadySetByOtherPackage()1023 public void requestProjection_automotive_failsIfAlreadySetByOtherPackage() throws Exception { 1024 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1025 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1026 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1027 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1028 1029 String otherPackage = "Raconteurs"; 1030 when(mPackageManager.getPackageUidAsUser(eq(otherPackage), anyInt())) 1031 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1032 assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, otherPackage)); 1033 assertThat(mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE), 1034 contains(PACKAGE_NAME)); 1035 } 1036 1037 @Test requestProjection_failsIfCannotLinkToDeath()1038 public void requestProjection_failsIfCannotLinkToDeath() throws Exception { 1039 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1040 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1041 doThrow(new RemoteException()).when(mBinder).linkToDeath(any(), anyInt()); 1042 1043 assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1044 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1045 } 1046 1047 @Test requestProjection()1048 public void requestProjection() throws Exception { 1049 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1050 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1051 // Should work for all powers of two. 1052 for (int i = 0; i < Integer.SIZE; ++i) { 1053 int projectionType = 1 << i; 1054 assertTrue(mService.requestProjection(mBinder, projectionType, PACKAGE_NAME)); 1055 assertTrue((mService.getActiveProjectionTypes() & projectionType) != 0); 1056 assertThat(mService.getProjectingPackages(projectionType), contains(PACKAGE_NAME)); 1057 // Subsequent calls should still succeed. 1058 assertTrue(mService.requestProjection(mBinder, projectionType, PACKAGE_NAME)); 1059 } 1060 assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes()); 1061 } 1062 1063 @Test releaseProjection_failsForBogusPackageName()1064 public void releaseProjection_failsForBogusPackageName() throws Exception { 1065 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1066 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1067 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1068 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1069 1070 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1071 .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1); 1072 1073 assertThrows(SecurityException.class, () -> mService.releaseProjection( 1074 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1075 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1076 } 1077 1078 @Test releaseProjection_failsIfNameNotFound()1079 public void releaseProjection_failsIfNameNotFound() throws Exception { 1080 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1081 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1082 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1083 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1084 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1085 .thenThrow(new PackageManager.NameNotFoundException()); 1086 1087 assertThrows(SecurityException.class, () -> mService.releaseProjection( 1088 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1089 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1090 } 1091 1092 @Test releaseProjection_enforcesToggleAutomotiveProjectionPermission()1093 public void releaseProjection_enforcesToggleAutomotiveProjectionPermission() throws Exception { 1094 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1095 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1096 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1097 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1098 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 1099 eq(Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION), any()); 1100 1101 // Should not be enforced for other types of projection. 1102 int nonAutomotiveProjectionType = PROJECTION_TYPE_AUTOMOTIVE * 2; 1103 mService.releaseProjection(nonAutomotiveProjectionType, PACKAGE_NAME); 1104 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1105 1106 assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder, 1107 PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1108 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1109 } 1110 1111 @Test releaseProjection()1112 public void releaseProjection() throws Exception { 1113 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1114 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1115 requestAllPossibleProjectionTypes(); 1116 assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes()); 1117 1118 assertTrue(mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME)); 1119 int everythingButAutomotive = PROJECTION_TYPE_ALL & ~PROJECTION_TYPE_AUTOMOTIVE; 1120 assertEquals(everythingButAutomotive, mService.getActiveProjectionTypes()); 1121 1122 for (int i = 0; i < Integer.SIZE; ++i) { 1123 int projectionType = 1 << i; 1124 assertEquals(projectionType != PROJECTION_TYPE_AUTOMOTIVE, 1125 (boolean) mService.releaseProjection(projectionType, PACKAGE_NAME)); 1126 } 1127 1128 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1129 } 1130 1131 @Test binderDeath_releasesProjection()1132 public void binderDeath_releasesProjection() throws Exception { 1133 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1134 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1135 requestAllPossibleProjectionTypes(); 1136 assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes()); 1137 ArgumentCaptor<IBinder.DeathRecipient> deathRecipientCaptor = ArgumentCaptor.forClass( 1138 IBinder.DeathRecipient.class); 1139 verify(mBinder, atLeastOnce()).linkToDeath(deathRecipientCaptor.capture(), anyInt()); 1140 1141 // Wipe them out. All of them. 1142 deathRecipientCaptor.getAllValues().forEach(IBinder.DeathRecipient::binderDied); 1143 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1144 } 1145 1146 @Test getActiveProjectionTypes()1147 public void getActiveProjectionTypes() throws Exception { 1148 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1149 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1150 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1151 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1152 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1153 mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1154 assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes()); 1155 } 1156 1157 @Test getProjectingPackages()1158 public void getProjectingPackages() throws Exception { 1159 assertTrue(mService.getProjectingPackages(PROJECTION_TYPE_ALL).isEmpty()); 1160 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1161 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1162 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1163 assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE).size()); 1164 assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_ALL).size()); 1165 assertThat(mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE), 1166 contains(PACKAGE_NAME)); 1167 assertThat(mService.getProjectingPackages(PROJECTION_TYPE_ALL), contains(PACKAGE_NAME)); 1168 mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1169 assertThat(mService.getProjectingPackages(PROJECTION_TYPE_ALL), empty()); 1170 } 1171 1172 @Test addOnProjectionStateChangedListener_enforcesReadProjStatePermission()1173 public void addOnProjectionStateChangedListener_enforcesReadProjStatePermission() { 1174 mPermissionEnforcer.revoke(android.Manifest.permission.READ_PROJECTION_STATE); 1175 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1176 1177 assertThrows(SecurityException.class, () -> mService.addOnProjectionStateChangedListener( 1178 listener, PROJECTION_TYPE_ALL)); 1179 } 1180 1181 @Test addOnProjectionStateChangedListener_callsListenerIfProjectionActive()1182 public void addOnProjectionStateChangedListener_callsListenerIfProjectionActive() 1183 throws Exception { 1184 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1185 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1186 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1187 assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes()); 1188 1189 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1190 when(listener.asBinder()).thenReturn(mBinder); // Any binder will do 1191 mService.addOnProjectionStateChangedListener(listener, PROJECTION_TYPE_ALL); 1192 verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_AUTOMOTIVE), 1193 eq(List.of(PACKAGE_NAME))); 1194 } 1195 1196 @Test removeOnProjectionStateChangedListener_enforcesReadProjStatePermission()1197 public void removeOnProjectionStateChangedListener_enforcesReadProjStatePermission() { 1198 mPermissionEnforcer.revoke(android.Manifest.permission.READ_PROJECTION_STATE); 1199 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1200 1201 assertThrows(SecurityException.class, () -> mService.removeOnProjectionStateChangedListener( 1202 listener)); 1203 } 1204 1205 @Test removeOnProjectionStateChangedListener()1206 public void removeOnProjectionStateChangedListener() throws Exception { 1207 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1208 when(listener.asBinder()).thenReturn(mBinder); // Any binder will do. 1209 mService.addOnProjectionStateChangedListener(listener, PROJECTION_TYPE_ALL); 1210 1211 mService.removeOnProjectionStateChangedListener(listener); 1212 // Now set automotive projection, should not call back. 1213 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1214 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1215 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1216 verify(listener, never()).onProjectionStateChanged(anyInt(), any()); 1217 } 1218 1219 @Test projectionStateChangedListener_calledWhenStateChanges()1220 public void projectionStateChangedListener_calledWhenStateChanges() throws Exception { 1221 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1222 when(listener.asBinder()).thenReturn(mBinder); // Any binder will do. 1223 mService.addOnProjectionStateChangedListener(listener, PROJECTION_TYPE_ALL); 1224 verify(listener, atLeastOnce()).asBinder(); // Called twice during register. 1225 1226 // No calls initially, no projection state set. 1227 verifyNoMoreInteractions(listener); 1228 1229 // Now set automotive projection, should call back. 1230 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1231 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1232 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1233 verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_AUTOMOTIVE), 1234 eq(List.of(PACKAGE_NAME))); 1235 1236 // Subsequent calls that are noops do nothing. 1237 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1238 int unsetProjectionType = 0x0002; 1239 mService.releaseProjection(unsetProjectionType, PACKAGE_NAME); 1240 verifyNoMoreInteractions(listener); 1241 1242 // Release should call back though. 1243 mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1244 verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_NONE), 1245 eq(List.of())); 1246 1247 // But only the first time. 1248 mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1249 verifyNoMoreInteractions(listener); 1250 } 1251 1252 @Test projectionStateChangedListener_calledForAnyRelevantStateChange()1253 public void projectionStateChangedListener_calledForAnyRelevantStateChange() throws Exception { 1254 int fakeProjectionType = 0x0002; 1255 int otherFakeProjectionType = 0x0004; 1256 String otherPackageName = "Internet Arms"; 1257 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1258 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1259 when(mPackageManager.getPackageUidAsUser(eq(otherPackageName), anyInt())) 1260 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1261 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1262 when(listener.asBinder()).thenReturn(mBinder); // Any binder will do. 1263 IOnProjectionStateChangedListener listener2 = mock(IOnProjectionStateChangedListener.class); 1264 when(listener2.asBinder()).thenReturn(mBinder); // Any binder will do. 1265 mService.addOnProjectionStateChangedListener(listener, fakeProjectionType); 1266 mService.addOnProjectionStateChangedListener(listener2, 1267 fakeProjectionType | otherFakeProjectionType); 1268 verify(listener, atLeastOnce()).asBinder(); // Called twice during register. 1269 verify(listener2, atLeastOnce()).asBinder(); // Called twice during register. 1270 1271 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1272 verifyNoMoreInteractions(listener, listener2); 1273 1274 // fakeProjectionType should trigger both. 1275 mService.requestProjection(mBinder, fakeProjectionType, PACKAGE_NAME); 1276 verify(listener).onProjectionStateChanged(eq(fakeProjectionType), 1277 eq(List.of(PACKAGE_NAME))); 1278 verify(listener2).onProjectionStateChanged(eq(fakeProjectionType), 1279 eq(List.of(PACKAGE_NAME))); 1280 1281 // otherFakeProjectionType should only trigger the second listener. 1282 mService.requestProjection(mBinder, otherFakeProjectionType, otherPackageName); 1283 verifyNoMoreInteractions(listener); 1284 verify(listener2).onProjectionStateChanged( 1285 eq(fakeProjectionType | otherFakeProjectionType), 1286 eq(List.of(PACKAGE_NAME, otherPackageName))); 1287 1288 // Turning off fakeProjectionType should trigger both again. 1289 mService.releaseProjection(fakeProjectionType, PACKAGE_NAME); 1290 verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_NONE), eq(List.of())); 1291 verify(listener2).onProjectionStateChanged(eq(otherFakeProjectionType), 1292 eq(List.of(otherPackageName))); 1293 1294 // Turning off otherFakeProjectionType should only trigger the second listener. 1295 mService.releaseProjection(otherFakeProjectionType, otherPackageName); 1296 verifyNoMoreInteractions(listener); 1297 verify(listener2).onProjectionStateChanged(eq(PROJECTION_TYPE_NONE), eq(List.of())); 1298 } 1299 1300 @Test projectionStateChangedListener_unregisteredOnDeath()1301 public void projectionStateChangedListener_unregisteredOnDeath() throws Exception { 1302 IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class); 1303 IBinder listenerBinder = mock(IBinder.class); 1304 when(listener.asBinder()).thenReturn(listenerBinder); 1305 mService.addOnProjectionStateChangedListener(listener, PROJECTION_TYPE_ALL); 1306 ArgumentCaptor<IBinder.DeathRecipient> listenerDeathRecipient = ArgumentCaptor.forClass( 1307 IBinder.DeathRecipient.class); 1308 verify(listenerBinder).linkToDeath(listenerDeathRecipient.capture(), anyInt()); 1309 1310 // Now kill the binder for the listener. This should remove it from the list of listeners. 1311 listenerDeathRecipient.getValue().binderDied(); 1312 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1313 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1314 mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME); 1315 verify(listener, never()).onProjectionStateChanged(anyInt(), any()); 1316 } 1317 1318 @Test enableCarMode_failsForBogusPackageName()1319 public void enableCarMode_failsForBogusPackageName() throws Exception { 1320 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1321 .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1); 1322 1323 assertThrows(SecurityException.class, () -> mService.enableCarMode(0, 0, PACKAGE_NAME)); 1324 assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR); 1325 } 1326 1327 @Test enableCarMode_shell()1328 public void enableCarMode_shell() throws Exception { 1329 mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true, 1330 mTwilightManager, new TestInjector(Process.SHELL_UID)); 1331 try { 1332 mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 1333 } catch (SecurityException e) {/* ignore for permission denial */} 1334 mService = mUiManagerService.getService(); 1335 1336 mService.enableCarMode(0, 0, PACKAGE_NAME); 1337 assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR); 1338 } 1339 1340 @Test disableCarMode_failsForBogusPackageName()1341 public void disableCarMode_failsForBogusPackageName() throws Exception { 1342 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1343 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1344 mService.enableCarMode(0, 0, PACKAGE_NAME); 1345 assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR); 1346 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1347 .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1); 1348 1349 assertThrows(SecurityException.class, 1350 () -> mService.disableCarModeByCallingPackage(0, PACKAGE_NAME)); 1351 assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR); 1352 1353 // Clean up 1354 when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt())) 1355 .thenReturn(TestInjector.DEFAULT_CALLING_UID); 1356 mService.disableCarModeByCallingPackage(0, PACKAGE_NAME); 1357 assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR); 1358 } 1359 1360 @Test disableCarMode_shell()1361 public void disableCarMode_shell() throws Exception { 1362 mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true, 1363 mTwilightManager, new TestInjector(Process.SHELL_UID)); 1364 try { 1365 mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 1366 } catch (SecurityException e) {/* ignore for permission denial */} 1367 mService = mUiManagerService.getService(); 1368 1369 mService.enableCarMode(0, 0, PACKAGE_NAME); 1370 assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR); 1371 1372 mService.disableCarModeByCallingPackage(0, PACKAGE_NAME); 1373 assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR); 1374 } 1375 1376 @Test dreamWhenDocked()1377 public void dreamWhenDocked() { 1378 triggerDockIntent(); 1379 verifyAndSendResultBroadcast(); 1380 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1381 } 1382 1383 @Test noDreamWhenDocked_keyguardNotShowing_interactive()1384 public void noDreamWhenDocked_keyguardNotShowing_interactive() { 1385 mUiManagerService.setStartDreamImmediatelyOnDock(false); 1386 when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false); 1387 when(mPowerManager.isInteractive()).thenReturn(true); 1388 1389 triggerDockIntent(); 1390 verifyAndSendResultBroadcast(); 1391 verify(mInjector, never()).startDreamWhenDockedIfAppropriate(mContext); 1392 } 1393 1394 @Test dreamWhenDocked_keyguardShowing_interactive()1395 public void dreamWhenDocked_keyguardShowing_interactive() { 1396 mUiManagerService.setStartDreamImmediatelyOnDock(false); 1397 when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true); 1398 when(mPowerManager.isInteractive()).thenReturn(false); 1399 1400 triggerDockIntent(); 1401 verifyAndSendResultBroadcast(); 1402 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1403 } 1404 1405 @Test dreamWhenDocked_keyguardNotShowing_notInteractive()1406 public void dreamWhenDocked_keyguardNotShowing_notInteractive() { 1407 mUiManagerService.setStartDreamImmediatelyOnDock(false); 1408 when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false); 1409 when(mPowerManager.isInteractive()).thenReturn(false); 1410 1411 triggerDockIntent(); 1412 verifyAndSendResultBroadcast(); 1413 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1414 } 1415 1416 @Test dreamWhenDocked_keyguardShowing_notInteractive()1417 public void dreamWhenDocked_keyguardShowing_notInteractive() { 1418 mUiManagerService.setStartDreamImmediatelyOnDock(false); 1419 when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true); 1420 when(mPowerManager.isInteractive()).thenReturn(false); 1421 1422 triggerDockIntent(); 1423 verifyAndSendResultBroadcast(); 1424 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1425 } 1426 1427 @Test dreamWhenDocked_ambientModeSuppressed_suppressionEnabled()1428 public void dreamWhenDocked_ambientModeSuppressed_suppressionEnabled() { 1429 mUiManagerService.setStartDreamImmediatelyOnDock(true); 1430 mUiManagerService.setDreamsDisabledByAmbientModeSuppression(true); 1431 1432 when(mLocalPowerManager.isAmbientDisplaySuppressed()).thenReturn(true); 1433 triggerDockIntent(); 1434 verifyAndSendResultBroadcast(); 1435 verify(mInjector, never()).startDreamWhenDockedIfAppropriate(mContext); 1436 } 1437 1438 @Test dreamWhenDocked_ambientModeSuppressed_suppressionDisabled()1439 public void dreamWhenDocked_ambientModeSuppressed_suppressionDisabled() { 1440 mUiManagerService.setStartDreamImmediatelyOnDock(true); 1441 mUiManagerService.setDreamsDisabledByAmbientModeSuppression(false); 1442 1443 when(mLocalPowerManager.isAmbientDisplaySuppressed()).thenReturn(true); 1444 triggerDockIntent(); 1445 verifyAndSendResultBroadcast(); 1446 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1447 } 1448 1449 @Test dreamWhenDocked_ambientModeNotSuppressed_suppressionEnabled()1450 public void dreamWhenDocked_ambientModeNotSuppressed_suppressionEnabled() { 1451 mUiManagerService.setStartDreamImmediatelyOnDock(true); 1452 mUiManagerService.setDreamsDisabledByAmbientModeSuppression(true); 1453 1454 when(mLocalPowerManager.isAmbientDisplaySuppressed()).thenReturn(false); 1455 triggerDockIntent(); 1456 verifyAndSendResultBroadcast(); 1457 verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); 1458 } 1459 testAttentionModeThemeOverlay(boolean modeNight)1460 private void testAttentionModeThemeOverlay(boolean modeNight) throws RemoteException { 1461 //setup 1462 if (modeNight) { 1463 mService.setNightMode(MODE_NIGHT_YES); 1464 assertTrue(mUiManagerService.getConfiguration().isNightModeActive()); 1465 } else { 1466 mService.setNightMode(MODE_NIGHT_NO); 1467 assertFalse(mUiManagerService.getConfiguration().isNightModeActive()); 1468 } 1469 1470 // attention modes with expected night modes 1471 Map<Integer, Boolean> modes = Map.of( 1472 MODE_ATTENTION_THEME_OVERLAY_OFF, modeNight, 1473 MODE_ATTENTION_THEME_OVERLAY_DAY, false, 1474 MODE_ATTENTION_THEME_OVERLAY_NIGHT, true 1475 ); 1476 1477 // test 1478 for (int aMode : modes.keySet()) { 1479 try { 1480 mService.setAttentionModeThemeOverlay(aMode); 1481 1482 int appliedAMode = mService.getAttentionModeThemeOverlay(); 1483 boolean nMode = modes.get(aMode); 1484 1485 assertEquals(aMode, appliedAMode); 1486 assertEquals(isNightModeActivated(), nMode); 1487 } catch (RemoteException e) { 1488 fail("Error communicating with server: " + e.getMessage()); 1489 } 1490 } 1491 } 1492 1493 @Test 1494 @EnableFlags(Flags.FLAG_MODES_API) testAttentionModeThemeOverlay_nightModeDisabled()1495 public void testAttentionModeThemeOverlay_nightModeDisabled() throws RemoteException { 1496 testAttentionModeThemeOverlay(false); 1497 } 1498 1499 @Test 1500 @EnableFlags(Flags.FLAG_MODES_API) testAttentionModeThemeOverlay_nightModeEnabled()1501 public void testAttentionModeThemeOverlay_nightModeEnabled() throws RemoteException { 1502 testAttentionModeThemeOverlay(true); 1503 } 1504 triggerDockIntent()1505 private void triggerDockIntent() { 1506 final Intent dockedIntent = 1507 new Intent(Intent.ACTION_DOCK_EVENT) 1508 .putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_DESK); 1509 mDockStateChangedCallback.onReceive(mContext, dockedIntent); 1510 } 1511 verifyAndSendResultBroadcast()1512 private void verifyAndSendResultBroadcast() { 1513 verify(mContext).sendOrderedBroadcastAsUser( 1514 mOrderedBroadcastIntent.capture(), 1515 any(UserHandle.class), 1516 nullable(String.class), 1517 mOrderedBroadcastReceiver.capture(), 1518 nullable(Handler.class), 1519 anyInt(), 1520 nullable(String.class), 1521 nullable(Bundle.class)); 1522 1523 mOrderedBroadcastReceiver.getValue().setPendingResult( 1524 new BroadcastReceiver.PendingResult( 1525 Activity.RESULT_OK, 1526 /* resultData= */ "", 1527 /* resultExtras= */ null, 1528 /* type= */ 0, 1529 /* ordered= */ true, 1530 /* sticky= */ false, 1531 /* token= */ null, 1532 /* userId= */ 0, 1533 /* flags= */ 0)); 1534 mOrderedBroadcastReceiver.getValue().onReceive( 1535 mContext, 1536 mOrderedBroadcastIntent.getValue()); 1537 } 1538 requestAllPossibleProjectionTypes()1539 private void requestAllPossibleProjectionTypes() throws RemoteException { 1540 for (int i = 0; i < Integer.SIZE; ++i) { 1541 mService.requestProjection(mBinder, 1 << i, PACKAGE_NAME); 1542 } 1543 } 1544 1545 private static class TestInjector extends UiModeManagerService.Injector { 1546 private static final int DEFAULT_CALLING_UID = 8675309; 1547 1548 private final int callingUid; 1549 TestInjector()1550 public TestInjector() { 1551 this(DEFAULT_CALLING_UID); 1552 } 1553 TestInjector(int callingUid)1554 public TestInjector(int callingUid) { 1555 this.callingUid = callingUid; 1556 } 1557 1558 @Override getCallingUid()1559 public int getCallingUid() { 1560 return callingUid; 1561 } 1562 1563 @Override startDreamWhenDockedIfAppropriate(Context context)1564 public void startDreamWhenDockedIfAppropriate(Context context) { 1565 // do nothing 1566 } 1567 } 1568 } 1569