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

Commit f6c8f5c9 authored by Joe Bolinger's avatar Joe Bolinger Committed by Android (Google) Code Review
Browse files

Merge "Replace FoldStateProvider with DeviceStateRepository." into main

parents d629395f 48d994f5
Loading
Loading
Loading
Loading
+16 −41
Original line number Diff line number Diff line
@@ -19,22 +19,15 @@ package com.android.systemui.biometrics.domain.interactor
import android.hardware.biometrics.AuthenticateOptions
import android.hardware.biometrics.IBiometricContextListener
import android.util.Log
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.display.data.repository.DeviceStateRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FoldStateProvider
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.catch
@@ -80,15 +73,11 @@ class LogContextInteractorImpl
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    private val foldProvider: FoldStateProvider,
    deviceStateRepository: DeviceStateRepository,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    udfpsOverlayInteractor: UdfpsOverlayInteractor,
) : LogContextInteractor {

    init {
        applicationScope.launch { foldProvider.start() }
    }

    override val displayState =
        keyguardTransitionInteractor.startedKeyguardTransitionStep.map {
            when (it.to) {
@@ -123,32 +112,21 @@ constructor(
            .distinctUntilChanged()

    override val foldState: Flow<Int> =
        conflatedCallbackFlow {
                val callback =
                    object : FoldStateProvider.FoldUpdatesListener {
                        override fun onHingeAngleUpdate(angle: Float) {}

                        override fun onFoldUpdate(@FoldStateProvider.FoldUpdate update: Int) {
                            val loggedState =
                                when (update) {
                                    FOLD_UPDATE_FINISH_HALF_OPEN ->
                                        IBiometricContextListener.FoldState.HALF_OPENED
                                    FOLD_UPDATE_FINISH_FULL_OPEN ->
        deviceStateRepository.state
            .map {
                when (it) {
                    DeviceStateRepository.DeviceState.UNFOLDED,
                    DeviceStateRepository.DeviceState.REAR_DISPLAY,
                    DeviceStateRepository.DeviceState.CONCURRENT_DISPLAY ->
                        IBiometricContextListener.FoldState.FULLY_OPENED
                                    FOLD_UPDATE_FINISH_CLOSED ->
                    DeviceStateRepository.DeviceState.FOLDED ->
                        IBiometricContextListener.FoldState.FULLY_CLOSED
                                    else -> null
                                }
                            if (loggedState != null) {
                                trySendWithFailureLogging(loggedState, TAG)
                            }
                        }
                    DeviceStateRepository.DeviceState.HALF_FOLDED ->
                        IBiometricContextListener.FoldState.HALF_OPENED
                    else -> IBiometricContextListener.FoldState.UNKNOWN
                }

                foldProvider.addCallback(callback)
                trySendWithFailureLogging(IBiometricContextListener.FoldState.UNKNOWN, TAG)
                awaitClose { foldProvider.removeCallback(callback) }
            }
            .distinctUntilChanged()
            .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)

    override fun addBiometricContextListener(listener: IBiometricContextListener): Job {
@@ -178,6 +156,3 @@ constructor(
        private const val TAG = "ContextRepositoryImpl"
    }
}

private val WakefulnessLifecycle.isAwake: Boolean
    get() = wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE
+44 −54
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.biometrics.domain.interactor

import android.hardware.biometrics.AuthenticateOptions
@@ -5,24 +21,19 @@ import android.hardware.biometrics.IBiometricContextListener
import android.hardware.biometrics.IBiometricContextListener.FoldState
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.DeviceStateRepository
import com.android.systemui.display.data.repository.fakeDeviceStateRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -30,8 +41,6 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit

@OptIn(ExperimentalCoroutinesApi::class)
@@ -41,31 +50,20 @@ class LogContextInteractorImplTest : SysuiTestCase() {

    @JvmField @Rule var mockitoRule = MockitoJUnit.rule()

    private val testScope = TestScope()

    @Mock private lateinit var foldProvider: FoldStateProvider
    @Mock private lateinit var authController: AuthController
    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor

    private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
    private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val deviceStateRepository = kosmos.fakeDeviceStateRepository
    private val udfpsOverlayInteractor = kosmos.udfpsOverlayInteractor
    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository

    private lateinit var interactor: LogContextInteractorImpl

    @Before
    fun setup() {
        keyguardTransitionRepository = FakeKeyguardTransitionRepository()
        udfpsOverlayInteractor =
            UdfpsOverlayInteractor(
                context,
                authController,
                selectedUserInteractor,
                testScope.backgroundScope,
            )
        interactor =
            LogContextInteractorImpl(
                testScope.backgroundScope,
                foldProvider,
                deviceStateRepository,
                KeyguardTransitionInteractorFactory.create(
                        repository = keyguardTransitionRepository,
                        scope = testScope.backgroundScope,
@@ -189,33 +187,31 @@ class LogContextInteractorImplTest : SysuiTestCase() {
    @Test
    fun foldStateChanges() =
        testScope.runTest {
            val foldState = collectLastValue(interactor.foldState)
            runCurrent()
            val listener = foldProvider.captureListener()
            val foldState by collectLastValue(interactor.foldState)

            deviceStateRepository.emit(DeviceStateRepository.DeviceState.HALF_FOLDED)
            assertThat(foldState).isEqualTo(FoldState.HALF_OPENED)

            listener.onFoldUpdate(FOLD_UPDATE_START_OPENING)
            assertThat(foldState()).isEqualTo(FoldState.UNKNOWN)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.CONCURRENT_DISPLAY)
            assertThat(foldState).isEqualTo(FoldState.FULLY_OPENED)

            listener.onFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
            assertThat(foldState()).isEqualTo(FoldState.HALF_OPENED)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.UNFOLDED)
            assertThat(foldState).isEqualTo(FoldState.FULLY_OPENED)

            listener.onFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
            assertThat(foldState()).isEqualTo(FoldState.FULLY_OPENED)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.FOLDED)
            assertThat(foldState).isEqualTo(FoldState.FULLY_CLOSED)

            listener.onFoldUpdate(FOLD_UPDATE_START_CLOSING)
            assertThat(foldState()).isEqualTo(FoldState.FULLY_OPENED)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.REAR_DISPLAY)
            assertThat(foldState).isEqualTo(FoldState.FULLY_OPENED)

            listener.onFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
            assertThat(foldState()).isEqualTo(FoldState.FULLY_CLOSED)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.UNKNOWN)
            assertThat(foldState).isEqualTo(FoldState.UNKNOWN)
        }

    @Test
    fun contextSubscriberChanges() =
        testScope.runTest {
            runCurrent()
            val foldListener = foldProvider.captureListener()
            foldListener.onFoldUpdate(FOLD_UPDATE_START_CLOSING)
            foldListener.onFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.FOLDED)
            keyguardTransitionRepository.startTransitionTo(KeyguardState.AOD)

            var folded: Int? = null
@@ -243,8 +239,7 @@ class LogContextInteractorImplTest : SysuiTestCase() {
            assertThat(displayState).isEqualTo(AuthenticateOptions.DISPLAY_STATE_AOD)
            assertThat(ignoreTouches).isFalse()

            foldListener.onFoldUpdate(FOLD_UPDATE_START_OPENING)
            foldListener.onFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.HALF_FOLDED)
            keyguardTransitionRepository.startTransitionTo(KeyguardState.LOCKSCREEN)
            runCurrent()

@@ -259,7 +254,7 @@ class LogContextInteractorImplTest : SysuiTestCase() {
            job.cancel()

            // stale updates should be ignored
            foldListener.onFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
            deviceStateRepository.emit(DeviceStateRepository.DeviceState.UNFOLDED)
            keyguardTransitionRepository.startTransitionTo(KeyguardState.AOD)
            runCurrent()

@@ -270,8 +265,3 @@ class LogContextInteractorImplTest : SysuiTestCase() {

private suspend fun FakeKeyguardTransitionRepository.startTransitionTo(newState: KeyguardState) =
    sendTransitionStep(TransitionStep(to = newState, transitionState = TransitionState.STARTED))

private fun FoldStateProvider.captureListener() =
    withArgCaptor<FoldStateProvider.FoldUpdatesListener> {
        verify(this@captureListener).addCallback(capture())
    }
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.display.data.repository

import com.android.systemui.kosmos.Kosmos

var Kosmos.deviceStateRepository: DeviceStateRepository by
    Kosmos.Fixture { fakeDeviceStateRepository }
val Kosmos.fakeDeviceStateRepository: FakeDeviceStateRepository by
    Kosmos.Fixture { FakeDeviceStateRepository() }