Create DisplayStateController

Creating DisplayStateControllerTest, which will be responsible for
updating and maintaining the display state of the associated display.

Bug: 260538147
Test: atest DisplayStateControllerTest
Change-Id: I04d2fff7af7643149c9a9f7107765c160fb3f483
This commit is contained in:
Rupesh Bansal
2022-11-24 13:57:14 +00:00
parent f8849f8572
commit 963f1ab512
4 changed files with 272 additions and 39 deletions

View File

@@ -71,6 +71,7 @@ import com.android.server.display.brightness.BrightnessReason;
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.state.DisplayStateController;
import com.android.server.display.utils.SensorUtils;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
@@ -346,6 +347,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// Tracks and manages the proximity state of the associated display.
private final DisplayPowerProximityStateController mDisplayPowerProximityStateController;
// Tracks and manages the display state of the associated display.
private final DisplayStateController mDisplayStateController;
// A record of state for skipping brightness ramps.
private int mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -434,6 +438,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
() -> updatePowerState(), mDisplayId, mSensorManager);
mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
mTag = "DisplayPowerController2[" + mDisplayId + "]";
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
@@ -1121,39 +1126,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mustNotify = !mDisplayReadyLocked;
}
// Compute the basic display state using the policy.
// We might override this below based on other factors.
// Initialise brightness as invalid.
int state;
boolean performScreenOffTransition = false;
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
case DisplayPowerRequest.POLICY_DOZE:
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
assert (state != Display.STATE_UNKNOWN);
mDisplayPowerProximityStateController.updateProximityState(mPowerRequest, state);
if (!mIsEnabled
|| mIsInTransition
|| mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
state = Display.STATE_OFF;
}
int state = mDisplayStateController
.updateDisplayState(mPowerRequest, mIsEnabled, mIsInTransition);
// Initialize things the first time the power state is changed.
if (mustInitialize) {
initialize(state);
@@ -1163,7 +1137,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// The transition may be deferred, so after this point we will use the
// actual state instead of the desired one.
final int oldState = mPowerState.getScreenState();
animateScreenStateChange(state, performScreenOffTransition);
animateScreenStateChange(state, mDisplayStateController.shouldPerformScreenOffTransition());
state = mPowerState.getScreenState();
DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController
@@ -2274,10 +2248,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
if (mDisplayBrightnessController != null) {
mDisplayBrightnessController.dump(pw);
}
if (mDisplayPowerProximityStateController != null) {
mDisplayPowerProximityStateController.dumpLocal(pw);
}
}

View File

