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

Commit 6dead15c authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge "Make DeviceStateController generic" into tm-qpr-dev

parents eefa9e10 b6e9d2fc
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -652,6 +652,16 @@
         The default is false. -->
    <bool name="config_lidControlsSleep">false</bool>

    <!-- The device states (supplied by DeviceStateManager) that should be treated as open by the
         device fold controller. Default is empty. -->
    <integer-array name="config_openDeviceStates">
        <!-- Example:
        <item>0</item>
        <item>1</item>
        <item>2</item>
        -->
    </integer-array>

    <!-- The device states (supplied by DeviceStateManager) that should be treated as folded by the
         display fold controller. Default is empty. -->
    <integer-array name="config_foldedDeviceStates">
@@ -672,6 +682,16 @@
        -->
    </integer-array>

    <!-- The device states (supplied by DeviceStateManager) that should be treated as a rear display
     state. Default is empty. -->
    <integer-array name="config_rearDisplayDeviceStates">
        <!-- Example:
        <item>0</item>
        <item>1</item>
        <item>2</item>
        -->
    </integer-array>

    <!-- Indicates whether the window manager reacts to half-fold device states by overriding
     rotation. -->
    <bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>
+2 −0
Original line number Diff line number Diff line
@@ -4014,8 +4014,10 @@
  <java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />

  <!-- For Foldables -->
  <java-symbol type="array" name="config_openDeviceStates" />
  <java-symbol type="array" name="config_foldedDeviceStates" />
  <java-symbol type="array" name="config_halfFoldedDeviceStates" />
  <java-symbol type="array" name="config_rearDisplayDeviceStates" />
  <java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
  <java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
  <java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
+58 −46
Original line number Diff line number Diff line
@@ -16,80 +16,92 @@

package com.android.server.wm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Handler;
import android.os.HandlerExecutor;

import com.android.internal.R;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Class that registers callbacks with the {@link DeviceStateManager} and
 * responds to fold state changes by forwarding such events to a delegate.
 * Class that registers callbacks with the {@link DeviceStateManager} and responds to device
 * changes.
 */
final class DeviceStateController {
final class DeviceStateController implements DeviceStateManager.DeviceStateCallback {

    @NonNull
    private final DeviceStateManager mDeviceStateManager;
    private final Context mContext;
    @NonNull
    private final int[] mOpenDeviceStates;
    @NonNull
    private final int[] mHalfFoldedDeviceStates;
    @NonNull
    private final int[] mFoldedDeviceStates;
    @NonNull
    private final int[] mRearDisplayDeviceStates;
    @NonNull
    private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();

    private FoldStateListener mDeviceStateListener;
    @Nullable
    private DeviceState mLastDeviceState;

    public enum FoldState {
        UNKNOWN, OPEN, FOLDED, HALF_FOLDED
    public enum DeviceState {
        UNKNOWN, OPEN, FOLDED, HALF_FOLDED, REAR,
    }

    DeviceStateController(Context context, Handler handler, Consumer<FoldState> delegate) {
        mContext = context;
        mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
    DeviceStateController(@NonNull Context context, @NonNull Handler handler) {
        mDeviceStateManager = context.getSystemService(DeviceStateManager.class);
        mOpenDeviceStates = context.getResources()
                .getIntArray(R.array.config_openDeviceStates);
        mHalfFoldedDeviceStates = context.getResources()
                .getIntArray(R.array.config_halfFoldedDeviceStates);
        mFoldedDeviceStates = context.getResources()
                .getIntArray(R.array.config_foldedDeviceStates);
        mRearDisplayDeviceStates = context.getResources()
                .getIntArray(R.array.config_rearDisplayDeviceStates);

        if (mDeviceStateManager != null) {
            mDeviceStateListener = new FoldStateListener(mContext, delegate);
            mDeviceStateManager
                    .registerCallback(new HandlerExecutor(handler),
                            mDeviceStateListener);
            mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this);
        }
    }

