Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 963f1ab5 authored by Rupesh Bansal's avatar Rupesh Bansal
Browse files

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
parent f8849f85
Loading
Loading
Loading
Loading
+8 −38
Original line number Diff line number Diff line
@@ -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);
        }
    }


+0 −1
Original line number Diff line number Diff line
@@ -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;
+108 −0
Original line number Diff line number Diff line
/*
 * 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);
        }
    }
}
+156 −0
Original line number Diff line number Diff line
/*
 * 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());
    }
}