Fade out UFPS icon when launching an app over it (1/2)
Before this CL, the UDFPS affordance would instantly disappear after
launching an Activity (like Device Controls) over the lockscreen.
This CL now nicely fades out the affordance during the launch animation,
unless the Activity requested the UDFPS (like the Wallet).
See b/213555622#comment1 for before/after videos.
Bug: 213555622
Test: Open device controls and wallet over lockscreen
Change-Id: I589a4a6c10a118d05fae87b70d14c924d468b63f
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 1b15d20..46adfeb 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -39,5 +39,5 @@
],
manifest: "AndroidManifest.xml",
-
+ kotlincflags: ["-Xjvm-default=enable"],
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index a0d335d..08d217d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -95,6 +95,9 @@
*/
var callback: Callback? = null
+ /** The set of [Listener] that should be notified of any animation started by this animator. */
+ private val listeners = LinkedHashSet<Listener>()
+
/**
* Start an intent and animate the opening window. The intent will be started by running
* [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch
@@ -214,6 +217,16 @@
}
}
+ /** Add a [Listener] that can listen to launch animations. */
+ fun addListener(listener: Listener) {
+ listeners.add(listener)
+ }
+
+ /** Remove a [Listener]. */
+ fun removeListener(listener: Listener) {
+ listeners.remove(listener)
+ }
+
/** Create a new animation [Runner] controlled by [controller]. */
@VisibleForTesting
fun createRunner(controller: Controller): Runner = Runner(controller)
@@ -234,13 +247,27 @@
/** Hide the keyguard and animate using [runner]. */
fun hideKeyguardWithAnimation(runner: IRemoteAnimationRunner)
- /** Enable/disable window blur so they don't overlap with the window launch animation **/
- fun setBlursDisabledForAppLaunch(disabled: Boolean)
-
/* Get the background color of [task]. */
fun getBackgroundColor(task: TaskInfo): Int
}
+ interface Listener {
+ /** Called when an activity launch animation started. */
+ @JvmDefault
+ fun onLaunchAnimationStart() {}
+
+ /**
+ * Called when an activity launch animation is finished. This will be called if and only if
+ * [onLaunchAnimationStart] was called earlier.
+ */
+ @JvmDefault
+ fun onLaunchAnimationEnd() {}
+
+ /** Called when an activity launch animation made progress. */
+ @JvmDefault
+ fun onLaunchAnimationProgress(linearProgress: Float) {}
+ }
+
/**
* A controller that takes care of applying the animation to an expanding view.
*
@@ -396,12 +423,12 @@
val delegate = this.controller
val controller = object : LaunchAnimator.Controller by delegate {
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
- callback.setBlursDisabledForAppLaunch(true)
+ listeners.forEach { it.onLaunchAnimationStart() }
delegate.onLaunchAnimationStart(isExpandingFullyAbove)
}
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
- callback.setBlursDisabledForAppLaunch(false)
+ listeners.forEach { it.onLaunchAnimationEnd() }
iCallback?.invoke()
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
}
@@ -413,6 +440,7 @@
) {
applyStateToWindow(window, state)
navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) }
+ listeners.forEach { it.onLaunchAnimationProgress(linearProgress) }
delegate.onLaunchAnimationProgress(state, progress, linearProgress)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index fd7ae32..d208441 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -53,6 +53,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
@@ -130,6 +131,7 @@
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
+ @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
// Tracks the velocity of a touch to help filter out the touches that move too fast.
@Nullable private VelocityTracker mVelocityTracker;
@@ -198,7 +200,8 @@
mLockscreenShadeTransitionController, mConfigurationController,
mSystemClock, mKeyguardStateController,
mUnlockedScreenOffAnimationController, mSensorProps, mHbmProvider,
- reason, callback, UdfpsController.this::onTouch)));
+ reason, callback, UdfpsController.this::onTouch,
+ mActivityLaunchAnimator)));
}
@Override
@@ -487,7 +490,8 @@
@NonNull SystemClock systemClock,
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager dialogManager,
- @NonNull LatencyTracker latencyTracker) {
+ @NonNull LatencyTracker latencyTracker,
+ @NonNull ActivityLaunchAnimator activityLaunchAnimator) {
mContext = context;
mExecution = execution;
mVibrator = vibrator;
@@ -516,6 +520,7 @@
mSystemClock = systemClock;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLatencyTracker = latencyTracker;
+ mActivityLaunchAnimator = activityLaunchAnimator;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index e091250..590963b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -41,6 +41,7 @@
import androidx.annotation.LayoutRes
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -81,7 +82,8 @@
private var hbmProvider: UdfpsHbmProvider,
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
- private val onTouch: (View, MotionEvent, Boolean) -> Boolean
+ private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
+ private val activityLaunchAnimator: ActivityLaunchAnimator
) {
/** The view, when [isShowing], or null. */
var overlayView: UdfpsView? = null
@@ -200,7 +202,8 @@
keyguardStateController,
unlockedScreenOffAnimationController,
dialogManager,
- controller
+ controller,
+ activityLaunchAnimator
)
}
BiometricOverlayConstants.REASON_AUTH_BP -> {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index d90a746..8b7aa09 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -25,6 +25,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -55,6 +56,7 @@
@NonNull private final UdfpsController mUdfpsController;
@NonNull private final UnlockedScreenOffAnimationController
mUnlockedScreenOffAnimationController;
+ @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
private boolean mShowingUdfpsBouncer;
private boolean mUdfpsRequested;
@@ -66,6 +68,8 @@
private long mLastUdfpsBouncerShowTime = -1;
private float mStatusBarExpansion;
private boolean mLaunchTransitionFadingAway;
+ private boolean mIsLaunchingActivity;
+ private float mActivityLaunchProgress;
/**
* hidden amount of pin/pattern/password bouncer
@@ -88,7 +92,8 @@
@NonNull KeyguardStateController keyguardStateController,
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager systemUIDialogManager,
- @NonNull UdfpsController udfpsController) {
+ @NonNull UdfpsController udfpsController,
+ @NonNull ActivityLaunchAnimator activityLaunchAnimator) {
super(view, statusBarStateController, panelExpansionStateManager, systemUIDialogManager,
dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
@@ -99,6 +104,7 @@
mKeyguardStateController = keyguardStateController;
mUdfpsController = udfpsController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mActivityLaunchAnimator = activityLaunchAnimator;
}
@Override
@@ -136,6 +142,7 @@
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
mUnlockedScreenOffAnimationController.addCallback(mUnlockedScreenOffCallback);
+ mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
}
@Override
@@ -153,6 +160,7 @@
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
}
mUnlockedScreenOffAnimationController.removeCallback(mUnlockedScreenOffCallback);
+ mActivityLaunchAnimator.removeListener(mActivityLaunchAnimatorListener);
}
@Override
@@ -294,6 +302,12 @@
0f, 255f);
if (!mShowingUdfpsBouncer) {
alpha *= (1.0f - mTransitionToFullShadeProgress);
+
+ // Fade out the icon if we are animating an activity launch over the lockscreen and the
+ // activity didn't request the UDFPS.
+ if (mIsLaunchingActivity && !mUdfpsRequested) {
+ alpha *= (1.0f - mActivityLaunchProgress);
+ }
}
mView.setUnpausedAlpha(alpha);
}
@@ -426,4 +440,26 @@
private final UnlockedScreenOffAnimationController.Callback mUnlockedScreenOffCallback =
(linear, eased) -> mStateListener.onDozeAmountChanged(linear, eased);
+
+ private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
+ new ActivityLaunchAnimator.Listener() {
+ @Override
+ public void onLaunchAnimationStart() {
+ mIsLaunchingActivity = true;
+ mActivityLaunchProgress = 0f;
+ updateAlpha();
+ }
+
+ @Override
+ public void onLaunchAnimationEnd() {
+ mIsLaunchingActivity = false;
+ updateAlpha();
+ }
+
+ @Override
+ public void onLaunchAnimationProgress(float linearProgress) {
+ mActivityLaunchProgress = linearProgress;
+ updateAlpha();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2ba70df..b991ea5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1383,7 +1383,8 @@
private void setUpPresenter() {
// Set up the initial notification state.
- mActivityLaunchAnimator.setCallback(mKeyguardHandler);
+ mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
+ mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
@@ -4367,7 +4368,7 @@
}
};
- private final ActivityLaunchAnimator.Callback mKeyguardHandler =
+ private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback =
new ActivityLaunchAnimator.Callback() {
@Override
public boolean isOnKeyguard() {
@@ -4386,11 +4387,6 @@
}
@Override
- public void setBlursDisabledForAppLaunch(boolean disabled) {
- mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
- }
-
- @Override
public int getBackgroundColor(TaskInfo task) {
if (!mStartingSurfaceOptional.isPresent()) {
Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
@@ -4401,6 +4397,19 @@
}
};
+ private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
+ new ActivityLaunchAnimator.Listener() {
+ @Override
+ public void onLaunchAnimationStart() {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
+ }
+
+ @Override
+ public void onLaunchAnimationEnd() {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
+ }
+ };
+
private final DemoMode mDemoModeCallback = new DemoMode() {
@Override
public void onDemoModeFinished() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 1fe3d44..589eeb5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -21,13 +21,12 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertNull
import junit.framework.Assert.assertTrue
import junit.framework.AssertionFailedError
-import kotlin.concurrent.thread
+import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -40,6 +39,7 @@
import org.mockito.Mockito.verify
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
+import kotlin.concurrent.thread
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -48,6 +48,7 @@
private val launchContainer = LinearLayout(mContext)
private val launchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
@Mock lateinit var callback: ActivityLaunchAnimator.Callback
+ @Mock lateinit var listener: ActivityLaunchAnimator.Listener
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
@Mock lateinit var iCallback: IRemoteAnimationFinishedCallback
@Mock lateinit var failHandler: Log.TerribleFailureHandler
@@ -59,6 +60,12 @@
fun setup() {
activityLaunchAnimator = ActivityLaunchAnimator(launchAnimator)
activityLaunchAnimator.callback = callback
+ activityLaunchAnimator.addListener(listener)
+ }
+
+ @After
+ fun tearDown() {
+ activityLaunchAnimator.removeListener(listener)
}
private fun startIntentWithAnimation(
@@ -177,7 +184,7 @@
val runner = activityLaunchAnimator.createRunner(controller)
runner.onAnimationStart(0, arrayOf(fakeWindow()), emptyArray(), emptyArray(), iCallback)
waitForIdleSync()
- verify(callback).setBlursDisabledForAppLaunch(eq(true))
+ verify(listener).onLaunchAnimationStart()
verify(controller).onLaunchAnimationStart(anyBoolean())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 84eb935..066a866 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -37,6 +37,7 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -89,6 +90,7 @@
@Mock private lateinit var udfpsController: UdfpsController
@Mock private lateinit var udfpsView: UdfpsView
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
+ @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
private val sensorProps = SensorLocationInternal("", 10, 100, 20)
.asFingerprintSensorProperties()
@@ -118,7 +120,7 @@
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, sensorProps, hbmProvider, reason,
- controllerCallback, onTouch)
+ controllerCallback, onTouch, activityLaunchAnimator)
block()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 2afcbda..159bdba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -58,6 +58,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
@@ -180,6 +181,8 @@
private TypedArray mBrightnessBacklight;
@Mock
private SystemUIDialogManager mSystemUIDialogManager;
+ @Mock
+ private ActivityLaunchAnimator mActivityLaunchAnimator;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -252,7 +255,8 @@
mSystemClock,
mUnlockedScreenOffAnimationController,
mSystemUIDialogManager,
- mLatencyTracker);
+ mLatencyTracker,
+ mActivityLaunchAnimator);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 0ae3c39..e9a4e15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -36,6 +36,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -96,6 +97,8 @@
private SystemUIDialogManager mDialogManager;
@Mock
private UdfpsController mUdfpsController;
+ @Mock
+ private ActivityLaunchAnimator mActivityLaunchAnimator;
private FakeSystemClock mSystemClock = new FakeSystemClock();
private UdfpsKeyguardViewController mController;
@@ -134,7 +137,8 @@
mKeyguardStateController,
mUnlockedScreenOffAnimationController,
mDialogManager,
- mUdfpsController);
+ mUdfpsController,
+ mActivityLaunchAnimator);
}
@Test