diff options
| author | 2022-12-15 10:05:23 +0000 | |
|---|---|---|
| committer | 2022-12-15 10:05:23 +0000 | |
| commit | 1ee2d82ef9cbbf68f09b003fec219ed05f76b426 (patch) | |
| tree | 6eeb568c58125388ac560824b7d5f7deb834ddbd | |
| parent | 667dc978e4bab612f5083891d505e36624ce647e (diff) | |
| parent | 963f1ab512936dce6fc62d9c5ceff0f6f2658e17 (diff) | |
Merge "Create DisplayStateController"
4 files changed, 272 insertions, 39 deletions
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 84b6da8ef17e..111caefa34da 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -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; @@ -436,6 +440,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(); @@ -1128,39 +1133,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); @@ -1170,7 +1144,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 @@ -2293,10 +2267,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal if (mDisplayBrightnessController != null) { mDisplayBrightnessController.dump(pw); } - - if (mDisplayPowerProximityStateController != null) { - mDisplayPowerProximityStateController.dumpLocal(pw); - } } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index c7b27deb420d..ad426b5e00a2 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -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; diff --git a/services/core/java/com/android/server/display/state/DisplayStateController.java b/services/core/java/com/android/server/display/state/DisplayStateController.java new file mode 100644 index 000000000000..546478e480e0 --- /dev/null +++ b/services/core/java/com/android/server/display/state/DisplayStateController.java @@ -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); + } + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/display/state/DisplayStateControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/state/DisplayStateControllerTest.java new file mode 100644 index 000000000000..880501f39ac2 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/display/state/DisplayStateControllerTest.java @@ -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()); + } +} |