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