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

Commit 531660d9 authored by Christian Göllner's avatar Christian Göllner Committed by Android (Google) Code Review
Browse files

Merge "Device state based auto-rotation setting: add fallback setting mechanism"

parents 720035dc d41d1a69
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -127,10 +127,12 @@ public final class DeviceStateRotationLockSettingController
        int rotationLockSetting =
                mDeviceStateRotationLockSettingsManager.getRotationLockSetting(state);
        if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
            // This should not happen. Device states that have an ignored setting, should also
            // specify a fallback device state which is not ignored.
            // We won't handle this device state. The same rotation lock setting as before should
            // apply and any changes to the rotation lock setting will be written for the previous
            // valid device state.
            Log.v(TAG, "Ignoring new device state: " + state);
            Log.w(TAG, "Missing fallback. Ignoring new device state: " + state);
            return;
        }

+54 −17
Original line number Diff line number Diff line
@@ -52,12 +52,14 @@ public final class DeviceStateRotationLockSettingsManager {
    private final Handler mMainHandler = Handler.getMain();
    private final Set<DeviceStateRotationLockSettingsListener> mListeners = new HashSet<>();
    private SparseIntArray mDeviceStateRotationLockSettings;
    private SparseIntArray mDeviceStateRotationLockFallbackSettings;

    private DeviceStateRotationLockSettingsManager(Context context) {
        mContentResolver = context.getContentResolver();
        mDeviceStateRotationLockDefaults =
                context.getResources()
                        .getStringArray(R.array.config_perDeviceStateRotationLockDefaults);
        loadDefaults();
        initializeInMemoryMap();
        listenForSettingsChange(context);
    }
@@ -114,6 +116,11 @@ public final class DeviceStateRotationLockSettingsManager {

    /** Updates the rotation lock setting for a specified device state. */
    public void updateSetting(int deviceState, boolean rotationLocked) {
        if (mDeviceStateRotationLockFallbackSettings.indexOfKey(deviceState) >= 0) {
            // The setting for this device state is IGNORED, and has a fallback device state.
            // The setting for that fallback device state should be the changed in this case.
            deviceState = mDeviceStateRotationLockFallbackSettings.get(deviceState);
        }
        mDeviceStateRotationLockSettings.put(
                deviceState,
                rotationLocked
@@ -123,16 +130,37 @@ public final class DeviceStateRotationLockSettingsManager {
    }

    /**
     * Returns the {@link DeviceStateRotationLockSetting} for the given device state. If no setting
     * is specified for this device state, it will return {@link
     * Returns the {@link Settings.Secure.DeviceStateRotationLockSetting} for the given device
     * state.
     *
     * <p>If the setting for this device state is {@link DEVICE_STATE_ROTATION_LOCK_IGNORED}, it
     * will return the setting for the fallback device state.
     *
     * <p>If no fallback is specified for this device state, it will return {@link
     * DEVICE_STATE_ROTATION_LOCK_IGNORED}.
     */
    @Settings.Secure.DeviceStateRotationLockSetting
    public int getRotationLockSetting(int deviceState) {
        return mDeviceStateRotationLockSettings.get(
                deviceState, DEVICE_STATE_ROTATION_LOCK_IGNORED);
        int rotationLockSetting = mDeviceStateRotationLockSettings.get(
                deviceState, /* valueIfKeyNotFound= */ DEVICE_STATE_ROTATION_LOCK_IGNORED);
        if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
            rotationLockSetting = getFallbackRotationLockSetting(deviceState);
        }
        return rotationLockSetting;
    }

    private int getFallbackRotationLockSetting(int deviceState) {
        int indexOfFallbackState = mDeviceStateRotationLockFallbackSettings.indexOfKey(deviceState);
        if (indexOfFallbackState < 0) {
            Log.w(TAG, "Setting is ignored, but no fallback was specified.");
            return DEVICE_STATE_ROTATION_LOCK_IGNORED;
        }
        int fallbackState = mDeviceStateRotationLockFallbackSettings.valueAt(indexOfFallbackState);
        return mDeviceStateRotationLockSettings.get(fallbackState,
                /* valueIfKeyNotFound= */ DEVICE_STATE_ROTATION_LOCK_IGNORED);
    }


    /** Returns true if the rotation is locked for the current device state */
    public boolean isRotationLocked(int deviceState) {
        return getRotationLockSetting(deviceState) == DEVICE_STATE_ROTATION_LOCK_LOCKED;
@@ -223,21 +251,30 @@ public final class DeviceStateRotationLockSettingsManager {
    }

    private void loadDefaults() {
        if (mDeviceStateRotationLockDefaults.length == 0) {
            Log.w(TAG, "Empty default settings");
            mDeviceStateRotationLockSettings = new SparseIntArray(/* initialCapacity= */ 0);
            return;
        }
        mDeviceStateRotationLockSettings =
                new SparseIntArray(mDeviceStateRotationLockDefaults.length);
        for (String serializedDefault : mDeviceStateRotationLockDefaults) {
            String[] entry = serializedDefault.split(SEPARATOR_REGEX);
        mDeviceStateRotationLockSettings = new SparseIntArray(
                mDeviceStateRotationLockDefaults.length);
        mDeviceStateRotationLockFallbackSettings = new SparseIntArray(1);
        for (String entry : mDeviceStateRotationLockDefaults) {
            String[] values = entry.split(SEPARATOR_REGEX);
            try {
                int key = Integer.parseInt(entry[0]);
                int value = Integer.parseInt(entry[1]);
                mDeviceStateRotationLockSettings.put(key, value);
                int deviceState = Integer.parseInt(values[0]);
                int rotationLockSetting = Integer.parseInt(values[1]);
                if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
                    if (values.length == 3) {
                        int fallbackDeviceState = Integer.parseInt(values[2]);
                        mDeviceStateRotationLockFallbackSettings.put(deviceState,
                                fallbackDeviceState);
                    } else {
                        Log.w(TAG,
                                "Rotation lock setting is IGNORED, but values have unexpected "
                                        + "size of "
                                        + values.length);
                    }
                }
                mDeviceStateRotationLockSettings.put(deviceState, rotationLockSetting);
            } catch (NumberFormatException e) {
                Log.wtf(TAG, "Error deserializing default settings", e);
                Log.wtf(TAG, "Error parsing settings entry. Entry was: " + entry, e);
                return;
            }
        }
    }
+102 −10
Original line number Diff line number Diff line
@@ -52,13 +52,14 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase {

    private static final String[] DEFAULT_SETTINGS = new String[] {"0:0", "1:2"};
    private static final String[] DEFAULT_SETTINGS = new String[]{"0:1", "2:0:1", "1:2"};

    private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
    private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
    @Mock DeviceStateManager mDeviceStateManager;
    RotationPolicyWrapper mFakeRotationPolicy = new FakeRotationPolicy();
    DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
    @Mock
    private DeviceStateManager mDeviceStateManager;
    private final RotationPolicyWrapper mFakeRotationPolicy = new FakeRotationPolicy();
    private DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
    private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
    private DeviceStateRotationLockSettingsManager mSettingsManager;
    private TestableContentResolver mContentResolver;
@@ -93,7 +94,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
                                mContentResolver,
                                Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
                                UserHandle.USER_CURRENT))
                .isEqualTo("0:0:1:2");
                .isEqualTo("0:1:1:2:2:0");
    }

    @Test
@@ -124,6 +125,31 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
        assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
    }

    @Test
    public void whenDeviceStateSwitched_settingIsIgnored_loadsDefaultFallbackSetting() {
        initializeSettingsWith();
        mFakeRotationPolicy.setRotationLock(true);

        // State 2 -> Ignored -> Fall back to state 1 which is unlocked
        mDeviceStateCallback.onStateChanged(2);

        assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
    }

    @Test
    public void whenDeviceStateSwitched_ignoredSetting_fallbackValueChanges_usesFallbackValue() {
        initializeSettingsWith(
                0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                1, DEVICE_STATE_ROTATION_LOCK_LOCKED,
                2, DEVICE_STATE_ROTATION_LOCK_IGNORED);
        mFakeRotationPolicy.setRotationLock(false);

        // State 2 -> Ignored -> Fall back to state 1 which is locked
        mDeviceStateCallback.onStateChanged(2);

        assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
    }

    @Test
    public void whenUserChangesSetting_saveSettingForCurrentState() {
        initializeSettingsWith(
@@ -159,15 +185,15 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
    }

    @Test
    public void whenDeviceStateSwitchedToIgnoredState_newSettingsSaveForPreviousState() {
    public void whenDeviceStateSwitchedToIgnoredState_noFallback_newSettingsSaveForPreviousState() {
        initializeSettingsWith(
                0, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
                8, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
        mFakeRotationPolicy.setRotationLock(true);

        mDeviceStateCallback.onStateChanged(1);
        assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();

        mDeviceStateCallback.onStateChanged(0);
        mDeviceStateCallback.onStateChanged(8);
        assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();

        mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
@@ -178,7 +204,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
                                mContentResolver,
                                Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
                                UserHandle.USER_CURRENT))
                .isEqualTo("0:0:1:1");
                .isEqualTo("1:1:8:0");
    }

    @Test
@@ -198,12 +224,78 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
        assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
    }

    @Test
    public void onRotationLockStateChanged_newSettingIsPersisted() {
        initializeSettingsWith(
                0, DEVICE_STATE_ROTATION_LOCK_LOCKED,
                1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
        mDeviceStateCallback.onStateChanged(0);

        mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
                /* rotationLocked= */ false,
                /* affordanceVisible= */ true
        );

        assertThat(
                Settings.Secure.getStringForUser(
                        mContentResolver,
                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
                        UserHandle.USER_CURRENT))
                .isEqualTo("0:2:1:2");
    }

    @Test
    public void onRotationLockStateChanged_deviceStateIsIgnored_newSettingIsPersistedToFallback() {
        initializeSettingsWith(
                0, DEVICE_STATE_ROTATION_LOCK_LOCKED,
                1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                2, DEVICE_STATE_ROTATION_LOCK_IGNORED);
        mDeviceStateCallback.onStateChanged(2);

        mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
                /* rotationLocked= */ true,
                /* affordanceVisible= */ true
        );

        assertThat(
                Settings.Secure.getStringForUser(
                        mContentResolver,
                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
                        UserHandle.USER_CURRENT))
                .isEqualTo("0:1:1:1:2:0");
    }

    @Test
    public void onRotationLockStateChange_stateIgnored_noFallback_settingIsPersistedToPrevious() {
        initializeSettingsWith(
                0, DEVICE_STATE_ROTATION_LOCK_LOCKED,
                1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                8, DEVICE_STATE_ROTATION_LOCK_IGNORED);
        mDeviceStateCallback.onStateChanged(1);
        mDeviceStateCallback.onStateChanged(8);

        mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
                /* rotationLocked= */ true,
                /* affordanceVisible= */ true
        );

        assertThat(
                Settings.Secure.getStringForUser(
                        mContentResolver,
                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
                        UserHandle.USER_CURRENT))
                .isEqualTo("0:1:1:1:8:0");
    }

    private void initializeSettingsWith(int... values) {
        if (values.length % 2 != 0) {
            throw new IllegalArgumentException("Expecting key-value pairs");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; sb.append(":")) {
        for (int i = 0; i < values.length; ) {
            if (i > 0) {
                sb.append(":");
            }
            sb.append(values[i++]).append(":").append(values[i++]);
        }