Merge "Trigger unfold animation without treshold while on keyguard" into tm-qpr-dev

This commit is contained in:
Nicolò Mazzucato
2022-12-29 13:39:58 +00:00
committed by Android (Google) Code Review
6 changed files with 169 additions and 4 deletions

View File

@@ -20,6 +20,7 @@ import com.android.keyguard.KeyguardUnfoldTransition
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shade.NotificationPanelUnfoldAnimationController import com.android.systemui.shade.NotificationPanelUnfoldAnimationController
import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.util.kotlin.getOrNull import com.android.systemui.util.kotlin.getOrNull
@@ -95,4 +96,6 @@ interface SysUIUnfoldComponent {
fun getUnfoldHapticsPlayer(): UnfoldHapticsPlayer fun getUnfoldHapticsPlayer(): UnfoldHapticsPlayer
fun getUnfoldLightRevealOverlayAnimation(): UnfoldLightRevealOverlayAnimation fun getUnfoldLightRevealOverlayAnimation(): UnfoldLightRevealOverlayAnimation
fun getUnfoldKeyguardVisibilityManager(): UnfoldKeyguardVisibilityManager
} }

View File

@@ -0,0 +1,39 @@
package com.android.systemui.unfold
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
import javax.inject.Inject
/**
* Used to set the keyguard visibility state to [UnfoldKeyguardVisibilityManager].
*
* It is not possible to directly inject a sysui class (e.g. [KeyguardStateController]) into
* [DeviceStateProvider], as it can't depend on google sysui directly. So,
* [UnfoldKeyguardVisibilityManager] is provided to clients, that can set the keyguard visibility
* accordingly.
*/
@SysUISingleton
class UnfoldKeyguardVisibilityListener
@Inject
constructor(
keyguardStateController: KeyguardStateController,
unfoldComponent: Optional<SysUIUnfoldComponent>,
) {
private val unfoldKeyguardVisibilityManager =
unfoldComponent.getOrNull()?.getUnfoldKeyguardVisibilityManager()
private val delegate = { keyguardStateController.isVisible }
fun init() {
unfoldKeyguardVisibilityManager?.setKeyguardVisibleDelegate(delegate).also {
Log.d(TAG, "setKeyguardVisibleDelegate set")
}
}
}
private const val TAG = "UnfoldKeyguardVisibilityListener"

View File

@@ -29,6 +29,7 @@ import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListen
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
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.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
@@ -56,6 +57,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Mock @Mock
private lateinit var rotationChangeProvider: RotationChangeProvider private lateinit var rotationChangeProvider: RotationChangeProvider
@Mock
private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider
@Captor @Captor
private lateinit var rotationListener: ArgumentCaptor<RotationListener> private lateinit var rotationListener: ArgumentCaptor<RotationListener>
@@ -87,6 +91,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
screenOnStatusProvider, screenOnStatusProvider,
foldProvider, foldProvider,
activityTypeProvider, activityTypeProvider,
unfoldKeyguardVisibilityProvider,
rotationChangeProvider, rotationChangeProvider,
context.mainExecutor, context.mainExecutor,
handler handler
@@ -379,6 +384,47 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING) assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
} }
@Test
fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
setKeyguardVisibility(visible = false)
setupForegroundActivityType(isHomeActivity = false)
sendHingeAngleEvent(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
assertThat(foldUpdates).isEmpty()
}
@Test
fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
setKeyguardVisibility(visible = null)
sendHingeAngleEvent(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@Test
fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
setKeyguardVisibility(visible = true)
sendHingeAngleEvent(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@Test
fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
setKeyguardVisibility(visible = false)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@Test @Test
fun screenOff_whileFolded_hingeAngleProviderRemainsOff() { fun screenOff_whileFolded_hingeAngleProviderRemainsOff() {
setFoldState(folded = true) setFoldState(folded = true)
@@ -445,6 +491,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity) whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
} }
private fun setKeyguardVisibility(visible: Boolean?) {
whenever(unfoldKeyguardVisibilityProvider.isKeyguardVisible).thenReturn(visible)
}
private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) { private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.") val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.")
if (waitTime >= runnableDelay) { if (waitTime >= runnableDelay) {

View File

@@ -28,6 +28,9 @@ import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener
import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManagerImpl
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import java.util.Optional import java.util.Optional
@@ -57,7 +60,8 @@ class UnfoldSharedModule {
scaleAwareProviderFactory.wrap(baseProgressProvider).apply { scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
// Always present callback that logs animation beginning and end. // Always present callback that logs animation beginning and end.
addCallback(tracingListener) addCallback(tracingListener)
}) }
)
} }
@Provides @Provides
@@ -77,4 +81,16 @@ class UnfoldSharedModule {
} else { } else {
EmptyHingeAngleProvider EmptyHingeAngleProvider
} }
@Provides
@Singleton
fun unfoldKeyguardVisibilityProvider(
impl: UnfoldKeyguardVisibilityManagerImpl
): UnfoldKeyguardVisibilityProvider = impl
@Provides
@Singleton
fun unfoldKeyguardVisibilityManager(
impl: UnfoldKeyguardVisibilityManagerImpl
): UnfoldKeyguardVisibilityManager = impl
} }

