Merge "Connect follower displays to lead display."
This commit is contained in:
committed by
Android (Google) Code Review
commit
3219191bc6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -848,9 +848,8 @@ final class LogicalDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
public int getLeadDisplayLocked() {
|
||||
public int getLeadDisplayIdLocked() {
|
||||
return mLeadDisplayId;
|
||||
|
||||
}
|
||||
|
||||
public void dumpLocked(PrintWriter pw) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user