Shell cmd power-reset instead of power-on

power-on command may not work as expected,
when display already asleep. The semantics
of power-off command means we need a
power-reset command to reset the display
to a state it supposed to have by removing
the 'overridden' power state.

Change-Id: Ib7acfa6cb7687df4f19877e3b9cf9b8d768151d6
Bug: 292300981
Test: atest DisplayManagerServiceTest
Test: adb shell cmd display power-off 0
Test: adb shell cmd display power-reset 0
Flag: EXEMPT bugfix in a new shell command not used anywhere
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 8519722..8748bb1 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -549,15 +549,20 @@
     }
 
     /**
-     * Request to power a display ON or OFF.
+     * Request to power a display OFF or reset it to a power state it supposed to have.
+     * @param displayId the id of the display
+     * @param state one of {@link android.view.Display#STATE_UNKNOWN} (to reset the state to
+     *  the one the display should have had now), {@link android.view.Display#STATE_OFF}.
+     * @return true if successful, false otherwise
      * @hide
      */
     @RequiresPermission("android.permission.MANAGE_DISPLAYS")
-    public boolean requestDisplayPower(int displayId, boolean on) {
+    public boolean requestDisplayPower(int displayId, int state) {
         try {
-            return mDm.requestDisplayPower(displayId, on);
+            return mDm.requestDisplayPower(displayId, state);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Error trying to request display power " + on, ex);
+            Log.e(TAG, "Error trying to request display power:"
+                    + " state=" + state, ex);
             return false;
         }
     }
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b7c02b0..28c71d9 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -236,9 +236,9 @@
     @EnforcePermission("MANAGE_DISPLAYS")
     void disableConnectedDisplay(int displayId);
 
-    // Request to power display ON or OFF.
+    // Request to power display OFF or reset it to a power state it supposed to have.
     @EnforcePermission("MANAGE_DISPLAYS")
-    boolean requestDisplayPower(int displayId, boolean on);
+    boolean requestDisplayPower(int displayId, int state);
 
     // Restricts display modes to specified modeIds.
     @EnforcePermission("RESTRICT_DISPLAY_MODES")
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 2d5f38e..08a9a77 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -822,6 +822,13 @@
     }
 
     @VisibleForTesting
+    void setDisplayState(int displayId, int state) {
+        synchronized (mSyncRoot) {
+            mDisplayStates.setValueAt(displayId, state);
+        }
+    }
+
+    @VisibleForTesting
     Handler getDisplayHandler() {
         return mHandler;
     }
@@ -3406,27 +3413,39 @@
         }
     }
 
-    boolean requestDisplayPower(int displayId, boolean on) {
+    boolean requestDisplayPower(int displayId, int requestedState) {
         synchronized (mSyncRoot) {
             final var display = mLogicalDisplayMapper.getDisplayLocked(displayId);
             if (display == null) {
-                Slog.w(TAG, "requestDisplayPower: Cannot find a display with displayId="
+                Slog.w(TAG, "requestDisplayPower: Cannot find the display with displayId="
                         + displayId);
                 return false;
             }
+            var state = requestedState;
+            if (state == Display.STATE_UNKNOWN) {
+                state = mDisplayStates.get(displayId);
+            }
+
             final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
+            var brightnessState = brightnessPair.brightness;
+            if (state == Display.STATE_OFF) {
+                brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
+            }
+
             var runnable = display.getPrimaryDisplayDeviceLocked().requestDisplayStateLocked(
-                    on ? Display.STATE_ON : Display.STATE_OFF,
-                    on ? brightnessPair.brightness : PowerManager.BRIGHTNESS_OFF_FLOAT,
+                    state,
+                    brightnessState,
                     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");
+                Slog.w(TAG, "requestDisplayPower: Cannot set power state = " + state
+                        + " for the display with displayId=" + displayId + ","
+                        + " requestedState=" + requestedState + ": runnable is null");
                 return false;
             }
             runnable.run();
-            Slog.i(TAG, "requestDisplayPower(displayId=" + displayId + ", on=" + on + ")");
+            Slog.i(TAG, "requestDisplayPower(displayId=" + displayId
+                    + ", requestedState=" + requestedState + "): state set to " + state);
         }
         return true;
     }
@@ -4655,9 +4674,9 @@
         }
 
         @EnforcePermission(MANAGE_DISPLAYS)
-        public boolean requestDisplayPower(int displayId, boolean on) {
+        public boolean requestDisplayPower(int displayId, int state) {
             requestDisplayPower_enforcePermission();
-            return DisplayManagerService.this.requestDisplayPower(displayId, on);
+            return DisplayManagerService.this.requestDisplayPower(displayId, state);
         }
 
         @EnforcePermission(RESTRICT_DISPLAY_MODES)
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index d973b71..9eef657 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -106,10 +106,10 @@
                 return setDisplayEnabled(true);
             case "disable-display":
                 return setDisplayEnabled(false);
-            case "power-on":
-                return requestDisplayPower(true);
+            case "power-reset":
+                return requestDisplayPower(Display.STATE_UNKNOWN);
             case "power-off":
-                return requestDisplayPower(false);
+                return requestDisplayPower(Display.STATE_OFF);
             default:
                 return handleDefaultCommands(cmd);
         }
@@ -183,6 +183,10 @@
             pw.println("  disable-display DISPLAY_ID");
             pw.println("    Disable the DISPLAY_ID. Only possible if this is a connected display.");
         }
+        pw.println("  power-reset DISPLAY_ID");
+        pw.println("    Turn the DISPLAY_ID power to a state the display supposed to have.");
+        pw.println("  power-off DISPLAY_ID");
+        pw.println("    Turn the display DISPLAY_ID power off.");
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
@@ -597,7 +601,7 @@
         return 0;
     }
 
-    private int requestDisplayPower(boolean enable) {
+    private int requestDisplayPower(int state) {
         final String displayIdText = getNextArg();
         if (displayIdText == null) {
             getErrPrintWriter().println("Error: no displayId specified");
@@ -610,7 +614,7 @@
             getErrPrintWriter().println("Error: invalid displayId: '" + displayIdText + "'");
             return 1;
         }
-        mService.requestDisplayPower(displayId, enable);
+        mService.requestDisplayPower(displayId, state);
         return 0;
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 211ab03..d268637 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -2584,18 +2584,19 @@
 
         LogicalDisplay display =
                 logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
+        displayManager.setDisplayState(display.getDisplayIdLocked(), Display.STATE_ON);
 
         assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                 .isEqualTo(Display.STATE_ON);
 
-        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(), false))
-                .isTrue();
+        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(),
+                Display.STATE_OFF)).isTrue();
 
         assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                 .isEqualTo(Display.STATE_OFF);
 
-        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(), true))
-                .isTrue();
+        assertThat(displayManager.requestDisplayPower(display.getDisplayIdLocked(),
+                Display.STATE_UNKNOWN)).isTrue();
 
         assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                 .isEqualTo(Display.STATE_ON);
@@ -2621,8 +2622,10 @@
         assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState)
                 .isEqualTo(Display.STATE_ON);
 
-        assertThrows(SecurityException.class, () -> bs.requestDisplayPower(displayId, true));
-        assertThrows(SecurityException.class, () -> bs.requestDisplayPower(displayId, false));
+        assertThrows(SecurityException.class,
+                () -> bs.requestDisplayPower(displayId, Display.STATE_UNKNOWN));
+        assertThrows(SecurityException.class,
+                () -> bs.requestDisplayPower(displayId, Display.STATE_OFF));
     }
 
     @Test