Merge "Start fold animation only when the large screen is visible" into tm-qpr-dev am: d96b67dacb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22168635 Change-Id: I8b3ec638dabea6edd835c698ef2693b831276fdc Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.systemui.unfold.updates
|
package com.android.systemui.unfold.updates
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.content.res.Resources
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import androidx.core.util.Consumer
|
import androidx.core.util.Consumer
|
||||||
@@ -33,6 +36,7 @@ import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenLis
|
|||||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.capture
|
import com.android.systemui.util.mockito.capture
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -49,20 +53,19 @@ import org.mockito.MockitoAnnotations
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
class DeviceFoldStateProviderTest : SysuiTestCase() {
|
class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||||
|
|
||||||
@Mock
|
@Mock private lateinit var activityTypeProvider: ActivityManagerActivityTypeProvider
|
||||||
private lateinit var activityTypeProvider: ActivityManagerActivityTypeProvider
|
|
||||||
|
|
||||||
@Mock
|
@Mock private lateinit var handler: Handler
|
||||||
private lateinit var handler: Handler
|
|
||||||
|
|
||||||
@Mock
|
@Mock private lateinit var rotationChangeProvider: RotationChangeProvider
|
||||||
private lateinit var rotationChangeProvider: RotationChangeProvider
|
|
||||||
|
|
||||||
@Mock
|
@Mock private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider
|
||||||
private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider
|
|
||||||
|
|
||||||
@Captor
|
@Mock private lateinit var resources: Resources
|
||||||
private lateinit var rotationListener: ArgumentCaptor<RotationListener>
|
|
||||||
|
@Mock private lateinit var context: Context
|
||||||
|
|
||||||
|
@Captor private lateinit var rotationListener: ArgumentCaptor<RotationListener>
|
||||||
|
|
||||||
private val foldProvider = TestFoldProvider()
|
private val foldProvider = TestFoldProvider()
|
||||||
private val screenOnStatusProvider = TestScreenOnStatusProvider()
|
private val screenOnStatusProvider = TestScreenOnStatusProvider()
|
||||||
@@ -81,10 +84,13 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
val config = object : UnfoldTransitionConfig by ResourceUnfoldTransitionConfig() {
|
val config =
|
||||||
|
object : UnfoldTransitionConfig by ResourceUnfoldTransitionConfig() {
|
||||||
override val halfFoldedTimeoutMillis: Int
|
override val halfFoldedTimeoutMillis: Int
|
||||||
get() = HALF_OPENED_TIMEOUT_MILLIS.toInt()
|
get() = HALF_OPENED_TIMEOUT_MILLIS.toInt()
|
||||||
}
|
}
|
||||||
|
whenever(context.resources).thenReturn(resources)
|
||||||
|
whenever(context.mainExecutor).thenReturn(mContext.mainExecutor)
|
||||||
|
|
||||||
foldStateProvider =
|
foldStateProvider =
|
||||||
DeviceFoldStateProvider(
|
DeviceFoldStateProvider(
|
||||||
@@ -95,6 +101,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
activityTypeProvider,
|
activityTypeProvider,
|
||||||
unfoldKeyguardVisibilityProvider,
|
unfoldKeyguardVisibilityProvider,
|
||||||
rotationChangeProvider,
|
rotationChangeProvider,
|
||||||
|
context,
|
||||||
context.mainExecutor,
|
context.mainExecutor,
|
||||||
handler
|
handler
|
||||||
)
|
)
|
||||||
@@ -112,7 +119,8 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
override fun onUnfoldedScreenAvailable() {
|
override fun onUnfoldedScreenAvailable() {
|
||||||
unfoldedScreenAvailabilityUpdates.add(Unit)
|
unfoldedScreenAvailabilityUpdates.add(Unit)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
foldStateProvider.start()
|
foldStateProvider.start()
|
||||||
|
|
||||||
verify(rotationChangeProvider).addCallback(capture(rotationListener))
|
verify(rotationChangeProvider).addCallback(capture(rotationListener))
|
||||||
@@ -134,6 +142,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
|
|
||||||
// By default, we're on launcher.
|
// By default, we're on launcher.
|
||||||
setupForegroundActivityType(isHomeActivity = true)
|
setupForegroundActivityType(isHomeActivity = true)
|
||||||
|
setIsLargeScreen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -387,7 +396,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
|
|
||||||
sendHingeAngleEvent(
|
sendHingeAngleEvent(
|
||||||
START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
|
START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
|
||||||
HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
|
HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() -
|
||||||
|
1
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||||
}
|
}
|
||||||
@@ -430,7 +441,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
|
|
||||||
sendHingeAngleEvent(
|
sendHingeAngleEvent(
|
||||||
START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
|
START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
|
||||||
HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
|
HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() -
|
||||||
|
1
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||||
}
|
}
|
||||||
@@ -531,8 +544,8 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
|
|
||||||
rotationListener.value.onRotationChanged(1)
|
rotationListener.value.onRotationChanged(1)
|
||||||
|
|
||||||
assertThat(foldUpdates).containsExactly(
|
assertThat(foldUpdates)
|
||||||
FOLD_UPDATE_START_OPENING, FOLD_UPDATE_FINISH_HALF_OPEN)
|
.containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_FINISH_HALF_OPEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -545,6 +558,45 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_FINISH_CLOSED)
|
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_FINISH_CLOSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onFolding_onSmallScreen_tansitionDoesNotStart() {
|
||||||
|
setIsLargeScreen(false)
|
||||||
|
|
||||||
|
setInitialHingeAngle(120)
|
||||||
|
sendHingeAngleEvent(110)
|
||||||
|
sendHingeAngleEvent(100)
|
||||||
|
|
||||||
|
assertThat(foldUpdates).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onFolding_onLargeScreen_tansitionStarts() {
|
||||||
|
setIsLargeScreen(true)
|
||||||
|
|
||||||
|
setInitialHingeAngle(120)
|
||||||
|
sendHingeAngleEvent(110)
|
||||||
|
sendHingeAngleEvent(100)
|
||||||
|
|
||||||
|
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onUnfold_onSmallScreen_emitsStartOpening() {
|
||||||
|
// the new display state might arrive later, so it shouldn't be used to decide to send the
|
||||||
|
// start opening event, but only for the closing.
|
||||||
|
setFoldState(folded = true)
|
||||||
|
setIsLargeScreen(false)
|
||||||
|
foldUpdates.clear()
|
||||||
|
|
||||||
|
setFoldState(folded = false)
|
||||||
|
screenOnStatusProvider.notifyScreenTurningOn()
|
||||||
|
sendHingeAngleEvent(10)
|
||||||
|
sendHingeAngleEvent(20)
|
||||||
|
screenOnStatusProvider.notifyScreenTurnedOn()
|
||||||
|
|
||||||
|
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupForegroundActivityType(isHomeActivity: Boolean?) {
|
private fun setupForegroundActivityType(isHomeActivity: Boolean?) {
|
||||||
whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
|
whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
|
||||||
}
|
}
|
||||||
@@ -566,6 +618,13 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
|||||||
foldProvider.notifyFolded(folded)
|
foldProvider.notifyFolded(folded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setIsLargeScreen(isLargeScreen: Boolean) {
|
||||||
|
val smallestScreenWidth = if (isLargeScreen) { 601 } else { 10 }
|
||||||
|
val configuration = Configuration()
|
||||||
|
configuration.smallestScreenWidthDp = smallestScreenWidth
|
||||||
|
whenever(resources.configuration).thenReturn(configuration)
|
||||||
|
}
|
||||||
|
|
||||||
private fun fireScreenOnEvent() {
|
private fun fireScreenOnEvent() {
|
||||||
screenOnStatusProvider.notifyScreenTurnedOn()
|
screenOnStatusProvider.notifyScreenTurnedOn()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,4 +53,4 @@ class ScreenSizeFoldProvider(private val context: Context) : FoldProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600
|
internal const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600
|
||||||
|
|||||||
@@ -15,12 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.unfold.updates
|
package com.android.systemui.unfold.updates
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Trace
|
import android.os.Trace
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.FloatRange
|
import androidx.annotation.FloatRange
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.core.util.Consumer
|
import androidx.core.util.Consumer
|
||||||
|
import com.android.systemui.unfold.compat.INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP
|
||||||
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
||||||
import com.android.systemui.unfold.dagger.UnfoldMain
|
import com.android.systemui.unfold.dagger.UnfoldMain
|
||||||
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
|
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
|
||||||
@@ -45,6 +47,7 @@ constructor(
|
|||||||
private val activityTypeProvider: CurrentActivityTypeProvider,
|
private val activityTypeProvider: CurrentActivityTypeProvider,
|
||||||
private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
|
private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
|
||||||
private val rotationChangeProvider: RotationChangeProvider,
|
private val rotationChangeProvider: RotationChangeProvider,
|
||||||
|
private val context: Context,
|
||||||
@UnfoldMain private val mainExecutor: Executor,
|
@UnfoldMain private val mainExecutor: Executor,
|
||||||
@UnfoldMain private val handler: Handler
|
@UnfoldMain private val handler: Handler
|
||||||
) : FoldStateProvider {
|
) : FoldStateProvider {
|
||||||
@@ -136,6 +139,7 @@ constructor(
|
|||||||
val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
|
val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
|
||||||
val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
|
val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
|
||||||
val screenAvailableEventSent = isUnfoldHandled
|
val screenAvailableEventSent = isUnfoldHandled
|
||||||
|
val isOnLargeScreen = isOnLargeScreen()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
|
angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
|
||||||
@@ -144,7 +148,9 @@ constructor(
|
|||||||
// angle range as closing threshold could overlap this range
|
// angle range as closing threshold could overlap this range
|
||||||
screenAvailableEventSent && // do not send transition event if we are still in the
|
screenAvailableEventSent && // do not send transition event if we are still in the
|
||||||
// process of turning on the inner display
|
// process of turning on the inner display
|
||||||
isClosingThresholdMet(angle) // hinge angle is below certain threshold.
|
isClosingThresholdMet(angle) && // hinge angle is below certain threshold.
|
||||||
|
isOnLargeScreen // Avoids sending closing event when on small screen.
|
||||||
|
// Start event is sent regardless due to hall sensor.
|
||||||
) {
|
) {
|
||||||
notifyFoldUpdate(transitionUpdate, lastHingeAngle)
|
notifyFoldUpdate(transitionUpdate, lastHingeAngle)
|
||||||
}
|
}
|
||||||
@@ -261,6 +267,11 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isOnLargeScreen(): Boolean {
|
||||||
|
return context.resources.configuration.smallestScreenWidthDp >
|
||||||
|
INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP
|
||||||
|
}
|
||||||
|
|
||||||
/** While the screen is off or the device is folded, hinge angle updates are not needed. */
|
/** While the screen is off or the device is folded, hinge angle updates are not needed. */
|
||||||
private fun updateHingeAngleProviderState() {
|
private fun updateHingeAngleProviderState() {
|
||||||
if (isScreenOn && !isFolded) {
|
if (isScreenOn && !isFolded) {
|
||||||
|
|||||||
Reference in New Issue
Block a user