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

Commit e24aa759 authored by Oleg Blinnikov's avatar Oleg Blinnikov Committed by Android (Google) Code Review
Browse files

Merge "API and adb command to power display off" into main

parents 6a62ec31 fd8b5efc
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -548,6 +548,20 @@ public final class DisplayManagerGlobal {
        }
    }

    /**
     * Request to power a display ON or OFF.
     * @hide
     */
    @RequiresPermission("android.permission.MANAGE_DISPLAYS")
    public boolean requestDisplayPower(int displayId, boolean on) {
        try {
            return mDm.requestDisplayPower(displayId, on);
        } catch (RemoteException ex) {
            Log.e(TAG, "Error trying to request display power " + on, ex);
            return false;
        }
    }

    public void startWifiDisplayScan() {
        synchronized (mLock) {
            if (mWifiDisplayScanNestCount++ == 0) {
+4 −0
Original line number Diff line number Diff line
@@ -236,6 +236,10 @@ interface IDisplayManager {
    @EnforcePermission("MANAGE_DISPLAYS")
    void disableConnectedDisplay(int displayId);

    // Request to power display ON or OFF.
    @EnforcePermission("MANAGE_DISPLAYS")
    boolean requestDisplayPower(int displayId, boolean on);

    // Restricts display modes to specified modeIds.
    @EnforcePermission("RESTRICT_DISPLAY_MODES")
    void requestDisplayModes(in IBinder token, int displayId, in @nullable int[] modeIds);
+31 −0
Original line number Diff line number Diff line
@@ -3406,6 +3406,31 @@ public final class DisplayManagerService extends SystemService {
        }
    }

    boolean requestDisplayPower(int displayId, boolean on) {
        synchronized (mSyncRoot) {
            final var display = mLogicalDisplayMapper.getDisplayLocked(displayId);
            if (display == null) {
                Slog.w(TAG, "requestDisplayPower: Cannot find a display with displayId="
                        + displayId);
                return false;
            }
            final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
            var runnable = display.getPrimaryDisplayDeviceLocked().requestDisplayStateLocked(
                    on ? Display.STATE_ON : Display.STATE_OFF,
                    on ? brightnessPair.brightness : PowerManager.BRIGHTNESS_OFF_FLOAT,
                    brightnessPair.sdrBrightness,
                    display.getDisplayOffloadSessionLocked());
            if (runnable == null) {
                Slog.w(TAG, "requestDisplayPower: Cannot update the power state to ON=" + on
                        + " for a display with displayId=" + displayId + ", runnable is null");
                return false;
            }
            runnable.run();
            Slog.i(TAG, "requestDisplayPower(displayId=" + displayId + ", on=" + on + ")");
        }
        return true;
    }

    /**
     * This is the object that everything in the display manager locks on.
     * We make it an inner class within the {@link DisplayManagerService} to so that it is
@@ -4629,6 +4654,12 @@ public final class DisplayManagerService extends SystemService {
            DisplayManagerService.this.enableConnectedDisplay(displayId, false);
        }

        @EnforcePermission(MANAGE_DISPLAYS)
        public boolean requestDisplayPower(int displayId, boolean on) {
            requestDisplayPower_enforcePermission();
            return DisplayManagerService.this.requestDisplayPower(displayId, on);
        }

        @EnforcePermission(RESTRICT_DISPLAY_MODES)
        @Override // Binder call
        public void requestDisplayModes(IBinder token, int displayId, @Nullable int[] modeIds) {
+21 −0
Original line number Diff line number Diff line
@@ -106,6 +106,10 @@ class DisplayManagerShellCommand extends ShellCommand {
                return setDisplayEnabled(true);
            case "disable-display":
                return setDisplayEnabled(false);
            case "power-on":
                return requestDisplayPower(true);
            case "power-off":
                return requestDisplayPower(false);
            default:
                return handleDefaultCommands(cmd);
        }
@@ -592,4 +596,21 @@ class DisplayManagerShellCommand extends ShellCommand {
        mService.enableConnectedDisplay(displayId, enable);
        return 0;
    }

    private int requestDisplayPower(boolean enable) {
        final String displayIdText = getNextArg();
        if (displayIdText == null) {
            getErrPrintWriter().println("Error: no displayId specified");
            return 1;
        }
        final int displayId;
        try {
            displayId = Integer.parseInt(displayIdText);
        } catch (NumberFormatException e) {
            getErrPrintWriter().println("Error: invalid displayId: '" + displayIdText + "'");
            return 1;
        }
        mService.requestDisplayPower(displayId, enable);
        return 0;
    }
}
+67 −0
Original line number Diff line number Diff line
@@ -2568,6 +2568,63 @@ public class DisplayManagerServiceTest {
                EVENT_DISPLAY_ADDED).inOrder();
    }

    @Test
    public void testPowerOnAndOffInternalDisplay() {
        manageDisplaysPermission(/* granted= */ true);
        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
        DisplayManagerService.BinderService bs = displayManager.new BinderService();
        LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
        FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
        bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);

        callback.expectsEvent(EVENT_DISPLAY_ADDED);
        FakeDisplayDevice displayDevice =
                createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
        callback.waitForExpectedEvent();

        LogicalDisplay display =
                logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);

        assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                .isEqualTo(Display.STATE_ON);

        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(), false))
                .isTrue();

        assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                .isEqualTo(Display.STATE_OFF);

        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(), true))
                .isTrue();

        assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                .isEqualTo(Display.STATE_ON);
    }

    @Test
    public void testPowerOnAndOffInternalDisplay_withoutPermission_shouldThrowException() {
        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
        DisplayManagerService.BinderService bs = displayManager.new BinderService();
        LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
        FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
        bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);

        callback.expectsEvent(EVENT_DISPLAY_ADDED);
        FakeDisplayDevice displayDevice =
                createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
        callback.waitForExpectedEvent();

        LogicalDisplay display =
                logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
        var displayId = display.getDisplayIdLocked();

        assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                .isEqualTo(Display.STATE_ON);

        assertThrows(SecurityException.class, () -> bs.requestDisplayPower(displayId, true));
        assertThrows(SecurityException.class, () -> bs.requestDisplayPower(displayId, false));
    }

    @Test
    public void testEnableExternalDisplay_withDisplayManagement_shouldSignalDisplayAdded() {
        when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
@@ -3529,6 +3586,7 @@ public class DisplayManagerServiceTest {

        public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
            mDisplayDeviceInfo = displayDeviceInfo;
            mDisplayDeviceInfo.committedState = Display.STATE_ON;
        }

        @Override
@@ -3558,5 +3616,14 @@ public class DisplayManagerServiceTest {
        public Display.Mode getUserPreferredDisplayModeLocked() {
            return mPreferredMode;
        }

        @Override
        public Runnable requestDisplayStateLocked(
                final int state,
                final float brightnessState,
                final float sdrBrightnessState,
                @Nullable DisplayOffloadSessionImpl displayOffloadSession) {
            return () -> mDisplayDeviceInfo.committedState = state;
        }
    }
}