Merge changes from topic "predback-qs-dialog" into tm-qpr-dev am: 1b5fb5d809

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20552932

Change-Id: I8e8d0b6af5ee18fc997f0b1adef0d435e027ee4f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Omar Miatello
2023-01-24 09:27:07 +00:00
committed by Automerger Merge Worker
13 changed files with 609 additions and 21 deletions

View File

@@ -0,0 +1,6 @@
package com.android.systemui.animation
interface AnimationFeatureFlags {
val isPredictiveBackQsDialogAnim: Boolean
get() = false
}

View File

@@ -33,8 +33,13 @@ import android.view.WindowInsets
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
import android.widget.FrameLayout
import android.window.OnBackInvokedDispatcher
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CujType
import com.android.systemui.animation.back.BackAnimationSpec
import com.android.systemui.animation.back.applyTo
import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi
import com.android.systemui.animation.back.onBackAnimationCallbackFrom
import kotlin.math.roundToInt
private const val TAG = "DialogLaunchAnimator"
@@ -55,8 +60,9 @@ class DialogLaunchAnimator
constructor(
private val callback: Callback,
private val interactionJankMonitor: InteractionJankMonitor,
private val featureFlags: AnimationFeatureFlags,
private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
private val isForTesting: Boolean = false
private val isForTesting: Boolean = false,
) {
private companion object {
private val TIMINGS = ActivityLaunchAnimator.TIMINGS
@@ -273,15 +279,16 @@ constructor(
val animatedDialog =
AnimatedDialog(
launchAnimator,
callback,
interactionJankMonitor,
controller,
launchAnimator = launchAnimator,
callback = callback,
interactionJankMonitor = interactionJankMonitor,
controller = controller,
onDialogDismissed = { openedDialogs.remove(it) },
dialog = dialog,
animateBackgroundBoundsChange,
animatedParent,
isForTesting,
animateBackgroundBoundsChange = animateBackgroundBoundsChange,
parentAnimatedDialog = animatedParent,
forceDisableSynchronization = isForTesting,
featureFlags = featureFlags,
)
openedDialogs.add(animatedDialog)
@@ -517,6 +524,7 @@ private class AnimatedDialog(
* Whether synchronization should be disabled, which can be useful if we are running in a test.
*/
private val forceDisableSynchronization: Boolean,
private val featureFlags: AnimationFeatureFlags,
) {
/**
* The DecorView of this dialog window.
@@ -778,12 +786,45 @@ private class AnimatedDialog(
// the dialog.
dialog.setDismissOverride(this::onDialogDismissed)
if (featureFlags.isPredictiveBackQsDialogAnim) {
// TODO(b/265923095) Improve animations for QS dialogs on configuration change
registerOnBackInvokedCallback(targetView = dialogContentWithBackground)
}
// Show the dialog.
dialog.show()
moveSourceDrawingToDialog()
}
private fun registerOnBackInvokedCallback(targetView: View) {
val metrics = targetView.resources.displayMetrics
val onBackAnimationCallback =
onBackAnimationCallbackFrom(
backAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi(metrics),
displayMetrics = metrics, // TODO(b/265060720): We could remove this
onBackProgressed = { backTransformation -> backTransformation.applyTo(targetView) },
onBackInvoked = { dialog.dismiss() },
)
val dispatcher = dialog.onBackInvokedDispatcher
targetView.addOnAttachStateChangeListener(
object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
dispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
onBackAnimationCallback
)
}
override fun onViewDetachedFromWindow(v: View) {
targetView.removeOnAttachStateChangeListener(this)
dispatcher.unregisterOnBackInvokedCallback(onBackAnimationCallback)
}
}
)
}
private fun moveSourceDrawingToDialog() {
if (decorView.viewRootImpl == null) {
// Make sure that we have access to the dialog view root to move the drawing to the

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2023 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.animation.back
import android.util.DisplayMetrics
import android.view.animation.Interpolator
import android.window.BackEvent
import com.android.systemui.animation.Interpolators
import com.android.systemui.util.dpToPx
/** Used to convert [BackEvent] into a [BackTransformation]. */
fun interface BackAnimationSpec {
/** Computes transformation based on a [backEvent] and sets it to [result]. */
fun getBackTransformation(
backEvent: BackEvent,
progressY: Float, // TODO(b/265060720): Remove progressY. Could be retrieved from backEvent
result: BackTransformation,
)
companion object
}
/** Create a [BackAnimationSpec] from [displayMetrics] and design specs. */
fun BackAnimationSpec.Companion.createFloatingSurfaceAnimationSpec(
displayMetrics: DisplayMetrics,
maxMarginXdp: Float,
maxMarginYdp: Float,
minScale: Float,
translateXEasing: Interpolator = Interpolators.STANDARD_DECELERATE,
translateYEasing: Interpolator = Interpolators.LINEAR,
scaleEasing: Interpolator = Interpolators.STANDARD_DECELERATE,
): BackAnimationSpec {
val screenWidthPx = displayMetrics.widthPixels
val screenHeightPx = displayMetrics.heightPixels
val maxMarginXPx = maxMarginXdp.dpToPx(displayMetrics)
val maxMarginYPx = maxMarginYdp.dpToPx(displayMetrics)
val maxTranslationXByScale = (screenWidthPx - screenWidthPx * minScale) / 2
val maxTranslationX = maxTranslationXByScale - maxMarginXPx
val maxTranslationYByScale = (screenHeightPx - screenHeightPx * minScale) / 2
val maxTranslationY = maxTranslationYByScale - maxMarginYPx
val minScaleReversed = 1f - minScale
return BackAnimationSpec { backEvent, progressY, result ->
val direction = if (backEvent.swipeEdge == BackEvent.EDGE_LEFT) 1 else -1
val progressX = backEvent.progress
val ratioTranslateX = translateXEasing.getInterpolation(progressX)
val ratioTranslateY = translateYEasing.getInterpolation(progressY)
val ratioScale = scaleEasing.getInterpolation(progressX)
result.apply {
translateX = ratioTranslateX * direction * maxTranslationX
translateY = ratioTranslateY * maxTranslationY
scale = 1f - (ratioScale * minScaleReversed)
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2023 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.animation.back
import android.util.DisplayMetrics
/**
* SysUI transitions - Dismiss app (ST1) Return to launching surface or place of origin
* https://carbon.googleplex.com/predictive-back-for-apps/pages/st-1-dismiss-app
*/
fun BackAnimationSpec.Companion.dismissAppForSysUi(
displayMetrics: DisplayMetrics,
): BackAnimationSpec =
BackAnimationSpec.createFloatingSurfaceAnimationSpec(
displayMetrics = displayMetrics,
maxMarginXdp = 8f,
maxMarginYdp = 8f,
minScale = 0.8f,
)
/**
* SysUI transitions - Cross task (ST2) Return to previous task/app, keeping the current one open
* https://carbon.googleplex.com/predictive-back-for-apps/pages/st-2-cross-task
*/
fun BackAnimationSpec.Companion.crossTaskForSysUi(
displayMetrics: DisplayMetrics,
): BackAnimationSpec =
BackAnimationSpec.createFloatingSurfaceAnimationSpec(
displayMetrics = displayMetrics,
maxMarginXdp = 8f,
maxMarginYdp = 8f,
minScale = 0.8f,
)
/**
* SysUI transitions - Inner area dismiss (ST3) Dismiss non-detachable surface
* https://carbon.googleplex.com/predictive-back-for-apps/pages/st-3-inner-area-dismiss
*/
fun BackAnimationSpec.Companion.innerAreaDismissForSysUi(
displayMetrics: DisplayMetrics,
): BackAnimationSpec =
BackAnimationSpec.createFloatingSurfaceAnimationSpec(
displayMetrics = displayMetrics,
maxMarginXdp = 0f,
maxMarginYdp = 0f,
minScale = 0.9f,
)
/**
* SysUI transitions - Floating system surfaces (ST4)
* https://carbon.googleplex.com/predictive-back-for-apps/pages/st-4-floating-system-surfaces
*/
fun BackAnimationSpec.Companion.floatingSystemSurfacesForSysUi(
displayMetrics: DisplayMetrics,
): BackAnimationSpec =
BackAnimationSpec.createFloatingSurfaceAnimationSpec(
displayMetrics = displayMetrics,
maxMarginXdp = 8f,
maxMarginYdp = 8f,
minScale = 0.8f,
)

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 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.animation.back
import android.view.View
/**
* This object that represents the transformation to apply to the target. The properties of this
* object are mutable for performance reasons (avoid recreating this object)
*/
data class BackTransformation(
var translateX: Float = Float.NaN,
var translateY: Float = Float.NaN,
var scale: Float = Float.NaN,
)
/** Apply the transformation to the [targetView] */
fun BackTransformation.applyTo(targetView: View) {
if (translateX.isFinite()) targetView.translationX = translateX
if (translateY.isFinite()) targetView.translationY = translateY
if (scale.isFinite()) {
targetView.scaleX = scale
targetView.scaleY = scale
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2023 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.animation.back
import android.util.DisplayMetrics
import android.window.BackEvent
import android.window.OnBackAnimationCallback
/**
* Generates an [OnBackAnimationCallback] given a [backAnimationSpec]. [onBackProgressed] will be
* called on each update passing the current [BackTransformation].
*
* Optionally, you can specify [onBackStarted], [onBackInvoked], and [onBackCancelled] callbacks.
*/
fun onBackAnimationCallbackFrom(
backAnimationSpec: BackAnimationSpec,
displayMetrics: DisplayMetrics, // TODO(b/265060720): We could remove this
onBackProgressed: (BackTransformation) -> Unit,
onBackStarted: (BackEvent) -> Unit = {},
onBackInvoked: () -> Unit = {},
onBackCancelled: () -> Unit = {},
): OnBackAnimationCallback {
return object : OnBackAnimationCallback {
private var initialY = 0f
private val lastTransformation = BackTransformation()
override fun onBackStarted(backEvent: BackEvent) {
initialY = backEvent.touchY
onBackStarted(backEvent)
}
override fun onBackProgressed(backEvent: BackEvent) {
val progressY = (backEvent.touchY - initialY) / displayMetrics.heightPixels
backAnimationSpec.getBackTransformation(
backEvent = backEvent,
progressY = progressY,
result = lastTransformation,
)
onBackProgressed(lastTransformation)
}
override fun onBackInvoked() {
onBackInvoked()
}
override fun onBackCancelled() {
onBackCancelled()
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 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.util
import android.content.Context
import android.content.res.Resources
import android.util.DisplayMetrics
import android.util.TypedValue
/** Convert [this] number of dps to device pixels. */
fun Number.dpToPx(context: Context): Float = dpToPx(resources = context.resources)
/** Convert [this] number of dps to device pixels. */
fun Number.dpToPx(resources: Resources): Float = dpToPx(displayMetrics = resources.displayMetrics)
/** Convert [this] number of dps to device pixels. */
fun Number.dpToPx(displayMetrics: DisplayMetrics): Float =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, toFloat(), displayMetrics)

View File

@@ -65,8 +65,7 @@ object Flags {
val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
// TODO(b/265804648): Tracking Bug
@JvmField
val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
@JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
// TODO(b/254512538): Tracking Bug
val INSTANT_VOICE_REPLY = unreleasedFlag(111, "instant_voice_reply", teamfood = true)
@@ -483,6 +482,11 @@ object Flags {
val WM_SHADE_ANIMATE_BACK_GESTURE =
unreleasedFlag(1208, "persist.wm.debug.shade_animate_back_gesture", teamfood = true)
// TODO(b/265639042): Tracking Bug
@JvmField
val WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM =
unreleasedFlag(1209, "persist.wm.debug.predictive_back_qs_dialog_anim", teamfood = true)
// 1300 - screenshots
// TODO(b/254513155): Tracking Bug
@JvmField
@@ -573,6 +577,5 @@ object Flags {
// 2600 - keyboard shortcut
// TODO(b/259352579): Tracking Bug
@JvmField
val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
@JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
}

View File

@@ -25,12 +25,15 @@ import android.util.Log;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.AnimationFeatureFlags;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpHandler;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.plugins.ActivityStarter;
@@ -281,7 +284,8 @@ public interface CentralSurfacesDependenciesModule {
static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
KeyguardStateController keyguardStateController,
Lazy<AlternateBouncerInteractor> alternateBouncerInteractor,
InteractionJankMonitor interactionJankMonitor) {
InteractionJankMonitor interactionJankMonitor,
AnimationFeatureFlags animationFeatureFlags) {
DialogLaunchAnimator.Callback callback = new DialogLaunchAnimator.Callback() {
@Override
public boolean isDreaming() {
@@ -303,6 +307,19 @@ public interface CentralSurfacesDependenciesModule {
return alternateBouncerInteractor.get().canShowAlternateBouncerForFingerprint();
}
};
return new DialogLaunchAnimator(callback, interactionJankMonitor);
return new DialogLaunchAnimator(callback, interactionJankMonitor, animationFeatureFlags);
}
/**
*/
@Provides
@SysUISingleton
static AnimationFeatureFlags provideAnimationFeatureFlags(FeatureFlags featureFlags) {
return new AnimationFeatureFlags() {
@Override
public boolean isPredictiveBackQsDialogAnim() {
return featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM);
}
};
}
}

View File

@@ -0,0 +1,87 @@
package com.android.systemui.animation.back
import android.util.DisplayMetrics
import android.window.BackEvent
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
private data class BackInput(val progressX: Float, val progressY: Float, val edge: Int)
@SmallTest
@RunWith(JUnit4::class)
class BackAnimationSpecTest : SysuiTestCase() {
private var displayMetrics =
DisplayMetrics().apply {
widthPixels = 100
heightPixels = 200
density = 3f
}
@Test
fun sysUi_floatingSystemSurfaces_animationValues() {
val maxX = 14.0f
val maxY = 4.0f
val minScale = 0.8f
val backAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi(displayMetrics)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 0f, progressY = 0f, edge = BackEvent.EDGE_LEFT),
expected = BackTransformation(translateX = 0f, translateY = 0f, scale = 1f),
)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 1f, progressY = 0f, edge = BackEvent.EDGE_LEFT),
expected = BackTransformation(translateX = -maxX, translateY = 0f, scale = minScale),
)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 1f, progressY = 0f, edge = BackEvent.EDGE_RIGHT),
expected = BackTransformation(translateX = maxX, translateY = 0f, scale = minScale),
)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 1f, progressY = 1f, edge = BackEvent.EDGE_LEFT),
expected = BackTransformation(translateX = -maxX, translateY = -maxY, scale = minScale),
)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 0f, progressY = 1f, edge = BackEvent.EDGE_LEFT),
expected = BackTransformation(translateX = 0f, translateY = -maxY, scale = 1f),
)
assertBackTransformation(
backAnimationSpec = backAnimationSpec,
backInput = BackInput(progressX = 0f, progressY = -1f, edge = BackEvent.EDGE_LEFT),
expected = BackTransformation(translateX = 0f, translateY = maxY, scale = 1f),
)
}
}
private fun assertBackTransformation(
backAnimationSpec: BackAnimationSpec,
backInput: BackInput,
expected: BackTransformation,
) {
val actual = BackTransformation()
backAnimationSpec.getBackTransformation(
backEvent =
BackEvent(
/* touchX = */ 0f,
/* touchY = */ 0f,
/* progress = */ backInput.progressX,
/* swipeEdge = */ backInput.edge,
),
progressY = backInput.progressY,
result = actual
)
val tolerance = 0f
assertThat(actual.translateX).isWithin(tolerance).of(expected.translateX)
assertThat(actual.translateY).isWithin(tolerance).of(expected.translateY)
assertThat(actual.scale).isWithin(tolerance).of(expected.scale)
}

View File

@@ -0,0 +1,80 @@
package com.android.systemui.animation.back
import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
@SmallTest
@RunWith(JUnit4::class)
class BackTransformationTest : SysuiTestCase() {
private val targetView: View = mock()
@Test
fun defaultValue_noTransformation() {
val transformation = BackTransformation()
assertThat(transformation.translateX).isNaN()
assertThat(transformation.translateY).isNaN()
assertThat(transformation.scale).isNaN()
}
@Test
fun applyTo_targetView_translateX_Y_Scale() {
val transformation = BackTransformation(translateX = 0f, translateY = 0f, scale = 1f)
transformation.applyTo(targetView = targetView)
verify(targetView).translationX = 0f
verify(targetView).translationY = 0f
verify(targetView).scaleX = 1f
verify(targetView).scaleY = 1f
verifyNoMoreInteractions(targetView)
}
@Test
fun applyTo_targetView_translateX() {
val transformation = BackTransformation(translateX = 1f)
transformation.applyTo(targetView = targetView)
verify(targetView).translationX = 1f
verifyNoMoreInteractions(targetView)
}
@Test
fun applyTo_targetView_translateY() {
val transformation = BackTransformation(translateY = 2f)
transformation.applyTo(targetView = targetView)
verify(targetView).translationY = 2f
verifyNoMoreInteractions(targetView)
}
@Test
fun applyTo_targetView_scale() {
val transformation = BackTransformation(scale = 3f)
transformation.applyTo(targetView = targetView)
verify(targetView).scaleX = 3f
verify(targetView).scaleY = 3f
verifyNoMoreInteractions(targetView)
}
@Test
fun applyTo_targetView_noTransformation() {
val transformation = BackTransformation()
transformation.applyTo(targetView = targetView)
verifyNoMoreInteractions(targetView)
}
}

View File

@@ -0,0 +1,63 @@
package com.android.systemui.animation.back
import android.util.DisplayMetrics
import android.window.BackEvent
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.mock
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mockito.verify
@SmallTest
@RunWith(JUnit4::class)
class OnBackAnimationCallbackExtensionTest : SysuiTestCase() {
private val onBackProgress: (BackTransformation) -> Unit = mock()
private val onBackStart: (BackEvent) -> Unit = mock()
private val onBackInvoke: () -> Unit = mock()
private val onBackCancel: () -> Unit = mock()
private val displayMetrics =
DisplayMetrics().apply {
widthPixels = 100
heightPixels = 100
density = 1f
}
private val onBackAnimationCallback =
onBackAnimationCallbackFrom(
backAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi(displayMetrics),
displayMetrics = displayMetrics,
onBackProgressed = onBackProgress,
onBackStarted = onBackStart,
onBackInvoked = onBackInvoke,
onBackCancelled = onBackCancel,
)
@Test
fun onBackProgressed_shouldInvoke_onBackProgress() {
val backEvent = BackEvent(0f, 0f, 0f, BackEvent.EDGE_LEFT)
onBackAnimationCallback.onBackStarted(backEvent)
onBackAnimationCallback.onBackProgressed(backEvent)
verify(onBackProgress).invoke(BackTransformation(0f, 0f, 1f))
}
@Test
fun onBackStarted_shouldInvoke_onBackStart() {
val backEvent = BackEvent(0f, 0f, 0f, BackEvent.EDGE_LEFT)
onBackAnimationCallback.onBackStarted(backEvent)
verify(onBackStart).invoke(backEvent)
}
@Test
fun onBackInvoked_shouldInvoke_onBackInvoke() {
onBackAnimationCallback.onBackInvoked()
verify(onBackInvoke).invoke()
}
}

View File

@@ -23,14 +23,20 @@ fun fakeDialogLaunchAnimator(
isUnlocked: Boolean = true,
isShowingAlternateAuthOnUnlock: Boolean = false,
interactionJankMonitor: InteractionJankMonitor = mock(InteractionJankMonitor::class.java),
isPredictiveBackQsDialogAnim: Boolean = false,
): DialogLaunchAnimator {
return DialogLaunchAnimator(
FakeCallback(
isUnlocked = isUnlocked,
isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
),
interactionJankMonitor,
fakeLaunchAnimator(),
callback =
FakeCallback(
isUnlocked = isUnlocked,
isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
),
interactionJankMonitor = interactionJankMonitor,
featureFlags =
object : AnimationFeatureFlags {
override val isPredictiveBackQsDialogAnim = isPredictiveBackQsDialogAnim
},
launchAnimator = fakeLaunchAnimator(),
isForTesting = true,
)
}