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

Commit 63cc5a64 authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge "Fixed an issue where a notification may not be updated"

parents 08096662 4a38f232
Loading
Loading
Loading
Loading
+56 −20
Original line number Diff line number Diff line
@@ -29,18 +29,14 @@ import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;

import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.shared.system.SurfaceControlCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowView;

/**
@@ -59,28 +55,28 @@ public class ActivityLaunchAnimator {
    private final NotificationPanelView mNotificationPanel;
    private final NotificationListContainer mNotificationContainer;
    private final StatusBarWindowView mStatusBarWindow;
    private final StatusBarStateController mStatusBarStateController;
    private StatusBar mStatusBar;
    private Callback mCallback;
    private final Runnable mTimeoutRunnable = () -> {
        setAnimationPending(false);
        mStatusBar.collapsePanel(true /* animate */);
        mCallback.onExpandAnimationTimedOut();
    };
    private boolean mAnimationPending;
    private boolean mAnimationRunning;
    private boolean mIsLaunchForActivity;

    public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
            StatusBar statusBar,
            Callback callback,
            NotificationPanelView notificationPanel,
            NotificationListContainer container) {
        mNotificationPanel = notificationPanel;
        mNotificationContainer = container;
        mStatusBarWindow = statusBarWindow;
        mStatusBar = statusBar;
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mCallback = callback;
    }

    public RemoteAnimationAdapter getLaunchAnimation(
            ExpandableNotificationRow sourceNotification, boolean occluded) {
        if (mStatusBarStateController.getState() != StatusBarState.SHADE || occluded) {
        if (!mCallback.areLaunchAnimationsEnabled() || occluded) {
            return null;
        }
        AnimationRunner animationRunner = new AnimationRunner(sourceNotification);
@@ -92,10 +88,21 @@ public class ActivityLaunchAnimator {
        return mAnimationPending;
    }

    public void setLaunchResult(int launchResult) {
    /**
     * Set the launch result the intent requested
     *
     * @param launchResult the launch result
     * @param wasIntentActivity was this launch for an activity
     */
    public void setLaunchResult(int launchResult, boolean wasIntentActivity) {
        mIsLaunchForActivity = wasIntentActivity;
        setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT
                || launchResult == ActivityManager.START_SUCCESS)
                        && mStatusBarStateController.getState() == StatusBarState.SHADE);
                        && mCallback.areLaunchAnimationsEnabled());
    }

    public boolean isLaunchForActivity() {
        return mIsLaunchForActivity;
    }

    private void setAnimationPending(boolean pending) {
@@ -108,12 +115,16 @@ public class ActivityLaunchAnimator {
        }
    }

    public boolean isAnimationRunning() {
        return mAnimationRunning;
    }

    class AnimationRunner extends IRemoteAnimationRunner.Stub {

        private final ExpandableNotificationRow mSourceNotification;
        private final ExpandAnimationParameters mParams;
        private final Rect mWindowCrop = new Rect();
        private boolean mInstantCollapsePanel = true;
        private boolean mIsFullScreenLaunch = true;
        private final SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;

        public AnimationRunner(ExpandableNotificationRow sourceNofitication) {
@@ -136,10 +147,10 @@ public class ActivityLaunchAnimator {
                }

                setExpandAnimationRunning(true);
                mInstantCollapsePanel = primary.position.y == 0
                mIsFullScreenLaunch = primary.position.y == 0
                        && primary.sourceContainerBounds.height()
                                >= mNotificationPanel.getHeight();
                if (!mInstantCollapsePanel) {
                if (!mIsFullScreenLaunch) {
                    mNotificationPanel.collapseWithDuration(ANIMATION_DURATION);
                }
                ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
@@ -192,9 +203,6 @@ public class ActivityLaunchAnimator {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        setExpandAnimationRunning(false);
                        if (mInstantCollapsePanel) {
                            mStatusBar.collapsePanel(false /* animate */);
                        }
                        invokeCallback(iRemoteAnimationFinishedCallback);
                    }
                });
@@ -228,7 +236,9 @@ public class ActivityLaunchAnimator {
            mSourceNotification.setExpandAnimationRunning(running);
            mStatusBarWindow.setExpandAnimationRunning(running);
            mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null);
            mAnimationRunning = running;
            if (!running) {
                mCallback.onExpandAnimationFinished(mIsFullScreenLaunch);
                applyParamsToNotification(null);
                applyParamsToNotificationList(null);
            }
@@ -257,7 +267,7 @@ public class ActivityLaunchAnimator {
        public void onAnimationCancelled() throws RemoteException {
            mSourceNotification.post(() -> {
                setAnimationPending(false);
                mStatusBar.onLaunchAnimationCancelled();
                mCallback.onLaunchAnimationCancelled();
            });
        }
    };
@@ -319,4 +329,30 @@ public class ActivityLaunchAnimator {
            return startTranslationZ;
        }
    }

    public interface Callback {

        /**
         * Called when the launch animation was cancelled.
         */
        void onLaunchAnimationCancelled();

        /**
         * Called when the launch animation has timed out without starting an actual animation.
         */
        void onExpandAnimationTimedOut();

        /**
         * Called when the expand animation has finished.
         *
         * @param launchIsFullScreen True if this launch was fullscreen, such that now the window
         *                           fills the whole screen
         */
        void onExpandAnimationFinished(boolean launchIsFullScreen);

        /**
         * Are animations currently enabled.
         */
        boolean areLaunchAnimationsEnabled();
    }
}
+37 −7
Original line number Diff line number Diff line
@@ -255,7 +255,8 @@ public class StatusBar extends SystemUI implements DemoMode,
        ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter,
        StatusBarStateController.StateListener,  AmbientPulseManager.OnAmbientChangedListener {
        StatusBarStateController.StateListener,  AmbientPulseManager.OnAmbientChangedListener,
        ActivityLaunchAnimator.Callback {
    public static final boolean MULTIUSER_DEBUG = false;

    public static final boolean ENABLE_CHILD_NOTIFICATIONS
@@ -1906,6 +1907,7 @@ public class StatusBar extends SystemUI implements DemoMode,
        }
    }

    @Override
    public void onLaunchAnimationCancelled() {
        if (!isCollapsing()) {
            onClosingFinished();
@@ -1916,6 +1918,31 @@ public class StatusBar extends SystemUI implements DemoMode,
        return mHeadsUpAppearanceController.shouldBeVisible();
    }

    @Override
    public void onExpandAnimationFinished(boolean launchIsFullScreen) {
        if (!isCollapsing()) {
            onClosingFinished();
        }
        if (launchIsFullScreen) {
            instantCollapseNotificationPanel();
        }
    }

    @Override
    public void onExpandAnimationTimedOut() {
        if (isPresenterFullyCollapsed() && !isCollapsing()
                && !mActivityLaunchAnimator.isLaunchForActivity()) {
            onClosingFinished();
        } else {
            collapsePanel(true /* animate */);
        }
    }

    @Override
    public boolean areLaunchAnimationsEnabled() {
        return mState == StatusBarState.SHADE;
    }

    /**
     * All changes to the status bar and notifications funnel through here and are batched.
     */
@@ -3353,7 +3380,9 @@ public class StatusBar extends SystemUI implements DemoMode,
    }

    public boolean isCollapsing() {
        return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending();
        return mNotificationPanel.isCollapsing()
                || mActivityLaunchAnimator.isAnimationPending()
                || mActivityLaunchAnimator.isAnimationRunning();
    }

    public void addPostCollapseAction(Runnable r) {
@@ -4738,7 +4767,8 @@ public class StatusBar extends SystemUI implements DemoMode,
                : notification.fullScreenIntent;
        final String notificationKey = sbn.getKey();

        final boolean afterKeyguardGone = intent.isActivity()
        boolean isActivityIntent = intent.isActivity();
        final boolean afterKeyguardGone = isActivityIntent
                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
                mLockscreenUserManager.getCurrentUserId());
        final boolean wasOccluded = mIsOccluded;
