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

Commit fa5f10e0 authored by Kenneth Ford's avatar Kenneth Ford
Browse files

Update DeviceStateController to use new DSM API's

Replaces the DeviceStateController overlay config usages to use
the updated DeviceStateManager property based API's instead.

Bug: 336640888
Test: DeviceStateControllerTests
Flag: android.hardware.devicestate.feature.flags.device_state_property_migration
Change-Id: I8070a28d65dfd3db61a8062aec8c5e109b68b9f8
parent 72977ba6
Loading
Loading
Loading
Loading
+80 −20
Original line number Diff line number Diff line
@@ -16,9 +16,19 @@

package com.android.server.wm;

import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT;
import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.feature.flags.FeatureFlags;
import android.hardware.devicestate.feature.flags.FeatureFlagsImpl;
import android.util.ArrayMap;
import android.util.Pair;

@@ -28,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
@@ -43,16 +54,16 @@ final class DeviceStateController {
    @NonNull
    private final WindowManagerGlobalLock mWmLock;
    @NonNull
    private final int[] mOpenDeviceStates;
    private final List<Integer> mOpenDeviceStates;
    @NonNull
    private final int[] mHalfFoldedDeviceStates;
    private final List<Integer> mHalfFoldedDeviceStates;
    @NonNull
    private final int[] mFoldedDeviceStates;
    private final List<Integer> mFoldedDeviceStates;
    @NonNull
    private final int[] mRearDisplayDeviceStates;
    private final int mConcurrentDisplayDeviceState;
    private final List<Integer> mRearDisplayDeviceStates;
    private final List<Integer> mConcurrentDisplayDeviceStates;
    @NonNull
    private final int[] mReverseRotationAroundZAxisStates;
    private final List<Integer> mReverseRotationAroundZAxisStates;
    @GuardedBy("mWmLock")
    @NonNull
    @VisibleForTesting
@@ -76,18 +87,55 @@ final class DeviceStateController {
    DeviceStateController(@NonNull Context context, @NonNull WindowManagerGlobalLock wmLock) {
        mWmLock = wmLock;

        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);
        mConcurrentDisplayDeviceState = context.getResources()
                .getInteger(R.integer.config_deviceStateConcurrentRearDisplay);
        mReverseRotationAroundZAxisStates = context.getResources()
                .getIntArray(R.array.config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis);
        final FeatureFlags deviceStateManagerFlags = new FeatureFlagsImpl();
        if (deviceStateManagerFlags.deviceStatePropertyMigration()) {
            mOpenDeviceStates = new ArrayList<>();
            mHalfFoldedDeviceStates = new ArrayList<>();
            mFoldedDeviceStates = new ArrayList<>();
            mRearDisplayDeviceStates = new ArrayList<>();
            mConcurrentDisplayDeviceStates = new ArrayList<>();

            final DeviceStateManager deviceStateManager =
                    context.getSystemService(DeviceStateManager.class);
            final List<android.hardware.devicestate.DeviceState> deviceStates =
                    deviceStateManager.getSupportedDeviceStates();

            for (int i = 0; i < deviceStates.size(); i++) {
                final android.hardware.devicestate.DeviceState state = deviceStates.get(i);
                if (state.hasProperty(
                        PROPERTY_FEATURE_REAR_DISPLAY)) {
                    mRearDisplayDeviceStates.add(state.getIdentifier());
                } else if (state.hasProperty(
                        PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT)) {
                    mConcurrentDisplayDeviceStates.add(state.getIdentifier());
                } else if (state.hasProperty(
                        PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)) {
                    mFoldedDeviceStates.add(state.getIdentifier());
                } else if (state.hasProperty(
                        PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)) {
                    if (state.hasProperty(
                            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN)) {
                        mHalfFoldedDeviceStates.add(state.getIdentifier());
                    } else {
                        mOpenDeviceStates.add(state.getIdentifier());
                    }
                }
            }
        } else {
            mOpenDeviceStates = copyIntArrayToList(context.getResources()
                    .getIntArray(R.array.config_openDeviceStates));
            mHalfFoldedDeviceStates = copyIntArrayToList(context.getResources()
                    .getIntArray(R.array.config_halfFoldedDeviceStates));
            mFoldedDeviceStates = copyIntArrayToList(context.getResources()
                    .getIntArray(R.array.config_foldedDeviceStates));
            mRearDisplayDeviceStates = copyIntArrayToList(context.getResources()
                    .getIntArray(R.array.config_rearDisplayDeviceStates));
            mConcurrentDisplayDeviceStates = new ArrayList<>(List.of(context.getResources()
                    .getInteger(R.integer.config_deviceStateConcurrentRearDisplay)));
        }

        mReverseRotationAroundZAxisStates = copyIntArrayToList(context.getResources().getIntArray(
                R.array.config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis));
        mMatchBuiltInDisplayOrientationToDefaultDisplay = context.getResources()
                .getBoolean(R.bool
                        .config_matchSecondaryInternalDisplaysOrientationToReverseDefaultDisplay);
@@ -145,7 +193,6 @@ final class DeviceStateController {
     */
    public void onDeviceStateReceivedByDisplayManager(int state) {
        mCurrentState = state;

        final DeviceState deviceState;
        if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) {
            deviceState = DeviceState.HALF_FOLDED;
@@ -155,9 +202,10 @@ final class DeviceStateController {
            deviceState = DeviceState.REAR;
        } else if (ArrayUtils.contains(mOpenDeviceStates, state)) {
            deviceState = DeviceState.OPEN;
        } else if (state == mConcurrentDisplayDeviceState) {
        } else if (ArrayUtils.contains(mConcurrentDisplayDeviceStates, state)) {
            deviceState = DeviceState.CONCURRENT;
        } else {

            deviceState = DeviceState.UNKNOWN;
        }

@@ -190,4 +238,16 @@ final class DeviceStateController {
        }
        return entries;
    }

    @NonNull
    private List<Integer> copyIntArrayToList(@Nullable int[] values) {
        if (values == null) {
            return Collections.emptyList();
        }
        final List<Integer> valueList = new ArrayList<>();
        for (int i = 0; i < values.length; i++) {
            valueList.add(values[i]);
        }
        return valueList;
    }
}
+118 −25
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@

package com.android.server.wm;

import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT;
import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
import static android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_MIGRATION;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;

@@ -24,8 +33,11 @@ import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.content.res.Resources;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.util.Pair;

import androidx.test.filters.SmallTest;
@@ -37,6 +49,8 @@ import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -79,39 +93,67 @@ public class DeviceStateControllerTests {
    @Test
    public void testInitialization() {
        initialize(true /* supportFold */, true /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
    }

    @Test
    public void testInitializationWithNoFoldSupport() {
        initialize(false /* supportFold */, false /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        // Note that the folded state is ignored.
        assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState);
    }

    @Test
    public void testWithFoldSupported() {
    @RequiresFlagsDisabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
    public void testWithFoldSupported_withOverlayConfigValues() {
        initialize(true /* supportFold */, false /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState); // Ignored
    }

    @Test
    public void testWithHalfFoldSupported() {
    @RequiresFlagsEnabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
    public void testWithFoldSupported_withDeviceStateManagerPropertyAPI() {
        initialize(true /* supportFold */, false /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState); // Ignored
    }

    @Test
    @RequiresFlagsDisabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
    public void testWithHalfFoldSupported_withOverlayConfigValue() {
        initialize(true /* supportFold */, true /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.HALF_FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mConcurrentDisplayState.getIdentifier());
        assertEquals(DeviceStateController.DeviceState.CONCURRENT, mCurrentState);
    }

    @Test
    @RequiresFlagsEnabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
    public void testWithHalfFoldSupported_withDeviceStateManagerPropertyApi() {
        initialize(true /* supportFold */, true /* supportHalfFolded */);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mHalfFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.HALF_FOLDED, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mConcurrentDisplayState);
        mTarget.onDeviceStateReceivedByDisplayManager(mConcurrentDisplayState.getIdentifier());
        assertEquals(DeviceStateController.DeviceState.CONCURRENT, mCurrentState);
    }

@@ -121,16 +163,18 @@ public class DeviceStateControllerTests {
        assertEquals(1, mTarget.mDeviceStateCallbacks.size());
        assertTrue(mTarget.mDeviceStateCallbacks.containsKey(mDelegate));

        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates[0]);
        mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);

        // The callback should not receive state change when it is unregistered.
        mTarget.unregisterDeviceStateCallback(mDelegate);
        assertTrue(mTarget.mDeviceStateCallbacks.isEmpty());
        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
        assertEquals(DeviceStateController.DeviceState.FOLDED /* unchanged */, mCurrentState);

        mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates.get(0).getIdentifier());
        assertEquals(DeviceStateController.DeviceState.FOLDED /* unchanged */,
                mCurrentState);
    }

    @Test
@@ -151,16 +195,50 @@ public class DeviceStateControllerTests {
        assertEquals(mExecutor, entries.get(0).second);
    }

    private final int[] mFoldedStates = {0};
    private final int[] mOpenDeviceStates = {1};
    private final int[] mHalfFoldedStates = {2};
    private final int[] mRearDisplayStates = {3};
    private final int mConcurrentDisplayState = 4;
    private final List<DeviceState> mFoldedStates = new ArrayList<>(
            List.of(new DeviceState(new DeviceState.Configuration.Builder(0,
                    "folded").setSystemProperties(new HashSet<>(
                    List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)))
                    .setPhysicalProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED)))
                    .build())));
    private final List<DeviceState> mOpenDeviceStates = new ArrayList<>(
            List.of(new DeviceState(new DeviceState.Configuration.Builder(1,
                    "open").setSystemProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)))
                    .setPhysicalProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN)))
                    .build())));
    private final List<DeviceState> mHalfFoldedStates = new ArrayList<>(
            List.of(new DeviceState(new DeviceState.Configuration.Builder(2,
                    "half_folded").setSystemProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)))
                    .setPhysicalProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN)))
                    .build())));
    private final List<DeviceState> mRearDisplayStates = new ArrayList<>(
            List.of(new DeviceState(new DeviceState.Configuration.Builder(3,
                    "rear_display").setSystemProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
                                    PROPERTY_FEATURE_REAR_DISPLAY)))
                    .setPhysicalProperties(new HashSet<>(
                            List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN)))
                    .build())));
    private final DeviceState mConcurrentDisplayState = new DeviceState(
            new DeviceState.Configuration.Builder(4, "concurrent_display")
                    .setSystemProperties(new HashSet<>(List.of(
                            PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
                            PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT)))
                    .setPhysicalProperties(new HashSet<>(List.of(
                            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN)))
                    .build());

    private class DeviceStateControllerBuilder {
        private boolean mSupportFold = false;
        private boolean mSupportHalfFold = false;

        private Consumer<DeviceStateController.DeviceState> mDelegate;
        private final List<DeviceState> mDeviceStateList = new ArrayList<>();

        DeviceStateControllerBuilder setSupportFold(
                boolean supportFold, boolean supportHalfFold) {
@@ -179,13 +257,17 @@ public class DeviceStateControllerTests {
            if (enableFold || enableHalfFold) {
                when(mMockContext.getResources()
                        .getIntArray(R.array.config_openDeviceStates))
                        .thenReturn(mOpenDeviceStates);
                        .thenReturn(mapDeviceStateListToIdentifierArray(mOpenDeviceStates));
                when(mMockContext.getResources()
                        .getIntArray(R.array.config_rearDisplayDeviceStates))
                        .thenReturn(mRearDisplayStates);
                        .thenReturn(mapDeviceStateListToIdentifierArray(mRearDisplayStates));
                when(mMockContext.getResources()
                        .getInteger(R.integer.config_deviceStateConcurrentRearDisplay))
                        .thenReturn(mConcurrentDisplayState);
                        .thenReturn(mConcurrentDisplayState.getIdentifier());

                mDeviceStateList.addAll(mOpenDeviceStates);
                mDeviceStateList.addAll(mRearDisplayStates);
                mDeviceStateList.add(mConcurrentDisplayState);
            } else {
                // Match the default value in framework resources
                when(mMockContext.getResources()
@@ -196,12 +278,14 @@ public class DeviceStateControllerTests {
            if (enableFold) {
                when(mMockContext.getResources()
                        .getIntArray(R.array.config_foldedDeviceStates))
                        .thenReturn(mFoldedStates);
                        .thenReturn(mapDeviceStateListToIdentifierArray(mFoldedStates));
                mDeviceStateList.addAll(mFoldedStates);
            }
            if (enableHalfFold) {
                when(mMockContext.getResources()
                        .getIntArray(R.array.config_halfFoldedDeviceStates))
                        .thenReturn(mHalfFoldedStates);
                        .thenReturn(mapDeviceStateListToIdentifierArray(mHalfFoldedStates));
                mDeviceStateList.addAll(mHalfFoldedStates);
            }
        }

@@ -210,11 +294,20 @@ public class DeviceStateControllerTests {
            mMockDeviceStateManager = mock(DeviceStateManager.class);
            when(mMockContext.getSystemService(DeviceStateManager.class))
                    .thenReturn(mMockDeviceStateManager);
            when(mMockDeviceStateManager.getSupportedDeviceStates()).thenReturn(mDeviceStateList);
            Resources mockRes = mock(Resources.class);
            when(mMockContext.getResources()).thenReturn((mockRes));
            mockFold(mSupportFold, mSupportHalfFold);
            mTarget = new DeviceStateController(mMockContext, new WindowManagerGlobalLock());
            mTarget.registerDeviceStateCallback(mDelegate, mExecutor);
        }

        private int[] mapDeviceStateListToIdentifierArray(List<DeviceState> deviceStates) {
            int[] identifiers = new int[deviceStates.size()];
            for (int i = 0; i < deviceStates.size(); i++) {
                identifiers[i] = deviceStates.get(i).getIdentifier();
            }
            return identifiers;
        }
    }
}