    void unregisterFromDeviceStateManager() {
        if (mDeviceStateListener != null) {
            mDeviceStateManager.unregisterCallback(mDeviceStateListener);
        if (mDeviceStateManager != null) {
            mDeviceStateManager.unregisterCallback(this);
        }
    }

    /**
     * A listener for half-fold device state events that dispatches state changes to a delegate.
     */
    static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {

        private final int[] mHalfFoldedDeviceStates;
        private final int[] mFoldedDeviceStates;

        @Nullable
        private FoldState mLastResult;
        private final Consumer<FoldState> mDelegate;

        FoldStateListener(Context context, Consumer<FoldState> delegate) {
            mFoldedDeviceStates = context.getResources().getIntArray(
                    com.android.internal.R.array.config_foldedDeviceStates);
            mHalfFoldedDeviceStates = context.getResources().getIntArray(
                    com.android.internal.R.array.config_halfFoldedDeviceStates);
            mDelegate = delegate;
    void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
        mDeviceStateCallbacks.add(callback);
    }

    @Override
    public void onStateChanged(int state) {
            final boolean halfFolded = ArrayUtils.contains(mHalfFoldedDeviceStates, state);
            FoldState result;
            if (halfFolded) {
                result = FoldState.HALF_FOLDED;
        final DeviceState deviceState;
        if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) {
            deviceState = DeviceState.HALF_FOLDED;
        } else if (ArrayUtils.contains(mFoldedDeviceStates, state)) {
            deviceState = DeviceState.FOLDED;
        } else if (ArrayUtils.contains(mRearDisplayDeviceStates, state)) {
            deviceState = DeviceState.REAR;
        } else if (ArrayUtils.contains(mOpenDeviceStates, state)) {
            deviceState = DeviceState.OPEN;
        } else {
                final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
                result = folded ? FoldState.FOLDED : FoldState.OPEN;
            deviceState = DeviceState.UNKNOWN;
        }
            if (mLastResult == null || !mLastResult.equals(result)) {
                mLastResult = result;
                mDelegate.accept(result);

        if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) {
            mLastDeviceState = deviceState;

            for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
                callback.accept(mLastDeviceState);
            }
        }
    }
+6 −3
Original line number Diff line number Diff line
@@ -1125,14 +1125,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                    mWmService.mAtmService.getRecentTasks().getInputListener());
        }

        mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH);

        mDisplayPolicy = new DisplayPolicy(mWmService, this);
        mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address);

        mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH,
                newFoldState -> {
        final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
                (@NonNull DeviceStateController.DeviceState newFoldState) -> {
                    mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
                    mDisplayRotation.foldStateChanged(newFoldState);
                });
                };
        mDeviceStateController.registerDeviceStateCallback(deviceStateConsumer);

        mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
                R.dimen.config_closeToSquareDisplayMaxAspectRatio);
+26 −25
Original line number Diff line number Diff line
@@ -1573,7 +1573,7 @@ public class DisplayRotation {
        proto.end(token);
    }

    boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
    boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
        if (mFoldController == null) return false;
        return mFoldController.isDeviceInPosture(state, isTabletop);
    }