View File

@@ -31,6 +31,7 @@ import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.util.CurrentActivityTypeProvider import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
import java.util.concurrent.Executor import java.util.concurrent.Executor
import javax.inject.Inject import javax.inject.Inject
@@ -42,6 +43,7 @@ constructor(
private val screenStatusProvider: ScreenStatusProvider, private val screenStatusProvider: ScreenStatusProvider,
private val foldProvider: FoldProvider, private val foldProvider: FoldProvider,
private val activityTypeProvider: CurrentActivityTypeProvider, private val activityTypeProvider: CurrentActivityTypeProvider,
private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
private val rotationChangeProvider: RotationChangeProvider, private val rotationChangeProvider: RotationChangeProvider,
@UnfoldMain private val mainExecutor: Executor, @UnfoldMain private val mainExecutor: Executor,
@UnfoldMain private val handler: Handler @UnfoldMain private val handler: Handler
@@ -152,12 +154,13 @@ constructor(
*/ */
private fun getClosingThreshold(): Int? { private fun getClosingThreshold(): Int? {
val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null
val isKeyguardVisible = unfoldKeyguardVisibilityProvider.isKeyguardVisible == true
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "isHomeActivity=$isHomeActivity") Log.d(TAG, "isHomeActivity=$isHomeActivity, isOnKeyguard=$isKeyguardVisible")
} }
return if (isHomeActivity) { return if (isHomeActivity || isKeyguardVisible) {
null null
} else { } else {
START_CLOSING_ON_APPS_THRESHOLD_DEGREES START_CLOSING_ON_APPS_THRESHOLD_DEGREES
@@ -257,7 +260,7 @@ fun @receiver:FoldUpdate Int.name() =
} }
private const val TAG = "DeviceFoldProvider" private const val TAG = "DeviceFoldProvider"
private const val DEBUG = false private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
/** Threshold after which we consider the device fully unfolded. */ /** Threshold after which we consider the device fully unfolded. */
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f @VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2022 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.unfold.util
import java.lang.ref.WeakReference
import javax.inject.Inject
import javax.inject.Singleton
interface UnfoldKeyguardVisibilityProvider {
/**
* True when the keyguard is visible.
*
* Might be [null] when it is not known.
*/
val isKeyguardVisible: Boolean?
}
/** Used to notify keyguard visibility. */
interface UnfoldKeyguardVisibilityManager {
/** Sets the delegate. [delegate] should return true when the keyguard is visible. */
fun setKeyguardVisibleDelegate(delegate: () -> Boolean)
}
/**
* Keeps a [WeakReference] for the keyguard visibility provider.
*
* It is a weak reference because this is in the global scope, while the delegate might be set from
* another subcomponent (that might have shorter lifespan).
*/
@Singleton
class UnfoldKeyguardVisibilityManagerImpl @Inject constructor() :
UnfoldKeyguardVisibilityProvider, UnfoldKeyguardVisibilityManager {
private var delegatedProvider: WeakReference<() -> Boolean?>? = null
override fun setKeyguardVisibleDelegate(delegate: () -> Boolean) {
delegatedProvider = WeakReference(delegate)
}
override val isKeyguardVisible: Boolean?
get() = delegatedProvider?.get()?.invoke()
}