@@ -4779,7 +4809,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                    // If we are launching a work activity and require to launch
                    // separate work challenge, we defer the activity action and cancel
                    // notification until work challenge is unlocked.
                    if (intent.isActivity()) {
                    if (isActivityIntent) {
                        final int userId = intent.getCreatorUserHandle().getIdentifier();
                        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                                && mKeyguardManager.isDeviceLocked(userId)) {
@@ -4815,7 +4845,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                        }
                        launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
                                null, null, getActivityOptions(adapter));
                        mActivityLaunchAnimator.setLaunchResult(launchResult);
                        mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
                    } catch (RemoteException | PendingIntent.CanceledException e) {
                        // the stack trace isn't very helpful here.
                        // Just log the exception message.
@@ -4823,7 +4853,7 @@ public class StatusBar extends SystemUI implements DemoMode,

                        // TODO: Dismiss Keyguard.
                    }
                    if (intent.isActivity()) {
                    if (isActivityIntent) {
                        mAssistManager.hideAssist();
                    }
                }
@@ -4942,7 +4972,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                        .startActivities(getActivityOptions(
                                mActivityLaunchAnimator.getLaunchAnimation(row, mIsOccluded)),
                                new UserHandle(UserHandle.getUserId(appUid)));
                mActivityLaunchAnimator.setLaunchResult(launchResult);
                mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
                if (shouldCollapse()) {
                    // Putting it back on the main thread, since we're touching views
                    mStatusBarWindow.post(() -> animateCollapsePanels(
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.statusbar.notification;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.RemoteAnimationAdapter;
import android.view.View;
import android.widget.FrameLayout;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBarWindowView;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.stubbing.Answer;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class ActivityLaunchAnimatorTest extends SysuiTestCase {

    private ActivityLaunchAnimator mLaunchAnimator;
    private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class);
    private StatusBarWindowView mStatusBarWindowView = mock(StatusBarWindowView.class);
    private NotificationListContainer mNotificationContainer
            = mock(NotificationListContainer.class);
    private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class);

    @Before
    public void setUp() throws Exception {
        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(true);
        mLaunchAnimator = new ActivityLaunchAnimator(
                mStatusBarWindowView,
                mCallback,
                mock(NotificationPanelView.class),
                mNotificationContainer);

    }

    @Test
    public void testReturnsNullIfNotEnabled() {
        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(false);
        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
                false /* occluded */);
        Assert.assertTrue("The LaunchAnimator generated an animation even though animations are "
                        + "disabled", launchAnimation == null);
    }

    @Test
    public void testNotWorkingWhenOccluded() {
        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(false);
        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
                true /* occluded */);
        Assert.assertTrue("The LaunchAnimator generated an animation even though we're occluded",
                launchAnimation == null);
    }

    @Test
    public void testTimeoutCalled() {
        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
                false /* occluded */);
        Assert.assertTrue("No animation generated", launchAnimation != null);
        executePostsImmediately(mStatusBarWindowView);
        mLaunchAnimator.setLaunchResult(ActivityManager.START_SUCCESS,
                true /* wasIntentActivity */);
        verify(mCallback).onExpandAnimationTimedOut();
    }

    private void executePostsImmediately(View view) {
        doAnswer((i) -> {
            Runnable run = i.getArgument(0);
            run.run();
            return null;
        }).when(view).post(any());
        doAnswer((i) -> {
            Runnable run = i.getArgument(0);
            run.run();
            return null;
        }).when(view).postDelayed(any(), anyLong());
    }
}