Loading core/java/android/hardware/display/DisplayManagerGlobal.java +14 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading core/java/android/hardware/display/IDisplayManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading services/core/java/com/android/server/display/DisplayManagerService.java +31 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading services/core/java/com/android/server/display/DisplayManagerShellCommand.java +21 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; } } services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +67 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -3529,6 +3586,7 @@ public class DisplayManagerServiceTest { public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) { mDisplayDeviceInfo = displayDeviceInfo; mDisplayDeviceInfo.committedState = Display.STATE_ON; } @Override Loading Loading @@ -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; } } } Loading
core/java/android/hardware/display/DisplayManagerGlobal.java +14 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
core/java/android/hardware/display/IDisplayManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
services/core/java/com/android/server/display/DisplayManagerService.java +31 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading
services/core/java/com/android/server/display/DisplayManagerShellCommand.java +21 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; } }
services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +67 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -3529,6 +3586,7 @@ public class DisplayManagerServiceTest { public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) { mDisplayDeviceInfo = displayDeviceInfo; mDisplayDeviceInfo.committedState = Display.STATE_ON; } @Override Loading Loading @@ -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; } } }