From 52ca3aed4fa38ed60a1d3955ba64218dc556207a Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 3 Feb 2023 04:20:46 +0000 Subject: [PATCH] Connect follower displays to lead display. Now that the lead display is defined in the DDC, we can use this information to connect followers to their appropriate leaders. Bug: 265793751 Test: atest DisplayPowerControllerTest Test: atest DisplayPowerController2Test Change-Id: I2ef55c44ba95d3cc71c7e81d7f2c45085a369d75 --- .../server/display/DisplayManagerService.java | 38 +- .../display/DisplayPowerController.java | 36 +- .../display/DisplayPowerController2.java | 29 +- .../DisplayPowerControllerInterface.java | 32 +- .../server/display/LogicalDisplay.java | 3 +- .../display/DisplayPowerController2Test.java | 476 ++++++++++-------- .../display/DisplayPowerControllerTest.java | 435 +++++++++------- .../display/LogicalDisplayMapperTest.java | 4 +- 8 files changed, 629 insertions(+), 424 deletions(-) diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 70069c60c330d..237e78bbb58a2 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -142,6 +142,7 @@ import com.android.server.SystemService; import com.android.server.UiThread; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import com.android.server.display.DisplayDeviceConfig.SensorData; +import com.android.server.display.layout.Layout; import com.android.server.display.utils.SensorUtils; import com.android.server.input.InputManagerInternal; import com.android.server.wm.SurfaceAnimationThread; @@ -1665,12 +1666,37 @@ public final class DisplayManagerService extends SystemService { return; } - // TODO (b/265793751): Set this DPC as a follower of the default DPC if needed, - // clear this DPC's followers if it's not a lead display + final int leadDisplayId = display.getLeadDisplayIdLocked(); + updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId); final String uniqueId = device.getUniqueId(); HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId); - dpc.onDisplayChanged(hbmMetadata); + dpc.onDisplayChanged(hbmMetadata, leadDisplayId); + } + } + + private void updateDisplayPowerControllerLeaderLocked(DisplayPowerControllerInterface dpc, + int leadDisplayId) { + if (dpc.getLeadDisplayId() == leadDisplayId) { + // Lead display hasn't changed, nothing to do. + return; + } + + // If it has changed, then we need to unregister from the previous leader if there was one. + final int prevLeaderId = dpc.getLeadDisplayId(); + if (prevLeaderId != Layout.NO_LEAD_DISPLAY) { + final DisplayPowerControllerInterface prevLeader = + mDisplayPowerControllers.get(prevLeaderId); + if (prevLeader != null) { + prevLeader.removeDisplayBrightnessFollower(dpc); + } + } + + // And then, if it's following, register it with the new one. + if (leadDisplayId != Layout.NO_LEAD_DISPLAY) { + final DisplayPowerControllerInterface newLead = + mDisplayPowerControllers.get(leadDisplayId); + newLead.addDisplayBrightnessFollower(dpc); } } @@ -1734,9 +1760,13 @@ public final class DisplayManagerService extends SystemService { + display.getDisplayIdLocked()); return; } + + final int leadDisplayId = display.getLeadDisplayIdLocked(); + updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId); + final String uniqueId = device.getUniqueId(); HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId); - dpc.onDisplayChanged(hbmMetadata); + dpc.onDisplayChanged(hbmMetadata, leadDisplayId); } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index b58d907c87ebe..1305d63a77d1a 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -18,6 +18,7 @@ package com.android.server.display; import android.animation.Animator; import android.animation.ObjectAnimator; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -74,6 +75,7 @@ import com.android.server.display.brightness.BrightnessEvent; import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal; import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener; +import com.android.server.display.layout.Layout; import com.android.server.display.utils.SensorUtils; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory; @@ -195,6 +197,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The ID of the LogicalDisplay tied to this DisplayPowerController. private final int mDisplayId; + // The ID of the display which this display follows for brightness purposes. + private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY; + // The unique ID of the primary display device currently tied to this logical display private String mUniqueDisplayId; @@ -509,8 +514,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there // is one lead display, the additional displays follow the brightness value of the lead display. @GuardedBy("mLock") - private SparseArray mDisplayBrightnessFollowers = - new SparseArray(); + private final SparseArray mDisplayBrightnessFollowers = + new SparseArray<>(); /** * Creates the display power controller. @@ -721,6 +726,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return mDisplayId; } + @Override + public int getLeadDisplayId() { + return mLeadDisplayId; + } + @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { mHbmController.onAmbientLuxChange(ambientLux); @@ -739,24 +749,20 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } @Override - public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) { + public void addDisplayBrightnessFollower(@NonNull DisplayPowerControllerInterface follower) { synchronized (mLock) { mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower); + sendUpdatePowerStateLocked(); } - sendUpdatePowerState(); } @Override - public void clearDisplayBrightnessFollowers() { - SparseArray followers; + public void removeDisplayBrightnessFollower(@NonNull DisplayPowerControllerInterface follower) { synchronized (mLock) { - followers = mDisplayBrightnessFollowers.clone(); - mDisplayBrightnessFollowers.clear(); - } - for (int i = 0; i < followers.size(); i++) { - DisplayPowerControllerInterface follower = followers.valueAt(i); - follower.setBrightnessToFollow(PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1, - /* ambientLux= */ 0); + mDisplayBrightnessFollowers.remove(follower.getDisplayId()); + mHandler.postAtTime(() -> follower.setBrightnessToFollow( + PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1, + /* ambientLux= */ 0), mClock.uptimeMillis()); } } @@ -851,7 +857,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call * Make sure DisplayManagerService.mSyncRoot is held when this is called */ @Override - public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) { + public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) { + mLeadDisplayId = leadDisplayId; final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); if (device == null) { Slog.wtf(mTag, "Display Device is null in DisplayPowerController for display: " @@ -2701,6 +2708,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(); pw.println("Display Power Controller:"); pw.println(" mDisplayId=" + mDisplayId); + pw.println(" mLeadDisplayId=" + mLeadDisplayId); pw.println(" mLightSensor=" + mLightSensor); pw.println(); diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 23ef680a0292b..82faa12be90ed 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -73,6 +73,7 @@ import com.android.server.display.brightness.BrightnessUtils; import com.android.server.display.brightness.DisplayBrightnessController; import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal; import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener; +import com.android.server.display.layout.Layout; import com.android.server.display.state.DisplayStateController; import com.android.server.display.utils.SensorUtils; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; @@ -179,6 +180,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // The ID of the LogicalDisplay tied to this DisplayPowerController2. private final int mDisplayId; + // The ID of the display which this display follows for brightness purposes. + private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY; + // The unique ID of the primary display device currently tied to this logical display private String mUniqueDisplayId; @@ -694,7 +698,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal * Make sure DisplayManagerService.mSyncRoot lock is held when this is called */ @Override - public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) { + public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) { + mLeadDisplayId = leadDisplayId; final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); if (device == null) { Slog.wtf(mTag, "Display Device is null in DisplayPowerController2 for display: " @@ -2148,6 +2153,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal return mDisplayId; } + @Override + public int getLeadDisplayId() { + return mLeadDisplayId; + } + @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { mHbmController.onAmbientLuxChange(ambientLux); @@ -2218,21 +2228,17 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) { synchronized (mLock) { mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower); + sendUpdatePowerStateLocked(); } - sendUpdatePowerState(); } @Override - public void clearDisplayBrightnessFollowers() { - SparseArray followers; + public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) { synchronized (mLock) { - followers = mDisplayBrightnessFollowers.clone(); - mDisplayBrightnessFollowers.clear(); - } - for (int i = 0; i < followers.size(); i++) { - DisplayPowerControllerInterface follower = followers.valueAt(i); - follower.setBrightnessToFollow(PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1, - /* ambientLux= */ 0); + mDisplayBrightnessFollowers.remove(follower.getDisplayId()); + mHandler.postAtTime(() -> follower.setBrightnessToFollow( + PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1, + /* ambientLux= */ 0), mClock.uptimeMillis()); } } @@ -2242,6 +2248,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal pw.println(); pw.println("Display Power Controller:"); pw.println(" mDisplayId=" + mDisplayId); + pw.println(" mLeadDisplayId=" + mLeadDisplayId); pw.println(" mLightSensor=" + mLightSensor); pw.println(); diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java index 4612ec9cf2dcc..0bc8154b610c0 100644 --- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java +++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java @@ -32,13 +32,18 @@ public interface DisplayPowerControllerInterface { /** * Notified when the display is changed. - * We use this to apply any changes that might be needed - * when displays get swapped on foldable devices. - * We also pass the High brightness mode metadata like - * remaining time and hbm events for the corresponding - * physical display, to update the values correctly. + * + * We use this to apply any changes that might be needed when displays get swapped on foldable + * devices, when layouts change, etc. + * + * Must be called while holding the SyncRoot lock. + * + * @param hbmInfo The high brightness mode metadata, like + * remaining time and hbm events, for the corresponding + * physical display, to make sure we stay within the safety margins. + * @param leadDisplayId The display who is considered our "leader" for things like brightness. */ - void onDisplayChanged(HighBrightnessModeMetadata hbmInfo); + void onDisplayChanged(HighBrightnessModeMetadata hbmInfo, int leadDisplayId); /** * Unregisters all listeners and interrupts all running threads; halting future work. @@ -168,6 +173,16 @@ public interface DisplayPowerControllerInterface { */ int getDisplayId(); + /** + * Get the ID of the display that is the leader of this DPC. + * + * Note that this is different than the display associated with the DPC. The leader is another + * display which we follow for things like brightness. + * + * Must be called while holding the SyncRoot lock. + */ + int getLeadDisplayId(); + /** * Set the brightness to follow if this is an additional display in a set of concurrent * displays. @@ -187,7 +202,8 @@ public interface DisplayPowerControllerInterface { void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower); /** - * Clear all the additional displays following the brightness value of this display. + * Removes the given display from the list of brightness followers. + * @param follower The DPC to remove from the followers list */ - void clearDisplayBrightnessFollowers(); + void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower); } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 473317c384f1c..60903864a8814 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -848,9 +848,8 @@ final class LogicalDisplay { } } - public int getLeadDisplayLocked() { + public int getLeadDisplayIdLocked() { return mLeadDisplayId; - } public void dumpLocked(PrintWriter pw) { diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java index 5ca01eeb69dbe..355ea1c6e72dc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java @@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -78,19 +79,19 @@ import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) public final class DisplayPowerController2Test { - private static final String UNIQUE_DISPLAY_ID = "unique_id_test123"; private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; - private static final int FOLLOWER_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1; + private static final String UNIQUE_DISPLAY_ID = "unique_id_test123"; + private static final int FOLLOWER_DISPLAY_ID = DISPLAY_ID + 1; + private static final String FOLLOWER_UNIQUE_ID = "unique_id_456"; + private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1; + private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789"; private MockitoSession mSession; private OffsettableClock mClock; private TestLooper mTestLooper; private Handler mHandler; - private DisplayPowerController2.Injector mInjector; - private DisplayPowerController2.Injector mFollowerInjector; private Context mContextSpy; private DisplayPowerController2 mDpc; - private DisplayPowerController2 mFollowerDpc; private Sensor mProxSensor; @Mock @@ -102,22 +103,14 @@ public final class DisplayPowerController2Test { @Mock private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock; @Mock - private HighBrightnessModeMetadata mFollowerHighBrightnessModeMetadataMock; - @Mock private LogicalDisplay mLogicalDisplayMock; @Mock - private LogicalDisplay mFollowerLogicalDisplayMock; - @Mock private DisplayDevice mDisplayDeviceMock; @Mock - private DisplayDevice mFollowerDisplayDeviceMock; - @Mock private BrightnessTracker mBrightnessTrackerMock; @Mock private BrightnessSetting mBrightnessSettingMock; @Mock - private BrightnessSetting mFollowerBrightnessSettingMock; - @Mock private WindowManagerPolicy mWindowManagerPolicyMock; @Mock private PowerManager mPowerManagerMock; @@ -126,18 +119,12 @@ public final class DisplayPowerController2Test { @Mock private DisplayDeviceConfig mDisplayDeviceConfigMock; @Mock - private DisplayDeviceConfig mFollowerDisplayDeviceConfigMock; - @Mock private DisplayPowerState mDisplayPowerStateMock; @Mock private DualRampAnimator mDualRampAnimatorMock; @Mock - private DualRampAnimator mFollowerDualRampAnimatorMock; - @Mock private AutomaticBrightnessController mAutomaticBrightnessControllerMock; @Mock - private AutomaticBrightnessController mFollowerAutomaticBrightnessControllerMock; - @Mock private BrightnessMappingStrategy mBrightnessMapperMock; @Mock private HysteresisLevels mHysteresisLevelsMock; @@ -162,149 +149,6 @@ public final class DisplayPowerController2Test { mClock = new OffsettableClock.Stopped(); mTestLooper = new TestLooper(mClock::now); mHandler = new Handler(mTestLooper.getLooper()); - mInjector = new DisplayPowerController2.Injector() { - @Override - DisplayPowerController2.Clock getClock() { - return mClock::now; - } - - @Override - DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, - int displayId, int displayState) { - return mDisplayPowerStateMock; - } - - @Override - DualRampAnimator getDualRampAnimator(DisplayPowerState dps, - FloatProperty firstProperty, - FloatProperty secondProperty) { - return mDualRampAnimatorMock; - } - - @Override - WakelockController getWakelockController(int displayId, - DisplayPowerCallbacks displayPowerCallbacks) { - return mWakelockController; - } - - @Override - DisplayPowerProximityStateController getDisplayPowerProximityStateController( - WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig, - Looper looper, Runnable nudgeUpdatePowerState, int displayId, - SensorManager sensorManager) { - return new DisplayPowerProximityStateController(wakelockController, - displayDeviceConfig, looper, nudgeUpdatePowerState, displayId, - sensorManager, /* injector= */ null); - } - - @Override - AutomaticBrightnessController 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, - HighBrightnessModeController hbmController, - BrightnessThrottler brightnessThrottler, - BrightnessMappingStrategy idleModeBrightnessMapper, - int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, - float userBrightness) { - return mAutomaticBrightnessControllerMock; - } - - @Override - BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, - DisplayDeviceConfig displayDeviceConfig, - DisplayWhiteBalanceController displayWhiteBalanceController) { - return mBrightnessMapperMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold) { - return mHysteresisLevelsMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold, boolean potentialOldBrightnessRange) { - return mHysteresisLevelsMock; - } - }; - mFollowerInjector = new DisplayPowerController2.Injector() { - @Override - DisplayPowerController2.Clock getClock() { - return mClock::now; - } - - @Override - DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, - int displayId, int displayState) { - return mDisplayPowerStateMock; - } - - @Override - DualRampAnimator getDualRampAnimator(DisplayPowerState dps, - FloatProperty firstProperty, - FloatProperty secondProperty) { - return mFollowerDualRampAnimatorMock; - } - - @Override - AutomaticBrightnessController 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, - HighBrightnessModeController hbmController, - BrightnessThrottler brightnessThrottler, - BrightnessMappingStrategy idleModeBrightnessMapper, - int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, - float userBrightness) { - return mFollowerAutomaticBrightnessControllerMock; - } - - @Override - BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, - DisplayDeviceConfig displayDeviceConfig, - DisplayWhiteBalanceController displayWhiteBalanceController) { - return mBrightnessMapperMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold) { - return mHysteresisLevelsMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold, boolean potentialOldBrightnessRange) { - return mHysteresisLevelsMock; - } - }; - addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock); when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock); @@ -319,21 +163,18 @@ public final class DisplayPowerController2Test { setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID, mLogicalDisplayMock, mDisplayDeviceMock, mDisplayDeviceConfigMock); - setUpDisplay(FOLLOWER_DISPLAY_ID, UNIQUE_DISPLAY_ID, mFollowerLogicalDisplayMock, - mFollowerDisplayDeviceMock, mFollowerDisplayDeviceConfigMock); mProxSensor = setUpProxSensor(); + TestInjector injector = new TestInjector(mDisplayPowerStateMock, mDualRampAnimatorMock, + mAutomaticBrightnessControllerMock, mWakelockController, mBrightnessMapperMock, + mHysteresisLevelsMock); + mDpc = new DisplayPowerController2( - mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler, + mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock, mBrightnessTrackerMock, mBrightnessSettingMock, () -> { }, mHighBrightnessModeMetadataMock); - mFollowerDpc = new DisplayPowerController2( - mContextSpy, mFollowerInjector, mDisplayPowerCallbacksMock, mHandler, - mSensorManagerMock, mDisplayBlankerMock, mFollowerLogicalDisplayMock, - mBrightnessTrackerMock, mFollowerBrightnessSettingMock, () -> { - }, mFollowerHighBrightnessModeMetadataMock); } @After @@ -382,7 +223,9 @@ public final class DisplayPowerController2Test { DisplayPowerRequest dpr = new DisplayPowerRequest(); dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; dpr.useProximitySensor = true; - mFollowerDpc.requestPowerState(dpr, false /* waitForNegativeProximity */); + final DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID); + followerDpc.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */); // Run updatePowerState advanceTime(1); @@ -448,9 +291,12 @@ public final class DisplayPowerController2Test { @Test public void testDisplayBrightnessFollowers_BothDpcsSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -458,53 +304,45 @@ public final class DisplayPowerController2Test { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); // Test different float scale values float leadBrightness = 0.3f; float followerBrightness = 0.4f; float nits = 300; when(mAutomaticBrightnessControllerMock.convertToNits(leadBrightness)).thenReturn(nits); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits)) + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) .thenReturn(followerBrightness); when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness); listener.onBrightnessChanged(leadBrightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(followerBrightness), anyFloat(), + verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(), anyFloat()); - clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock); + clearInvocations(mDualRampAnimatorMock, followerDpc.animator); // Test the same float scale value float brightness = 0.6f; nits = 600; when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits)) + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) .thenReturn(brightness); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - - clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock); - - // Test clear followers - mDpc.clearDisplayBrightnessFollowers(); - when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness); - listener.onBrightnessChanged(leadBrightness); - advanceTime(1); // Send messages, run updatePowerState - verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock, never()).animateTo(eq(followerBrightness), anyFloat(), - anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -512,24 +350,27 @@ public final class DisplayPowerController2Test { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(300f); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat())) + when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat())) .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -537,7 +378,7 @@ public final class DisplayPowerController2Test { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f); @@ -545,14 +386,17 @@ public final class DisplayPowerController2Test { listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -560,16 +404,248 @@ public final class DisplayPowerController2Test { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat())) + when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat())) .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + } + + + @Test + public void testDisplayBrightnessFollowersRemoval() { + DisplayPowerControllerHolder followerDpc = createDisplayPowerController(FOLLOWER_DISPLAY_ID, + FOLLOWER_UNIQUE_ID); + DisplayPowerControllerHolder secondFollowerDpc = createDisplayPowerController( + SECOND_FOLLOWER_DISPLAY_ID, SECOND_FOLLOWER_UNIQUE_DISPLAY_ID); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + secondFollowerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); + + // Set the initial brightness on the DPC we're going to remove so we have a fixed value for + // it to return to. + listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(followerDpc.brightnessSetting).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue(); + final float initialFollowerBrightness = 0.3f; + when(followerDpc.brightnessSetting.getBrightness()).thenReturn(initialFollowerBrightness); + followerListener.onBrightnessChanged(initialFollowerBrightness); + advanceTime(1); + verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), + anyFloat(), anyFloat()); + + + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); + mDpc.addDisplayBrightnessFollower(secondFollowerDpc.dpc); + clearInvocations(followerDpc.animator); + + // Validate both followers are correctly registered and receiving brightness updates + float brightness = 0.6f; + float nits = 600; + when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + + clearInvocations(mDualRampAnimatorMock, followerDpc.animator, secondFollowerDpc.animator); + + // Remove the first follower and validate it goes back to its original brightness. + mDpc.removeDisplayBrightnessFollower(followerDpc.dpc); + advanceTime(1); + verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), + anyFloat(), anyFloat()); + clearInvocations(followerDpc.animator); + + // Change the brightness of the lead display and validate only the second follower responds + brightness = 0.7f; + nits = 700; + when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator, never()).animateTo(anyFloat(), anyFloat(), anyFloat()); + verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + } + + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, + String uniqueId) { + final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); + final DualRampAnimator animator = mock(DualRampAnimator.class); + final AutomaticBrightnessController automaticBrightnessController = + mock(AutomaticBrightnessController.class); + final WakelockController wakelockController = mock(WakelockController.class); + final BrightnessMappingStrategy brightnessMappingStrategy = + mock(BrightnessMappingStrategy.class); + final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class); + + TestInjector injector = new TestInjector(displayPowerState, animator, + automaticBrightnessController, wakelockController, brightnessMappingStrategy, + hysteresisLevels); + + final LogicalDisplay display = mock(LogicalDisplay.class); + final DisplayDevice device = mock(DisplayDevice.class); + final HighBrightnessModeMetadata hbmMetadata = mock(HighBrightnessModeMetadata.class); + final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class); + final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class); + + setUpDisplay(displayId, uniqueId, display, device, config); + + final DisplayPowerController2 dpc = new DisplayPowerController2( + mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, + mSensorManagerMock, mDisplayBlankerMock, display, + mBrightnessTrackerMock, brightnessSetting, () -> {}, + hbmMetadata); + + return new DisplayPowerControllerHolder(dpc, brightnessSetting, animator, + automaticBrightnessController, wakelockController); + } + + /** + * A class for holding a DisplayPowerController under test and all the mocks specifically + * related to it. + */ + private static class DisplayPowerControllerHolder { + public final DisplayPowerController2 dpc; + public final BrightnessSetting brightnessSetting; + public final DualRampAnimator animator; + public final AutomaticBrightnessController automaticBrightnessController; + public final WakelockController wakelockController; + + DisplayPowerControllerHolder(DisplayPowerController2 dpc, + BrightnessSetting brightnessSetting, DualRampAnimator animator, + AutomaticBrightnessController automaticBrightnessController, + WakelockController wakelockController) { + this.dpc = dpc; + this.brightnessSetting = brightnessSetting; + this.animator = animator; + this.automaticBrightnessController = automaticBrightnessController; + this.wakelockController = wakelockController; + } + } + + private class TestInjector extends DisplayPowerController2.Injector { + private final DisplayPowerState mDisplayPowerState; + private final DualRampAnimator mAnimator; + private final AutomaticBrightnessController mAutomaticBrightnessController; + private final WakelockController mWakelockController; + private final BrightnessMappingStrategy mBrightnessMappingStrategy; + private final HysteresisLevels mHysteresisLevels; + + TestInjector(DisplayPowerState dps, DualRampAnimator animator, + AutomaticBrightnessController automaticBrightnessController, + WakelockController wakelockController, + BrightnessMappingStrategy brightnessMappingStrategy, + HysteresisLevels hysteresisLevels) { + mDisplayPowerState = dps; + mAnimator = animator; + mAutomaticBrightnessController = automaticBrightnessController; + mWakelockController = wakelockController; + mBrightnessMappingStrategy = brightnessMappingStrategy; + mHysteresisLevels = hysteresisLevels; + } + + @Override + DisplayPowerController2.Clock getClock() { + return mClock::now; + } + + @Override + DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, + int displayId, int displayState) { + return mDisplayPowerState; + } + + @Override + DualRampAnimator getDualRampAnimator(DisplayPowerState dps, + FloatProperty firstProperty, + FloatProperty secondProperty) { + return mAnimator; + } + + @Override + WakelockController getWakelockController(int displayId, + DisplayPowerCallbacks displayPowerCallbacks) { + return mWakelockController; + } + + @Override + DisplayPowerProximityStateController getDisplayPowerProximityStateController( + WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig, + Looper looper, Runnable nudgeUpdatePowerState, int displayId, + SensorManager sensorManager) { + return new DisplayPowerProximityStateController(wakelockController, + displayDeviceConfig, looper, nudgeUpdatePowerState, displayId, + sensorManager, /* injector= */ null); + } + + @Override + AutomaticBrightnessController 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, + HighBrightnessModeController hbmController, + BrightnessThrottler brightnessThrottler, + BrightnessMappingStrategy idleModeBrightnessMapper, + int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, + float userBrightness) { + return mAutomaticBrightnessController; + } + + @Override + BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, + DisplayDeviceConfig displayDeviceConfig, + DisplayWhiteBalanceController displayWhiteBalanceController) { + return mBrightnessMappingStrategy; + } + + @Override + HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, + float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, + float[] darkeningThresholdLevels, float minDarkeningThreshold, + float minBrighteningThreshold) { + return mHysteresisLevels; + } + + @Override + HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, + float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, + float[] darkeningThresholdLevels, float minDarkeningThreshold, + float minBrighteningThreshold, boolean potentialOldBrightnessRange) { + return mHysteresisLevels; + } } } diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java index 996a9abb81fdb..e39a2e0e6e11b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -78,19 +79,19 @@ import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) public final class DisplayPowerControllerTest { - private static final String UNIQUE_DISPLAY_ID = "unique_id_test123"; private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; - private static final int FOLLOWER_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1; + private static final String UNIQUE_DISPLAY_ID = "unique_id_test123"; + private static final int FOLLOWER_DISPLAY_ID = DISPLAY_ID + 1; + private static final String FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_456"; + private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1; + private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789"; private MockitoSession mSession; private OffsettableClock mClock; private TestLooper mTestLooper; private Handler mHandler; - private DisplayPowerController.Injector mInjector; - private DisplayPowerController.Injector mFollowerInjector; private Context mContextSpy; private DisplayPowerController mDpc; - private DisplayPowerController mFollowerDpc; private Sensor mProxSensor; @Mock @@ -102,22 +103,14 @@ public final class DisplayPowerControllerTest { @Mock private LogicalDisplay mLogicalDisplayMock; @Mock - private LogicalDisplay mFollowerLogicalDisplayMock; - @Mock private DisplayDevice mDisplayDeviceMock; @Mock - private DisplayDevice mFollowerDisplayDeviceMock; - @Mock private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock; @Mock - private HighBrightnessModeMetadata mFollowerHighBrightnessModeMetadataMock; - @Mock private BrightnessTracker mBrightnessTrackerMock; @Mock private BrightnessSetting mBrightnessSettingMock; @Mock - private BrightnessSetting mFollowerBrightnessSettingMock; - @Mock private WindowManagerPolicy mWindowManagerPolicyMock; @Mock private PowerManager mPowerManagerMock; @@ -126,18 +119,12 @@ public final class DisplayPowerControllerTest { @Mock private DisplayDeviceConfig mDisplayDeviceConfigMock; @Mock - private DisplayDeviceConfig mFollowerDisplayDeviceConfigMock; - @Mock private DisplayPowerState mDisplayPowerStateMock; @Mock private DualRampAnimator mDualRampAnimatorMock; @Mock - private DualRampAnimator mFollowerDualRampAnimatorMock; - @Mock private AutomaticBrightnessController mAutomaticBrightnessControllerMock; @Mock - private AutomaticBrightnessController mFollowerAutomaticBrightnessControllerMock; - @Mock private BrightnessMappingStrategy mBrightnessMapperMock; @Mock private HysteresisLevels mHysteresisLevelsMock; @@ -160,132 +147,6 @@ public final class DisplayPowerControllerTest { mClock = new OffsettableClock.Stopped(); mTestLooper = new TestLooper(mClock::now); mHandler = new Handler(mTestLooper.getLooper()); - mInjector = new DisplayPowerController.Injector() { - @Override - DisplayPowerController.Clock getClock() { - return mClock::now; - } - - @Override - DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, - int displayId, int displayState) { - return mDisplayPowerStateMock; - } - - @Override - DualRampAnimator getDualRampAnimator(DisplayPowerState dps, - FloatProperty firstProperty, - FloatProperty secondProperty) { - return mDualRampAnimatorMock; - } - - @Override - AutomaticBrightnessController 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, - HighBrightnessModeController hbmController, - BrightnessThrottler brightnessThrottler, - BrightnessMappingStrategy idleModeBrightnessMapper, - int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, - float userBrightness) { - return mAutomaticBrightnessControllerMock; - } - - @Override - BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, - DisplayDeviceConfig displayDeviceConfig, - DisplayWhiteBalanceController displayWhiteBalanceController) { - return mBrightnessMapperMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold) { - return mHysteresisLevelsMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold, boolean potentialOldBrightnessRange) { - return mHysteresisLevelsMock; - } - }; - mFollowerInjector = new DisplayPowerController.Injector() { - @Override - DisplayPowerController.Clock getClock() { - return mClock::now; - } - - @Override - DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, - int displayId, int displayState) { - return mDisplayPowerStateMock; - } - - @Override - DualRampAnimator getDualRampAnimator(DisplayPowerState dps, - FloatProperty firstProperty, - FloatProperty secondProperty) { - return mFollowerDualRampAnimatorMock; - } - - @Override - AutomaticBrightnessController 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, - HighBrightnessModeController hbmController, - BrightnessThrottler brightnessThrottler, - BrightnessMappingStrategy idleModeBrightnessMapper, - int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, - float userBrightness) { - return mFollowerAutomaticBrightnessControllerMock; - } - - @Override - BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, - DisplayDeviceConfig displayDeviceConfig, - DisplayWhiteBalanceController displayWhiteBalanceController) { - return mBrightnessMapperMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold) { - return mHysteresisLevelsMock; - } - - @Override - HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, - float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, - float[] darkeningThresholdLevels, float minDarkeningThreshold, - float minBrighteningThreshold, boolean potentialOldBrightnessRange) { - return mHysteresisLevelsMock; - } - }; addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock); @@ -301,21 +162,17 @@ public final class DisplayPowerControllerTest { setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID, mLogicalDisplayMock, mDisplayDeviceMock, mDisplayDeviceConfigMock); - setUpDisplay(FOLLOWER_DISPLAY_ID, UNIQUE_DISPLAY_ID, mFollowerLogicalDisplayMock, - mFollowerDisplayDeviceMock, mFollowerDisplayDeviceConfigMock); mProxSensor = setUpProxSensor(); + TestInjector injector = new TestInjector(mDisplayPowerStateMock, mDualRampAnimatorMock, + mAutomaticBrightnessControllerMock, mBrightnessMapperMock, mHysteresisLevelsMock); + mDpc = new DisplayPowerController( - mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler, + mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock, mBrightnessTrackerMock, mBrightnessSettingMock, () -> { }, mHighBrightnessModeMetadataMock); - mFollowerDpc = new DisplayPowerController( - mContextSpy, mFollowerInjector, mDisplayPowerCallbacksMock, mHandler, - mSensorManagerMock, mDisplayBlankerMock, mFollowerLogicalDisplayMock, - mBrightnessTrackerMock, mFollowerBrightnessSettingMock, () -> { - }, mFollowerHighBrightnessModeMetadataMock); } @After @@ -360,12 +217,15 @@ public final class DisplayPowerControllerTest { @Test public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON); // send a display power request DisplayPowerRequest dpr = new DisplayPowerRequest(); dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; dpr.useProximitySensor = true; - mFollowerDpc.requestPowerState(dpr, false /* waitForNegativeProximity */); + followerDpc.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */); // Run updatePowerState advanceTime(1); @@ -431,9 +291,12 @@ public final class DisplayPowerControllerTest { @Test public void testDisplayBrightnessFollowers_BothDpcsSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -441,53 +304,45 @@ public final class DisplayPowerControllerTest { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); // Test different float scale values float leadBrightness = 0.3f; float followerBrightness = 0.4f; float nits = 300; when(mAutomaticBrightnessControllerMock.convertToNits(leadBrightness)).thenReturn(nits); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits)) + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) .thenReturn(followerBrightness); when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness); listener.onBrightnessChanged(leadBrightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(followerBrightness), anyFloat(), + verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(), anyFloat()); - clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock); + clearInvocations(mDualRampAnimatorMock, followerDpc.animator); // Test the same float scale value float brightness = 0.6f; nits = 600; when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits)) + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) .thenReturn(brightness); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - - clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock); - - // Test clear followers - mDpc.clearDisplayBrightnessFollowers(); - when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness); - listener.onBrightnessChanged(leadBrightness); - advanceTime(1); // Send messages, run updatePowerState - verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock, never()).animateTo(eq(followerBrightness), anyFloat(), - anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -495,24 +350,27 @@ public final class DisplayPowerControllerTest { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(300f); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat())) + when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat())) .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -520,7 +378,7 @@ public final class DisplayPowerControllerTest { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f); @@ -528,14 +386,17 @@ public final class DisplayPowerControllerTest { listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); } @Test public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + DisplayPowerRequest dpr = new DisplayPowerRequest(); mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState ArgumentCaptor listenerCaptor = @@ -543,16 +404,224 @@ public final class DisplayPowerControllerTest { verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); - mDpc.addDisplayBrightnessFollower(mFollowerDpc); + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); float brightness = 0.3f; when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f); - when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat())) + when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat())) .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); listener.onBrightnessChanged(brightness); advanceTime(1); // Send messages, run updatePowerState verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); - verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + } + + @Test + public void testDisplayBrightnessFollowersRemoval() { + DisplayPowerControllerHolder followerDpc = + createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID); + DisplayPowerControllerHolder secondFollowerDpc = + createDisplayPowerController(SECOND_FOLLOWER_DISPLAY_ID, + SECOND_FOLLOWER_UNIQUE_DISPLAY_ID); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + secondFollowerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); + + // Set the initial brightness on the DPC we're going to remove so we have a fixed value for + // it to return to. + listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(followerDpc.brightnessSetting).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue(); + final float initialFollowerBrightness = 0.3f; + when(followerDpc.brightnessSetting.getBrightness()).thenReturn(initialFollowerBrightness); + followerListener.onBrightnessChanged(initialFollowerBrightness); + advanceTime(1); + verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), + anyFloat(), anyFloat()); + + + mDpc.addDisplayBrightnessFollower(followerDpc.dpc); + mDpc.addDisplayBrightnessFollower(secondFollowerDpc.dpc); + clearInvocations(followerDpc.animator); + + // Validate both followers are correctly registered and receiving brightness updates + float brightness = 0.6f; + float nits = 600; + when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + + clearInvocations(mDualRampAnimatorMock, followerDpc.animator, secondFollowerDpc.animator); + + // Remove the first follower and validate it goes back to its original brightness. + mDpc.removeDisplayBrightnessFollower(followerDpc.dpc); + advanceTime(1); + verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness), + anyFloat(), anyFloat()); + clearInvocations(followerDpc.animator); + + // Change the brightness of the lead display and validate only the second follower responds + brightness = 0.7f; + nits = 700; + when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits); + when(followerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(brightness); + when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat()); + verify(followerDpc.animator, never()).animateTo(anyFloat(), anyFloat(), anyFloat()); + verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); + } + + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, + String uniqueId) { + final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); + final DualRampAnimator animator = mock(DualRampAnimator.class); + final AutomaticBrightnessController automaticBrightnessController = + mock(AutomaticBrightnessController.class); + final BrightnessMappingStrategy brightnessMappingStrategy = + mock(BrightnessMappingStrategy.class); + final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class); + + DisplayPowerController.Injector injector = new TestInjector(displayPowerState, animator, + automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels); + + final LogicalDisplay display = mock(LogicalDisplay.class); + final DisplayDevice device = mock(DisplayDevice.class); + final HighBrightnessModeMetadata hbmMetadata = mock(HighBrightnessModeMetadata.class); + final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class); + final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class); + + setUpDisplay(displayId, uniqueId, display, device, config); + + final DisplayPowerController dpc = new DisplayPowerController( + mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, + mSensorManagerMock, mDisplayBlankerMock, display, + mBrightnessTrackerMock, brightnessSetting, () -> {}, + hbmMetadata); + + return new DisplayPowerControllerHolder(dpc, brightnessSetting, animator, + automaticBrightnessController); + } + + /** + * A class for holding a DisplayPowerController under test and all the mocks specifically + * related to it. + */ + private static class DisplayPowerControllerHolder { + public final DisplayPowerController dpc; + public final BrightnessSetting brightnessSetting; + public final DualRampAnimator animator; + public final AutomaticBrightnessController automaticBrightnessController; + + DisplayPowerControllerHolder(DisplayPowerController dpc, + BrightnessSetting brightnessSetting, DualRampAnimator animator, + AutomaticBrightnessController automaticBrightnessController) { + this.dpc = dpc; + this.brightnessSetting = brightnessSetting; + this.animator = animator; + this.automaticBrightnessController = automaticBrightnessController; + } + } + + private class TestInjector extends DisplayPowerController.Injector { + private final DisplayPowerState mDisplayPowerState; + private final DualRampAnimator mAnimator; + private final AutomaticBrightnessController mAutomaticBrightnessController; + private final BrightnessMappingStrategy mBrightnessMappingStrategy; + private final HysteresisLevels mHysteresisLevels; + + TestInjector(DisplayPowerState dps, DualRampAnimator animator, + AutomaticBrightnessController automaticBrightnessController, + BrightnessMappingStrategy brightnessMappingStrategy, + HysteresisLevels hysteresisLevels) { + mDisplayPowerState = dps; + mAnimator = animator; + mAutomaticBrightnessController = automaticBrightnessController; + mBrightnessMappingStrategy = brightnessMappingStrategy; + mHysteresisLevels = hysteresisLevels; + } + + @Override + DisplayPowerController.Clock getClock() { + return mClock::now; + } + + @Override + DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, + int displayId, int displayState) { + return mDisplayPowerState; + } + + @Override + DualRampAnimator getDualRampAnimator(DisplayPowerState dps, + FloatProperty firstProperty, + FloatProperty secondProperty) { + return mAnimator; + } + + @Override + AutomaticBrightnessController 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, + HighBrightnessModeController hbmController, + BrightnessThrottler brightnessThrottler, + BrightnessMappingStrategy idleModeBrightnessMapper, + int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, + float userBrightness) { + return mAutomaticBrightnessController; + } + + @Override + BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, + DisplayDeviceConfig displayDeviceConfig, + DisplayWhiteBalanceController displayWhiteBalanceController) { + return mBrightnessMappingStrategy; + } + + @Override + HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, + float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, + float[] darkeningThresholdLevels, float minDarkeningThreshold, + float minBrighteningThreshold) { + return mHysteresisLevels; + } + + @Override + HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages, + float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, + float[] darkeningThresholdLevels, float minDarkeningThreshold, + float minBrighteningThreshold, boolean potentialOldBrightnessRange) { + return mHysteresisLevels; + } } } diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java index bd2b5fdb37684..ac1dca9653102 100644 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java @@ -614,9 +614,9 @@ public class LogicalDisplayMapperTest { assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked()); assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked()); assertEquals(-1, mLogicalDisplayMapper.getDisplayLocked(device1) - .getLeadDisplayLocked()); + .getLeadDisplayIdLocked()); assertEquals(0, mLogicalDisplayMapper.getDisplayLocked(device2) - .getLeadDisplayLocked()); + .getLeadDisplayIdLocked()); assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device1) .getBrightnessThrottlingDataIdLocked()); assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device2)