Merge "Fixed an issue where a notification may not be updated"
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user