diff options
7 files changed, 117 insertions, 38 deletions
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java index b6eb015008af..e2eb3fb5ddc6 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java @@ -45,6 +45,7 @@ import com.android.systemui.car.bluetooth.CarBatteryController; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.DismissCallbackRegistry; @@ -172,6 +173,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, + @Main Executor mainExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, @@ -252,6 +254,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt displayMetrics, metricsLogger, uiBgExecutor, + mainExecutor, notificationMediaManager, lockScreenUserManager, remoteInputManager, diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java index dc2eb04c2990..4f6890e3aba1 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java @@ -33,6 +33,7 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -147,6 +148,7 @@ public class CarStatusBarModule { DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, + @Main Executor mainExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, @@ -226,6 +228,7 @@ public class CarStatusBarModule { displayMetrics, metricsLogger, uiBgExecutor, + mainExecutor, notificationMediaManager, lockScreenUserManager, remoteInputManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java index 6aef6b407f37..85560fefd952 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.Nullable; import android.app.ActivityManager; import android.graphics.Matrix; import android.graphics.Rect; @@ -41,6 +42,8 @@ import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; +import java.util.concurrent.Executor; + /** * A class that allows activities to be launched in a seamless way where the notification * transforms nicely into the starting window. @@ -59,6 +62,7 @@ public class ActivityLaunchAnimator { private final float mWindowCornerRadius; private final NotificationShadeWindowViewController mNotificationShadeWindowViewController; private final NotificationShadeDepthController mDepthController; + private final Executor mMainExecutor; private Callback mCallback; private final Runnable mTimeoutRunnable = () -> { setAnimationPending(false); @@ -73,12 +77,14 @@ public class ActivityLaunchAnimator { Callback callback, NotificationPanelViewController notificationPanel, NotificationShadeDepthController depthController, - NotificationListContainer container) { + NotificationListContainer container, + Executor mainExecutor) { mNotificationPanel = notificationPanel; mNotificationContainer = container; mDepthController = depthController; mNotificationShadeWindowViewController = notificationShadeWindowViewController; mCallback = callback; + mMainExecutor = mainExecutor; mWindowCornerRadius = ScreenDecorationsUtils .getWindowCornerRadius(mNotificationShadeWindowViewController.getView() .getResources()); @@ -91,7 +97,7 @@ public class ActivityLaunchAnimator { return null; } AnimationRunner animationRunner = new AnimationRunner( - (ExpandableNotificationRow) sourceView); + (ExpandableNotificationRow) sourceView, mMainExecutor); return new RemoteAnimationAdapter(animationRunner, ANIMATION_DURATION, ANIMATION_DURATION - 150 /* statusBarTransitionDelay */); } @@ -134,17 +140,18 @@ public class ActivityLaunchAnimator { class AnimationRunner extends IRemoteAnimationRunner.Stub { - private final ExpandableNotificationRow mSourceNotification; - private final ExpandAnimationParameters mParams; + private final ExpandAnimationParameters mParams = new ExpandAnimationParameters(); private final Rect mWindowCrop = new Rect(); private final float mNotificationCornerRadius; + private final Executor mMainExecutor; + @Nullable private ExpandableNotificationRow mSourceNotification; + @Nullable private SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier; private float mCornerRadius; private boolean mIsFullScreenLaunch = true; - private final SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier; - public AnimationRunner(ExpandableNotificationRow sourceNofitication) { - mSourceNotification = sourceNofitication; - mParams = new ExpandAnimationParameters(); + AnimationRunner(ExpandableNotificationRow sourceNotification, Executor mainExecutor) { + mMainExecutor = mainExecutor; + mSourceNotification = sourceNotification; mSyncRtTransactionApplier = new SyncRtSurfaceTransactionApplier(mSourceNotification); mNotificationCornerRadius = Math.max(mSourceNotification.getCurrentTopRoundness(), mSourceNotification.getCurrentBottomRoundness()); @@ -155,13 +162,15 @@ public class ActivityLaunchAnimator { RemoteAnimationTarget[] remoteAnimationWallpaperTargets, IRemoteAnimationFinishedCallback iRemoteAnimationFinishedCallback) throws RemoteException { - mSourceNotification.post(() -> { + mMainExecutor.execute(() -> { RemoteAnimationTarget primary = getPrimaryRemoteAnimationTarget( remoteAnimationTargets); - if (primary == null) { + if (primary == null || mSourceNotification == null) { setAnimationPending(false); invokeCallback(iRemoteAnimationFinishedCallback); mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */); + mSourceNotification = null; + mSyncRtTransactionApplier = null; return; } @@ -172,28 +181,14 @@ public class ActivityLaunchAnimator { if (!mIsFullScreenLaunch) { mNotificationPanel.collapseWithDuration(ANIMATION_DURATION); } - ValueAnimator anim = ValueAnimator.ofFloat(0, 1); - mParams.startPosition = mSourceNotification.getLocationOnScreen(); - mParams.startTranslationZ = mSourceNotification.getTranslationZ(); - mParams.startClipTopAmount = mSourceNotification.getClipTopAmount(); - if (mSourceNotification.isChildInGroup()) { - int parentClip = mSourceNotification - .getNotificationParent().getClipTopAmount(); - mParams.parentStartClipTopAmount = parentClip; - // We need to calculate how much the child is clipped by the parent - // because children always have 0 clipTopAmount - if (parentClip != 0) { - float childClip = parentClip - - mSourceNotification.getTranslationY(); - if (childClip > 0.0f) { - mParams.startClipTopAmount = (int) Math.ceil(childClip); - } - } - } - int targetWidth = primary.sourceContainerBounds.width(); - int notificationHeight = mSourceNotification.getActualHeight() + mParams.initFrom(mSourceNotification); + final int targetWidth = primary.sourceContainerBounds.width(); + final int notificationHeight; + final int notificationWidth; + notificationHeight = mSourceNotification.getActualHeight() - mSourceNotification.getClipBottomAmount(); - int notificationWidth = mSourceNotification.getWidth(); + notificationWidth = mSourceNotification.getWidth(); + ValueAnimator anim = ValueAnimator.ofFloat(0, 1); anim.setDuration(ANIMATION_DURATION); anim.setInterpolator(Interpolators.LINEAR); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @@ -231,6 +226,11 @@ public class ActivityLaunchAnimator { }); } + @Nullable + ExpandableNotificationRow getRow() { + return mSourceNotification; + } + private void invokeCallback(IRemoteAnimationFinishedCallback callback) { try { callback.onAnimationFinished(); @@ -253,7 +253,9 @@ public class ActivityLaunchAnimator { private void setExpandAnimationRunning(boolean running) { mNotificationPanel.setLaunchingNotification(running); - mSourceNotification.setExpandAnimationRunning(running); + if (mSourceNotification != null) { + mSourceNotification.setExpandAnimationRunning(running); + } mNotificationShadeWindowViewController.setExpandAnimationRunning(running); mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null); mAnimationRunning = running; @@ -261,6 +263,8 @@ public class ActivityLaunchAnimator { mCallback.onExpandAnimationFinished(mIsFullScreenLaunch); applyParamsToNotification(null); applyParamsToNotificationShade(null); + mSourceNotification = null; + mSyncRtTransactionApplier = null; } } @@ -272,7 +276,9 @@ public class ActivityLaunchAnimator { } private void applyParamsToNotification(ExpandAnimationParameters params) { - mSourceNotification.applyExpandAnimationParams(params); + if (mSourceNotification != null) { + mSourceNotification.applyExpandAnimationParams(params); + } } private void applyParamsToWindow(RemoteAnimationTarget app) { @@ -287,14 +293,18 @@ public class ActivityLaunchAnimator { .withCornerRadius(mCornerRadius) .withVisibility(true) .build(); - mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params); + if (mSyncRtTransactionApplier != null) { + mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params); + } } @Override public void onAnimationCancelled() throws RemoteException { - mSourceNotification.post(() -> { + mMainExecutor.execute(() -> { setAnimationPending(false); mCallback.onLaunchAnimationCancelled(); + mSourceNotification = null; + mSyncRtTransactionApplier = null; }); } }; @@ -359,6 +369,28 @@ public class ActivityLaunchAnimator { public float getStartTranslationZ() { return startTranslationZ; } + + /** Initialize with data pulled from the row. */ + void initFrom(@Nullable ExpandableNotificationRow row) { + if (row == null) { + return; + } + startPosition = row.getLocationOnScreen(); + startTranslationZ = row.getTranslationZ(); + startClipTopAmount = row.getClipTopAmount(); + if (row.isChildInGroup()) { + int parentClip = row.getNotificationParent().getClipTopAmount(); + parentStartClipTopAmount = parentClip; + // We need to calculate how much the child is clipped by the parent + // because children always have 0 clipTopAmount + if (parentClip != 0) { + float childClip = parentClip - row.getTranslationY(); + if (childClip > 0.0f) { + startClipTopAmount = (int) Math.ceil(childClip); + } + } + } + } } public interface Callback { 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 ca65665d4ae5..420b75c688ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -140,6 +140,7 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; @@ -467,6 +468,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final ScrimController mScrimController; protected DozeScrimController mDozeScrimController; private final Executor mUiBgExecutor; + private final Executor mMainExecutor; protected boolean mDozing; @@ -625,6 +627,7 @@ public class StatusBar extends SystemUI implements DemoMode, DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, + @Main Executor mainExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, @@ -705,6 +708,7 @@ public class StatusBar extends SystemUI implements DemoMode, mDisplayMetrics = displayMetrics; mMetricsLogger = metricsLogger; mUiBgExecutor = uiBgExecutor; + mMainExecutor = mainExecutor; mMediaManager = notificationMediaManager; mLockscreenUserManager = lockScreenUserManager; mRemoteInputManager = remoteInputManager; @@ -1232,7 +1236,8 @@ public class StatusBar extends SystemUI implements DemoMode, mActivityLaunchAnimator = new ActivityLaunchAnimator( mNotificationShadeWindowViewController, this, mNotificationPanelViewController, mNotificationShadeDepthControllerLazy.get(), - (NotificationListContainer) mStackScroller); + (NotificationListContainer) mStackScroller, + mMainExecutor); // TODO: inject this. mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 02e031217904..62a3cf040d7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -33,6 +33,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -145,6 +146,7 @@ public interface StatusBarPhoneModule { DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, + @Main Executor mainExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, @@ -224,6 +226,7 @@ public interface StatusBarPhoneModule { displayMetrics, metricsLogger, uiBgExecutor, + mainExecutor, notificationMediaManager, lockScreenUserManager, remoteInputManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java index cdef49d6c94d..1654a5442635 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java @@ -19,14 +19,18 @@ package com.android.systemui.statusbar.notification; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; +import android.os.RemoteException; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.IRemoteAnimationFinishedCallback; import android.view.RemoteAnimationAdapter; +import android.view.RemoteAnimationTarget; import android.view.View; import com.android.systemui.SysuiTestCase; @@ -36,6 +40,8 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Assert; import org.junit.Before; @@ -68,9 +74,11 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase { private NotificationPanelViewController mNotificationPanelViewController; @Rule public MockitoRule rule = MockitoJUnit.rule(); + private FakeExecutor mExecutor; @Before public void setUp() throws Exception { + mExecutor = new FakeExecutor(new FakeSystemClock()); when(mNotificationShadeWindowViewController.getView()) .thenReturn(mNotificationShadeWindowView); when(mNotificationShadeWindowView.getResources()).thenReturn(mContext.getResources()); @@ -80,8 +88,8 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase { mCallback, mNotificationPanelViewController, mNotificationShadeDepthController, - mNotificationContainer); - + mNotificationContainer, + mExecutor); } @Test @@ -113,6 +121,29 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase { verify(mCallback).onExpandAnimationTimedOut(); } + @Test + public void testRowLinkBrokenOnAnimationStartFail() throws RemoteException { + ActivityLaunchAnimator.AnimationRunner runner = mLaunchAnimator.new AnimationRunner(mRow, + mExecutor); + // WHEN onAnimationStart with no valid remote target + runner.onAnimationStart(new RemoteAnimationTarget[0], new RemoteAnimationTarget[0], + mock(IRemoteAnimationFinishedCallback.class)); + mExecutor.runAllReady(); + // THEN the row is nulled out so that it won't be retained + Assert.assertTrue("The row should be null", runner.getRow() == null); + } + + @Test + public void testRowLinkBrokenOnAnimationCancelled() throws RemoteException { + ActivityLaunchAnimator.AnimationRunner runner = mLaunchAnimator.new AnimationRunner(mRow, + mExecutor); + // WHEN onAnimationCancelled + runner.onAnimationCancelled(); + mExecutor.runAllReady(); + // THEN the row is nulled out so that it won't be retained + Assert.assertTrue("The row should be null", runner.getRow() == null); + } + private void executePostsImmediately(View view) { doAnswer((i) -> { Runnable run = i.getArgument(0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 5a08c9ca017b..27cbb03b4e9d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -251,6 +251,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy; private ShadeController mShadeController; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); + private FakeExecutor mMainExecutor = new FakeExecutor(new FakeSystemClock()); private InitController mInitController = new InitController(); @Before @@ -353,6 +354,7 @@ public class StatusBarTest extends SysuiTestCase { new DisplayMetrics(), mMetricsLogger, mUiBgExecutor, + mMainExecutor, mNotificationMediaManager, mLockscreenUserManager, mRemoteInputManager, |