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

Commit 06d96ba8 authored by Beverly Tai's avatar Beverly Tai Committed by Beverly
Browse files

Revert^2 "DevicePostureControlller to use the device posture of the device display"

This reverts commit 9990f220.

Reason for revert: This change was reverted due to potentially
being a culprit for b/312755362. However, after merging the revert,
the test was still failing - so it's unlikely this change was actually
the culrpit. Therefore, let's remerge this change.

Fixes: 303543453
Flag: NONE

Change-Id: If6234cd65799108b135da356e1f19ccf21e8568f
parent 2bea0e44
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -73,7 +73,11 @@ public interface DevicePostureController extends CallbackController<Callback> {

    /** Callback to be notified about device posture changes. */
    interface Callback {
        /** Called when the posture changes. */
        /**
         * Called when the posture changes. If there are multiple active displays ("concurrent"),
         * this will report the physical posture of the device (also known as the base device
         * state).
         */
        void onPostureChanged(@DevicePostureInt int posture);
    }
}
+34 −7
Original line number Diff line number Diff line
@@ -39,8 +39,11 @@ import javax.inject.Inject;
/** Implementation of {@link DevicePostureController} using the DeviceStateManager. */
@SysUISingleton
public class DevicePostureControllerImpl implements DevicePostureController {
    /** From androidx.window.common.COMMON_STATE_USE_BASE_STATE */
    private static final int COMMON_STATE_USE_BASE_STATE = 1000;
    private final List<Callback> mListeners = new ArrayList<>();
    private int mCurrentDevicePosture = DEVICE_POSTURE_UNKNOWN;
    private int mCurrentBasePosture = DEVICE_POSTURE_UNKNOWN;

    private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();

@@ -73,16 +76,32 @@ public class DevicePostureControllerImpl implements DevicePostureController {
            mDeviceStateToPostureMap.put(deviceState, posture);
        }

        deviceStateManager.registerCallback(executor, state -> {
        deviceStateManager.registerCallback(executor, new DeviceStateManager.DeviceStateCallback() {
            @Override
            public void onStateChanged(int state) {
                Assert.isMainThread();
                mCurrentDevicePosture =
                        mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN);
                sendUpdatePosture();
            }

            @Override
            public void onBaseStateChanged(int state) {
                Assert.isMainThread();
                mCurrentBasePosture = mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN);

                if (useBaseState()) {
                    sendUpdatePosture();
                }
            }

            private void sendUpdatePosture() {
                ListenersTracing.INSTANCE.forEachTraced(mListeners, "DevicePostureControllerImpl",
                    l -> {
                        l.onPostureChanged(mCurrentDevicePosture);
                        l.onPostureChanged(getDevicePosture());
                        return Unit.INSTANCE;
                    });
            }
        });
    }

@@ -100,6 +119,14 @@ public class DevicePostureControllerImpl implements DevicePostureController {

    @Override
    public int getDevicePosture() {
        if (useBaseState()) {
            return mCurrentBasePosture;
        } else {
            return mCurrentDevicePosture;
        }
    }

    private boolean useBaseState() {
        return mCurrentDevicePosture == COMMON_STATE_USE_BASE_STATE;
    }
}
+143 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.policy

import android.hardware.devicestate.DeviceStateManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableResources
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_FLIPPED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN
import com.android.systemui.statusbar.policy.DevicePostureController.SUPPORTED_POSTURES_SIZE
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class DevicePostureControllerImplTest : SysuiTestCase() {
    private val useBaseStateDeviceState = SUPPORTED_POSTURES_SIZE
    private val deviceStateToPostureMapping =
        arrayOf(
            "$DEVICE_POSTURE_UNKNOWN:$DEVICE_POSTURE_UNKNOWN",
            "$DEVICE_POSTURE_CLOSED:$DEVICE_POSTURE_CLOSED",
            "$DEVICE_POSTURE_HALF_OPENED:$DEVICE_POSTURE_HALF_OPENED",
            "$DEVICE_POSTURE_OPENED:$DEVICE_POSTURE_OPENED",
            "$DEVICE_POSTURE_FLIPPED:$DEVICE_POSTURE_FLIPPED",
            "$useBaseStateDeviceState:1000"
        )
    @Mock private lateinit var deviceStateManager: DeviceStateManager
    @Captor
    private lateinit var deviceStateCallback: ArgumentCaptor<DeviceStateManager.DeviceStateCallback>

    private lateinit var mainExecutor: FakeExecutor
    private lateinit var testableResources: TestableResources
    private lateinit var underTest: DevicePostureControllerImpl

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        mainExecutor = FakeExecutor(FakeSystemClock())
        testableResources = context.getOrCreateTestableResources()
        testableResources.addOverride(
            com.android.internal.R.array.config_device_state_postures,
            deviceStateToPostureMapping
        )
        underTest =
            DevicePostureControllerImpl(
                context,
                deviceStateManager,
                mainExecutor,
            )
        verifyRegistersForDeviceStateCallback()
    }

    @Test
    fun testPostureChanged_updates() {
        var posture = -1
        underTest.addCallback { posture = it }

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_UNKNOWN)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_UNKNOWN)

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_CLOSED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_CLOSED)

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED)

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_OPENED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_OPENED)

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_FLIPPED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_FLIPPED)
    }

    @Test
    fun testPostureChanged_useBaseUpdate() {
        var posture = -1
        underTest.addCallback { posture = it }

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED)

        // base state change doesn't change the posture
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_CLOSED)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED)

        // WHEN the display state maps to using the base state, then posture updates
        deviceStateCallback.value.onStateChanged(useBaseStateDeviceState)
        assertThat(posture).isEqualTo(DEVICE_POSTURE_CLOSED)
    }

    @Test
    fun baseStateChanges_doesNotUpdatePosture() {
        var numPostureChanges = 0
        underTest.addCallback { numPostureChanges++ }

        deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED)
        assertThat(numPostureChanges).isEqualTo(1)

        // base state changes doesn't send another posture update since the device state isn't
        // useBaseStateDeviceState
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_CLOSED)
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_HALF_OPENED)
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_FLIPPED)
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_OPENED)
        deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_UNKNOWN)
        assertThat(numPostureChanges).isEqualTo(1)
    }

    private fun verifyRegistersForDeviceStateCallback() {
        verify(deviceStateManager).registerCallback(eq(mainExecutor), deviceStateCallback.capture())
    }
}