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