Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2dc14459 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Automerger Merge Worker
Browse files

Merge "Fix HUN launch animation." into sc-dev am: 969eda42 am: 23ac6132

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

Change-Id: If06b1fa5d1c483d6241b8d3f395f7db97cbe4954
parents 83c89ff6 23ac6132
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -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]. */
+23 −3
Original line number Diff line number Diff line
@@ -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?) {
+13 −1
Original line number Diff line number Diff line
@@ -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:

+48 −47
Original line number Diff line number Diff line
@@ -1412,7 +1412,8 @@ public class StatusBar extends SystemUI implements DemoMode,
        mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
                mNotificationShadeWindowViewController,
                mStackScrollerController.getNotificationListContainer(),
                mNotificationShadeDepthControllerLazy.get()
                mNotificationShadeDepthControllerLazy.get(),
                mHeadsUpManager
        );

        // TODO: inject this.
@@ -2785,7 +2786,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;
@@ -2803,7 +2804,8 @@ public class StatusBar extends SystemUI implements DemoMode,
            intent.addFlags(flags);
            int[] result = new int[]{ActivityManager.START_CANCELED};

            mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda, (adapter) -> {
            mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda,
                    areLaunchAnimationsEnabled(), (adapter) -> {
                        ActivityOptions options = new ActivityOptions(
                                getActivityOptions(mDisplayId, adapter));
                        options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -2831,7 +2833,8 @@ public class StatusBar extends SystemUI implements DemoMode,

                        try {
                            result[0] = ActivityTaskManager.getService().startActivityAsUser(
                            null, mContext.getBasePackageName(), mContext.getAttributionTag(),
                                    null, mContext.getBasePackageName(),
                                    mContext.getAttributionTag(),
                                    intent,
                                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                    null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
@@ -4559,19 +4562,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) {
+24 −54
Original line number Diff line number Diff line
@@ -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(
            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 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 */);
Loading