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

Commit 812542c7 authored by Santos Cordon's avatar Santos Cordon
Browse files

Wake foldable device when device unfolds.

Trigger a wake from within the display-layout transition
for the device-state specified in the config.xml file.

Bug: 190593710
Test: Manually verify that the device wakes when opening
Change-Id: I28419ce93a5df6caa7a116860d891814118c7bc2
parent 25025619
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -548,6 +548,7 @@ public final class PowerManager {
            WAKE_REASON_HDMI,
            WAKE_REASON_DISPLAY_GROUP_ADDED,
            WAKE_REASON_DISPLAY_GROUP_TURNED_ON,
            WAKE_REASON_UNFOLD_DEVICE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface WakeReason{}
@@ -646,6 +647,12 @@ public final class PowerManager {
     */
    public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11;

    /**
     * Wake up reason code: Waking the device due to unfolding of a foldable device.
     * @hide
     */
    public static final int WAKE_REASON_UNFOLD_DEVICE = 12;

    /**
     * Convert the wake reason to a string for debugging purposes.
     * @hide
@@ -664,6 +671,7 @@ public final class PowerManager {
            case WAKE_REASON_LID: return "WAKE_REASON_LID";
            case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED";
            case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON";
            case WAKE_REASON_UNFOLD_DEVICE: return "WAKE_REASON_UNFOLD_DEVICE";
            default: return Integer.toString(wakeReason);
        }
    }
+5 −0
Original line number Diff line number Diff line
@@ -654,6 +654,11 @@
        -->
    </integer-array>

    <!-- When entering this device state (defined in device_state_configuration.xml),
         we should wake the device. -1 to disable the feature (do not wake on any device-state
         transition). -->
    <integer name="config_deviceStateOnWhichToWakeUp">-1</integer>

    <!-- Indicate the display area rect for foldable devices in folded state. -->
    <string name="config_foldedArea"></string>

+1 −0
Original line number Diff line number Diff line
@@ -3837,6 +3837,7 @@

  <!-- For Foldables -->
  <java-symbol type="array" name="config_foldedDeviceStates" />
  <java-symbol type="integer" name="config_deviceStateOnWhichToWakeUp" />
  <java-symbol type="string" name="config_foldedArea" />
  <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" />
  <java-symbol type="bool" name="config_unfoldTransitionEnabled" />
+6 −6
Original line number Diff line number Diff line
@@ -721,13 +721,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        final IBinder token = device.getDisplayTokenLocked();
        final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
        mHandler.post(() -> {
            if (mDisplayDevice == device) {
                return;
            }
            if (mDisplayDevice != device) {
                mDisplayDevice = device;
                mUniqueDisplayId = uniqueId;
                mDisplayDeviceConfig = config;
                loadFromDisplayDeviceConfig(token, info);
                updatePowerState();
            }
        });
    }

+35 −7
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.hardware.devicestate.DeviceStateManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.IndentingPrintWriter;
@@ -67,7 +69,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    public static final int DISPLAY_GROUP_EVENT_CHANGED = 2;
    public static final int DISPLAY_GROUP_EVENT_REMOVED = 3;

    private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500;
    private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 300;

    private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1;

@@ -95,6 +97,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
     */
    private final boolean mSupportsConcurrentInternalDisplays;

    /**
     * Wake the device when transitioning into this device state.
     */
    private final int mDeviceStateOnWhichToWakeUp;

    /**
     * Map of all logical displays indexed by logical display id.
     * Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache.
@@ -111,6 +118,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    private final Listener mListener;
    private final DisplayManagerService.SyncRoot mSyncRoot;
    private final LogicalDisplayMapperHandler mHandler;
    private final PowerManager mPowerManager;

    /**
     * Has an entry for every logical display that the rest of the system has been notified about.
@@ -148,12 +156,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
            @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
            @NonNull Handler handler) {
        mSyncRoot = syncRoot;
        mPowerManager = context.getSystemService(PowerManager.class);
        mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
        mDisplayDeviceRepo = repo;
        mListener = listener;
        mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
        mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
                com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
        mDeviceStateOnWhichToWakeUp = context.getResources().getInteger(
                com.android.internal.R.integer.config_deviceStateOnWhichToWakeUp);
        mDisplayDeviceRepo.addListener(this);
        mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
    }
@@ -261,6 +272,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {

        ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
        ipw.println("mCurrentLayout=" + mCurrentLayout);
        ipw.println("mDeviceStateOnWhichToWakeUp=" + mDeviceStateOnWhichToWakeUp);

        final int logicalDisplayCount = mLogicalDisplays.size();
        ipw.println();
@@ -278,7 +290,9 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    }

    void setDeviceStateLocked(int state) {
        Slog.i(TAG, "Requesting Transition to state: " + state);
        final boolean isInteractive  = mPowerManager.isInteractive();
        Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
                + ", interactive=" + isInteractive);
        // As part of a state transition, we may need to turn off some displays temporarily so that
        // the transition is smooth. Plus, on some devices, only one internal displays can be
        // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be
@@ -287,8 +301,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
            resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
        }
        mPendingDeviceState = state;
        if (areAllTransitioningDisplaysOffLocked()) {
            // Nothing to wait on, we're good to go
        final boolean wakeDevice = mPendingDeviceState == mDeviceStateOnWhichToWakeUp
                && !isInteractive;

        // If all displays are off already, we can just transition here, unless the device is asleep
        // and we plan on waking it up. In that case, fall through to the call to wakeUp, and defer
        // the final transition until later once the device is awake.
        if (areAllTransitioningDisplaysOffLocked() && !wakeDevice) {
            transitionToPendingStateLocked();
            return;
        }
@@ -299,6 +318,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
        // Send the transitioning phase updates to DisplayManager so that the displays can
        // start turning OFF in preparation for the new layout.
        updateLogicalDisplaysLocked();

        if (wakeDevice) {
            // We already told the displays to turn off, now we need to wake the device as
            // we transition to this new state. We do it here so that the waking happens between the
            // transition from one layout to another.
            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_UNFOLD_DEVICE,
                    "server.display:unfold");
        }
        mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE,
                TIMEOUT_STATE_TRANSITION_MILLIS);
    }
@@ -425,6 +452,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
                assignDisplayGroupLocked(display);
                mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);

            // The display is involved in a display layout transition
            } else if (updateState == UPDATE_STATE_TRANSITION) {
                mLogicalDisplaysToUpdate.put(displayId,
                        LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
@@ -615,14 +643,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {

            // We consider a display-device as changing/transition if
            // 1) It's already marked as transitioning
            // 2) It's going from enabled to disabled
            // 2) It's going from enabled to disabled, or vice versa
            // 3) It's enabled, but it's mapped to a new logical display ID. To the user this
            //    would look like apps moving from one screen to another since task-stacks stay
            //    with the logical display [ID].
            final boolean isTransitioning =
                    (logicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION)
                    || (wasEnabled && !willBeEnabled)
                    || (wasEnabled && deviceHasNewLogicalDisplayId);
                    || (wasEnabled != willBeEnabled)
                    || deviceHasNewLogicalDisplayId;

            if (isTransitioning) {
                setDisplayPhase(logicalDisplay, phase);