Merge "Do not animate dialogs into activites when locked (1/n)" into tm-qpr-dev am: 4dd2341342
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19500371 Change-Id: I0f49759874813a76fbf0506a055a20e6f3653033 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
committed by
Automerger Merge Worker
commit
b1c7838da7
@@ -23,7 +23,6 @@ import android.app.Dialog
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.service.dreams.IDreamManager
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.MathUtils
|
import android.util.MathUtils
|
||||||
import android.view.GhostView
|
import android.view.GhostView
|
||||||
@@ -54,7 +53,7 @@ private const val TAG = "DialogLaunchAnimator"
|
|||||||
class DialogLaunchAnimator
|
class DialogLaunchAnimator
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
private val dreamManager: IDreamManager,
|
private val callback: Callback,
|
||||||
private val interactionJankMonitor: InteractionJankMonitor,
|
private val interactionJankMonitor: InteractionJankMonitor,
|
||||||
private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
|
private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
|
||||||
private val isForTesting: Boolean = false
|
private val isForTesting: Boolean = false
|
||||||
@@ -126,7 +125,7 @@ constructor(
|
|||||||
val animatedDialog =
|
val animatedDialog =
|
||||||
AnimatedDialog(
|
AnimatedDialog(
|
||||||
launchAnimator,
|
launchAnimator,
|
||||||
dreamManager,
|
callback,
|
||||||
interactionJankMonitor,
|
interactionJankMonitor,
|
||||||
animateFrom,
|
animateFrom,
|
||||||
onDialogDismissed = { openedDialogs.remove(it) },
|
onDialogDismissed = { openedDialogs.remove(it) },
|
||||||
@@ -194,8 +193,12 @@ constructor(
|
|||||||
|
|
||||||
val dialog = animatedDialog.dialog
|
val dialog = animatedDialog.dialog
|
||||||
|
|
||||||
// Don't animate if the dialog is not showing.
|
// Don't animate if the dialog is not showing or if we are locked and going to show the
|
||||||
if (!dialog.isShowing) {
|
// bouncer.
|
||||||
|
if (
|
||||||
|
!dialog.isShowing ||
|
||||||
|
(!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +288,23 @@ constructor(
|
|||||||
?.let { it.touchSurface = it.prepareForStackDismiss() }
|
?.let { it.touchSurface = it.prepareForStackDismiss() }
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
/** Whether the device is currently in dreaming (screensaver) mode. */
|
||||||
|
fun isDreaming(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the device is currently unlocked, i.e. if it is *not* on the keyguard or if the
|
||||||
|
* keyguard can be dismissed.
|
||||||
|
*/
|
||||||
|
fun isUnlocked(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we are going to show alternate authentication (like UDFPS) instead of the
|
||||||
|
* traditional bouncer when unlocking the device.
|
||||||
|
*/
|
||||||
|
fun isShowingAlternateAuthOnUnlock(): Boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,7 +316,7 @@ data class DialogCuj(@CujType val cujType: Int, val tag: String? = null)
|
|||||||
|
|
||||||
private class AnimatedDialog(
|
private class AnimatedDialog(
|
||||||
private val launchAnimator: LaunchAnimator,
|
private val launchAnimator: LaunchAnimator,
|
||||||
private val dreamManager: IDreamManager,
|
private val callback: DialogLaunchAnimator.Callback,
|
||||||
private val interactionJankMonitor: InteractionJankMonitor,
|
private val interactionJankMonitor: InteractionJankMonitor,
|
||||||
|
|
||||||
/** The view that triggered the dialog after being tapped. */
|
/** The view that triggered the dialog after being tapped. */
|
||||||
@@ -850,7 +870,7 @@ private class AnimatedDialog(
|
|||||||
|
|
||||||
// If we are dreaming, the dialog was probably closed because of that so we don't animate
|
// If we are dreaming, the dialog was probably closed because of that so we don't animate
|
||||||
// into the touchSurface.
|
// into the touchSurface.
|
||||||
if (dreamManager.isDreaming) {
|
if (callback.isDreaming()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package com.android.systemui.statusbar.dagger;
|
|||||||
import android.app.IActivityManager;
|
import android.app.IActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.service.dreams.IDreamManager;
|
import android.service.dreams.IDreamManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.jank.InteractionJankMonitor;
|
import com.android.internal.jank.InteractionJankMonitor;
|
||||||
import com.android.internal.statusbar.IStatusBarService;
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
@@ -60,10 +62,12 @@ import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
|
|||||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
|
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconList;
|
import com.android.systemui.statusbar.phone.StatusBarIconList;
|
||||||
|
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
|
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
|
||||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
|
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
|
||||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
|
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
|
||||||
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.statusbar.policy.RemoteInputUriController;
|
import com.android.systemui.statusbar.policy.RemoteInputUriController;
|
||||||
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
||||||
import com.android.systemui.tracing.ProtoTracer;
|
import com.android.systemui.tracing.ProtoTracer;
|
||||||
@@ -274,7 +278,30 @@ public interface CentralSurfacesDependenciesModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
|
static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
|
||||||
|
KeyguardStateController keyguardStateController,
|
||||||
|
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManager,
|
||||||
InteractionJankMonitor interactionJankMonitor) {
|
InteractionJankMonitor interactionJankMonitor) {
|
||||||
return new DialogLaunchAnimator(dreamManager, interactionJankMonitor);
|
DialogLaunchAnimator.Callback callback = new DialogLaunchAnimator.Callback() {
|
||||||
|
@Override
|
||||||
|
public boolean isDreaming() {
|
||||||
|
try {
|
||||||
|
return dreamManager.isDreaming();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e("DialogLaunchAnimator.Callback", "dreamManager.isDreaming failed", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnlocked() {
|
||||||
|
return keyguardStateController.isUnlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShowingAlternateAuthOnUnlock() {
|
||||||
|
return statusBarKeyguardViewManager.get().shouldShowAltAuth();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new DialogLaunchAnimator(callback, interactionJankMonitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -471,7 +471,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
showBouncer(scrimmed);
|
showBouncer(scrimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldShowAltAuth() {
|
/** Whether we should show the alternate authentication instead of the traditional bouncer. */
|
||||||
|
public boolean shouldShowAltAuth() {
|
||||||
return mAlternateAuthInterceptor != null
|
return mAlternateAuthInterceptor != null
|
||||||
&& mKeyguardUpdateManager.isUnlockingWithBiometricAllowed(true);
|
&& mKeyguardUpdateManager.isUnlockingWithBiometricAllowed(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import junit.framework.Assert.assertNotNull
|
|||||||
import junit.framework.Assert.assertNull
|
import junit.framework.Assert.assertNull
|
||||||
import junit.framework.Assert.assertTrue
|
import junit.framework.Assert.assertTrue
|
||||||
import junit.framework.AssertionFailedError
|
import junit.framework.AssertionFailedError
|
||||||
|
import kotlin.concurrent.thread
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
@@ -34,19 +35,18 @@ import org.junit.runner.RunWith
|
|||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.ArgumentMatchers.anyBoolean
|
import org.mockito.ArgumentMatchers.anyBoolean
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.`when`
|
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.Spy
|
import org.mockito.Spy
|
||||||
import org.mockito.junit.MockitoJUnit
|
import org.mockito.junit.MockitoJUnit
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper
|
@RunWithLooper
|
||||||
class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
||||||
private val launchContainer = LinearLayout(mContext)
|
private val launchContainer = LinearLayout(mContext)
|
||||||
private val testLaunchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
|
private val testLaunchAnimator = fakeLaunchAnimator()
|
||||||
@Mock lateinit var callback: ActivityLaunchAnimator.Callback
|
@Mock lateinit var callback: ActivityLaunchAnimator.Callback
|
||||||
@Mock lateinit var listener: ActivityLaunchAnimator.Listener
|
@Mock lateinit var listener: ActivityLaunchAnimator.Listener
|
||||||
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
|
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
|
||||||
@@ -82,7 +82,8 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
animate = animate,
|
animate = animate,
|
||||||
intentStarter = intentStarter
|
intentStarter = intentStarter
|
||||||
)
|
)
|
||||||
}.join()
|
}
|
||||||
|
.join()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -197,14 +198,25 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
|
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
|
||||||
val taskInfo = ActivityManager.RunningTaskInfo()
|
val taskInfo = ActivityManager.RunningTaskInfo()
|
||||||
taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
|
taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
|
||||||
taskInfo.topActivityInfo = ActivityInfo().apply {
|
taskInfo.topActivityInfo = ActivityInfo().apply { applicationInfo = ApplicationInfo() }
|
||||||
applicationInfo = ApplicationInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemoteAnimationTarget(
|
return RemoteAnimationTarget(
|
||||||
0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
|
0,
|
||||||
Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
|
RemoteAnimationTarget.MODE_OPENING,
|
||||||
taskInfo, false
|
SurfaceControl(),
|
||||||
|
false,
|
||||||
|
Rect(),
|
||||||
|
Rect(),
|
||||||
|
0,
|
||||||
|
Point(),
|
||||||
|
Rect(),
|
||||||
|
bounds,
|
||||||
|
WindowConfiguration(),
|
||||||
|
false,
|
||||||
|
SurfaceControl(),
|
||||||
|
Rect(),
|
||||||
|
taskInfo,
|
||||||
|
false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,10 +225,10 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
* A simple implementation of [ActivityLaunchAnimator.Controller] which throws if it is called
|
* A simple implementation of [ActivityLaunchAnimator.Controller] which throws if it is called
|
||||||
* outside of the main thread.
|
* outside of the main thread.
|
||||||
*/
|
*/
|
||||||
private class TestLaunchAnimatorController(
|
private class TestLaunchAnimatorController(override var launchContainer: ViewGroup) :
|
||||||
override var launchContainer: ViewGroup
|
ActivityLaunchAnimator.Controller {
|
||||||
) : ActivityLaunchAnimator.Controller {
|
override fun createAnimatorState() =
|
||||||
override fun createAnimatorState() = LaunchAnimator.State(
|
LaunchAnimator.State(
|
||||||
top = 100,
|
top = 100,
|
||||||
bottom = 200,
|
bottom = 200,
|
||||||
left = 300,
|
left = 300,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.content.Context
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.service.dreams.IDreamManager
|
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
import android.testing.ViewUtils
|
import android.testing.ViewUtils
|
||||||
@@ -38,19 +37,16 @@ import org.mockito.junit.MockitoJUnit
|
|||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@TestableLooper.RunWithLooper
|
@TestableLooper.RunWithLooper
|
||||||
class DialogLaunchAnimatorTest : SysuiTestCase() {
|
class DialogLaunchAnimatorTest : SysuiTestCase() {
|
||||||
private val launchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
|
|
||||||
private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
|
private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
|
||||||
private val attachedViews = mutableSetOf<View>()
|
private val attachedViews = mutableSetOf<View>()
|
||||||
|
|
||||||
@Mock lateinit var dreamManager: IDreamManager
|
|
||||||
@Mock lateinit var interactionJankMonitor: InteractionJankMonitor
|
@Mock lateinit var interactionJankMonitor: InteractionJankMonitor
|
||||||
@get:Rule val rule = MockitoJUnit.rule()
|
@get:Rule val rule = MockitoJUnit.rule()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
dialogLaunchAnimator = DialogLaunchAnimator(
|
dialogLaunchAnimator =
|
||||||
dreamManager, interactionJankMonitor, launchAnimator, isForTesting = true
|
fakeDialogLaunchAnimator(interactionJankMonitor = interactionJankMonitor)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -152,6 +148,22 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
assertNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
|
assertNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testActivityLaunchWhenLockedWithoutAlternateAuth() {
|
||||||
|
val dialogLaunchAnimator =
|
||||||
|
fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = false)
|
||||||
|
val dialog = createAndShowDialog(dialogLaunchAnimator)
|
||||||
|
assertNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testActivityLaunchWhenLockedWithAlternateAuth() {
|
||||||
|
val dialogLaunchAnimator =
|
||||||
|
fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = true)
|
||||||
|
val dialog = createAndShowDialog(dialogLaunchAnimator)
|
||||||
|
assertNotNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDialogAnimationIsChangedByAnimator() {
|
fun testDialogAnimationIsChangedByAnimator() {
|
||||||
// Important: the power menu animation relies on this behavior to know when to animate (see
|
// Important: the power menu animation relies on this behavior to know when to animate (see
|
||||||
@@ -193,11 +205,13 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
|
verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAndShowDialog(): TestDialog {
|
private fun createAndShowDialog(
|
||||||
|
animator: DialogLaunchAnimator = dialogLaunchAnimator,
|
||||||
|
): TestDialog {
|
||||||
val touchSurface = createTouchSurface()
|
val touchSurface = createTouchSurface()
|
||||||
return runOnMainThreadAndWaitForIdleSync {
|
return runOnMainThreadAndWaitForIdleSync {
|
||||||
val dialog = TestDialog(context)
|
val dialog = TestDialog(context)
|
||||||
dialogLaunchAnimator.showFromView(dialog, touchSurface)
|
animator.showFromView(dialog, touchSurface)
|
||||||
dialog
|
dialog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.android.systemui.animation
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [LaunchAnimator.Timings] to be used in tests.
|
|
||||||
*
|
|
||||||
* Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
|
|
||||||
* when computing the progress of a sub-animation (the contents fade in/out).
|
|
||||||
*/
|
|
||||||
val TEST_TIMINGS = LaunchAnimator.Timings(
|
|
||||||
totalDuration = 0L,
|
|
||||||
contentBeforeFadeOutDelay = 1L,
|
|
||||||
contentBeforeFadeOutDuration = 1L,
|
|
||||||
contentAfterFadeInDelay = 1L,
|
|
||||||
contentAfterFadeInDuration = 1L
|
|
||||||
)
|
|
||||||
|
|
||||||
/** A [LaunchAnimator.Interpolators] to be used in tests. */
|
|
||||||
val TEST_INTERPOLATORS = LaunchAnimator.Interpolators(
|
|
||||||
positionInterpolator = Interpolators.STANDARD,
|
|
||||||
positionXInterpolator = Interpolators.STANDARD,
|
|
||||||
contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
|
|
||||||
contentAfterFadeInInterpolator = Interpolators.STANDARD
|
|
||||||
)
|
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui;
|
package com.android.systemui;
|
||||||
|
|
||||||
|
import static com.android.systemui.animation.FakeDialogLaunchAnimatorKt.fakeDialogLaunchAnimator;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -34,6 +36,7 @@ import androidx.test.uiautomator.UiDevice;
|
|||||||
|
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.broadcast.FakeBroadcastDispatcher;
|
import com.android.systemui.broadcast.FakeBroadcastDispatcher;
|
||||||
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
|
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
|
||||||
@@ -119,6 +122,7 @@ public abstract class SysuiTestCase {
|
|||||||
// is missing (constructing the actual one would throw).
|
// is missing (constructing the actual one would throw).
|
||||||
// TODO(b/219008720): Remove this.
|
// TODO(b/219008720): Remove this.
|
||||||
mDependency.injectMockDependency(SystemUIDialogManager.class);
|
mDependency.injectMockDependency(SystemUIDialogManager.class);
|
||||||
|
mDependency.injectTestDependency(DialogLaunchAnimator.class, fakeDialogLaunchAnimator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.animation
|
||||||
|
|
||||||
|
import com.android.internal.jank.InteractionJankMonitor
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
|
||||||
|
/** A [DialogLaunchAnimator] to be used in tests. */
|
||||||
|
@JvmOverloads
|
||||||
|
fun fakeDialogLaunchAnimator(
|
||||||
|
isUnlocked: Boolean = true,
|
||||||
|
isShowingAlternateAuthOnUnlock: Boolean = false,
|
||||||
|
interactionJankMonitor: InteractionJankMonitor = mock(InteractionJankMonitor::class.java),
|
||||||
|
): DialogLaunchAnimator {
|
||||||
|
return DialogLaunchAnimator(
|
||||||
|
FakeCallback(
|
||||||
|
isUnlocked = isUnlocked,
|
||||||
|
isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
|
||||||
|
),
|
||||||
|
interactionJankMonitor,
|
||||||
|
fakeLaunchAnimator(),
|
||||||
|
isForTesting = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FakeCallback(
|
||||||
|
private val isDreaming: Boolean = false,
|
||||||
|
private val isUnlocked: Boolean = true,
|
||||||
|
private val isShowingAlternateAuthOnUnlock: Boolean = false,
|
||||||
|
) : DialogLaunchAnimator.Callback {
|
||||||
|
override fun isDreaming(): Boolean = isDreaming
|
||||||
|
override fun isUnlocked(): Boolean = isUnlocked
|
||||||
|
override fun isShowingAlternateAuthOnUnlock() = isShowingAlternateAuthOnUnlock
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.animation
|
||||||
|
|
||||||
|
/** A [LaunchAnimator] to be used in tests. */
|
||||||
|
fun fakeLaunchAnimator(): LaunchAnimator {
|
||||||
|
return LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [LaunchAnimator.Timings] to be used in tests.
|
||||||
|
*
|
||||||
|
* Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
|
||||||
|
* when computing the progress of a sub-animation (the contents fade in/out).
|
||||||
|
*/
|
||||||
|
private val TEST_TIMINGS =
|
||||||
|
LaunchAnimator.Timings(
|
||||||
|
totalDuration = 0L,
|
||||||
|
contentBeforeFadeOutDelay = 1L,
|
||||||
|
contentBeforeFadeOutDuration = 1L,
|
||||||
|
contentAfterFadeInDelay = 1L,
|
||||||
|
contentAfterFadeInDuration = 1L
|
||||||
|
)
|
||||||
|
|
||||||
|
/** A [LaunchAnimator.Interpolators] to be used in tests. */
|
||||||
|
private val TEST_INTERPOLATORS =
|
||||||
|
LaunchAnimator.Interpolators(
|
||||||
|
positionInterpolator = Interpolators.STANDARD,
|
||||||
|
positionXInterpolator = Interpolators.STANDARD,
|
||||||
|
contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
|
||||||
|
contentAfterFadeInInterpolator = Interpolators.STANDARD
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user