1 /* 2 * Copyright (C) 2022 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.display.brightness; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.Mockito.clearInvocations; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.never; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.verifyNoMoreInteractions; 29 import static org.mockito.Mockito.verifyZeroInteractions; 30 import static org.mockito.Mockito.when; 31 32 import android.content.Context; 33 import android.content.res.Resources; 34 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; 35 import android.os.HandlerExecutor; 36 import android.os.PowerManager; 37 import android.view.Display; 38 39 import androidx.test.filters.SmallTest; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import com.android.server.display.AutomaticBrightnessController; 43 import com.android.server.display.BrightnessSetting; 44 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy; 45 import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.Mock; 51 import org.mockito.MockitoAnnotations; 52 53 @SmallTest 54 @RunWith(AndroidJUnit4.class) 55 public final class DisplayBrightnessControllerTest { 56 private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; 57 private static final float DEFAULT_BRIGHTNESS = 0.15f; 58 59 @Mock 60 private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector; 61 @Mock 62 private Context mContext; 63 @Mock 64 private Resources mResources; 65 @Mock 66 private BrightnessSetting mBrightnessSetting; 67 @Mock 68 private Runnable mOnBrightnessChangeRunnable; 69 70 @Mock 71 private HandlerExecutor mBrightnessChangeExecutor; 72 73 private final DisplayBrightnessController.Injector mInjector = new 74 DisplayBrightnessController.Injector() { 75 @Override 76 DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector( 77 Context context, int displayId) { 78 return mDisplayBrightnessStrategySelector; 79 } 80 }; 81 82 private DisplayBrightnessController mDisplayBrightnessController; 83 84 @Before before()85 public void before() { 86 MockitoAnnotations.initMocks(this); 87 when(mContext.getResources()).thenReturn(mResources); 88 when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN); 89 when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(-1f); 90 when(mResources.getBoolean( 91 com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay)) 92 .thenReturn(true); 93 mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector, 94 DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable, 95 mBrightnessChangeExecutor); 96 } 97 98 @Test testIfFirstScreenBrightnessIsDefault()99 public void testIfFirstScreenBrightnessIsDefault() { 100 assertEquals(DEFAULT_BRIGHTNESS, mDisplayBrightnessController.getCurrentBrightness(), 101 /* delta= */ 0.0f); 102 } 103 104 @Test testUpdateBrightness()105 public void testUpdateBrightness() { 106 DisplayPowerRequest displayPowerRequest = mock(DisplayPowerRequest.class); 107 DisplayBrightnessStrategy displayBrightnessStrategy = mock(DisplayBrightnessStrategy.class); 108 int targetDisplayState = Display.STATE_DOZE; 109 when(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest, 110 targetDisplayState)).thenReturn(displayBrightnessStrategy); 111 mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState); 112 verify(displayBrightnessStrategy).updateBrightness(displayPowerRequest); 113 assertEquals(mDisplayBrightnessController.getCurrentDisplayBrightnessStrategy(), 114 displayBrightnessStrategy); 115 } 116 117 @Test isAllowAutoBrightnessWhileDozingConfigDelegatesToDozeBrightnessStrategy()118 public void isAllowAutoBrightnessWhileDozingConfigDelegatesToDozeBrightnessStrategy() { 119 mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(); 120 verify(mDisplayBrightnessStrategySelector).isAllowAutoBrightnessWhileDozingConfig(); 121 } 122 123 @Test setTemporaryBrightness()124 public void setTemporaryBrightness() { 125 float temporaryBrightness = 0.4f; 126 TemporaryBrightnessStrategy temporaryBrightnessStrategy = mock( 127 TemporaryBrightnessStrategy.class); 128 when(mDisplayBrightnessStrategySelector.getTemporaryDisplayBrightnessStrategy()).thenReturn( 129 temporaryBrightnessStrategy); 130 mDisplayBrightnessController.setTemporaryBrightness(temporaryBrightness); 131 verify(temporaryBrightnessStrategy).setTemporaryScreenBrightness(temporaryBrightness); 132 } 133 134 @Test setCurrentScreenBrightness()135 public void setCurrentScreenBrightness() { 136 // Current Screen brightness is set as expected when a different value than the current 137 // is set 138 float currentScreenBrightness = 0.4f; 139 mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentScreenBrightness); 140 assertEquals(mDisplayBrightnessController.getCurrentBrightness(), 141 currentScreenBrightness, /* delta= */ 0.0f); 142 verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable); 143 144 // No change to the current screen brightness is same as the existing one 145 mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentScreenBrightness); 146 verifyNoMoreInteractions(mBrightnessChangeExecutor); 147 } 148 149 @Test setPendingScreenBrightnessSetting()150 public void setPendingScreenBrightnessSetting() { 151 float pendingScreenBrightness = 0.4f; 152 mDisplayBrightnessController.setPendingScreenBrightness(pendingScreenBrightness); 153 assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), 154 pendingScreenBrightness, /* delta= */ 0.0f); 155 } 156 157 @Test updateUserSetScreenBrightness()158 public void updateUserSetScreenBrightness() { 159 // No brightness is set if the pending brightness is invalid 160 mDisplayBrightnessController.setPendingScreenBrightness(Float.NaN); 161 assertFalse(mDisplayBrightnessController.updateUserSetScreenBrightness()); 162 163 // user set brightness is not set if the current and the pending brightness are same. 164 float currentBrightness = 0.4f; 165 TemporaryBrightnessStrategy temporaryBrightnessStrategy = mock( 166 TemporaryBrightnessStrategy.class); 167 when(mDisplayBrightnessStrategySelector.getTemporaryDisplayBrightnessStrategy()).thenReturn( 168 temporaryBrightnessStrategy); 169 mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentBrightness); 170 mDisplayBrightnessController.setPendingScreenBrightness(currentBrightness); 171 mDisplayBrightnessController.setTemporaryBrightness(currentBrightness); 172 assertFalse(mDisplayBrightnessController.updateUserSetScreenBrightness()); 173 verify(temporaryBrightnessStrategy).setTemporaryScreenBrightness( 174 PowerManager.BRIGHTNESS_INVALID_FLOAT); 175 assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), 176 PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f); 177 178 // user set brightness is set as expected 179 currentBrightness = 0.4f; 180 float pendingScreenBrightness = 0.3f; 181 float temporaryScreenBrightness = 0.2f; 182 mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentBrightness); 183 mDisplayBrightnessController.setPendingScreenBrightness(pendingScreenBrightness); 184 mDisplayBrightnessController.setTemporaryBrightness(temporaryScreenBrightness); 185 assertTrue(mDisplayBrightnessController.updateUserSetScreenBrightness()); 186 assertEquals(mDisplayBrightnessController.getCurrentBrightness(), 187 pendingScreenBrightness, /* delta= */ 0.0f); 188 assertEquals(mDisplayBrightnessController.getLastUserSetScreenBrightness(), 189 pendingScreenBrightness, /* delta= */ 0.0f); 190 verify(mBrightnessChangeExecutor, times(2)) 191 .execute(mOnBrightnessChangeRunnable); 192 verify(temporaryBrightnessStrategy, times(2)) 193 .setTemporaryScreenBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT); 194 assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), 195 PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f); 196 } 197 198 @Test registerBrightnessSettingChangeListener()199 public void registerBrightnessSettingChangeListener() { 200 BrightnessSetting.BrightnessSettingListener brightnessSettingListener = mock( 201 BrightnessSetting.BrightnessSettingListener.class); 202 mDisplayBrightnessController.registerBrightnessSettingChangeListener( 203 brightnessSettingListener); 204 verify(mBrightnessSetting).registerListener(brightnessSettingListener); 205 assertEquals(mDisplayBrightnessController.getBrightnessSettingListener(), 206 brightnessSettingListener); 207 } 208 209 @Test getScreenBrightnessSetting()210 public void getScreenBrightnessSetting() { 211 // getScreenBrightnessSetting returns the value relayed by BrightnessSetting, if the 212 // valid is valid and in range 213 float brightnessSetting = 0.2f; 214 when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); 215 assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), brightnessSetting, 216 /* delta= */ 0.0f); 217 218 // getScreenBrightnessSetting value is clamped if BrightnessSetting returns value beyond max 219 brightnessSetting = 1.1f; 220 when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); 221 assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), 1.0f, 222 /* delta= */ 0.0f); 223 224 // getScreenBrightnessSetting returns default value is BrightnessSetting returns invalid 225 // value. 226 brightnessSetting = Float.NaN; 227 when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); 228 assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), DEFAULT_BRIGHTNESS, 229 /* delta= */ 0.0f); 230 } 231 232 @Test setBrightnessSetsInBrightnessSetting()233 public void setBrightnessSetsInBrightnessSetting() { 234 float brightnessValue = 0.3f; 235 mDisplayBrightnessController.setBrightness(brightnessValue); 236 verify(mBrightnessSetting).setBrightness(brightnessValue); 237 } 238 239 @Test updateScreenBrightnessSetting()240 public void updateScreenBrightnessSetting() { 241 // This interaction happens in the constructor itself 242 verify(mBrightnessSetting).getBrightness(); 243 244 // Sets the appropriate value when valid, and not equal to the current brightness 245 float brightnessValue = 0.3f; 246 mDisplayBrightnessController.updateScreenBrightnessSetting(brightnessValue); 247 assertEquals(mDisplayBrightnessController.getCurrentBrightness(), brightnessValue, 248 0.0f); 249 verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable); 250 verify(mBrightnessSetting).setBrightness(brightnessValue); 251 verify(mBrightnessSetting).setUserSerial(anyInt()); 252 253 // Does nothing if the value is invalid 254 mDisplayBrightnessController.updateScreenBrightnessSetting(Float.NaN); 255 verifyNoMoreInteractions(mBrightnessChangeExecutor, mBrightnessSetting); 256 257 // Does nothing if the value is same as the current brightness 258 brightnessValue = 0.2f; 259 mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(brightnessValue); 260 verify(mBrightnessChangeExecutor, times(2)) 261 .execute(mOnBrightnessChangeRunnable); 262 mDisplayBrightnessController.updateScreenBrightnessSetting(brightnessValue); 263 verifyNoMoreInteractions(mBrightnessChangeExecutor, mBrightnessSetting); 264 } 265 266 @Test testConvertToNits()267 public void testConvertToNits() { 268 final float brightness = 0.5f; 269 final float nits = 300; 270 final float adjustedNits = 200; 271 272 // ABC is null 273 assertEquals(-1f, mDisplayBrightnessController.convertToNits(brightness), 274 /* delta= */ 0); 275 assertEquals(-1f, mDisplayBrightnessController.convertToAdjustedNits(brightness), 276 /* delta= */ 0); 277 278 AutomaticBrightnessController automaticBrightnessController = 279 mock(AutomaticBrightnessController.class); 280 when(automaticBrightnessController.convertToNits(brightness)).thenReturn(nits); 281 when(automaticBrightnessController.convertToAdjustedNits(brightness)) 282 .thenReturn(adjustedNits); 283 mDisplayBrightnessController.setAutomaticBrightnessController( 284 automaticBrightnessController); 285 286 assertEquals(nits, mDisplayBrightnessController.convertToNits(brightness), /* delta= */ 0); 287 assertEquals(adjustedNits, mDisplayBrightnessController.convertToAdjustedNits(brightness), 288 /* delta= */ 0); 289 } 290 291 @Test testConvertToFloatScale()292 public void testConvertToFloatScale() { 293 float brightness = 0.5f; 294 float nits = 300; 295 296 // ABC is null 297 assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT, 298 mDisplayBrightnessController.convertToFloatScale(nits), /* delta= */ 0); 299 300 AutomaticBrightnessController automaticBrightnessController = 301 mock(AutomaticBrightnessController.class); 302 when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness); 303 mDisplayBrightnessController.setAutomaticBrightnessController( 304 automaticBrightnessController); 305 306 assertEquals(brightness, mDisplayBrightnessController.convertToFloatScale(nits), 307 /* delta= */ 0); 308 } 309 310 @Test stop()311 public void stop() { 312 BrightnessSetting.BrightnessSettingListener brightnessSettingListener = mock( 313 BrightnessSetting.BrightnessSettingListener.class); 314 mDisplayBrightnessController.registerBrightnessSettingChangeListener( 315 brightnessSettingListener); 316 mDisplayBrightnessController.stop(); 317 verify(mBrightnessSetting).unregisterListener(brightnessSettingListener); 318 } 319 320 @Test testLoadNitBasedBrightnessSetting()321 public void testLoadNitBasedBrightnessSetting() { 322 // When the nits value is valid, the brightness is set from the old default display nits 323 // value 324 float nits = 200f; 325 float brightness = 0.3f; 326 AutomaticBrightnessController automaticBrightnessController = 327 mock(AutomaticBrightnessController.class); 328 when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness); 329 when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits); 330 mDisplayBrightnessController.setAutomaticBrightnessController( 331 automaticBrightnessController); 332 verify(mBrightnessSetting).setBrightness(brightness); 333 assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f); 334 clearInvocations(automaticBrightnessController, mBrightnessSetting); 335 336 // When the nits value is invalid, the brightness is resumed from where it was last set 337 nits = -1; 338 brightness = 0.4f; 339 when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness); 340 when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits); 341 when(mBrightnessSetting.getBrightness()).thenReturn(brightness); 342 mDisplayBrightnessController.setAutomaticBrightnessController( 343 automaticBrightnessController); 344 verify(mBrightnessSetting, never()).setBrightness(brightness); 345 assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f); 346 clearInvocations(automaticBrightnessController, mBrightnessSetting); 347 348 // When the display is a non-default display, the brightness is resumed from where it was 349 // last set 350 int nonDefaultDisplayId = 1; 351 mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector, 352 nonDefaultDisplayId, DEFAULT_BRIGHTNESS, mBrightnessSetting, 353 mOnBrightnessChangeRunnable, mBrightnessChangeExecutor); 354 brightness = 0.5f; 355 when(mBrightnessSetting.getBrightness()).thenReturn(brightness); 356 mDisplayBrightnessController.setAutomaticBrightnessController( 357 automaticBrightnessController); 358 assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f); 359 verifyZeroInteractions(automaticBrightnessController); 360 verify(mBrightnessSetting, never()).getBrightnessNitsForDefaultDisplay(); 361 verify(mBrightnessSetting, never()).setBrightness(brightness); 362 } 363 364 @Test testChangeBrightnessNitsWhenUserChanges()365 public void testChangeBrightnessNitsWhenUserChanges() { 366 float brightnessValue1 = 0.3f; 367 float nits1 = 200f; 368 float brightnessValue2 = 0.5f; 369 float nits2 = 300f; 370 AutomaticBrightnessController automaticBrightnessController = 371 mock(AutomaticBrightnessController.class); 372 when(automaticBrightnessController.convertToNits(brightnessValue1)).thenReturn(nits1); 373 when(automaticBrightnessController.convertToNits(brightnessValue2)).thenReturn(nits2); 374 mDisplayBrightnessController.setAutomaticBrightnessController( 375 automaticBrightnessController); 376 377 mDisplayBrightnessController.setBrightness(brightnessValue1, 1 /* user-serial */); 378 verify(mBrightnessSetting).setUserSerial(1); 379 verify(mBrightnessSetting).setBrightness(brightnessValue1); 380 verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits1); 381 382 mDisplayBrightnessController.setBrightness(brightnessValue2, 2 /* user-serial */); 383 verify(mBrightnessSetting).setUserSerial(2); 384 verify(mBrightnessSetting).setBrightness(brightnessValue2); 385 verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits2); 386 } 387 } 388