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
This commit is contained in:
Michael Wright
2023-02-03 04:20:46 +00:00
parent cfe5b618c8
commit 52ca3aed4f
8 changed files with 629 additions and 424 deletions

View File

@@ -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);
}
}

View File

@@ -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<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
new SparseArray();
private final SparseArray<DisplayPowerControllerInterface> 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<DisplayPowerControllerInterface> 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();

View File

@@ -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<DisplayPowerControllerInterface> 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();

View File

@@ -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);
}

View File

@@ -848,9 +848,8 @@ final class LogicalDisplay {
}
}
public int getLeadDisplayLocked() {
public int getLeadDisplayIdLocked() {
return mLeadDisplayId;
}
public void dumpLocked(PrintWriter pw) {

View File

@@ -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<DisplayPowerState> mDualRampAnimatorMock;
@Mock
private DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<DisplayPowerState> 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<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
public final WakelockController wakelockController;
DisplayPowerControllerHolder(DisplayPowerController2 dpc,
BrightnessSetting brightnessSetting, DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> mAnimator;
private final AutomaticBrightnessController mAutomaticBrightnessController;
private final WakelockController mWakelockController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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;
}
}
}

View File

@@ -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<DisplayPowerState> mDualRampAnimatorMock;
@Mock
private DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<BrightnessSetting.BrightnessSettingListener> 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<DisplayPowerState> 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<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
DisplayPowerControllerHolder(DisplayPowerController dpc,
BrightnessSetting brightnessSetting, DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> mAnimator;
private final AutomaticBrightnessController mAutomaticBrightnessController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> 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<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> 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;
}
}
}

View File

@@ -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)