Merge "Trigger unfold animation without treshold while on keyguard" into tm-qpr-dev am: c3f30502f8
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20814450 Change-Id: Idc2429dd81f74528561cc749ef09d4838f412d0a Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import com.android.keyguard.KeyguardUnfoldTransition
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.shade.NotificationPanelUnfoldAnimationController
|
||||
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.ScopedUnfoldTransitionProgressProvider
|
||||
import com.android.systemui.util.kotlin.getOrNull
|
||||
@@ -95,4 +96,6 @@ interface SysUIUnfoldComponent {
|
||||
fun getUnfoldHapticsPlayer(): UnfoldHapticsPlayer
|
||||
|
||||
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.screen.ScreenStatusProvider
|
||||
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.capture
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
@@ -56,6 +57,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var rotationChangeProvider: RotationChangeProvider
|
||||
|
||||
@Mock
|
||||
private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider
|
||||
|
||||
@Captor
|
||||
private lateinit var rotationListener: ArgumentCaptor<RotationListener>
|
||||
|
||||
@@ -87,6 +91,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
screenOnStatusProvider,
|
||||
foldProvider,
|
||||
activityTypeProvider,
|
||||
unfoldKeyguardVisibilityProvider,
|
||||
rotationChangeProvider,
|
||||
context.mainExecutor,
|
||||
handler
|
||||
@@ -379,6 +384,47 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
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
|
||||
fun screenOff_whileFolded_hingeAngleProviderRemainsOff() {
|
||||
setFoldState(folded = true)
|
||||
@@ -445,6 +491,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
|
||||
}
|
||||
|
||||
private fun setKeyguardVisibility(visible: Boolean?) {
|
||||
whenever(unfoldKeyguardVisibilityProvider.isKeyguardVisible).thenReturn(visible)
|
||||
}
|
||||
|
||||
private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
|
||||
val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.")
|
||||
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.util.ATraceLoggerTransitionProgressListener
|
||||
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.Provides
|
||||
import java.util.Optional
|
||||
@@ -57,7 +60,8 @@ class UnfoldSharedModule {
|
||||
scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
|
||||
// Always present callback that logs animation beginning and end.
|
||||
addCallback(tracingListener)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -77,4 +81,16 @@ class UnfoldSharedModule {
|
||||
} else {
|
||||
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.screen.ScreenStatusProvider
|
||||
import com.android.systemui.unfold.util.CurrentActivityTypeProvider
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -42,6 +43,7 @@ constructor(
|
||||
private val screenStatusProvider: ScreenStatusProvider,
|
||||
private val foldProvider: FoldProvider,
|
||||
private val activityTypeProvider: CurrentActivityTypeProvider,
|
||||
private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
|
||||
private val rotationChangeProvider: RotationChangeProvider,
|
||||
@UnfoldMain private val mainExecutor: Executor,
|
||||
@UnfoldMain private val handler: Handler
|
||||
@@ -152,12 +154,13 @@ constructor(
|
||||
*/
|
||||
private fun getClosingThreshold(): Int? {
|
||||
val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null
|
||||
val isKeyguardVisible = unfoldKeyguardVisibilityProvider.isKeyguardVisible == true
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "isHomeActivity=$isHomeActivity")
|
||||
Log.d(TAG, "isHomeActivity=$isHomeActivity, isOnKeyguard=$isKeyguardVisible")
|
||||
}
|
||||
|
||||
return if (isHomeActivity) {
|
||||
return if (isHomeActivity || isKeyguardVisible) {
|
||||
null
|
||||
} else {
|
||||
START_CLOSING_ON_APPS_THRESHOLD_DEGREES
|
||||
@@ -257,7 +260,7 @@ fun @receiver:FoldUpdate Int.name() =
|
||||
}
|
||||
|
||||
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. */
|
||||
@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