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