@@ -66,7 +66,6 @@ import java.util.Objects;
*/
final class LogicalDisplay {
private static final String TAG = "LogicalDisplay";
// The layer stack we use when the display has been blanked to prevent any
// of its content from appearing.
private static final int BLANK_LAYER_STACK = -1;

View File

@@ -0,0 +1,108 @@
/*
* 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.state;
import android.hardware.display.DisplayManagerInternal;
import android.util.IndentingPrintWriter;
import android.view.Display;
import com.android.server.display.DisplayPowerProximityStateController;
import java.io.PrintWriter;
/**
* Maintains the DisplayState of the system.
* Internally, this accounts for the proximity changes, and notifying the system
* clients about the changes
*/
public class DisplayStateController {
private DisplayPowerProximityStateController mDisplayPowerProximityStateController;
private boolean mPerformScreenOffTransition = false;
public DisplayStateController(DisplayPowerProximityStateController
displayPowerProximityStateController) {
this.mDisplayPowerProximityStateController = displayPowerProximityStateController;
}
/**
* Updates the DisplayState and notifies the system. Also accounts for the
* events being emitted by the proximity sensors
*
* @param displayPowerRequest The request to update the display state
* @param isDisplayEnabled A boolean flag representing if the display is enabled
* @param isDisplayInTransition A boolean flag representing if the display is undergoing the
* transition phase
*/
public int updateDisplayState(DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
boolean isDisplayEnabled, boolean isDisplayInTransition) {
mPerformScreenOffTransition = false;
// Compute the basic display state using the policy.
// We might override this below based on other factors.
// Initialise brightness as invalid.
int state;
switch (displayPowerRequest.policy) {
case DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
mPerformScreenOffTransition = true;
break;
case DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE:
if (displayPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = displayPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
break;
case DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM:
case DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
assert (state != Display.STATE_UNKNOWN);
mDisplayPowerProximityStateController.updateProximityState(displayPowerRequest, state);
if (!isDisplayEnabled || isDisplayInTransition
|| mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
state = Display.STATE_OFF;
}
return state;
}
/**
* Checks if the screen off transition is to be performed or not.
*/
public boolean shouldPerformScreenOffTransition() {
return mPerformScreenOffTransition;
}
/**
* Used to dump the state.
*
* @param pw The PrintWriter used to dump the state.
*/
public void dumpsys(PrintWriter pw) {
pw.println();
pw.println("DisplayPowerProximityStateController:");
pw.println(" mPerformScreenOffTransition:" + mPerformScreenOffTransition);
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
if (mDisplayPowerProximityStateController != null) {
mDisplayPowerProximityStateController.dumpLocal(ipw);
}
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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.state;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.display.DisplayManagerInternal;
import android.view.Display;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.display.DisplayPowerProximityStateController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class DisplayStateControllerTest {
private static final boolean DISPLAY_ENABLED = true;
private static final boolean DISPLAY_IN_TRANSITION = true;
private DisplayStateController mDisplayStateController;
@Mock
private DisplayPowerProximityStateController mDisplayPowerProximityStateController;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
}
@Test
public void updateProximityStateEvaluatesStateOffPolicyAsExpected() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
int state = mDisplayStateController.updateDisplayState(displayPowerRequest, DISPLAY_ENABLED,
!DISPLAY_IN_TRANSITION);
assertEquals(Display.STATE_OFF, state);
verify(mDisplayPowerProximityStateController).updateProximityState(displayPowerRequest,
Display.STATE_OFF);
assertEquals(true, mDisplayStateController.shouldPerformScreenOffTransition());
}
@Test
public void updateProximityStateEvaluatesDozePolicyAsExpected() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
validDisplayState(DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE,
Display.STATE_DOZE, DISPLAY_ENABLED, !DISPLAY_IN_TRANSITION);
}
@Test
public void updateProximityStateEvaluatesDimPolicyAsExpected() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
validDisplayState(DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM,
Display.STATE_ON, DISPLAY_ENABLED, !DISPLAY_IN_TRANSITION);
}
@Test
public void updateProximityStateEvaluatesDimBrightAsExpected() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
validDisplayState(DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
Display.STATE_ON, DISPLAY_ENABLED, !DISPLAY_IN_TRANSITION);
}
@Test
public void updateProximityStateWorksAsExpectedWhenDisplayDisabled() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
int state = mDisplayStateController.updateDisplayState(displayPowerRequest,
!DISPLAY_ENABLED, !DISPLAY_IN_TRANSITION);
assertEquals(Display.STATE_OFF, state);
verify(mDisplayPowerProximityStateController).updateProximityState(displayPowerRequest,
Display.STATE_ON);
assertEquals(false, mDisplayStateController.shouldPerformScreenOffTransition());
}
@Test
public void updateProximityStateWorksAsExpectedWhenTransitionPhase() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
false);
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
int state = mDisplayStateController.updateDisplayState(displayPowerRequest, DISPLAY_ENABLED,
DISPLAY_IN_TRANSITION);
assertEquals(Display.STATE_OFF, state);
verify(mDisplayPowerProximityStateController).updateProximityState(displayPowerRequest,
Display.STATE_ON);
assertEquals(false, mDisplayStateController.shouldPerformScreenOffTransition());
}
@Test
public void updateProximityStateWorksAsExpectedWhenScreenOffBecauseOfProximity() {
when(mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()).thenReturn(
true);
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
int state = mDisplayStateController.updateDisplayState(displayPowerRequest, DISPLAY_ENABLED,
!DISPLAY_IN_TRANSITION);
assertEquals(Display.STATE_OFF, state);
verify(mDisplayPowerProximityStateController).updateProximityState(displayPowerRequest,
Display.STATE_ON);
assertEquals(false, mDisplayStateController.shouldPerformScreenOffTransition());
}
private void validDisplayState(int policy, int displayState, boolean isEnabled,
boolean isInTransition) {
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
displayPowerRequest.policy = policy;
int state = mDisplayStateController.updateDisplayState(displayPowerRequest, isEnabled,
isInTransition);
assertEquals(displayState, state);
verify(mDisplayPowerProximityStateController).updateProximityState(displayPowerRequest,
displayState);
assertEquals(false, mDisplayStateController.shouldPerformScreenOffTransition());
}
}