Loading packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryImplTest.kt +67 −5 Original line number Diff line number Diff line Loading @@ -14,8 +14,10 @@ * limitations under the License. */ package com.android.systemui.keyguard.data.repository package com.android.systemui.biometrics.data.repository import android.content.res.Configuration import android.util.DisplayMetrics import android.util.Size import android.view.Display import android.view.Display.DEFAULT_DISPLAY Loading @@ -24,8 +26,6 @@ import android.view.Surface import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.DisplayStateRepository import com.android.systemui.biometrics.data.repository.DisplayStateRepositoryImpl import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.coroutines.collectLastValue import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState Loading @@ -35,6 +35,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent Loading @@ -44,13 +45,15 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class DisplayStateRepositoryTest : SysuiTestCase() { class DisplayStateRepositoryImplTest : SysuiTestCase() { private val display = mock<Display>() private val testScope = TestScope(StandardTestDispatcher()) private val fakeDeviceStateRepository = FakeDeviceStateRepository() private val fakeDisplayRepository = FakeDisplayRepository() private val configuration = Configuration() private lateinit var underTest: DisplayStateRepository Loading @@ -58,11 +61,16 @@ class DisplayStateRepositoryTest : SysuiTestCase() { fun setUp() { mContext.orCreateTestableResources.addOverride( com.android.internal.R.bool.config_reverseDefaultRotation, false false, ) // Set densityDpi such that pixels and DP are the same; Makes it easier to read and write // tests. configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT mContext = spy(mContext) whenever(mContext.display).thenReturn(display) whenever(mContext.resources.configuration).thenReturn(configuration) underTest = DisplayStateRepositoryImpl( Loading Loading @@ -137,4 +145,58 @@ class DisplayStateRepositoryTest : SysuiTestCase() { fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(currentSize).isEqualTo(Size(200, 100)) } @Test fun updatesIsLargeScreen_whenDisplayStateChanges() = testScope.runTest { val isLargeScreen by collectLastValue(underTest.isLargeScreen) runCurrent() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 100 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isLargeScreen).isFalse() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 800 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isLargeScreen).isTrue() } @Test fun updatesIsWideScreen_whenDisplayStateChanges() = testScope.runTest { val isWideScreen by collectLastValue(underTest.isWideScreen) runCurrent() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 200 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isWideScreen).isFalse() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_90 info.logicalWidth = 700 info.logicalHeight = 200 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isWideScreen).isTrue() } } packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt +11 −8 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import com.android.systemui.biometrics.domain.interactor.displayStateInteractor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractorImpl import com.android.systemui.coroutines.collectLastValue import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.dump.DumpManager import com.android.systemui.kosmos.testCase import com.android.systemui.kosmos.testDispatcher Loading @@ -37,7 +36,9 @@ import com.android.systemui.qs.QSImpl import com.android.systemui.qs.dagger.QSComponent import com.android.systemui.qs.dagger.QSSceneComponent import com.android.systemui.settings.brightness.MirrorController import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.domain.interactor.enableDualShade import com.android.systemui.shade.domain.interactor.enableSingleShade import com.android.systemui.shade.domain.interactor.enableSplitShade import com.android.systemui.shade.domain.interactor.shadeModeInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading @@ -50,6 +51,7 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import java.util.Locale import javax.inject.Provider import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test Loading @@ -61,6 +63,7 @@ import org.mockito.Mockito.inOrder import org.mockito.Mockito.never import org.mockito.Mockito.verify @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class QSSceneAdapterImplTest : SysuiTestCase() { Loading Loading @@ -550,16 +553,17 @@ class QSSceneAdapterImplTest : SysuiTestCase() { @Test fun dispatchSplitShade() = testScope.runTest { val shadeRepository = kosmos.fakeShadeRepository shadeRepository.setShadeLayoutWide(false) val qsImpl by collectLastValue(underTest.qsImpl) kosmos.enableSingleShade() runCurrent() underTest.inflate(context) runCurrent() verify(qsImpl!!).setInSplitShade(false) shadeRepository.setShadeLayoutWide(true) kosmos.enableSplitShade() runCurrent() verify(qsImpl!!).setInSplitShade(true) } Loading @@ -581,11 +585,10 @@ class QSSceneAdapterImplTest : SysuiTestCase() { testScope.runTest { val qsImpl by collectLastValue(underTest.qsImpl) underTest.inflate(context) kosmos.enableDualShade(wideLayout = true) runCurrent() kosmos.displayStateRepository.setIsLargeScreen(true) runCurrent() underTest.inflate(context) verify(qsImpl!!).setIsNotificationPanelFullWidth(false) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -214,7 +214,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() { testScope.runTest { underTest.start() kosmos.displayStateRepository.setIsLargeScreen(true) kosmos.displayStateRepository.setIsWideScreen(true) runCurrent() verify(kosmos.notificationStackScrollLayoutController).setIsFullWidth(false) assertThat(kosmos.scrimController.clipQsScrim).isFalse() Loading packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt +40 −34 Original line number Diff line number Diff line Loading @@ -56,8 +56,19 @@ interface DisplayStateRepository { /** Provides the current display size */ val currentDisplaySize: StateFlow<Size> /** Provides whether the current display is large screen */ /** * Provides whether the current display is a large screen (i.e. all edges are >= 600dp). This is * agnostic of display rotation. */ val isLargeScreen: StateFlow<Boolean> /** * Provides whether the display's current horizontal width is large (>= 600dp). * * Note that unlike [isLargeScreen], which checks whether either one of the screen's width or * height is large, this flow's state is sensitive to the current display's orientation. */ val isWideScreen: StateFlow<Boolean> } @SysUISingleton Loading @@ -75,17 +86,7 @@ constructor( override val isInRearDisplayMode: StateFlow<Boolean> = deviceStateRepository.state .map { it == REAR_DISPLAY } .stateIn( backgroundScope, started = SharingStarted.Eagerly, initialValue = false, ) private fun getDisplayInfo(): DisplayInfo { val cachedDisplayInfo = DisplayInfo() context.display?.getDisplayInfo(cachedDisplayInfo) return cachedDisplayInfo } .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) private val currentDisplayInfo: StateFlow<DisplayInfo> = displayRepository.displayChangeEvent Loading @@ -96,21 +97,13 @@ constructor( initialValue = getDisplayInfo(), ) private fun rotationToDisplayRotation(rotation: Int): DisplayRotation { var adjustedRotation = rotation if (isReverseDefaultRotation) { adjustedRotation = (rotation + 1) % 4 } return adjustedRotation.toDisplayRotation() } override val currentRotation: StateFlow<DisplayRotation> = currentDisplayInfo .map { rotationToDisplayRotation(it.rotation) } .stateIn( backgroundScope, started = SharingStarted.WhileSubscribed(), initialValue = rotationToDisplayRotation(currentDisplayInfo.value.rotation) initialValue = rotationToDisplayRotation(currentDisplayInfo.value.rotation), ) override val currentDisplaySize: StateFlow<Size> = Loading @@ -122,7 +115,7 @@ constructor( initialValue = Size( currentDisplayInfo.value.naturalWidth, currentDisplayInfo.value.naturalHeight currentDisplayInfo.value.naturalHeight, ), ) Loading @@ -130,22 +123,35 @@ constructor( currentDisplayInfo .map { // copied from systemui/shared/...Utilities.java val smallestWidth = dpiFromPx( min(it.logicalWidth, it.logicalHeight).toFloat(), context.resources.configuration.densityDpi ) val smallestWidth = min(it.logicalWidth, it.logicalHeight).toDpi() smallestWidth >= LARGE_SCREEN_MIN_DPS } .stateIn( backgroundScope, started = SharingStarted.Eagerly, initialValue = false, ) .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) override val isWideScreen: StateFlow<Boolean> = currentDisplayInfo .map { it.logicalWidth.toDpi() >= LARGE_SCREEN_MIN_DPS } .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) private fun getDisplayInfo(): DisplayInfo { val cachedDisplayInfo = DisplayInfo() context.display.getDisplayInfo(cachedDisplayInfo) return cachedDisplayInfo } private fun rotationToDisplayRotation(rotation: Int): DisplayRotation { return if (isReverseDefaultRotation) { (rotation + 1) % 4 } else { rotation } .toDisplayRotation() } private fun dpiFromPx(size: Float, densityDpi: Int): Float { private fun Int.toDpi(): Float { val densityDpi = context.resources.configuration.densityDpi val densityRatio = densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT return size / densityRatio return this / densityRatio } companion object { Loading packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt +26 −16 Original line number Diff line number Diff line Loading @@ -21,12 +21,12 @@ import android.content.res.Configuration import com.android.systemui.biometrics.data.repository.DisplayStateRepository import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.unfold.compat.ScreenSizeFoldProvider import com.android.systemui.unfold.updates.FoldProvider import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope Loading @@ -37,6 +37,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn /** Aggregates display state information. */ // TODO(b/411335091): Move to com.android.systemui.display.domain.interactor. interface DisplayStateInteractor { /** Whether the default display is currently off. */ val isDefaultDisplayOff: Flow<Boolean> Loading Loading @@ -65,8 +66,19 @@ interface DisplayStateInteractor { /** Called on configuration changes, used to keep the display state in sync */ fun onConfigurationChanged(newConfig: Configuration) /** Provides whether the current display is large screen */ /** * Provides whether the current display is a large screen (i.e. all edges are >= 600dp). This is * agnostic of display rotation. */ val isLargeScreen: StateFlow<Boolean> /** * Provides whether the display's current horizontal width is large (>= 600dp). * * Note: Unlike [isLargeScreen], which checks whether either one of the screen's width or height * is large, this flow's state is sensitive to the current display's rotation. */ val isWideScreen: StateFlow<Boolean> } /** Encapsulates logic for interacting with the display state. */ Loading @@ -81,10 +93,6 @@ constructor( ) : DisplayStateInteractor { private var screenSizeFoldProvider: ScreenSizeFoldProvider = ScreenSizeFoldProvider(context) fun setScreenSizeFoldProvider(foldProvider: ScreenSizeFoldProvider) { screenSizeFoldProvider = foldProvider } override val displayChanges = displayRepository.displayChangeEvent override val isFolded: Flow<Boolean> = Loading @@ -93,7 +101,7 @@ constructor( trySendWithFailureLogging( state, TAG, "Error sending fold state update to $state" "Error sending fold state update to $state", ) } Loading @@ -108,11 +116,7 @@ constructor( screenSizeFoldProvider.registerCallback(callback, mainExecutor) awaitClose { screenSizeFoldProvider.unregisterCallback(callback) } } .stateIn( applicationScope, started = SharingStarted.Eagerly, initialValue = false, ) .stateIn(applicationScope, started = SharingStarted.Eagerly, initialValue = false) override val isInRearDisplayMode: StateFlow<Boolean> = displayStateRepository.isInRearDisplayMode Loading @@ -122,14 +126,20 @@ constructor( override val isReverseDefaultRotation: Boolean = displayStateRepository.isReverseDefaultRotation override fun onConfigurationChanged(newConfig: Configuration) { screenSizeFoldProvider.onConfigurationChange(newConfig) } override val isDefaultDisplayOff = displayRepository.defaultDisplayOff override val isLargeScreen: StateFlow<Boolean> = displayStateRepository.isLargeScreen override val isWideScreen: StateFlow<Boolean> = displayStateRepository.isWideScreen fun setScreenSizeFoldProvider(foldProvider: ScreenSizeFoldProvider) { screenSizeFoldProvider = foldProvider } override fun onConfigurationChanged(newConfig: Configuration) { screenSizeFoldProvider.onConfigurationChange(newConfig) } companion object { private const val TAG = "DisplayStateInteractor" } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryImplTest.kt +67 −5 Original line number Diff line number Diff line Loading @@ -14,8 +14,10 @@ * limitations under the License. */ package com.android.systemui.keyguard.data.repository package com.android.systemui.biometrics.data.repository import android.content.res.Configuration import android.util.DisplayMetrics import android.util.Size import android.view.Display import android.view.Display.DEFAULT_DISPLAY Loading @@ -24,8 +26,6 @@ import android.view.Surface import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.DisplayStateRepository import com.android.systemui.biometrics.data.repository.DisplayStateRepositoryImpl import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.coroutines.collectLastValue import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState Loading @@ -35,6 +35,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent Loading @@ -44,13 +45,15 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class DisplayStateRepositoryTest : SysuiTestCase() { class DisplayStateRepositoryImplTest : SysuiTestCase() { private val display = mock<Display>() private val testScope = TestScope(StandardTestDispatcher()) private val fakeDeviceStateRepository = FakeDeviceStateRepository() private val fakeDisplayRepository = FakeDisplayRepository() private val configuration = Configuration() private lateinit var underTest: DisplayStateRepository Loading @@ -58,11 +61,16 @@ class DisplayStateRepositoryTest : SysuiTestCase() { fun setUp() { mContext.orCreateTestableResources.addOverride( com.android.internal.R.bool.config_reverseDefaultRotation, false false, ) // Set densityDpi such that pixels and DP are the same; Makes it easier to read and write // tests. configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT mContext = spy(mContext) whenever(mContext.display).thenReturn(display) whenever(mContext.resources.configuration).thenReturn(configuration) underTest = DisplayStateRepositoryImpl( Loading Loading @@ -137,4 +145,58 @@ class DisplayStateRepositoryTest : SysuiTestCase() { fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(currentSize).isEqualTo(Size(200, 100)) } @Test fun updatesIsLargeScreen_whenDisplayStateChanges() = testScope.runTest { val isLargeScreen by collectLastValue(underTest.isLargeScreen) runCurrent() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 100 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isLargeScreen).isFalse() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 800 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isLargeScreen).isTrue() } @Test fun updatesIsWideScreen_whenDisplayStateChanges() = testScope.runTest { val isWideScreen by collectLastValue(underTest.isWideScreen) runCurrent() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_0 info.logicalWidth = 200 info.logicalHeight = 700 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isWideScreen).isFalse() whenever(display.getDisplayInfo(any())).then { val info = it.getArgument<DisplayInfo>(0) info.rotation = Surface.ROTATION_90 info.logicalWidth = 700 info.logicalHeight = 200 return@then true } fakeDisplayRepository.emitDisplayChangeEvent(DEFAULT_DISPLAY) assertThat(isWideScreen).isTrue() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt +11 −8 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import com.android.systemui.biometrics.domain.interactor.displayStateInteractor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractorImpl import com.android.systemui.coroutines.collectLastValue import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.dump.DumpManager import com.android.systemui.kosmos.testCase import com.android.systemui.kosmos.testDispatcher Loading @@ -37,7 +36,9 @@ import com.android.systemui.qs.QSImpl import com.android.systemui.qs.dagger.QSComponent import com.android.systemui.qs.dagger.QSSceneComponent import com.android.systemui.settings.brightness.MirrorController import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.domain.interactor.enableDualShade import com.android.systemui.shade.domain.interactor.enableSingleShade import com.android.systemui.shade.domain.interactor.enableSplitShade import com.android.systemui.shade.domain.interactor.shadeModeInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading @@ -50,6 +51,7 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import java.util.Locale import javax.inject.Provider import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test Loading @@ -61,6 +63,7 @@ import org.mockito.Mockito.inOrder import org.mockito.Mockito.never import org.mockito.Mockito.verify @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class QSSceneAdapterImplTest : SysuiTestCase() { Loading Loading @@ -550,16 +553,17 @@ class QSSceneAdapterImplTest : SysuiTestCase() { @Test fun dispatchSplitShade() = testScope.runTest { val shadeRepository = kosmos.fakeShadeRepository shadeRepository.setShadeLayoutWide(false) val qsImpl by collectLastValue(underTest.qsImpl) kosmos.enableSingleShade() runCurrent() underTest.inflate(context) runCurrent() verify(qsImpl!!).setInSplitShade(false) shadeRepository.setShadeLayoutWide(true) kosmos.enableSplitShade() runCurrent() verify(qsImpl!!).setInSplitShade(true) } Loading @@ -581,11 +585,10 @@ class QSSceneAdapterImplTest : SysuiTestCase() { testScope.runTest { val qsImpl by collectLastValue(underTest.qsImpl) underTest.inflate(context) kosmos.enableDualShade(wideLayout = true) runCurrent() kosmos.displayStateRepository.setIsLargeScreen(true) runCurrent() underTest.inflate(context) verify(qsImpl!!).setIsNotificationPanelFullWidth(false) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -214,7 +214,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() { testScope.runTest { underTest.start() kosmos.displayStateRepository.setIsLargeScreen(true) kosmos.displayStateRepository.setIsWideScreen(true) runCurrent() verify(kosmos.notificationStackScrollLayoutController).setIsFullWidth(false) assertThat(kosmos.scrimController.clipQsScrim).isFalse() Loading
packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt +40 −34 Original line number Diff line number Diff line Loading @@ -56,8 +56,19 @@ interface DisplayStateRepository { /** Provides the current display size */ val currentDisplaySize: StateFlow<Size> /** Provides whether the current display is large screen */ /** * Provides whether the current display is a large screen (i.e. all edges are >= 600dp). This is * agnostic of display rotation. */ val isLargeScreen: StateFlow<Boolean> /** * Provides whether the display's current horizontal width is large (>= 600dp). * * Note that unlike [isLargeScreen], which checks whether either one of the screen's width or * height is large, this flow's state is sensitive to the current display's orientation. */ val isWideScreen: StateFlow<Boolean> } @SysUISingleton Loading @@ -75,17 +86,7 @@ constructor( override val isInRearDisplayMode: StateFlow<Boolean> = deviceStateRepository.state .map { it == REAR_DISPLAY } .stateIn( backgroundScope, started = SharingStarted.Eagerly, initialValue = false, ) private fun getDisplayInfo(): DisplayInfo { val cachedDisplayInfo = DisplayInfo() context.display?.getDisplayInfo(cachedDisplayInfo) return cachedDisplayInfo } .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) private val currentDisplayInfo: StateFlow<DisplayInfo> = displayRepository.displayChangeEvent Loading @@ -96,21 +97,13 @@ constructor( initialValue = getDisplayInfo(), ) private fun rotationToDisplayRotation(rotation: Int): DisplayRotation { var adjustedRotation = rotation if (isReverseDefaultRotation) { adjustedRotation = (rotation + 1) % 4 } return adjustedRotation.toDisplayRotation() } override val currentRotation: StateFlow<DisplayRotation> = currentDisplayInfo .map { rotationToDisplayRotation(it.rotation) } .stateIn( backgroundScope, started = SharingStarted.WhileSubscribed(), initialValue = rotationToDisplayRotation(currentDisplayInfo.value.rotation) initialValue = rotationToDisplayRotation(currentDisplayInfo.value.rotation), ) override val currentDisplaySize: StateFlow<Size> = Loading @@ -122,7 +115,7 @@ constructor( initialValue = Size( currentDisplayInfo.value.naturalWidth, currentDisplayInfo.value.naturalHeight currentDisplayInfo.value.naturalHeight, ), ) Loading @@ -130,22 +123,35 @@ constructor( currentDisplayInfo .map { // copied from systemui/shared/...Utilities.java val smallestWidth = dpiFromPx( min(it.logicalWidth, it.logicalHeight).toFloat(), context.resources.configuration.densityDpi ) val smallestWidth = min(it.logicalWidth, it.logicalHeight).toDpi() smallestWidth >= LARGE_SCREEN_MIN_DPS } .stateIn( backgroundScope, started = SharingStarted.Eagerly, initialValue = false, ) .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) override val isWideScreen: StateFlow<Boolean> = currentDisplayInfo .map { it.logicalWidth.toDpi() >= LARGE_SCREEN_MIN_DPS } .stateIn(backgroundScope, started = SharingStarted.Eagerly, initialValue = false) private fun getDisplayInfo(): DisplayInfo { val cachedDisplayInfo = DisplayInfo() context.display.getDisplayInfo(cachedDisplayInfo) return cachedDisplayInfo } private fun rotationToDisplayRotation(rotation: Int): DisplayRotation { return if (isReverseDefaultRotation) { (rotation + 1) % 4 } else { rotation } .toDisplayRotation() } private fun dpiFromPx(size: Float, densityDpi: Int): Float { private fun Int.toDpi(): Float { val densityDpi = context.resources.configuration.densityDpi val densityRatio = densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT return size / densityRatio return this / densityRatio } companion object { Loading
packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt +26 −16 Original line number Diff line number Diff line Loading @@ -21,12 +21,12 @@ import android.content.res.Configuration import com.android.systemui.biometrics.data.repository.DisplayStateRepository import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.unfold.compat.ScreenSizeFoldProvider import com.android.systemui.unfold.updates.FoldProvider import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope Loading @@ -37,6 +37,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn /** Aggregates display state information. */ // TODO(b/411335091): Move to com.android.systemui.display.domain.interactor. interface DisplayStateInteractor { /** Whether the default display is currently off. */ val isDefaultDisplayOff: Flow<Boolean> Loading Loading @@ -65,8 +66,19 @@ interface DisplayStateInteractor { /** Called on configuration changes, used to keep the display state in sync */ fun onConfigurationChanged(newConfig: Configuration) /** Provides whether the current display is large screen */ /** * Provides whether the current display is a large screen (i.e. all edges are >= 600dp). This is * agnostic of display rotation. */ val isLargeScreen: StateFlow<Boolean> /** * Provides whether the display's current horizontal width is large (>= 600dp). * * Note: Unlike [isLargeScreen], which checks whether either one of the screen's width or height * is large, this flow's state is sensitive to the current display's rotation. */ val isWideScreen: StateFlow<Boolean> } /** Encapsulates logic for interacting with the display state. */ Loading @@ -81,10 +93,6 @@ constructor( ) : DisplayStateInteractor { private var screenSizeFoldProvider: ScreenSizeFoldProvider = ScreenSizeFoldProvider(context) fun setScreenSizeFoldProvider(foldProvider: ScreenSizeFoldProvider) { screenSizeFoldProvider = foldProvider } override val displayChanges = displayRepository.displayChangeEvent override val isFolded: Flow<Boolean> = Loading @@ -93,7 +101,7 @@ constructor( trySendWithFailureLogging( state, TAG, "Error sending fold state update to $state" "Error sending fold state update to $state", ) } Loading @@ -108,11 +116,7 @@ constructor( screenSizeFoldProvider.registerCallback(callback, mainExecutor) awaitClose { screenSizeFoldProvider.unregisterCallback(callback) } } .stateIn( applicationScope, started = SharingStarted.Eagerly, initialValue = false, ) .stateIn(applicationScope, started = SharingStarted.Eagerly, initialValue = false) override val isInRearDisplayMode: StateFlow<Boolean> = displayStateRepository.isInRearDisplayMode Loading @@ -122,14 +126,20 @@ constructor( override val isReverseDefaultRotation: Boolean = displayStateRepository.isReverseDefaultRotation override fun onConfigurationChanged(newConfig: Configuration) { screenSizeFoldProvider.onConfigurationChange(newConfig) } override val isDefaultDisplayOff = displayRepository.defaultDisplayOff override val isLargeScreen: StateFlow<Boolean> = displayStateRepository.isLargeScreen override val isWideScreen: StateFlow<Boolean> = displayStateRepository.isWideScreen fun setScreenSizeFoldProvider(foldProvider: ScreenSizeFoldProvider) { screenSizeFoldProvider = foldProvider } override fun onConfigurationChanged(newConfig: Configuration) { screenSizeFoldProvider.onConfigurationChange(newConfig) } companion object { private const val TAG = "DisplayStateInteractor" } Loading