Merge "Fix HUN launch animation." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
969eda4226
@@ -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]. */
|
||||
|
||||
@@ -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?) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -2801,46 +2802,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]);
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
@@ -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 */)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user