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

Commit a6e6daf4 authored by Shivangi Dubey's avatar Shivangi Dubey Committed by Android (Google) Code Review
Browse files

Merge "Handle auto-rotate setting is being set while device-state is unavailable" into main

parents 2c7dd5ad c5e18c89
Loading
Loading
Loading
Loading
+31 −8
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;

@@ -44,6 +45,8 @@ import com.android.server.wm.DeviceStateAutoRotateSettingController.Event.Update
import com.android.server.wm.DeviceStateController.DeviceStateEnum;
import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@@ -68,6 +71,7 @@ public class DeviceStateAutoRotateSettingController {
    private static final String SEPARATOR_REGEX = ":";
    private static final int ACCELEROMETER_ROTATION_OFF = 0;
    private static final int ACCELEROMETER_ROTATION_ON = 1;
    private static final int INVALID_DEVICE_STATE = -1;
    // TODO(b/413598268): Disable debugging after the
    //  com.android.window.flags.enable_device_state_auto_rotate_setting_refactor flag is rolled-out
    private static final boolean DEBUG = true;
@@ -78,10 +82,9 @@ public class DeviceStateAutoRotateSettingController {
    private final DeviceStateAutoRotateSettingManager mDeviceStateAutoRotateSettingManager;
    private final ContentResolver mContentResolver;
    private final DeviceStateController mDeviceStateController;
    private final List<Event> mPendingEvents = new ArrayList<>();

    // TODO(b/413639166): Handle device state being missing until we receive first device state
    //  update
    private int mDeviceState = -1;
    private int mDeviceState = INVALID_DEVICE_STATE;
    private boolean mAccelerometerSetting;
    private SparseIntArray mDeviceStateAutoRotateSetting;

@@ -103,10 +106,23 @@ public class DeviceStateAutoRotateSettingController {
            @Override
            public void handleMessage(@NonNull Message msg) {
                final Event event = (Event) msg.obj;
                final boolean inMemoryStateUpdated = updateInMemoryState(event);
                if (mDeviceState == INVALID_DEVICE_STATE && !(event instanceof UpdateDeviceState)) {
                    mPendingEvents.add(event);
                    Log.w(TAG, "Trying to write into auto-rotate settings, while "
                            + "device-state is unavailable.\n" + "Could not process the event="
                            + event.getClass().getSimpleName() + ".\n"
                            + "This event will be queued and processed later once we receive "
                            + "device-state update.");
                    return;
                }

                if (inMemoryStateUpdated) {
                    writeInMemoryStateIntoPersistedSetting();
                handleEvent(event);

                if (!mPendingEvents.isEmpty()) {
                    for (int i = 0; i < mPendingEvents.size(); i++) {
                        handleEvent(mPendingEvents.get(i));
                    }
                    mPendingEvents.clear();
                }
            }
        };
@@ -116,6 +132,14 @@ public class DeviceStateAutoRotateSettingController {
        registerDeviceStateObserver();
    }

    private void handleEvent(@NonNull Event event) {
        final boolean inMemoryStateUpdated = updateInMemoryState(event);

        if (inMemoryStateUpdated) {
            writeInMemoryStateIntoPersistedSetting();
        }
    }

    /** Request to change {@link DEVICE_STATE_ROTATION_LOCK} persisted setting. */
    public void requestDeviceStateAutoRotateSettingChange(int deviceState, boolean autoRotate) {
        postUpdate(new UpdateDeviceStateAutoRotateSetting(deviceState, autoRotate));
@@ -128,8 +152,7 @@ public class DeviceStateAutoRotateSettingController {

    private void registerDeviceStateAutoRotateSettingObserver() {
        mDeviceStateAutoRotateSettingManager.registerListener(
                () -> postUpdate(
                        PersistedSettingUpdate.INSTANCE));
                () -> postUpdate(PersistedSettingUpdate.INSTANCE));
    }

    private void registerAccelerometerRotationSettingObserver() {
+118 −32
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.server.wm;

import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK;
import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED;
import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED;
import static android.provider.Settings.System.ACCELEROMETER_ROTATION;
import static android.provider.Settings.System.getUriFor;
@@ -28,11 +27,13 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.devicestate.DeviceState;
import android.os.Handler;
@@ -45,11 +46,14 @@ import android.util.SparseIntArray;

import androidx.test.filters.SmallTest;

import com.android.internal.R;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.wm.utils.DeviceStateTestUtils;
import com.android.settingslib.devicestate.AndroidSecureSettings;
import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager.DeviceStateAutoRotateSettingListener;
import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManagerImpl;
import com.android.settingslib.devicestate.PostureDeviceStateConverter;

import org.junit.Before;
import org.junit.Rule;
@@ -59,6 +63,8 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.concurrent.Executor;

/**
 * Test class for {@link DeviceStateAutoRotateSettingController}.
 *
@@ -66,8 +72,6 @@ import org.mockito.MockitoAnnotations;
 */
@SmallTest
@Presubmit
// TODO(b/413639166): Add testcase to check if class under test behaves expectedly when
//  deviceState = -1
public class DeviceStateAutoRotateSettingControllerTests {
    private static final int ACCELEROMETER_ROTATION_OFF = 0;
    private static final int ACCELEROMETER_ROTATION_ON = 1;
@@ -79,8 +83,6 @@ public class DeviceStateAutoRotateSettingControllerTests {
    @Rule
    public final FakeSettingsProviderRule rule = FakeSettingsProvider.rule();

    @Mock
    private DeviceStateAutoRotateSettingManagerImpl mMockAutoRotateSettingManager;
    @Mock
    private DeviceStateController mMockDeviceStateController;
    @Mock
@@ -95,41 +97,48 @@ public class DeviceStateAutoRotateSettingControllerTests {

    private final TestLooper mTestLooper = new TestLooper();
    private DeviceStateAutoRotateSettingController mDeviceStateAutoRotateSettingController;
    private DeviceStateAutoRotateSettingManagerImpl mSpyAutoRotateSettingManager;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        final Context mockContext = mock(Context.class);
        when(mockContext.getContentResolver()).thenReturn(mMockResolver);
        final Resources mockResources = mock(Resources.class);
        final FakeSettingsProvider fakeSettingsProvider = new FakeSettingsProvider();
        when(mMockResolver.acquireProvider(Settings.AUTHORITY))
                .thenReturn(fakeSettingsProvider.getIContentProvider());
        final Looper looper = mTestLooper.getLooper();
        final Handler handler = new Handler(looper);

        when(mockContext.getContentResolver()).thenReturn(mMockResolver);
        when(mockContext.getResources()).thenReturn(mockResources);
        when(mockResources.getStringArray(
                R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(new String[]{});
        when(mMockResolver.acquireProvider(Settings.AUTHORITY)).thenReturn(
                fakeSettingsProvider.getIContentProvider());
        mSpyAutoRotateSettingManager = spy(
                new DeviceStateAutoRotateSettingManagerImpl(mockContext, mock(Executor.class),
                        new AndroidSecureSettings(mMockResolver), handler,
                        mock(PostureDeviceStateConverter.class)));

        setAccelerometerRotationSetting(ACCELEROMETER_ROTATION_OFF);
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_LOCKED,
                        DEVICE_STATE_ROTATION_LOCK_LOCKED));
        setDeviceStateAutoRotateSetting(FOLDED_LOCKED_OPEN_LOCKED_SETTING);

        mDeviceStateAutoRotateSettingController = new DeviceStateAutoRotateSettingController(
                mockContext, looper, handler, mMockDeviceStateController,
                mMockAutoRotateSettingManager);
                mSpyAutoRotateSettingManager);
        mTestLooper.dispatchAll();

        verify(mMockAutoRotateSettingManager).registerListener(
        verify(mSpyAutoRotateSettingManager).registerListener(
                mSettingListenerArgumentCaptor.capture());
        verify(mMockResolver).registerContentObserver(
                eq(getUriFor(ACCELEROMETER_ROTATION)), anyBoolean(),
                mAccelerometerRotationSettingObserver.capture(), eq(UserHandle.USER_CURRENT));
        verify(mMockDeviceStateController).registerDeviceStateCallback(
                mDeviceStateListenerCaptor.capture(), any());

        setDeviceState(DeviceStateTestUtils.FOLDED);
    }

    @Test
    public void requestDSAutoRotateSettingChange_updatesDeviceStateAutoRotateSetting() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mTestLooper.dispatchAll();
@@ -140,6 +149,7 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void requestAccelerometerRotationChange_updatesAccelerometerRotation() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(true);
        mTestLooper.dispatchAll();

@@ -148,6 +158,7 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void requestDSAutoRotateSettingChange_curDeviceState_updatesAccelerometerRotation() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mTestLooper.dispatchAll();
@@ -157,6 +168,7 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void requestAccelerometerRotationChange_updatesDSAutoRotateSetting() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(true);
        mTestLooper.dispatchAll();

@@ -165,6 +177,7 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void accelerometerRotationSettingChanged_updatesDSAutoRotateSetting() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setAccelerometerRotationSetting(ACCELEROMETER_ROTATION_ON);

        mAccelerometerRotationSettingObserver.getValue().onChange(false);
@@ -175,9 +188,8 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void dSAutoRotateSettingChanged_updatesAccelerometerRotation() {
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                        DEVICE_STATE_ROTATION_LOCK_LOCKED));
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setDeviceStateAutoRotateSetting(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);

        mSettingListenerArgumentCaptor.getValue().onSettingsChanged();
        mTestLooper.dispatchAll();
@@ -187,9 +199,8 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void onDeviceStateChange_updatesAccelerometerRotation() {
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_LOCKED,
                        DEVICE_STATE_ROTATION_LOCK_UNLOCKED));
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setDeviceStateAutoRotateSetting(FOLDED_LOCKED_OPEN_UNLOCKED_SETTING);
        mSettingListenerArgumentCaptor.getValue().onSettingsChanged();
        mTestLooper.dispatchAll();

@@ -200,6 +211,7 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void requestDSAutoRotateSettingChange_nonCurDeviceState_noUpdateAccelerometerRotation() {
        setDeviceState(DeviceStateTestUtils.FOLDED);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.OPEN.getIdentifier(), true);
        mTestLooper.dispatchAll();
@@ -209,8 +221,9 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void dSAutoRotateCorrupted_writesDefaultSettingWhileRespectingAccelerometerRotation() {
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation -> null);
        when(mMockAutoRotateSettingManager.getDefaultRotationLockSetting()).thenReturn(
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setDeviceStateAutoRotateSetting("invalid");
        when(mSpyAutoRotateSettingManager.getDefaultRotationLockSetting()).thenReturn(
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                        DEVICE_STATE_ROTATION_LOCK_UNLOCKED));

@@ -222,9 +235,8 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void multipleSettingChanges_accelerometerRotationSettingTakesPrecedenceWhenConflict() {
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                        DEVICE_STATE_ROTATION_LOCK_LOCKED));
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setDeviceStateAutoRotateSetting(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);
        setAccelerometerRotationSetting(ACCELEROMETER_ROTATION_ON);
        mAccelerometerRotationSettingObserver.getValue().onChange(false);
        mTestLooper.dispatchAll();
@@ -237,9 +249,7 @@ public class DeviceStateAutoRotateSettingControllerTests {
        verifyDeviceStateAutoRotateSettingSet(FOLDED_LOCKED_OPEN_LOCKED_SETTING);

        // Change device state auto rotate setting to unlocked for both states
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_LOCKED,
                        DEVICE_STATE_ROTATION_LOCK_UNLOCKED));
        setDeviceStateAutoRotateSetting(FOLDED_LOCKED_OPEN_UNLOCKED_SETTING);
        setAccelerometerRotationSetting(ACCELEROMETER_ROTATION_ON);
        mSettingListenerArgumentCaptor.getValue().onSettingsChanged();
        mTestLooper.dispatchAll();
@@ -249,9 +259,8 @@ public class DeviceStateAutoRotateSettingControllerTests {

    @Test
    public void multipleDeviceStateChanges_updatesAccelerometerRotationForRespectiveDeviceState() {
        when(mMockAutoRotateSettingManager.getRotationLockSetting()).thenAnswer(invocation ->
                createDeviceStateAutoRotateSettingMap(DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
                        DEVICE_STATE_ROTATION_LOCK_LOCKED));
        setDeviceState(DeviceStateTestUtils.FOLDED);
        setDeviceStateAutoRotateSetting(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);
        setAccelerometerRotationSetting(ACCELEROMETER_ROTATION_ON);
        mSettingListenerArgumentCaptor.getValue().onSettingsChanged();
        mTestLooper.dispatchAll();
@@ -266,6 +275,83 @@ public class DeviceStateAutoRotateSettingControllerTests {
        verifyDeviceStateAutoRotateSettingSet(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);
    }

    @Test
    public void requestAccelerometerRotationChange_dSUnavailable_noSettingUpdate() {
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(true);
        mTestLooper.dispatchAll();

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_OFF);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_LOCKED_OPEN_LOCKED_SETTING);
    }

    @Test
    public void requestDSAutoRotateSettingChange_dSUnavailable_noSettingUpdate() {
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mTestLooper.dispatchAll();

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_OFF);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_LOCKED_OPEN_LOCKED_SETTING);
    }

    @Test
    public void requestAccelerometerRotationChange_dSUnavailable_writeAfterReceivingDSUpdate() {
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(true);
        mTestLooper.dispatchAll();

        setDeviceState(DeviceStateTestUtils.FOLDED);

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_ON);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);
    }

    @Test
    public void requestDSAutoRotateSettingChange_dSUnavailable_writeAfterReceivingDSUpdate() {
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mTestLooper.dispatchAll();

        setDeviceState(DeviceStateTestUtils.FOLDED);

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_ON);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_UNLOCKED_OPEN_LOCKED_SETTING);
    }

    @Test
    public void dSUnavailable_sendMultipleRequests_accelerometerPrecedesAfterReceivingDSUpdate() {
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(false);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.OPEN.getIdentifier(), true);
        mTestLooper.dispatchAll();

        setDeviceState(DeviceStateTestUtils.FOLDED);

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_OFF);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_LOCKED_OPEN_UNLOCKED_SETTING);
    }

    @Test
    public void dSUnavailable_sendMultipleRequests_dSAutoRotatePrecedesAfterReceivingDSUpdate() {
        mDeviceStateAutoRotateSettingController.requestAccelerometerRotationSettingChange(false);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.OPEN.getIdentifier(), true);
        mDeviceStateAutoRotateSettingController.requestDeviceStateAutoRotateSettingChange(
                DeviceStateTestUtils.FOLDED.getIdentifier(), true);
        mTestLooper.dispatchAll();

        setDeviceState(DeviceStateTestUtils.FOLDED);

        verifyAccelerometerRotationSettingSet(ACCELEROMETER_ROTATION_ON);
        verifyDeviceStateAutoRotateSettingSet(FOLDED_UNLOCKED_OPEN_UNLOCKED_SETTING);
    }

    private void setDeviceStateAutoRotateSetting(String deviceStateAutoRotateSetting) {
        Settings.Secure.putStringForUser(mMockResolver, DEVICE_STATE_ROTATION_LOCK,
                deviceStateAutoRotateSetting, UserHandle.USER_CURRENT);
    }

    private void setAccelerometerRotationSetting(int accelerometerRotationSetting) {
        Settings.System.putIntForUser(mMockResolver, ACCELEROMETER_ROTATION,
                accelerometerRotationSetting, UserHandle.USER_CURRENT);