From 147de5aa3d917bf4a9715b55a03a5c2ed4d5447e Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Mon, 26 Apr 2021 15:08:25 +0200 Subject: [PATCH] Fix HUN launch animation. This CL fixes HUN launch animation by making sure that the HUN is hidden only when the launch animation is ended, cancelled, aborted or timed out. See b/186389197#comment2 for before/after videos. Bug: 186389197 Test: Click a HUN notification Test: atest ActivityLaunchAnimatorTest Change-Id: I3c8e1d8195124946aef5a25c411b6913157179b8 --- .../animation/ActivityLaunchAnimator.kt | 26 +++++- .../NotificationLaunchAnimatorController.kt | 26 +++++- .../statusbar/phone/HeadsUpManagerPhone.java | 14 ++- .../systemui/statusbar/phone/StatusBar.java | 93 ++++++++++--------- .../StatusBarNotificationActivityStarter.java | 78 +++++----------- .../policy/SmartReplyStateInflater.kt | 1 - .../animation/ActivityLaunchAnimatorTest.kt | 13 ++- ...tusBarNotificationActivityStarterTest.java | 18 +++- 8 files changed, 155 insertions(+), 114 deletions(-) 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 6d6bc07c01b52..20273d05f0597 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -8,6 +8,7 @@ import android.app.PendingIntent import android.content.Context import android.graphics.Matrix import android.graphics.Rect +import android.os.Looper import android.os.RemoteException import android.util.MathUtils import android.view.IRemoteAnimationFinishedCallback @@ -73,16 +74,20 @@ class ActivityLaunchAnimator(context: Context) { * in [Controller.onLaunchAnimationProgress]. No animation will start if there is no window * opening. * - * If [controller] is null, then the intent will be started and no animation will run. + * If [controller] is null or [animate] is false, then the intent will be started and no + * animation will run. * * This method will throw any exception thrown by [intentStarter]. */ + @JvmOverloads inline fun startIntentWithAnimation( controller: Controller?, + animate: Boolean = true, intentStarter: (RemoteAnimationAdapter?) -> Int ) { - if (controller == null) { + if (controller == null || !animate) { intentStarter(null) + controller?.callOnIntentStartedOnMainThread(willAnimate = false) return } @@ -95,7 +100,7 @@ class ActivityLaunchAnimator(context: Context) { val launchResult = intentStarter(animationAdapter) val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT || launchResult == ActivityManager.START_SUCCESS - runner.context.mainExecutor.execute { controller.onIntentStarted(willAnimate) } + controller.callOnIntentStartedOnMainThread(willAnimate) // If we expect an animation, post a timeout to cancel it in case the remote animation is // never started. @@ -104,17 +109,30 @@ class ActivityLaunchAnimator(context: Context) { } } + @PublishedApi + internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) { + if (Looper.myLooper() != Looper.getMainLooper()) { + this.getRootView().context.mainExecutor.execute { + this.onIntentStarted(willAnimate) + } + } else { + this.onIntentStarted(willAnimate) + } + } + /** * Same as [startIntentWithAnimation] but allows [intentStarter] to throw a * [PendingIntent.CanceledException] which must then be handled by the caller. This is useful * for Java caller starting a [PendingIntent]. */ @Throws(PendingIntent.CanceledException::class) + @JvmOverloads fun startPendingIntentWithAnimation( controller: Controller?, + animate: Boolean = true, intentStarter: PendingIntentStarter ) { - startIntentWithAnimation(controller) { intentStarter.startPendingIntent(it) } + startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) } } /** Create a new animation [Runner] controlled by [controller]. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt index c85b62fc0d9a8..81942209a055a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt @@ -6,6 +6,7 @@ import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.statusbar.NotificationShadeDepthController import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController import kotlin.math.ceil import kotlin.math.max @@ -14,7 +15,8 @@ import kotlin.math.max class NotificationLaunchAnimatorControllerProvider( private val notificationShadeWindowViewController: NotificationShadeWindowViewController, private val notificationListContainer: NotificationListContainer, - private val depthController: NotificationShadeDepthController + private val depthController: NotificationShadeDepthController, + private val headsUpManager: HeadsUpManagerPhone ) { fun getAnimatorController( notification: ExpandableNotificationRow @@ -23,7 +25,8 @@ class NotificationLaunchAnimatorControllerProvider( notificationShadeWindowViewController, notificationListContainer, depthController, - notification + notification, + headsUpManager ) } } @@ -37,8 +40,11 @@ class NotificationLaunchAnimatorController( private val notificationShadeWindowViewController: NotificationShadeWindowViewController, private val notificationListContainer: NotificationListContainer, private val depthController: NotificationShadeDepthController, - private val notification: ExpandableNotificationRow + private val notification: ExpandableNotificationRow, + private val headsUpManager: HeadsUpManagerPhone ) : ActivityLaunchAnimator.Controller { + private val notificationKey = notification.entry.sbn.key + override fun getRootView(): View = notification.rootView override fun createAnimatorState(): ActivityLaunchAnimator.State { @@ -76,12 +82,25 @@ class NotificationLaunchAnimatorController( override fun onIntentStarted(willAnimate: Boolean) { notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate) + + if (!willAnimate) { + removeHun(animate = true) + } + } + + private fun removeHun(animate: Boolean) { + if (!headsUpManager.isAlerting(notificationKey)) { + return + } + + headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate) } override fun onLaunchAnimationCancelled() { // TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started // here? notificationShadeWindowViewController.setExpandAnimationRunning(false) + removeHun(animate = true) } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { @@ -99,6 +118,7 @@ class NotificationLaunchAnimatorController( notificationShadeWindowViewController.setExpandAnimationRunning(false) notificationListContainer.setExpandingNotification(null) applyParams(null) + removeHun(animate = false) } private fun applyParams(params: ExpandAnimationParameters?) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 3827123f0160b..4b545ebf2a057 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -301,7 +301,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } /////////////////////////////////////////////////////////////////////////////////////////////// - // HeadsUpManager public methods overrides: + // HeadsUpManager public methods overrides and overloads: @Override public boolean isTrackingHeadsUp() { @@ -318,6 +318,18 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, mSwipedOutKeys.add(key); } + public boolean removeNotification(@NonNull String key, boolean releaseImmediately, + boolean animate) { + if (animate) { + return removeNotification(key, releaseImmediately); + } else { + mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false); + boolean removed = removeNotification(key, releaseImmediately); + mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true); + return removed; + } + } + /////////////////////////////////////////////////////////////////////////////////////////////// // Dumpable overrides: 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 dd9ebfcd03de0..190dca0579c22 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1422,7 +1422,8 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider( mNotificationShadeWindowViewController, mStackScrollerController.getNotificationListContainer(), - mNotificationShadeDepthControllerLazy.get() + mNotificationShadeDepthControllerLazy.get(), + mHeadsUpManager ); // TODO: inject this. @@ -2795,7 +2796,7 @@ public class StatusBar extends SystemUI implements DemoMode, intent, mLockscreenUserManager.getCurrentUserId()); ActivityLaunchAnimator.Controller animController = null; - if (animationController != null && areLaunchAnimationsEnabled()) { + if (animationController != null) { animController = dismissShade ? new StatusBarLaunchAnimatorController( animationController, this, true /* isLaunchForActivity */) : animationController; @@ -2811,46 +2812,48 @@ public class StatusBar extends SystemUI implements DemoMode, intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(flags); - int[] result = new int[] { ActivityManager.START_CANCELED }; + int[] result = new int[]{ActivityManager.START_CANCELED}; - mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda, (adapter) -> { - ActivityOptions options = new ActivityOptions( - getActivityOptions(mDisplayId, adapter)); - options.setDisallowEnterPictureInPictureWhileLaunching( - disallowEnterPictureInPictureWhileLaunching); - if (CameraIntents.isInsecureCameraIntent(intent)) { - // Normally an activity will set it's requested rotation - // animation on its window. However when launching an activity - // causes the orientation to change this is too late. In these cases - // the default animation is used. This doesn't look good for - // the camera (as it rotates the camera contents out of sync - // with physical reality). So, we ask the WindowManager to - // force the crossfade animation if an orientation change - // happens to occur during the launch. - options.setRotationAnimationHint( - WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); - } - if (intent.getAction() == Settings.Panel.ACTION_VOLUME) { - // Settings Panel is implemented as activity(not a dialog), so - // underlying app is paused and may enter picture-in-picture mode - // as a result. - // So we need to disable picture-in-picture mode here - // if it is volume panel. - options.setDisallowEnterPictureInPictureWhileLaunching(true); - } + mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda, + areLaunchAnimationsEnabled(), (adapter) -> { + ActivityOptions options = new ActivityOptions( + getActivityOptions(mDisplayId, adapter)); + options.setDisallowEnterPictureInPictureWhileLaunching( + disallowEnterPictureInPictureWhileLaunching); + if (CameraIntents.isInsecureCameraIntent(intent)) { + // Normally an activity will set it's requested rotation + // animation on its window. However when launching an activity + // causes the orientation to change this is too late. In these cases + // the default animation is used. This doesn't look good for + // the camera (as it rotates the camera contents out of sync + // with physical reality). So, we ask the WindowManager to + // force the crossfade animation if an orientation change + // happens to occur during the launch. + options.setRotationAnimationHint( + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); + } + if (intent.getAction() == Settings.Panel.ACTION_VOLUME) { + // Settings Panel is implemented as activity(not a dialog), so + // underlying app is paused and may enter picture-in-picture mode + // as a result. + // So we need to disable picture-in-picture mode here + // if it is volume panel. + options.setDisallowEnterPictureInPictureWhileLaunching(true); + } - try { - result[0] = ActivityTaskManager.getService().startActivityAsUser( - null, mContext.getBasePackageName(), mContext.getAttributionTag(), - intent, - intent.resolveTypeIfNeeded(mContext.getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, - options.toBundle(), UserHandle.CURRENT.getIdentifier()); - } catch (RemoteException e) { - Log.w(TAG, "Unable to start activity", e); - } - return result[0]; - }); + try { + result[0] = ActivityTaskManager.getService().startActivityAsUser( + null, mContext.getBasePackageName(), + mContext.getAttributionTag(), + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, + options.toBundle(), UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start activity", e); + } + return result[0]; + }); if (callback != null) { callback.onActivityStarted(result[0]); @@ -4569,19 +4572,17 @@ public class StatusBar extends SystemUI implements DemoMode, && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); - boolean animate = animationController != null && areLaunchAnimationsEnabled(); - boolean collapse = !animate; + boolean collapse = animationController == null; executeActionDismissingKeyguard(() -> { try { // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the // shade is collapsed after the animation (or when it is cancelled, aborted, etc). ActivityLaunchAnimator.Controller controller = - animate ? new StatusBarLaunchAnimatorController(animationController, this, - intent.isActivity()) - : null; + animationController != null ? new StatusBarLaunchAnimatorController( + animationController, this, intent.isActivity()) : null; mActivityLaunchAnimator.startPendingIntentWithAnimation( - controller, + controller, areLaunchAnimationsEnabled(), (animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null, null, getActivityOptions(mDisplayId, animationAdapter))); } catch (PendingIntent.CanceledException e) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 4356b52d27ea6..ab58aae6857e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -283,7 +283,13 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey()); // TODO: Some of this code may be able to move to NotificationEntryManager. - removeHUN(row); + String key = row.getEntry().getSbn().getKey(); + if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) { + // Release the HUN notification to the shade. + if (mPresenter.isPresenterFullyCollapsed()) { + HeadsUpUtil.setIsClickedHeadsUpNotification(row, true); + } + } final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed( entry, row, controller, intent, @@ -331,6 +337,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // bypass work challenge if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId, intent.getIntentSender(), notificationKey)) { + removeHUN(row); // Show work challenge, do not run PendingIntent and // remove notification collapseOnMainThread(); @@ -350,6 +357,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit final boolean canBubble = entry.canBubble(); if (canBubble) { mLogger.logExpandingBubble(notificationKey); + removeHUN(row); expandBubbleStackOnMainThread(entry); } else { startNotificationIntent( @@ -422,14 +430,13 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit boolean isActivityIntent) { mLogger.logStartNotificationIntent(entry.getKey(), intent); try { - ActivityLaunchAnimator.Controller animationController = null; - if (!wasOccluded && mStatusBar.areLaunchAnimationsEnabled()) { - animationController = new StatusBarLaunchAnimatorController( - mNotificationAnimationProvider.getAnimatorController(row), mStatusBar, - isActivityIntent); - } + ActivityLaunchAnimator.Controller animationController = + new StatusBarLaunchAnimatorController( + mNotificationAnimationProvider.getAnimatorController(row), mStatusBar, + isActivityIntent); mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController, + !wasOccluded && mStatusBar.areLaunchAnimationsEnabled(), (adapter) -> { long eventTime = row.getAndResetLastActionUpTime(); Bundle options = eventTime > 0 @@ -442,13 +449,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit return intent.sendAndReturnResult(mContext, 0, fillInIntent, null, null, null, options); }); - - // Note that other cases when we should still collapse (like activity already on top) is - // handled by the StatusBarLaunchAnimatorController. - boolean shouldCollapse = animationController == null; - if (shouldCollapse) { - collapseOnMainThread(); - } } catch (PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. // Just log the exception message. @@ -462,34 +462,19 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit ExpandableNotificationRow row) { mActivityStarter.dismissKeyguardThenExecute(() -> { AsyncTask.execute(() -> { - ActivityLaunchAnimator.Controller animationController = null; - if (mStatusBar.areLaunchAnimationsEnabled()) { - animationController = new StatusBarLaunchAnimatorController( - mNotificationAnimationProvider.getAnimatorController(row), mStatusBar, - true /* isActivityIntent */); - } + ActivityLaunchAnimator.Controller animationController = + new StatusBarLaunchAnimatorController( + mNotificationAnimationProvider.getAnimatorController(row), + mStatusBar, true /* isActivityIntent */); mActivityLaunchAnimator.startIntentWithAnimation( - animationController, + animationController, mStatusBar.areLaunchAnimationsEnabled(), (adapter) -> TaskStackBuilder.create(mContext) .addNextIntentWithParentStack(intent) .startActivities(getActivityOptions( mStatusBar.getDisplayId(), adapter), new UserHandle(UserHandle.getUserId(appUid)))); - - // Note that other cases when we should still collapse (like activity already on - // top) is handled by the StatusBarLaunchAnimatorController. - boolean shouldCollapse = animationController == null; - - // Putting it back on the main thread, since we're touching views - mMainThreadHandler.post(() -> { - removeHUN(row); - if (shouldCollapse) { - mCommandQueue.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, - true /* force */); - } - }); }); return true; }, null, false /* afterKeyguardGone */); @@ -508,26 +493,16 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit tsb.addNextIntent(intent); } - ActivityLaunchAnimator.Controller animationController = null; - if (mStatusBar.areLaunchAnimationsEnabled()) { - animationController = new StatusBarLaunchAnimatorController( - ActivityLaunchAnimator.Controller.fromView(view), mStatusBar, - true /* isActivityIntent */); - } + ActivityLaunchAnimator.Controller animationController = + new StatusBarLaunchAnimatorController( + ActivityLaunchAnimator.Controller.fromView(view), mStatusBar, + true /* isActivityIntent */); mActivityLaunchAnimator.startIntentWithAnimation(animationController, + mStatusBar.areLaunchAnimationsEnabled(), (adapter) -> tsb.startActivities( getActivityOptions(mStatusBar.getDisplayId(), adapter), UserHandle.CURRENT)); - - // Note that other cases when we should still collapse (like activity already on - // top) is handled by the StatusBarLaunchAnimatorController. - boolean shouldCollapse = animationController == null; - if (shouldCollapse) { - // Putting it back on the main thread, since we're touching views - mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); - } }); return true; }, null, false /* afterKeyguardGone */); @@ -536,11 +511,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private void removeHUN(ExpandableNotificationRow row) { String key = row.getEntry().getSbn().getKey(); if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) { - // Release the HUN notification to the shade. - if (mPresenter.isPresenterFullyCollapsed()) { - HeadsUpUtil.setIsClickedHeadsUpNotification(row, true); - } - // In most cases, when FLAG_AUTO_CANCEL is set, the notification will // become canceled shortly by NoMan, but we can't assume that. mHeadsUpManager.removeNotification(key, true /* releaseImmediately */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt index 0bf2d503e5a05..e3e2572b9b4ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt @@ -341,7 +341,6 @@ interface SmartActionInflater { activityStarter.startPendingIntentDismissingKeyguard(action.actionIntent, entry.row) { smartReplyController .smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant) - headsUpManager.removeNotification(entry.key, true /* releaseImmediately */) } } } 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 c023610b6052b..fbba09a255e73 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt @@ -44,12 +44,13 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { private fun startIntentWithAnimation( controller: ActivityLaunchAnimator.Controller? = this.controller, + animate: Boolean = true, intentStarter: (RemoteAnimationAdapter?) -> Int ) { // We start in a new thread so that we can ensure that the callbacks are called in the main // thread. thread { - activityLaunchAnimator.startIntentWithAnimation(controller, intentStarter) + activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter) }.join() } @@ -94,6 +95,16 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { assertFalse(willAnimateCaptor.value) } + @Test + fun doesNotAnimateIfAnimateIsFalse() { + val willAnimateCaptor = ArgumentCaptor.forClass(Boolean::class.java) + startIntentWithAnimation(animate = false) { ActivityManager.START_SUCCESS } + + waitForIdleSync() + verify(controller).onIntentStarted(willAnimateCaptor.capture()) + assertFalse(willAnimateCaptor.value) + } + @Test fun doesNotStartIfAnimationIsCancelled() { val runner = activityLaunchAnimator.createRunner(controller) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 5170168c174ca..be86af585fc5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -61,6 +61,7 @@ import com.android.systemui.statusbar.NotificationClickNotifier; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -73,6 +74,7 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; +import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -184,6 +186,14 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry())) .thenReturn(null); + HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class); + NotificationLaunchAnimatorControllerProvider notificationAnimationProvider = + new NotificationLaunchAnimatorControllerProvider( + mock(NotificationShadeWindowViewController.class), mock( + NotificationListContainer.class), + mock(NotificationShadeDepthController.class), + headsUpManager); + mNotificationActivityStarter = new StatusBarNotificationActivityStarter.Builder( getContext(), @@ -192,7 +202,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mUiBgExecutor, mEntryManager, mNotifPipeline, - mock(HeadsUpManagerPhone.class), + headsUpManager, mActivityStarter, mClickNotifier, mock(StatusBarStateController.class), @@ -220,8 +230,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { .setNotificationPanelViewController( mock(NotificationPanelViewController.class)) .setActivityLaunchAnimator(mActivityLaunchAnimator) - .setNotificationAnimatorControllerProvider( - mock(NotificationLaunchAnimatorControllerProvider.class)) + .setNotificationAnimatorControllerProvider(notificationAnimationProvider) .build(); // set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg @@ -259,7 +268,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { // Then verify(mShadeController, atLeastOnce()).collapsePanel(); - verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(eq(null), any()); + verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(), + eq(false) /* animate */, any()); verify(mAssistManager).hideAssist();