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;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
21 
22 import static org.junit.Assert.assertNotNull;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyBoolean;
25 import static org.mockito.ArgumentMatchers.anyFloat;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyLong;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.ArgumentMatchers.isA;
31 import static org.mockito.ArgumentMatchers.isNull;
32 import static org.mockito.Mockito.atLeastOnce;
33 import static org.mockito.Mockito.clearInvocations;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.never;
36 import static org.mockito.Mockito.reset;
37 import static org.mockito.Mockito.spy;
38 import static org.mockito.Mockito.times;
39 import static org.mockito.Mockito.when;
40 
41 import android.content.Context;
42 import android.content.res.Resources;
43 import android.hardware.Sensor;
44 import android.hardware.SensorEventListener;
45 import android.hardware.SensorManager;
46 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
47 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
48 import android.os.Handler;
49 import android.os.IBinder;
50 import android.os.Looper;
51 import android.os.PowerManager;
52 import android.os.SystemProperties;
53 import android.os.UserHandle;
54 import android.os.test.TestLooper;
55 import android.provider.Settings;
56 import android.testing.TestableContext;
57 import android.util.FloatProperty;
58 import android.view.Display;
59 import android.view.DisplayInfo;
60 
61 import androidx.test.ext.junit.runners.AndroidJUnit4;
62 import androidx.test.filters.SmallTest;
63 import androidx.test.platform.app.InstrumentationRegistry;
64 
65 import com.android.server.ExtendedMockitoRule;
66 import com.android.server.LocalServices;
67 import com.android.server.am.BatteryStatsService;
68 import com.android.server.display.RampAnimator.DualRampAnimator;
69 import com.android.server.display.brightness.BrightnessEvent;
70 import com.android.server.display.color.ColorDisplayService;
71 import com.android.server.display.layout.Layout;
72 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
73 import com.android.server.policy.WindowManagerPolicy;
74 import com.android.server.testutils.OffsettableClock;
75 
76 import org.junit.After;
77 import org.junit.Before;
78 import org.junit.Rule;
79 import org.junit.Test;
80 import org.junit.runner.RunWith;
81 import org.mockito.ArgumentCaptor;
82 import org.mockito.Captor;
83 import org.mockito.Mock;
84 import org.mockito.quality.Strictness;
85 import org.mockito.stubbing.Answer;
86 
87 import java.util.List;
88 
89 
90 @SmallTest
91 @RunWith(AndroidJUnit4.class)
92 public final class DisplayPowerControllerTest {
93     private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
94     private static final String UNIQUE_ID = "unique_id_test123";
95     private static final int FOLLOWER_DISPLAY_ID = DISPLAY_ID + 1;
96     private static final String FOLLOWER_UNIQUE_ID = "unique_id_456";
97     private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
98     private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
99     private static final float PROX_SENSOR_MAX_RANGE = 5;
100     private static final float BRIGHTNESS_RAMP_RATE_FAST_DECREASE = 0.3f;
101     private static final float BRIGHTNESS_RAMP_RATE_FAST_INCREASE = 0.4f;
102     private static final float BRIGHTNESS_RAMP_RATE_SLOW_DECREASE = 0.1f;
103     private static final float BRIGHTNESS_RAMP_RATE_SLOW_INCREASE = 0.2f;
104 
105     private OffsettableClock mClock;
106     private TestLooper mTestLooper;
107     private Handler mHandler;
108     private DisplayPowerControllerHolder mHolder;
109     private Sensor mProxSensor;
110 
111     @Mock
112     private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
113     @Mock
114     private SensorManager mSensorManagerMock;
115     @Mock
116     private DisplayBlanker mDisplayBlankerMock;
117     @Mock
118     private BrightnessTracker mBrightnessTrackerMock;
119     @Mock
120     private WindowManagerPolicy mWindowManagerPolicyMock;
121     @Mock
122     private PowerManager mPowerManagerMock;
123     @Mock
124     private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
125     @Mock
126     private DisplayWhiteBalanceController mDisplayWhiteBalanceControllerMock;
127     @Captor
128     private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
129 
130     @Rule
131     public final TestableContext mContext = new TestableContext(
132             InstrumentationRegistry.getInstrumentation().getContext());
133 
134     @Rule
135     public final ExtendedMockitoRule mExtendedMockitoRule =
136             new ExtendedMockitoRule.Builder(this)
137                     .setStrictness(Strictness.LENIENT)
138                     .spyStatic(SystemProperties.class)
139                     .spyStatic(BatteryStatsService.class)
140                     .build();
141 
142     @Before
setUp()143     public void setUp() throws Exception {
144         mClock = new OffsettableClock.Stopped();
145         mTestLooper = new TestLooper(mClock::now);
146         mHandler = new Handler(mTestLooper.getLooper());
147 
148         // Set some settings to minimize unexpected events and have a consistent starting state
149         Settings.System.putInt(mContext.getContentResolver(),
150                 Settings.System.SCREEN_BRIGHTNESS_MODE,
151                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
152         Settings.System.putFloatForUser(mContext.getContentResolver(),
153                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0, UserHandle.USER_CURRENT);
154 
155         addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
156         addLocalServiceMock(ColorDisplayService.ColorDisplayServiceInternal.class,
157                 mCdsiMock);
158 
159         mContext.addMockSystemService(PowerManager.class, mPowerManagerMock);
160 
161         doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
162                 SystemProperties.set(anyString(), any()));
163         doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
164 
165         setUpSensors();
166         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
167     }
168 
169     @After
tearDown()170     public void tearDown() {
171         LocalServices.removeServiceForTest(WindowManagerPolicy.class);
172         LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
173     }
174 
175     @Test
testReleaseProxSuspendBlockersOnExit()176     public void testReleaseProxSuspendBlockersOnExit() throws Exception {
177         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
178         // Send a display power request
179         DisplayPowerRequest dpr = new DisplayPowerRequest();
180         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
181         dpr.useProximitySensor = true;
182         mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
183 
184         // Run updatePowerState to start listener for the prox sensor
185         advanceTime(1);
186 
187         SensorEventListener listener = getSensorEventListener(mProxSensor);
188         assertNotNull(listener);
189 
190         listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 5));
191         advanceTime(1);
192 
193         // two times, one for unfinished business and one for proximity
194         verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
195                 mHolder.dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
196         verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
197                 mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
198 
199         mHolder.dpc.stop();
200         advanceTime(1);
201 
202         // two times, one for unfinished business and one for proximity
203         verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
204                 mHolder.dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
205         verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
206                 mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
207     }
208 
209     @Test
testScreenOffBecauseOfProximity()210     public void testScreenOffBecauseOfProximity() throws Exception {
211         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
212         // Send a display power request
213         DisplayPowerRequest dpr = new DisplayPowerRequest();
214         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
215         dpr.useProximitySensor = true;
216         mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
217 
218         // Run updatePowerState to start listener for the prox sensor
219         advanceTime(1);
220 
221         SensorEventListener listener = getSensorEventListener(mProxSensor);
222         assertNotNull(listener);
223 
224         // Send a positive proximity event
225         listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
226         advanceTime(1);
227 
228         // The display should have been turned off
229         verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
230 
231         clearInvocations(mHolder.displayPowerState);
232         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
233         // Send a negative proximity event
234         listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor,
235                 (int) PROX_SENSOR_MAX_RANGE + 1));
236         // Advance time by less than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
237         advanceTime(1);
238 
239         // The prox sensor is debounced so the display should not have been turned back on yet
240         verify(mHolder.displayPowerState, never()).setScreenState(Display.STATE_ON);
241 
242         // Advance time by more than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
243         advanceTime(1000);
244 
245         // The display should have been turned back on
246         verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
247     }
248 
249     @Test
testScreenOffBecauseOfProximity_ProxSensorGone()250     public void testScreenOffBecauseOfProximity_ProxSensorGone() throws Exception {
251         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
252         // Send a display power request
253         DisplayPowerRequest dpr = new DisplayPowerRequest();
254         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
255         dpr.useProximitySensor = true;
256         mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
257 
258         // Run updatePowerState to start listener for the prox sensor
259         advanceTime(1);
260 
261         SensorEventListener listener = getSensorEventListener(mProxSensor);
262         assertNotNull(listener);
263 
264         // Send a positive proximity event
265         listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
266         advanceTime(1);
267 
268         // The display should have been turned off
269         verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
270 
271         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
272         // The display device changes and we no longer have a prox sensor
273         reset(mSensorManagerMock);
274         setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
275                 mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
276         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
277 
278         advanceTime(1); // Run updatePowerState
279 
280         // The display should have been turned back on and the listener should have been
281         // unregistered
282         verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
283         verify(mSensorManagerMock).unregisterListener(listener);
284     }
285 
286     @Test
testProximitySensorListenerNotRegisteredForNonDefaultDisplay()287     public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
288         DisplayPowerControllerHolder followerDpc =
289                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
290 
291         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
292         // send a display power request
293         DisplayPowerRequest dpr = new DisplayPowerRequest();
294         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
295         dpr.useProximitySensor = true;
296         followerDpc.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
297 
298         // Run updatePowerState
299         advanceTime(1);
300 
301         verify(mSensorManagerMock, never()).registerListener(any(SensorEventListener.class),
302                 eq(mProxSensor), anyInt(), any(Handler.class));
303     }
304 
305     @Test
testDisplayBrightnessFollowers_BothDpcsSupportNits()306     public void testDisplayBrightnessFollowers_BothDpcsSupportNits() {
307         DisplayPowerControllerHolder followerDpc =
308                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
309         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
310         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
311 
312         DisplayPowerRequest dpr = new DisplayPowerRequest();
313         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
314         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
315         advanceTime(1); // Run updatePowerState
316 
317         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
318                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
319         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
320         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
321 
322         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
323 
324         // Test different float scale values
325         float leadBrightness = 0.3f;
326         float followerBrightness = 0.4f;
327         float nits = 300;
328         when(mHolder.automaticBrightnessController.convertToNits(leadBrightness)).thenReturn(nits);
329         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
330                 .thenReturn(followerBrightness);
331         when(mHolder.brightnessSetting.getBrightness()).thenReturn(leadBrightness);
332         listener.onBrightnessChanged(leadBrightness);
333         advanceTime(1); // Send messages, run updatePowerState
334         verify(mHolder.animator).animateTo(eq(leadBrightness), anyFloat(),
335                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
336         verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(),
337                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
338 
339         when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(leadBrightness);
340         when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(followerBrightness);
341         clearInvocations(mHolder.animator, followerDpc.animator);
342 
343         // Test the same float scale value
344         float brightness = 0.6f;
345         nits = 600;
346         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
347         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
348                 .thenReturn(brightness);
349         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
350         listener.onBrightnessChanged(brightness);
351         advanceTime(1); // Send messages, run updatePowerState
352         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
353                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
354         verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(),
355                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
356     }
357 
358     @Test
testDisplayBrightnessFollowers_FollowerDoesNotSupportNits()359     public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() {
360         DisplayPowerControllerHolder followerDpc =
361                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
362         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
363         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
364 
365         DisplayPowerRequest dpr = new DisplayPowerRequest();
366         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
367         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
368         advanceTime(1); // Run updatePowerState
369 
370         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
371                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
372         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
373         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
374 
375         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
376 
377         float brightness = 0.3f;
378         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(300f);
379         when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
380                 .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
381         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
382         listener.onBrightnessChanged(brightness);
383         advanceTime(1); // Send messages, run updatePowerState
384         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
385                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
386         verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(),
387                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
388     }
389 
390     @Test
testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits()391     public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() {
392         DisplayPowerControllerHolder followerDpc =
393                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
394         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
395         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
396 
397         DisplayPowerRequest dpr = new DisplayPowerRequest();
398         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
399         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
400         advanceTime(1); // Run updatePowerState
401 
402         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
403                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
404         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
405         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
406 
407         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
408 
409         float brightness = 0.3f;
410         when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
411         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
412         listener.onBrightnessChanged(brightness);
413         advanceTime(1); // Send messages, run updatePowerState
414         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
415                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
416         verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(),
417                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
418     }
419 
420     @Test
testDisplayBrightnessFollowers_NeitherDpcSupportsNits()421     public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() {
422         DisplayPowerControllerHolder followerDpc =
423                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
424         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
425         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
426 
427         DisplayPowerRequest dpr = new DisplayPowerRequest();
428         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
429         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
430         advanceTime(1); // Run updatePowerState
431 
432         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
433                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
434         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
435         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
436 
437         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
438 
439         float brightness = 0.3f;
440         when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
441         when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
442                 .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
443         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
444         listener.onBrightnessChanged(brightness);
445         advanceTime(1); // Send messages, run updatePowerState
446         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
447                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
448         verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(),
449                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
450     }
451 
452     @Test
testDisplayBrightnessFollowers_AutomaticBrightness()453     public void testDisplayBrightnessFollowers_AutomaticBrightness() {
454         Settings.System.putInt(mContext.getContentResolver(),
455                 Settings.System.SCREEN_BRIGHTNESS_MODE,
456                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
457         DisplayPowerControllerHolder followerDpc =
458                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
459         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
460         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
461         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
462         float leadBrightness = 0.1f;
463         float rawLeadBrightness = 0.3f;
464         float followerBrightness = 0.4f;
465         float nits = 300;
466         float ambientLux = 3000;
467         when(mHolder.automaticBrightnessController.getRawAutomaticScreenBrightness())
468                 .thenReturn(rawLeadBrightness);
469         when(mHolder.automaticBrightnessController
470                 .getAutomaticScreenBrightness(any(BrightnessEvent.class)))
471                 .thenReturn(leadBrightness);
472         when(mHolder.automaticBrightnessController.convertToNits(rawLeadBrightness))
473                 .thenReturn(nits);
474         when(mHolder.automaticBrightnessController.getAmbientLux()).thenReturn(ambientLux);
475         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
476                 .thenReturn(followerBrightness);
477 
478         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
479 
480         DisplayPowerRequest dpr = new DisplayPowerRequest();
481         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
482         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
483         advanceTime(1); // Run updatePowerState
484 
485         verify(mHolder.animator).animateTo(eq(leadBrightness), anyFloat(),
486                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
487         // One triggered by handleBrightnessModeChange, another triggered by setBrightnessToFollow
488         verify(followerDpc.hbmController, times(2)).onAmbientLuxChange(ambientLux);
489         verify(followerDpc.animator, times(2)).animateTo(eq(followerBrightness), anyFloat(),
490                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
491 
492         when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(leadBrightness);
493         when(followerDpc.displayPowerState.getScreenBrightness()).thenReturn(followerBrightness);
494         clearInvocations(mHolder.animator, followerDpc.animator);
495 
496         leadBrightness = 0.05f;
497         rawLeadBrightness = 0.2f;
498         followerBrightness = 0.3f;
499         nits = 200;
500         ambientLux = 2000;
501         when(mHolder.automaticBrightnessController.getRawAutomaticScreenBrightness())
502                 .thenReturn(rawLeadBrightness);
503         when(mHolder.automaticBrightnessController
504                 .getAutomaticScreenBrightness(any(BrightnessEvent.class)))
505                 .thenReturn(leadBrightness);
506         when(mHolder.automaticBrightnessController.convertToNits(rawLeadBrightness))
507                 .thenReturn(nits);
508         when(mHolder.automaticBrightnessController.getAmbientLux()).thenReturn(ambientLux);
509         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
510                 .thenReturn(followerBrightness);
511 
512         mHolder.dpc.updateBrightness();
513         advanceTime(1); // Run updatePowerState
514 
515         // The second time, the animation rate should be slow
516         verify(mHolder.animator).animateTo(eq(leadBrightness), anyFloat(),
517                 eq(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE));
518         verify(followerDpc.hbmController).onAmbientLuxChange(ambientLux);
519         verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(),
520                 eq(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE));
521     }
522 
523     @Test
testDisplayBrightnessFollowersRemoval_RemoveSingleFollower()524     public void testDisplayBrightnessFollowersRemoval_RemoveSingleFollower() {
525         DisplayPowerControllerHolder followerDpc = createDisplayPowerController(FOLLOWER_DISPLAY_ID,
526                 FOLLOWER_UNIQUE_ID);
527         DisplayPowerControllerHolder secondFollowerDpc = createDisplayPowerController(
528                 SECOND_FOLLOWER_DISPLAY_ID, SECOND_FOLLOWER_UNIQUE_DISPLAY_ID);
529         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
530         when(followerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
531         when(secondFollowerDpc.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
532 
533         DisplayPowerRequest dpr = new DisplayPowerRequest();
534         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
535         followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
536         secondFollowerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
537         advanceTime(1); // Run updatePowerState
538 
539         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
540                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
541         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
542         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
543 
544         // Set the initial brightness on the DPC we're going to remove so we have a fixed value for
545         // it to return to.
546         listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
547         verify(followerDpc.brightnessSetting).registerListener(listenerCaptor.capture());
548         BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue();
549         final float initialFollowerBrightness = 0.3f;
550         when(followerDpc.brightnessSetting.getBrightness()).thenReturn(initialFollowerBrightness);
551         followerListener.onBrightnessChanged(initialFollowerBrightness);
552         advanceTime(1);
553         verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
554                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
555 
556         when(followerDpc.displayPowerState.getScreenBrightness())
557                 .thenReturn(initialFollowerBrightness);
558 
559         mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
560         mHolder.dpc.addDisplayBrightnessFollower(secondFollowerDpc.dpc);
561         clearInvocations(followerDpc.animator);
562 
563         // Validate both followers are correctly registered and receiving brightness updates
564         float brightness = 0.6f;
565         float nits = 600;
566         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
567         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
568                 .thenReturn(brightness);
569         when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits))
570                 .thenReturn(brightness);
571         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
572         listener.onBrightnessChanged(brightness);
573         advanceTime(1); // Send messages, run updatePowerState
574         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
575                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
576         verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(),
577                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
578         verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(),
579                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
580 
581         when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
582         when(followerDpc.displayPowerState.getScreenBrightness()).thenReturn(brightness);
583         when(secondFollowerDpc.displayPowerState.getScreenBrightness()).thenReturn(brightness);
584         clearInvocations(mHolder.animator, followerDpc.animator, secondFollowerDpc.animator);
585 
586         // Remove the first follower and validate it goes back to its original brightness.
587         mHolder.dpc.removeDisplayBrightnessFollower(followerDpc.dpc);
588         advanceTime(1);
589         verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
590                 eq(BRIGHTNESS_RAMP_RATE_FAST_DECREASE));
591 
592         when(followerDpc.displayPowerState.getScreenBrightness())
593                 .thenReturn(initialFollowerBrightness);
594         clearInvocations(followerDpc.animator);
595 
596         // Change the brightness of the lead display and validate only the second follower responds
597         brightness = 0.7f;
598         nits = 700;
599         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
600         when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
601                 .thenReturn(brightness);
602         when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits))
603                 .thenReturn(brightness);
604         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
605         listener.onBrightnessChanged(brightness);
606         advanceTime(1); // Send messages, run updatePowerState
607         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
608                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
609         verify(followerDpc.animator, never()).animateTo(anyFloat(), anyFloat(), anyFloat());
610         verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(),
611                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
612     }
613 
614     @Test
testDisplayBrightnessFollowersRemoval_RemoveAllFollowers()615     public void testDisplayBrightnessFollowersRemoval_RemoveAllFollowers() {
616         DisplayPowerControllerHolder followerHolder =
617                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
618         DisplayPowerControllerHolder secondFollowerHolder =
619                 createDisplayPowerController(SECOND_FOLLOWER_DISPLAY_ID,
620                         SECOND_FOLLOWER_UNIQUE_DISPLAY_ID);
621         when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
622         when(followerHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
623         when(secondFollowerHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
624 
625         DisplayPowerRequest dpr = new DisplayPowerRequest();
626         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
627         followerHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
628         secondFollowerHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
629         advanceTime(1); // Run updatePowerState
630 
631         ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
632                 ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
633         verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
634         BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
635 
636         // Set the initial brightness on the DPCs we're going to remove so we have a fixed value for
637         // it to return to.
638         listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
639         verify(followerHolder.brightnessSetting).registerListener(listenerCaptor.capture());
640         BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue();
641         listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
642         verify(secondFollowerHolder.brightnessSetting).registerListener(listenerCaptor.capture());
643         BrightnessSetting.BrightnessSettingListener secondFollowerListener =
644                 listenerCaptor.getValue();
645         final float initialFollowerBrightness = 0.3f;
646         when(followerHolder.brightnessSetting.getBrightness()).thenReturn(
647                 initialFollowerBrightness);
648         when(secondFollowerHolder.brightnessSetting.getBrightness()).thenReturn(
649                 initialFollowerBrightness);
650         followerListener.onBrightnessChanged(initialFollowerBrightness);
651         secondFollowerListener.onBrightnessChanged(initialFollowerBrightness);
652         advanceTime(1);
653         verify(followerHolder.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
654                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
655         verify(secondFollowerHolder.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
656                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
657 
658         when(followerHolder.displayPowerState.getScreenBrightness())
659                 .thenReturn(initialFollowerBrightness);
660         when(secondFollowerHolder.displayPowerState.getScreenBrightness())
661                 .thenReturn(initialFollowerBrightness);
662 
663         mHolder.dpc.addDisplayBrightnessFollower(followerHolder.dpc);
664         mHolder.dpc.addDisplayBrightnessFollower(secondFollowerHolder.dpc);
665         clearInvocations(followerHolder.animator, secondFollowerHolder.animator);
666 
667         // Validate both followers are correctly registered and receiving brightness updates
668         float brightness = 0.6f;
669         float nits = 600;
670         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
671         when(followerHolder.automaticBrightnessController.convertToFloatScale(nits))
672                 .thenReturn(brightness);
673         when(secondFollowerHolder.automaticBrightnessController.convertToFloatScale(nits))
674                 .thenReturn(brightness);
675         when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
676         listener.onBrightnessChanged(brightness);
677         advanceTime(1); // Send messages, run updatePowerState
678         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
679                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
680         verify(followerHolder.animator).animateTo(eq(brightness), anyFloat(),
681                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
682         verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(),
683                 eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
684 
685         when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
686         when(followerHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
687         when(secondFollowerHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
688         clearInvocations(mHolder.animator, followerHolder.animator, secondFollowerHolder.animator);
689 
690         // Stop the lead DPC and validate that the followers go back to their original brightness.
691         mHolder.dpc.stop();
692         advanceTime(1);
693         verify(followerHolder.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
694                 eq(BRIGHTNESS_RAMP_RATE_FAST_DECREASE));
695         verify(secondFollowerHolder.animator).animateTo(eq(initialFollowerBrightness), anyFloat(),
696                 eq(BRIGHTNESS_RAMP_RATE_FAST_DECREASE));
697         clearInvocations(followerHolder.animator, secondFollowerHolder.animator);
698     }
699 
700     @Test
testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted()701     public void testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted() {
702         // We should still set screen state for the default display
703         DisplayPowerRequest dpr = new DisplayPowerRequest();
704         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
705         advanceTime(1); // Run updatePowerState
706         verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
707 
708         mHolder = createDisplayPowerController(42, UNIQUE_ID);
709 
710         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
711         advanceTime(1); // Run updatePowerState
712         verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
713 
714         mHolder.dpc.onBootCompleted();
715         advanceTime(1); // Run updatePowerState
716         verify(mHolder.displayPowerState).setScreenState(anyInt());
717     }
718 
719     @Test
testSetScreenOffBrightnessSensorEnabled_DisplayIsOff()720     public void testSetScreenOffBrightnessSensorEnabled_DisplayIsOff() {
721         Settings.System.putInt(mContext.getContentResolver(),
722                 Settings.System.SCREEN_BRIGHTNESS_MODE,
723                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
724 
725         DisplayPowerRequest dpr = new DisplayPowerRequest();
726         dpr.policy = DisplayPowerRequest.POLICY_OFF;
727         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
728         advanceTime(1); // Run updatePowerState
729 
730         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
731                 .setLightSensorEnabled(true);
732 
733         // The display turns on and we use the brightness value recommended by
734         // ScreenOffBrightnessSensorController
735         clearInvocations(mHolder.screenOffBrightnessSensorController);
736         float brightness = 0.14f;
737         when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
738                 .thenReturn(brightness);
739         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
740         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
741         when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
742                 any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
743 
744         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
745         advanceTime(1); // Run updatePowerState
746 
747         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
748                 .getAutomaticScreenBrightness();
749         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
750     }
751 
752     @Test
testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze()753     public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
754         Settings.System.putInt(mContext.getContentResolver(),
755                 Settings.System.SCREEN_BRIGHTNESS_MODE,
756                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
757 
758         DisplayPowerRequest dpr = new DisplayPowerRequest();
759         dpr.policy = DisplayPowerRequest.POLICY_DOZE;
760         mContext.getOrCreateTestableResources().addOverride(
761                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
762         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
763         advanceTime(1); // Run updatePowerState
764 
765         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
766                 .setLightSensorEnabled(true);
767 
768         // The display turns on and we use the brightness value recommended by
769         // ScreenOffBrightnessSensorController
770         clearInvocations(mHolder.screenOffBrightnessSensorController);
771         float brightness = 0.14f;
772         when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
773                 .thenReturn(brightness);
774         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
775         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
776         when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
777                 any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
778 
779         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
780         advanceTime(1); // Run updatePowerState
781 
782         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
783                 .getAutomaticScreenBrightness();
784         verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
785     }
786 
787     @Test
testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled()788     public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled() {
789         // Tests are set up with manual brightness by default, so no need to set it here.
790         DisplayPowerRequest dpr = new DisplayPowerRequest();
791         dpr.policy = DisplayPowerRequest.POLICY_OFF;
792         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
793         advanceTime(1); // Run updatePowerState
794 
795         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
796                 .setLightSensorEnabled(false);
797     }
798 
799     @Test
testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled()800     public void testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled() {
801         Settings.System.putInt(mContext.getContentResolver(),
802                 Settings.System.SCREEN_BRIGHTNESS_MODE,
803                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
804 
805         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ false);
806 
807         DisplayPowerRequest dpr = new DisplayPowerRequest();
808         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
809         advanceTime(1); // Run updatePowerState
810 
811         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
812                 .setLightSensorEnabled(false);
813     }
814 
815     @Test
testSetScreenOffBrightnessSensorDisabled_DisplayIsOn()816     public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
817         DisplayPowerRequest dpr = new DisplayPowerRequest();
818         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
819 
820         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
821         advanceTime(1); // Run updatePowerState
822 
823         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
824                 .setLightSensorEnabled(false);
825     }
826 
827     @Test
testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower()828     public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
829         DisplayPowerRequest dpr = new DisplayPowerRequest();
830         dpr.policy = DisplayPowerRequest.POLICY_OFF;
831 
832         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, /* leadDisplayId= */ 42);
833         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
834         advanceTime(1); // Run updatePowerState
835 
836         verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
837                 .setLightSensorEnabled(false);
838     }
839 
840     @Test
testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges()841     public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
842         // New display device
843         setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
844                 mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
845 
846         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
847         DisplayPowerRequest dpr = new DisplayPowerRequest();
848         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
849         advanceTime(1); // Run updatePowerState
850 
851         verify(mHolder.screenOffBrightnessSensorController).stop();
852     }
853 
854     @Test
testAutoBrightnessEnabled_DisplayIsOn()855     public void testAutoBrightnessEnabled_DisplayIsOn() {
856         Settings.System.putInt(mContext.getContentResolver(),
857                 Settings.System.SCREEN_BRIGHTNESS_MODE,
858                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
859 
860         DisplayPowerRequest dpr = new DisplayPowerRequest();
861         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
862         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
863         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
864         advanceTime(1); // Run updatePowerState
865 
866         verify(mHolder.automaticBrightnessController).configure(
867                 AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
868                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
869                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
870                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT,
871                 /* shouldResetShortTermModel= */ false
872         );
873         verify(mHolder.hbmController)
874                 .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED);
875     }
876 
877     @Test
testAutoBrightnessEnabled_DisplayIsInDoze()878     public void testAutoBrightnessEnabled_DisplayIsInDoze() {
879         Settings.System.putInt(mContext.getContentResolver(),
880                 Settings.System.SCREEN_BRIGHTNESS_MODE,
881                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
882         mContext.getOrCreateTestableResources().addOverride(
883                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
884         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
885 
886         DisplayPowerRequest dpr = new DisplayPowerRequest();
887         dpr.policy = DisplayPowerRequest.POLICY_DOZE;
888         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE);
889         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
890         advanceTime(1); // Run updatePowerState
891 
892         verify(mHolder.automaticBrightnessController).configure(
893                 AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
894                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
895                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
896                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE,
897                 /* shouldResetShortTermModel= */ false
898         );
899         verify(mHolder.hbmController)
900                 .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED);
901     }
902 
903     @Test
testAutoBrightnessDisabled_ManualBrightnessMode()904     public void testAutoBrightnessDisabled_ManualBrightnessMode() {
905         Settings.System.putInt(mContext.getContentResolver(),
906                 Settings.System.SCREEN_BRIGHTNESS_MODE,
907                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
908 
909         DisplayPowerRequest dpr = new DisplayPowerRequest();
910         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
911         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
912         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
913         advanceTime(1); // Run updatePowerState
914 
915         // One triggered by the test, the other by handleBrightnessModeChange
916         verify(mHolder.automaticBrightnessController, times(2)).configure(
917                 AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
918                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
919                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
920                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT,
921                 /* shouldResetShortTermModel= */ false
922         );
923         verify(mHolder.hbmController, times(2))
924                 .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
925     }
926 
927     @Test
testAutoBrightnessDisabled_DisplayIsOff()928     public void testAutoBrightnessDisabled_DisplayIsOff() {
929         Settings.System.putInt(mContext.getContentResolver(),
930                 Settings.System.SCREEN_BRIGHTNESS_MODE,
931                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
932 
933         DisplayPowerRequest dpr = new DisplayPowerRequest();
934         dpr.policy = DisplayPowerRequest.POLICY_OFF;
935         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
936         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
937         advanceTime(1); // Run updatePowerState
938 
939         verify(mHolder.automaticBrightnessController).configure(
940                 AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
941                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
942                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
943                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_OFF,
944                 /* shouldResetShortTermModel= */ false
945         );
946         verify(mHolder.hbmController).setAutoBrightnessEnabled(
947                 AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE);
948     }
949 
950     @Test
testAutoBrightnessDisabled_DisplayIsInDoze()951     public void testAutoBrightnessDisabled_DisplayIsInDoze() {
952         Settings.System.putInt(mContext.getContentResolver(),
953                 Settings.System.SCREEN_BRIGHTNESS_MODE,
954                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
955         mContext.getOrCreateTestableResources().addOverride(
956                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, false);
957         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
958 
959         DisplayPowerRequest dpr = new DisplayPowerRequest();
960         dpr.policy = DisplayPowerRequest.POLICY_DOZE;
961         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE);
962         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
963         advanceTime(1); // Run updatePowerState
964 
965         verify(mHolder.automaticBrightnessController).configure(
966                 AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
967                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
968                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
969                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE,
970                 /* shouldResetShortTermModel= */ false
971         );
972         verify(mHolder.hbmController).setAutoBrightnessEnabled(
973                 AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE);
974     }
975 
976     @Test
testAutoBrightnessDisabled_FollowerDisplay()977     public void testAutoBrightnessDisabled_FollowerDisplay() {
978         Settings.System.putInt(mContext.getContentResolver(),
979                 Settings.System.SCREEN_BRIGHTNESS_MODE,
980                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
981         mHolder.dpc.setBrightnessToFollow(0.3f, -1, 0, /* slowChange= */ false);
982 
983         DisplayPowerRequest dpr = new DisplayPowerRequest();
984         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
985         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
986         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
987         advanceTime(1); // Run updatePowerState
988 
989         // One triggered by the test, the other by handleBrightnessModeChange
990         verify(mHolder.automaticBrightnessController, times(2)).configure(
991                 AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
992                 /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT,
993                 /* userChangedBrightness= */ false, /* adjustment= */ 0,
994                 /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT,
995                 /* shouldResetShortTermModel= */ false
996         );
997 
998         // HBM should be allowed for the follower display
999         verify(mHolder.hbmController)
1000                 .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED);
1001     }
1002 
1003     @Test
testBrightnessNitsPersistWhenDisplayDeviceChanges()1004     public void testBrightnessNitsPersistWhenDisplayDeviceChanges() {
1005         float brightness = 0.3f;
1006         float nits = 500;
1007         mContext.getOrCreateTestableResources().addOverride(
1008                 com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay,
1009                 true);
1010 
1011         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
1012         when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
1013 
1014         mHolder.dpc.setBrightness(brightness);
1015         verify(mHolder.brightnessSetting).setBrightnessNitsForDefaultDisplay(nits);
1016 
1017         float newBrightness = 0.4f;
1018         when(mHolder.brightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
1019         when(mHolder.automaticBrightnessController.convertToFloatScale(nits))
1020                 .thenReturn(newBrightness);
1021         // New display device
1022         setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
1023                 mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
1024         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
1025         DisplayPowerRequest dpr = new DisplayPowerRequest();
1026         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
1027         advanceTime(1); // Run updatePowerState
1028         // One triggered by handleBrightnessModeChange, another triggered by onDisplayChanged
1029         verify(mHolder.animator, times(2)).animateTo(eq(newBrightness), anyFloat(), anyFloat());
1030     }
1031 
1032     @Test
testShortTermModelPersistsWhenDisplayDeviceChanges()1033     public void testShortTermModelPersistsWhenDisplayDeviceChanges() {
1034         float lux = 2000;
1035         float brightness = 0.4f;
1036         float nits = 500;
1037         when(mHolder.brightnessMappingStrategy.getUserLux()).thenReturn(lux);
1038         when(mHolder.brightnessMappingStrategy.getUserBrightness()).thenReturn(brightness);
1039         when(mHolder.brightnessMappingStrategy.convertToNits(brightness)).thenReturn(nits);
1040         when(mHolder.brightnessMappingStrategy.convertToFloatScale(nits)).thenReturn(brightness);
1041         DisplayPowerRequest dpr = new DisplayPowerRequest();
1042         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
1043         advanceTime(1);
1044         clearInvocations(mHolder.injector);
1045 
1046         // New display device
1047         setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
1048                 mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
1049         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
1050         advanceTime(1);
1051 
1052         verify(mHolder.injector).getAutomaticBrightnessController(
1053                 any(AutomaticBrightnessController.Callbacks.class),
1054                 any(Looper.class),
1055                 eq(mSensorManagerMock),
1056                 any(),
1057                 eq(mHolder.brightnessMappingStrategy),
1058                 anyInt(),
1059                 anyFloat(),
1060                 anyFloat(),
1061                 anyFloat(),
1062                 anyInt(),
1063                 anyInt(),
1064                 anyLong(),
1065                 anyLong(),
1066                 anyBoolean(),
1067                 any(HysteresisLevels.class),
1068                 any(HysteresisLevels.class),
1069                 any(HysteresisLevels.class),
1070                 any(HysteresisLevels.class),
1071                 eq(mContext),
1072                 any(BrightnessRangeController.class),
1073                 any(BrightnessThrottler.class),
1074                 isNull(),
1075                 anyInt(),
1076                 anyInt(),
1077                 eq(lux),
1078                 eq(brightness)
1079         );
1080     }
1081 
1082     @Test
testUpdateBrightnessThrottlingDataId()1083     public void testUpdateBrightnessThrottlingDataId() {
1084         mHolder.display.getDisplayInfoLocked().thermalBrightnessThrottlingDataId =
1085                 "throttling-data-id";
1086         clearInvocations(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig());
1087 
1088         mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
1089         DisplayPowerRequest dpr = new DisplayPowerRequest();
1090         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
1091         advanceTime(1); // Run updatePowerState
1092 
1093         verify(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig())
1094                 .getThermalBrightnessThrottlingDataMapByThrottlingId();
1095     }
1096 
1097     @Test
testDwbcCallsHappenOnHandler()1098     public void testDwbcCallsHappenOnHandler() {
1099         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
1100 
1101         mHolder.dpc.setAutomaticScreenBrightnessMode(true);
1102         verify(mDisplayWhiteBalanceControllerMock, never()).setStrongModeEnabled(true);
1103 
1104         // dispatch handler looper
1105         advanceTime(1);
1106         verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
1107     }
1108 
1109     /**
1110      * Creates a mock and registers it to {@link LocalServices}.
1111      */
addLocalServiceMock(Class<T> clazz, T mock)1112     private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
1113         LocalServices.removeServiceForTest(clazz);
1114         LocalServices.addService(clazz, mock);
1115     }
1116 
advanceTime(long timeMs)1117     private void advanceTime(long timeMs) {
1118         mClock.fastForward(timeMs);
1119         mTestLooper.dispatchAll();
1120     }
1121 
setUpSensors()1122     private void setUpSensors() throws Exception {
1123         mProxSensor = TestUtils.createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY,
1124                 PROX_SENSOR_MAX_RANGE);
1125         Sensor screenOffBrightnessSensor = TestUtils.createSensor(
1126                 Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
1127         when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
1128                 .thenReturn(List.of(mProxSensor, screenOffBrightnessSensor));
1129     }
1130 
getSensorEventListener(Sensor sensor)1131     private SensorEventListener getSensorEventListener(Sensor sensor) {
1132         verify(mSensorManagerMock).registerListener(mSensorEventListenerCaptor.capture(),
1133                 eq(sensor), eq(SensorManager.SENSOR_DELAY_NORMAL), isA(Handler.class));
1134         return mSensorEventListenerCaptor.getValue();
1135     }
1136 
setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock, DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock, boolean isEnabled)1137     private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
1138             DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock,
1139             boolean isEnabled) {
1140         DisplayInfo info = new DisplayInfo();
1141         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
1142         deviceInfo.uniqueId = uniqueId;
1143 
1144         when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
1145         when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
1146         when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
1147         when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
1148         when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
1149         when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
1150         when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
1151         when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
1152         when(displayDeviceConfigMock.getProximitySensor()).thenReturn(
1153                 new DisplayDeviceConfig.SensorData() {
1154                     {
1155                         type = Sensor.STRING_TYPE_PROXIMITY;
1156                         name = null;
1157                     }
1158                 });
1159         when(displayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
1160         when(displayDeviceConfigMock.isAutoBrightnessAvailable()).thenReturn(true);
1161         when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
1162                 new DisplayDeviceConfig.SensorData());
1163         when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
1164                 new DisplayDeviceConfig.SensorData() {
1165                     {
1166                         type = Sensor.STRING_TYPE_LIGHT;
1167                         name = null;
1168                     }
1169                 });
1170         when(displayDeviceConfigMock.getScreenOffBrightnessSensorValueToLux())
1171                 .thenReturn(new int[0]);
1172         when(displayDeviceConfigMock.getBrightnessRampFastDecrease())
1173                 .thenReturn(BRIGHTNESS_RAMP_RATE_FAST_DECREASE);
1174         when(displayDeviceConfigMock.getBrightnessRampFastIncrease())
1175                 .thenReturn(BRIGHTNESS_RAMP_RATE_FAST_INCREASE);
1176         when(displayDeviceConfigMock.getBrightnessRampSlowDecrease())
1177                 .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE);
1178         when(displayDeviceConfigMock.getBrightnessRampSlowIncrease())
1179                 .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE);
1180     }
1181 
createDisplayPowerController(int displayId, String uniqueId)1182     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
1183             String uniqueId) {
1184         return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
1185     }
1186 
createDisplayPowerController(int displayId, String uniqueId, boolean isEnabled)1187     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
1188             String uniqueId, boolean isEnabled) {
1189         final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
1190         final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
1191         final AutomaticBrightnessController automaticBrightnessController =
1192                 mock(AutomaticBrightnessController.class);
1193         final BrightnessMappingStrategy brightnessMappingStrategy =
1194                 mock(BrightnessMappingStrategy.class);
1195         final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
1196         final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
1197                 mock(ScreenOffBrightnessSensorController.class);
1198         final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class);
1199 
1200         when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX);
1201 
1202         DisplayPowerController.Injector injector = spy(new TestInjector(displayPowerState, animator,
1203                 automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels,
1204                 screenOffBrightnessSensorController, hbmController));
1205 
1206         final LogicalDisplay display = mock(LogicalDisplay.class);
1207         final DisplayDevice device = mock(DisplayDevice.class);
1208         final HighBrightnessModeMetadata hbmMetadata = mock(HighBrightnessModeMetadata.class);
1209         final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
1210         final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
1211 
1212         setUpDisplay(displayId, uniqueId, display, device, config, isEnabled);
1213 
1214         final DisplayPowerController dpc = new DisplayPowerController(
1215                 mContext, injector, mDisplayPowerCallbacksMock, mHandler,
1216                 mSensorManagerMock, mDisplayBlankerMock, display,
1217                 mBrightnessTrackerMock, brightnessSetting, () -> {},
1218                 hbmMetadata, /* bootCompleted= */ false);
1219 
1220         return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
1221                 animator, automaticBrightnessController, screenOffBrightnessSensorController,
1222                 hbmController, hbmMetadata, brightnessMappingStrategy, injector);
1223     }
1224 
1225     /**
1226      * A class for holding a DisplayPowerController under test and all the mocks specifically
1227      * related to it.
1228      */
1229     private static class DisplayPowerControllerHolder {
1230         public final DisplayPowerController dpc;
1231         public final LogicalDisplay display;
1232         public final DisplayPowerState displayPowerState;
1233         public final BrightnessSetting brightnessSetting;
1234         public final DualRampAnimator<DisplayPowerState> animator;
1235         public final AutomaticBrightnessController automaticBrightnessController;
1236         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
1237         public final HighBrightnessModeController hbmController;
1238         public final HighBrightnessModeMetadata hbmMetadata;
1239         public final BrightnessMappingStrategy brightnessMappingStrategy;
1240         public final DisplayPowerController.Injector injector;
1241 
DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display, DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting, DualRampAnimator<DisplayPowerState> animator, AutomaticBrightnessController automaticBrightnessController, ScreenOffBrightnessSensorController screenOffBrightnessSensorController, HighBrightnessModeController hbmController, HighBrightnessModeMetadata hbmMetadata, BrightnessMappingStrategy brightnessMappingStrategy, DisplayPowerController.Injector injector)1242         DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display,
1243                 DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
1244                 DualRampAnimator<DisplayPowerState> animator,
1245                 AutomaticBrightnessController automaticBrightnessController,
1246                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
1247                 HighBrightnessModeController hbmController,
1248                 HighBrightnessModeMetadata hbmMetadata,
1249                 BrightnessMappingStrategy brightnessMappingStrategy,
1250                 DisplayPowerController.Injector injector) {
1251             this.dpc = dpc;
1252             this.display = display;
1253             this.displayPowerState = displayPowerState;
1254             this.brightnessSetting = brightnessSetting;
1255             this.animator = animator;
1256             this.automaticBrightnessController = automaticBrightnessController;
1257             this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
1258             this.hbmController = hbmController;
1259             this.hbmMetadata = hbmMetadata;
1260             this.brightnessMappingStrategy = brightnessMappingStrategy;
1261             this.injector = injector;
1262         }
1263     }
1264 
1265     private class TestInjector extends DisplayPowerController.Injector {
1266         private final DisplayPowerState mDisplayPowerState;
1267         private final DualRampAnimator<DisplayPowerState> mAnimator;
1268         private final AutomaticBrightnessController mAutomaticBrightnessController;
1269         private final BrightnessMappingStrategy mBrightnessMappingStrategy;
1270         private final HysteresisLevels mHysteresisLevels;
1271         private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
1272         private final HighBrightnessModeController mHighBrightnessModeController;
1273 
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator, AutomaticBrightnessController automaticBrightnessController, BrightnessMappingStrategy brightnessMappingStrategy, HysteresisLevels hysteresisLevels, ScreenOffBrightnessSensorController screenOffBrightnessSensorController, HighBrightnessModeController highBrightnessModeController)1274         TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
1275                 AutomaticBrightnessController automaticBrightnessController,
1276                 BrightnessMappingStrategy brightnessMappingStrategy,
1277                 HysteresisLevels hysteresisLevels,
1278                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
1279                 HighBrightnessModeController highBrightnessModeController) {
1280             mDisplayPowerState = dps;
1281             mAnimator = animator;
1282             mAutomaticBrightnessController = automaticBrightnessController;
1283             mBrightnessMappingStrategy = brightnessMappingStrategy;
1284             mHysteresisLevels = hysteresisLevels;
1285             mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
1286             mHighBrightnessModeController = highBrightnessModeController;
1287         }
1288 
1289         @Override
getClock()1290         DisplayPowerController.Clock getClock() {
1291             return mClock::now;
1292         }
1293 
1294         @Override
getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState)1295         DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
1296                 int displayId, int displayState) {
1297             return mDisplayPowerState;
1298         }
1299 
1300         @Override
getDualRampAnimator(DisplayPowerState dps, FloatProperty<DisplayPowerState> firstProperty, FloatProperty<DisplayPowerState> secondProperty)1301         DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
1302                 FloatProperty<DisplayPowerState> firstProperty,
1303                 FloatProperty<DisplayPowerState> secondProperty) {
1304             return mAnimator;
1305         }
1306 
1307         @Override
getAutomaticBrightnessController( AutomaticBrightnessController.Callbacks callbacks, Looper looper, SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy interactiveModeBrightnessMapper, int lightSensorWarmUpTime, float brightnessMin, float brightnessMax, float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessRangeController, BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userBrightness)1308         AutomaticBrightnessController getAutomaticBrightnessController(
1309                 AutomaticBrightnessController.Callbacks callbacks, Looper looper,
1310                 SensorManager sensorManager, Sensor lightSensor,
1311                 BrightnessMappingStrategy interactiveModeBrightnessMapper,
1312                 int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
1313                 float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
1314                 long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
1315                 boolean resetAmbientLuxAfterWarmUpConfig,
1316                 HysteresisLevels ambientBrightnessThresholds,
1317                 HysteresisLevels screenBrightnessThresholds,
1318                 HysteresisLevels ambientBrightnessThresholdsIdle,
1319                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
1320                 BrightnessRangeController brightnessRangeController,
1321                 BrightnessThrottler brightnessThrottler,
1322                 BrightnessMappingStrategy idleModeBrightnessMapper,
1323                 int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
1324                 float userBrightness) {
1325             return mAutomaticBrightnessController;
1326         }
1327 
1328         @Override
getInteractiveModeBrightnessMapper(Resources resources, DisplayDeviceConfig displayDeviceConfig, DisplayWhiteBalanceController displayWhiteBalanceController)1329         BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
1330                 DisplayDeviceConfig displayDeviceConfig,
1331                 DisplayWhiteBalanceController displayWhiteBalanceController) {
1332             return mBrightnessMappingStrategy;
1333         }
1334 
1335         @Override
getHysteresisLevels(float[] brighteningThresholdsPercentages, float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, float[] darkeningThresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold)1336         HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
1337                 float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
1338                 float[] darkeningThresholdLevels, float minDarkeningThreshold,
1339                 float minBrighteningThreshold) {
1340             return mHysteresisLevels;
1341         }
1342 
1343         @Override
getHysteresisLevels(float[] brighteningThresholdsPercentages, float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, float[] darkeningThresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold, boolean potentialOldBrightnessRange)1344         HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
1345                 float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
1346                 float[] darkeningThresholdLevels, float minDarkeningThreshold,
1347                 float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
1348             return mHysteresisLevels;
1349         }
1350 
1351         @Override
getScreenOffBrightnessSensorController( SensorManager sensorManager, Sensor lightSensor, Handler handler, ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux, BrightnessMappingStrategy brightnessMapper)1352         ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
1353                 SensorManager sensorManager, Sensor lightSensor, Handler handler,
1354                 ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
1355                 BrightnessMappingStrategy brightnessMapper) {
1356             return mScreenOffBrightnessSensorController;
1357         }
1358 
1359         @Override
getHighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax, DisplayDeviceConfig.HighBrightnessModeData hbmData, HighBrightnessModeController.HdrBrightnessDeviceConfig hdrBrightnessCfg, Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context)1360         HighBrightnessModeController getHighBrightnessModeController(Handler handler, int width,
1361                 int height, IBinder displayToken, String displayUniqueId, float brightnessMin,
1362                 float brightnessMax, DisplayDeviceConfig.HighBrightnessModeData hbmData,
1363                 HighBrightnessModeController.HdrBrightnessDeviceConfig hdrBrightnessCfg,
1364                 Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata,
1365                 Context context) {
1366             return mHighBrightnessModeController;
1367         }
1368 
1369         @Override
getDisplayWhiteBalanceController(Handler handler, SensorManager sensorManager, Resources resources)1370         DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
1371                 SensorManager sensorManager, Resources resources) {
1372             return mDisplayWhiteBalanceControllerMock;
1373         }
1374     }
1375 }
1376