Adding Tests for SuspendBlocker.Display usage

Bug: 213407479
Test: atest DisplayPowerControllerTest
Change-Id: I0ee03f704349729d3298e7b3cd26dd870d61935f
This commit is contained in:
Santos Cordon
2022-06-24 02:36:32 +00:00
committed by Rupesh Bansal
parent 95fab76bcc
commit d0894ea2ab
4 changed files with 357 additions and 61 deletions

View File

@@ -2583,8 +2583,8 @@ public final class DisplayManagerService extends SystemService {
final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
display, mSyncRoot);
final DisplayPowerController displayPowerController = new DisplayPowerController(
mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
() -> handleBrightnessChange(display));
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
}

View File

@@ -48,6 +48,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.FloatProperty;
import android.util.Log;
import android.util.MathUtils;
import android.util.MutableFloat;
@@ -58,6 +59,7 @@ import android.view.Display;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
@@ -97,7 +99,7 @@ import java.io.PrintWriter;
* blocker as long as the display is not ready. So most of the work done here
* does not need to worry about holding a suspend blocker unless it happens
* independently of the display ready signal.
*
*
* For debugging, you can make the color fade and brightness animations run
* slower by changing the "animator duration scale" option in Development Settings.
*/
@@ -256,6 +258,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// to reach the final state.
private final boolean mBrightnessBucketsInDozeConfig;
private final Clock mClock;
private final Injector mInjector;
// Maximum time a ramp animation can take.
private long mBrightnessRampIncreaseMaxTimeMillis;
private long mBrightnessRampDecreaseMaxTimeMillis;
@@ -495,20 +500,22 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
/**
* Creates the display power controller.
*/
public DisplayPowerController(Context context,
DisplayPowerController(Context context, Injector injector,
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
Runnable onBrightnessChangeRunnable) {
mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock();
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
final String displayIdStr = "[" + mDisplayId + "]";
TAG = "DisplayPowerController" + displayIdStr;
mSuspendBlockerIdUnfinishedBusiness = displayIdStr + "unfinished business";
mSuspendBlockerIdOnStateChanged = displayIdStr + "on state changed";
mSuspendBlockerIdProxPositive = displayIdStr + "prox positive";
mSuspendBlockerIdProxNegative = displayIdStr + "prox negative";
mSuspendBlockerIdProxDebounce = displayIdStr + "prox debounce";
TAG = "DisplayPowerController[" + mDisplayId + "]";
mSuspendBlockerIdUnfinishedBusiness = getSuspendBlockerUnfinishedBusinessId(mDisplayId);
mSuspendBlockerIdOnStateChanged = getSuspendBlockerOnStateChangedId(mDisplayId);
mSuspendBlockerIdProxPositive = getSuspendBlockerProxPositiveId(mDisplayId);
mSuspendBlockerIdProxNegative = getSuspendBlockerProxNegativeId(mDisplayId);
mSuspendBlockerIdProxDebounce = getSuspendBlockerProxDebounceId(mDisplayId);
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
@@ -681,7 +688,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
/**
* Get the {@link BrightnessChangeEvent}s for the specified user.
* @param userId userId to fetch data for
*
* @param userId userId to fetch data for
* @param includePackage if false will null out the package name in events
*/
@Nullable
@@ -723,10 +731,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
* The controller makes a copy of the provided object and then
* begins adjusting the power state to match what was requested.
*
* @param request The requested power state.
* @param request The requested power state.
* @param waitForNegativeProximity If true, issues a request to wait for
* negative proximity before turning the screen back on, assuming the screen
* was turned off by the proximity sensor.
* negative proximity before turning the screen back on,
* assuming the screen
* was turned off by the proximity sensor.
* @return True if display is ready, false if there are important changes that must
* be made asynchronously (such as turning the screen on), in which case the caller
* should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
@@ -834,7 +843,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
synchronized (mLock) {
mStopped = true;
Message msg = mHandler.obtainMessage(MSG_STOP);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
if (mDisplayWhiteBalanceController != null) {
mDisplayWhiteBalanceController.setEnabled(false);
@@ -888,12 +897,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (!mStopped && !mPendingUpdatePowerStateLocked) {
mPendingUpdatePowerStateLocked = true;
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
private void initialize(int displayState) {
mPowerState = new DisplayPowerState(mBlanker,
mPowerState = mInjector.getDisplayPowerState(mBlanker,
mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId, displayState);
if (mColorFadeEnabled) {
@@ -908,7 +917,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mColorFadeOffAnimator.addListener(mAnimatorListener);
}
mScreenBrightnessRampAnimator = new DualRampAnimator<>(mPowerState,
mScreenBrightnessRampAnimator = mInjector.getDualRampAnimator(mPowerState,
DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
mScreenBrightnessRampAnimator.setAnimationTimeLimits(
@@ -1077,13 +1086,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
sendUpdatePowerState();
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@@ -1124,8 +1136,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mOnProximityNegativeMessages = 0;
final float brightness = mPowerState != null
? mPowerState.getScreenBrightness()
: PowerManager.BRIGHTNESS_MIN;
? mPowerState.getScreenBrightness()
: PowerManager.BRIGHTNESS_MIN;
reportStats(brightness);
if (mPowerState != null) {
@@ -1203,7 +1215,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
state = Display.STATE_ON;
break;
}
assert(state != Display.STATE_UNKNOWN);
assert (state != Display.STATE_UNKNOWN);
// Apply the proximity sensor.
if (mProximitySensor != null) {
@@ -1290,16 +1302,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean autoBrightnessEnabledInDoze =
mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& Float.isNaN(brightnessState)
&& mAutomaticBrightnessController != null;
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& Float.isNaN(brightnessState)
&& mAutomaticBrightnessController != null;
final boolean autoBrightnessDisabledDueToDisplayOff = mPowerRequest.useAutoBrightness
&& !(state == Display.STATE_ON || autoBrightnessEnabledInDoze);
&& !(state == Display.STATE_ON || autoBrightnessEnabledInDoze);
final int autoBrightnessState = autoBrightnessEnabled
? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
: autoBrightnessDisabledDueToDisplayOff
? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
: AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
: AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
@@ -1589,9 +1601,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// AND if we are not in idle screen brightness mode.
if (!brightnessIsTemporary
&& (mAutomaticBrightnessController != null
&& !mAutomaticBrightnessController.isInIdleMode())) {
&& !mAutomaticBrightnessController.isInIdleMode())) {
if (userInitiatedChange && (mAutomaticBrightnessController == null
|| !mAutomaticBrightnessController.hasValidAmbientLux())) {
|| !mAutomaticBrightnessController.hasValidAmbientLux())) {
// If we don't have a valid lux reading we can't report a valid
// slider event so notify as if the system changed the brightness.
userInitiatedChange = false;
@@ -1781,26 +1793,26 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
boolean changed = false;
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
brightness);
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
brightness);
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
adjustedBrightness);
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
adjustedBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
minBrightness);
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
minBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
maxBrightness);
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
maxBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
mHbmController.getHighBrightnessMode());
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
mHbmController.getHighBrightnessMode());
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
mHbmController.getTransitionPoint());
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
mHbmController.getTransitionPoint());
changed |=
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
mBrightnessThrottler.getBrightnessMaxReason());
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
mBrightnessThrottler.getBrightnessMaxReason());
return changed;
}
@@ -1942,7 +1954,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
if (!isOff
&& (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
|| mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
|| mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn();
@@ -2070,7 +2082,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else if (mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE :
ColorFade.MODE_WARM_UP)) {
ColorFade.MODE_WARM_UP)) {
mColorFadeOnAnimator.start();
} else {
mColorFadeOnAnimator.end();
@@ -2172,8 +2184,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
mColorFadeFadesConfig
? ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
&& mPowerState.getScreenState() != Display.STATE_OFF) {
// Perform the screen off animation.
mColorFadeOffAnimator.start();
@@ -2244,7 +2256,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mProximitySensorEnabled
&& mPendingProximity != PROXIMITY_UNKNOWN
&& mPendingProximityDebounceTime >= 0) {
final long now = SystemClock.uptimeMillis();
final long now = mClock.uptimeMillis();
if (mPendingProximityDebounceTime <= now) {
if (mProximity != mPendingProximity) {
// if the status of the sensor changed, stop ignoring.
@@ -2522,7 +2534,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mCachedBrightnessInfo.hbmTransitionPoint=" +
mCachedBrightnessInfo.hbmTransitionPoint.value);
pw.println(" mCachedBrightnessInfo.brightnessMaxReason =" +
mCachedBrightnessInfo.brightnessMaxReason .value);
mCachedBrightnessInfo.brightnessMaxReason.value);
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -2705,7 +2717,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
synchronized(mCachedBrightnessInfo) {
synchronized (mCachedBrightnessInfo) {
if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
return;
}
@@ -2739,8 +2751,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -2805,7 +2815,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
break;
case MSG_BRIGHTNESS_RAMP_DONE:
if (mPowerState != null) {
if (mPowerState != null) {
final float brightness = mPowerState.getScreenBrightness();
reportStats(brightness);
}
@@ -2822,7 +2832,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void onSensorChanged(SensorEvent event) {
if (mProximitySensorEnabled) {
final long time = SystemClock.uptimeMillis();
final long time = mClock.uptimeMillis();
final float distance = event.values[0];
boolean positive = distance >= 0.0f && distance < mProximityThreshold;
handleProximitySensorEvent(time, positive);
@@ -2891,19 +2901,68 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
@VisibleForTesting
String getSuspendBlockerUnfinishedBusinessId(int displayId) {
return "[" + displayId + "]unfinished business";
}
String getSuspendBlockerOnStateChangedId(int displayId) {
return "[" + displayId + "]on state changed";
}
String getSuspendBlockerProxPositiveId(int displayId) {
return "[" + displayId + "]prox positive";
}
String getSuspendBlockerProxNegativeId(int displayId) {
return "[" + displayId + "]prox negative";
}
@VisibleForTesting
String getSuspendBlockerProxDebounceId(int displayId) {
return "[" + displayId + "]prox debounce";
}
/** Functional interface for providing time. */
@VisibleForTesting
interface Clock {
/**
* Returns current time in milliseconds since boot, not counting time spent in deep sleep.
*/
long uptimeMillis();
}
@VisibleForTesting
static class Injector {
Clock getClock() {
return SystemClock::uptimeMillis;
}
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
return new DisplayPowerState(blanker, colorFade, displayId, displayState);
}
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> secondProperty) {
return new DualRampAnimator(dps, firstProperty, secondProperty);
}
}
static class CachedBrightnessInfo {
public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
public MutableFloat adjustedBrightness =
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
public MutableFloat brightnessMin =
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
public MutableFloat brightnessMax =
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
public MutableFloat hbmTransitionPoint =
new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
public MutableInt brightnessMaxReason =
new MutableInt(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
new MutableInt(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
public boolean checkAndSetFloat(MutableFloat mf, float f) {
if (mf.value != f) {

View File

@@ -0,0 +1,236 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.display;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
import android.os.PowerManager;
import android.os.test.TestLooper;
import android.util.FloatProperty;
import android.view.Display;
import android.view.DisplayInfo;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
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 = 42;
private OffsettableClock mClock;
private TestLooper mTestLooper;
private Handler mHandler;
private DisplayPowerController.Injector mInjector;
private Context mContextSpy;
@Mock
private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
@Mock
private SensorManager mSensorManagerMock;
@Mock
private DisplayBlanker mDisplayBlankerMock;
@Mock
private LogicalDisplay mLogicalDisplayMock;
@Mock
private DisplayDevice mDisplayDeviceMock;
@Mock
private BrightnessTracker mBrightnessTrackerMock;
@Mock
private BrightnessSetting mBrightnessSettingMock;
@Mock
private WindowManagerPolicy mWindowManagerPolicyMock;
@Mock
private PowerManager mPowerManagerMock;
@Mock
private Resources mResourcesMock;
@Mock
private DisplayDeviceConfig mDisplayDeviceConfigMock;
@Mock
private DisplayPowerState mDisplayPowerStateMock;
@Mock
private DualRampAnimator<DisplayPowerState> mDualRampAnimatorMock;
@Captor
private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
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;
}
};
addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock);
when(mContextSpy.getResources()).thenReturn(mResourcesMock);
}
@After
public void tearDown() {
LocalServices.removeServiceForTest(WindowManagerPolicy.class);
}
@Test
public void testReleaseProxSuspendBlockersOnExit() throws Exception {
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
Sensor proxSensor = setUpProxSensor();
DisplayPowerController dpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
});
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(proxSensor);
assertNotNull(listener);
listener.onSensorChanged(TestUtils.createSensorEvent(proxSensor, 5 /* lux */));
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
dpc.stop();
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
}
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
LocalServices.removeServiceForTest(clazz);
LocalServices.addService(clazz, mock);
}
private void advanceTime(long timeMs) {
mClock.fastForward(timeMs);
mTestLooper.dispatchAll();
}
private Sensor setUpProxSensor() throws Exception {
Sensor proxSensor = TestUtils.createSensor(
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
.thenReturn(List.of(proxSensor));
return proxSensor;
}
private SensorEventListener getSensorEventListener(Sensor sensor) {
verify(mSensorManagerMock).registerListener(mSensorEventListenerCaptor.capture(),
eq(sensor), eq(SensorManager.SENSOR_DELAY_NORMAL), isA(Handler.class));
return mSensorEventListenerCaptor.getValue();
}
private void setUpDisplay(int displayId, String uniqueId) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(mLogicalDisplayMock.isEnabled()).thenReturn(true);
when(mLogicalDisplayMock.getPhase()).thenReturn(LogicalDisplay.DISPLAY_PHASE_ENABLED);
when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
when(mDisplayDeviceConfigMock.getProximitySensor()).thenReturn(
new DisplayDeviceConfig.SensorData() {
{
type = Sensor.STRING_TYPE_PROXIMITY;
name = null;
}
});
when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
}
}

View File

@@ -131,8 +131,9 @@ android_test {
java_library {
name: "servicestests-core-utils",
srcs: [
"src/com/android/server/pm/PackageSettingBuilder.java",
"src/com/android/server/am/DeviceConfigSession.java",
"src/com/android/server/display/TestUtils.java",
"src/com/android/server/pm/PackageSettingBuilder.java",
],
static_libs: [
"services.core",