Merge "Trigger unfold animation without treshold while on keyguard" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c3f30502f8
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user