@@ -1585,10 +1585,10 @@ public class DisplayRotation {
    /**
     * Called by the DeviceStateManager callback when the device state changes.
     */
    void foldStateChanged(DeviceStateController.FoldState foldState) {
    void foldStateChanged(DeviceStateController.DeviceState deviceState) {
        if (mFoldController != null) {
            synchronized (mLock) {
                mFoldController.foldStateChanged(foldState);
                mFoldController.foldStateChanged(deviceState);
            }
        }
    }
@@ -1596,8 +1596,8 @@ public class DisplayRotation {
    private class FoldController {
        @Surface.Rotation
        private int mHalfFoldSavedRotation = -1; // No saved rotation
        private DeviceStateController.FoldState mFoldState =
                DeviceStateController.FoldState.UNKNOWN;
        private DeviceStateController.DeviceState mDeviceState =
                DeviceStateController.DeviceState.UNKNOWN;
        private boolean mInHalfFoldTransition = false;
        private final boolean mIsDisplayAlwaysSeparatingHinge;
        private final Set<Integer> mTabletopRotations;
@@ -1637,32 +1637,33 @@ public class DisplayRotation {
                    R.bool.config_isDisplayHingeAlwaysSeparating);
        }

        boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
            if (state != mFoldState) {
        boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
            if (state != mDeviceState) {
                return false;
            }
            if (mFoldState == DeviceStateController.FoldState.HALF_FOLDED) {
            if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
                return !(isTabletop ^ mTabletopRotations.contains(mRotation));
            }
            return true;
        }

        DeviceStateController.FoldState getFoldState() {
            return mFoldState;
        DeviceStateController.DeviceState getFoldState() {
            return mDeviceState;
        }

        boolean isSeparatingHinge() {
            return mFoldState == DeviceStateController.FoldState.HALF_FOLDED
                    || (mFoldState == DeviceStateController.FoldState.OPEN
            return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED
                    || (mDeviceState == DeviceStateController.DeviceState.OPEN
                        && mIsDisplayAlwaysSeparatingHinge);
        }

        boolean overrideFrozenRotation() {
            return mFoldState == DeviceStateController.FoldState.HALF_FOLDED;
            return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;
        }

        boolean shouldRevertOverriddenRotation() {
            return mFoldState == DeviceStateController.FoldState.OPEN // When transitioning to open.
            // When transitioning to open.
            return mDeviceState == DeviceStateController.DeviceState.OPEN
                    && mInHalfFoldTransition
                    && mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
                    && mUserRotationMode
@@ -1676,30 +1677,30 @@ public class DisplayRotation {
            return savedRotation;
        }

        void foldStateChanged(DeviceStateController.FoldState newState) {
        void foldStateChanged(DeviceStateController.DeviceState newState) {
            ProtoLog.v(WM_DEBUG_ORIENTATION,
                    "foldStateChanged: displayId %d, halfFoldStateChanged %s, "
                    + "saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, "
                    + "mLastOrientation: %d, mRotation: %d",
                    mDisplayContent.getDisplayId(), newState.name(), mHalfFoldSavedRotation,
                    mUserRotation, mLastSensorRotation, mLastOrientation, mRotation);
            if (mFoldState == DeviceStateController.FoldState.UNKNOWN) {
                mFoldState = newState;
            if (mDeviceState == DeviceStateController.DeviceState.UNKNOWN) {
                mDeviceState = newState;
                return;
            }
            if (newState == DeviceStateController.FoldState.HALF_FOLDED
                    && mFoldState != DeviceStateController.FoldState.HALF_FOLDED) {
            if (newState == DeviceStateController.DeviceState.HALF_FOLDED
                    && mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
                // The device has transitioned to HALF_FOLDED state: save the current rotation and
                // update the device rotation.
                mHalfFoldSavedRotation = mRotation;
                mFoldState = newState;
                mDeviceState = newState;
                // Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
                // return true, so rotation is unlocked.
                mService.updateRotation(false /* alwaysSendConfiguration */,
                        false /* forceRelayout */);
            } else {
                mInHalfFoldTransition = true;
                mFoldState = newState;
                mDeviceState = newState;
                // Tell the device to update its orientation.
                mService.updateRotation(false /* alwaysSendConfiguration */,
                        false /* forceRelayout */);
@@ -1822,7 +1823,7 @@ public class DisplayRotation {
            final long mTimestamp = System.currentTimeMillis();
            final int mHalfFoldSavedRotation;
            final boolean mInHalfFoldTransition;
            final DeviceStateController.FoldState mFoldState;
            final DeviceStateController.DeviceState mDeviceState;
            @Nullable final String mDisplayRotationCompatPolicySummary;

            Record(DisplayRotation dr, int fromRotation, int toRotation) {
@@ -1852,11 +1853,11 @@ public class DisplayRotation {
                if (dr.mFoldController != null) {
                    mHalfFoldSavedRotation = dr.mFoldController.mHalfFoldSavedRotation;
                    mInHalfFoldTransition = dr.mFoldController.mInHalfFoldTransition;
                    mFoldState = dr.mFoldController.mFoldState;
                    mDeviceState = dr.mFoldController.mDeviceState;
                } else {
                    mHalfFoldSavedRotation = NO_FOLD_CONTROLLER;
                    mInHalfFoldTransition = false;
                    mFoldState = DeviceStateController.FoldState.UNKNOWN;
                    mDeviceState = DeviceStateController.DeviceState.UNKNOWN;
                }
                mDisplayRotationCompatPolicySummary = dc.mDisplayRotationCompatPolicy == null
                        ? null
@@ -1882,7 +1883,7 @@ public class DisplayRotation {
                    pw.println(prefix + " halfFoldSavedRotation="
                            + mHalfFoldSavedRotation
                            + " mInHalfFoldTransition=" + mInHalfFoldTransition
                            + " mFoldState=" + mFoldState);
                            + " mFoldState=" + mDeviceState);
                }
                if (mDisplayRotationCompatPolicySummary != null) {
                    pw.println(prefix + mDisplayRotationCompatPolicySummary);
Loading