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.content.Context
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.os.Looper
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.util.MathUtils
|
import android.util.MathUtils
|
||||||
import android.view.IRemoteAnimationFinishedCallback
|
import android.view.IRemoteAnimationFinishedCallback
|
||||||
@@ -73,16 +74,20 @@ class ActivityLaunchAnimator(context: Context) {
|
|||||||
* in [Controller.onLaunchAnimationProgress]. No animation will start if there is no window
|
* in [Controller.onLaunchAnimationProgress]. No animation will start if there is no window
|
||||||
* opening.
|
* 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].
|
* This method will throw any exception thrown by [intentStarter].
|
||||||
*/
|
*/
|
||||||
|
@JvmOverloads
|
||||||
inline fun startIntentWithAnimation(
|
inline fun startIntentWithAnimation(
|
||||||
controller: Controller?,
|
controller: Controller?,
|
||||||
|
animate: Boolean = true,
|
||||||
intentStarter: (RemoteAnimationAdapter?) -> Int
|
intentStarter: (RemoteAnimationAdapter?) -> Int
|
||||||
) {
|
) {
|
||||||
if (controller == null) {
|
if (controller == null || !animate) {
|
||||||
intentStarter(null)
|
intentStarter(null)
|
||||||
|
controller?.callOnIntentStartedOnMainThread(willAnimate = false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +100,7 @@ class ActivityLaunchAnimator(context: Context) {
|
|||||||
val launchResult = intentStarter(animationAdapter)
|
val launchResult = intentStarter(animationAdapter)
|
||||||
val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
|
val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
|
||||||
launchResult == ActivityManager.START_SUCCESS
|
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
|
// If we expect an animation, post a timeout to cancel it in case the remote animation is
|
||||||
// never started.
|
// 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
|
* Same as [startIntentWithAnimation] but allows [intentStarter] to throw a
|
||||||
* [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
|
* [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
|
||||||
* for Java caller starting a [PendingIntent].
|
* for Java caller starting a [PendingIntent].
|
||||||
*/
|
*/
|
||||||
@Throws(PendingIntent.CanceledException::class)
|
@Throws(PendingIntent.CanceledException::class)
|
||||||
|
@JvmOverloads
|
||||||
fun startPendingIntentWithAnimation(
|
fun startPendingIntentWithAnimation(
|
||||||
controller: Controller?,
|
controller: Controller?,
|
||||||
|
animate: Boolean = true,
|
||||||
intentStarter: PendingIntentStarter
|
intentStarter: PendingIntentStarter
|
||||||
) {
|
) {
|
||||||
startIntentWithAnimation(controller) { intentStarter.startPendingIntent(it) }
|
startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a new animation [Runner] controlled by [controller]. */
|
/** 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.NotificationShadeDepthController
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
||||||
|
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||||
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
|
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
@@ -14,7 +15,8 @@ import kotlin.math.max
|
|||||||
class NotificationLaunchAnimatorControllerProvider(
|
class NotificationLaunchAnimatorControllerProvider(
|
||||||
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
||||||
private val notificationListContainer: NotificationListContainer,
|
private val notificationListContainer: NotificationListContainer,
|
||||||
private val depthController: NotificationShadeDepthController
|
private val depthController: NotificationShadeDepthController,
|
||||||
|
private val headsUpManager: HeadsUpManagerPhone
|
||||||
) {
|
) {
|
||||||
fun getAnimatorController(
|
fun getAnimatorController(
|
||||||
notification: ExpandableNotificationRow
|
notification: ExpandableNotificationRow
|
||||||
@@ -23,7 +25,8 @@ class NotificationLaunchAnimatorControllerProvider(
|
|||||||
notificationShadeWindowViewController,
|
notificationShadeWindowViewController,
|
||||||
notificationListContainer,
|
notificationListContainer,
|
||||||
depthController,
|
depthController,
|
||||||
notification
|
notification,
|
||||||
|
headsUpManager
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +40,11 @@ class NotificationLaunchAnimatorController(
|
|||||||
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
||||||
private val notificationListContainer: NotificationListContainer,
|
private val notificationListContainer: NotificationListContainer,
|
||||||
private val depthController: NotificationShadeDepthController,
|
private val depthController: NotificationShadeDepthController,
|
||||||
private val notification: ExpandableNotificationRow
|
private val notification: ExpandableNotificationRow,
|
||||||
|
private val headsUpManager: HeadsUpManagerPhone
|
||||||
) : ActivityLaunchAnimator.Controller {
|
) : ActivityLaunchAnimator.Controller {
|
||||||
|
private val notificationKey = notification.entry.sbn.key
|
||||||
|
|
||||||
override fun getRootView(): View = notification.rootView
|
override fun getRootView(): View = notification.rootView
|
||||||
|
|
||||||
override fun createAnimatorState(): ActivityLaunchAnimator.State {
|
override fun createAnimatorState(): ActivityLaunchAnimator.State {
|
||||||
@@ -76,12 +82,25 @@ class NotificationLaunchAnimatorController(
|
|||||||
|
|
||||||
override fun onIntentStarted(willAnimate: Boolean) {
|
override fun onIntentStarted(willAnimate: Boolean) {
|
||||||
notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate)
|
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() {
|
override fun onLaunchAnimationCancelled() {
|
||||||
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
|
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
|
||||||
// here?
|
// here?
|
||||||
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
||||||
|
removeHun(animate = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
|
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
|
||||||
@@ -99,6 +118,7 @@ class NotificationLaunchAnimatorController(
|
|||||||
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
||||||
notificationListContainer.setExpandingNotification(null)
|
notificationListContainer.setExpandingNotification(null)
|
||||||
applyParams(null)
|
applyParams(null)
|
||||||
|
removeHun(animate = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyParams(params: ExpandAnimationParameters?) {
|
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
|
@Override
|
||||||
public boolean isTrackingHeadsUp() {
|
public boolean isTrackingHeadsUp() {
|
||||||
@@ -318,6 +318,18 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
|
|||||||
mSwipedOutKeys.add(key);
|
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:
|
// Dumpable overrides:
|
||||||
|
|
||||||
|
|||||||
@@ -1412,7 +1412,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
|
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
|
||||||
mNotificationShadeWindowViewController,
|
mNotificationShadeWindowViewController,
|
||||||
mStackScrollerController.getNotificationListContainer(),
|
mStackScrollerController.getNotificationListContainer(),
|
||||||
mNotificationShadeDepthControllerLazy.get()
|
mNotificationShadeDepthControllerLazy.get(),
|
||||||
|
mHeadsUpManager
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: inject this.
|
// TODO: inject this.
|
||||||
@@ -2785,7 +2786,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
intent, mLockscreenUserManager.getCurrentUserId());
|
intent, mLockscreenUserManager.getCurrentUserId());
|
||||||
|
|
||||||
ActivityLaunchAnimator.Controller animController = null;
|
ActivityLaunchAnimator.Controller animController = null;
|
||||||
if (animationController != null && areLaunchAnimationsEnabled()) {
|
if (animationController != null) {
|
||||||
animController = dismissShade ? new StatusBarLaunchAnimatorController(
|
animController = dismissShade ? new StatusBarLaunchAnimatorController(
|
||||||
animationController, this, true /* isLaunchForActivity */)
|
animationController, this, true /* isLaunchForActivity */)
|
||||||
: animationController;
|
: animationController;
|
||||||
@@ -2801,46 +2802,48 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
intent.setFlags(
|
intent.setFlags(
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
intent.addFlags(flags);
|
intent.addFlags(flags);
|
||||||
int[] result = new int[] { ActivityManager.START_CANCELED };
|
int[] result = new int[]{ActivityManager.START_CANCELED};
|
||||||
|
|
||||||
mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda, (adapter) -> {
|
mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda,
|
||||||
ActivityOptions options = new ActivityOptions(
|
areLaunchAnimationsEnabled(), (adapter) -> {
|
||||||
getActivityOptions(mDisplayId, adapter));
|
ActivityOptions options = new ActivityOptions(
|
||||||
options.setDisallowEnterPictureInPictureWhileLaunching(
|
getActivityOptions(mDisplayId, adapter));
|
||||||
disallowEnterPictureInPictureWhileLaunching);
|
options.setDisallowEnterPictureInPictureWhileLaunching(
|
||||||
if (CameraIntents.isInsecureCameraIntent(intent)) {
|
disallowEnterPictureInPictureWhileLaunching);
|
||||||
// Normally an activity will set it's requested rotation
|
if (CameraIntents.isInsecureCameraIntent(intent)) {
|
||||||
// animation on its window. However when launching an activity
|
// Normally an activity will set it's requested rotation
|
||||||
// causes the orientation to change this is too late. In these cases
|
// animation on its window. However when launching an activity
|
||||||
// the default animation is used. This doesn't look good for
|
// causes the orientation to change this is too late. In these cases
|
||||||
// the camera (as it rotates the camera contents out of sync
|
// the default animation is used. This doesn't look good for
|
||||||
// with physical reality). So, we ask the WindowManager to
|
// the camera (as it rotates the camera contents out of sync
|
||||||
// force the crossfade animation if an orientation change
|
// with physical reality). So, we ask the WindowManager to
|
||||||
// happens to occur during the launch.
|
// force the crossfade animation if an orientation change
|
||||||
options.setRotationAnimationHint(
|
// happens to occur during the launch.
|
||||||
WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
|
options.setRotationAnimationHint(
|
||||||
}
|
WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
|
||||||
if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
|
}
|
||||||
// Settings Panel is implemented as activity(not a dialog), so
|
if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
|
||||||
// underlying app is paused and may enter picture-in-picture mode
|
// Settings Panel is implemented as activity(not a dialog), so
|
||||||
// as a result.
|
// underlying app is paused and may enter picture-in-picture mode
|
||||||
// So we need to disable picture-in-picture mode here
|
// as a result.
|
||||||
// if it is volume panel.
|
// So we need to disable picture-in-picture mode here
|
||||||
options.setDisallowEnterPictureInPictureWhileLaunching(true);
|
// if it is volume panel.
|
||||||
}
|
options.setDisallowEnterPictureInPictureWhileLaunching(true);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result[0] = ActivityTaskManager.getService().startActivityAsUser(
|
result[0] = ActivityTaskManager.getService().startActivityAsUser(
|
||||||
null, mContext.getBasePackageName(), mContext.getAttributionTag(),
|
null, mContext.getBasePackageName(),
|
||||||
intent,
|
mContext.getAttributionTag(),
|
||||||
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
|
intent,
|
||||||
null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
|
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
|
||||||
options.toBundle(), UserHandle.CURRENT.getIdentifier());
|
null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
|
||||||
} catch (RemoteException e) {
|
options.toBundle(), UserHandle.CURRENT.getIdentifier());
|
||||||
Log.w(TAG, "Unable to start activity", e);
|
} catch (RemoteException e) {
|
||||||
}
|
Log.w(TAG, "Unable to start activity", e);
|
||||||
return result[0];
|
}
|
||||||
});
|
return result[0];
|
||||||
|
});
|
||||||
|
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onActivityStarted(result[0]);
|
callback.onActivityStarted(result[0]);
|
||||||
@@ -4559,19 +4562,17 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
|
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
|
||||||
mLockscreenUserManager.getCurrentUserId());
|
mLockscreenUserManager.getCurrentUserId());
|
||||||
|
|
||||||
boolean animate = animationController != null && areLaunchAnimationsEnabled();
|
boolean collapse = animationController == null;
|
||||||
boolean collapse = !animate;
|
|
||||||
executeActionDismissingKeyguard(() -> {
|
executeActionDismissingKeyguard(() -> {
|
||||||
try {
|
try {
|
||||||
// We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
|
// We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
|
||||||
// shade is collapsed after the animation (or when it is cancelled, aborted, etc).
|
// shade is collapsed after the animation (or when it is cancelled, aborted, etc).
|
||||||
ActivityLaunchAnimator.Controller controller =
|
ActivityLaunchAnimator.Controller controller =
|
||||||
animate ? new StatusBarLaunchAnimatorController(animationController, this,
|
animationController != null ? new StatusBarLaunchAnimatorController(
|
||||||
intent.isActivity())
|
animationController, this, intent.isActivity()) : null;
|
||||||
: null;
|
|
||||||
|
|
||||||
mActivityLaunchAnimator.startPendingIntentWithAnimation(
|
mActivityLaunchAnimator.startPendingIntentWithAnimation(
|
||||||
controller,
|
controller, areLaunchAnimationsEnabled(),
|
||||||
(animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
|
(animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
|
||||||
null, getActivityOptions(mDisplayId, animationAdapter)));
|
null, getActivityOptions(mDisplayId, animationAdapter)));
|
||||||
} catch (PendingIntent.CanceledException e) {
|
} catch (PendingIntent.CanceledException e) {
|
||||||
|
|||||||
@@ -283,7 +283,13 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
|
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
|
||||||
|
|
||||||
// TODO: Some of this code may be able to move to NotificationEntryManager.
|
// 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(
|
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
|
||||||
entry, row, controller, intent,
|
entry, row, controller, intent,
|
||||||
@@ -331,6 +337,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
// bypass work challenge
|
// bypass work challenge
|
||||||
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
|
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
|
||||||
intent.getIntentSender(), notificationKey)) {
|
intent.getIntentSender(), notificationKey)) {
|
||||||
|
removeHUN(row);
|
||||||
// Show work challenge, do not run PendingIntent and
|
// Show work challenge, do not run PendingIntent and
|
||||||
// remove notification
|
// remove notification
|
||||||
collapseOnMainThread();
|
collapseOnMainThread();
|
||||||
@@ -350,6 +357,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
final boolean canBubble = entry.canBubble();
|
final boolean canBubble = entry.canBubble();
|
||||||
if (canBubble) {
|
if (canBubble) {
|
||||||
mLogger.logExpandingBubble(notificationKey);
|
mLogger.logExpandingBubble(notificationKey);
|
||||||
|
removeHUN(row);
|
||||||
expandBubbleStackOnMainThread(entry);
|
expandBubbleStackOnMainThread(entry);
|
||||||
} else {
|
} else {
|
||||||
startNotificationIntent(
|
startNotificationIntent(
|
||||||
@@ -422,14 +430,13 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
boolean isActivityIntent) {
|
boolean isActivityIntent) {
|
||||||
mLogger.logStartNotificationIntent(entry.getKey(), intent);
|
mLogger.logStartNotificationIntent(entry.getKey(), intent);
|
||||||
try {
|
try {
|
||||||
ActivityLaunchAnimator.Controller animationController = null;
|
ActivityLaunchAnimator.Controller animationController =
|
||||||
if (!wasOccluded && mStatusBar.areLaunchAnimationsEnabled()) {
|
new StatusBarLaunchAnimatorController(
|
||||||
animationController = new StatusBarLaunchAnimatorController(
|
mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
|
||||||
mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
|
isActivityIntent);
|
||||||
isActivityIntent);
|
|
||||||
}
|
|
||||||
|
|
||||||
mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
|
mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
|
||||||
|
!wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
|
||||||
(adapter) -> {
|
(adapter) -> {
|
||||||
long eventTime = row.getAndResetLastActionUpTime();
|
long eventTime = row.getAndResetLastActionUpTime();
|
||||||
Bundle options = eventTime > 0
|
Bundle options = eventTime > 0
|
||||||
@@ -442,13 +449,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
return intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
|
return intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
|
||||||
null, null, options);
|
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) {
|
} catch (PendingIntent.CanceledException e) {
|
||||||
// the stack trace isn't very helpful here.
|
// the stack trace isn't very helpful here.
|
||||||
// Just log the exception message.
|
// Just log the exception message.
|
||||||
@@ -462,34 +462,19 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
ExpandableNotificationRow row) {
|
ExpandableNotificationRow row) {
|
||||||
mActivityStarter.dismissKeyguardThenExecute(() -> {
|
mActivityStarter.dismissKeyguardThenExecute(() -> {
|
||||||
AsyncTask.execute(() -> {
|
AsyncTask.execute(() -> {
|
||||||
ActivityLaunchAnimator.Controller animationController = null;
|
ActivityLaunchAnimator.Controller animationController =
|
||||||
if (mStatusBar.areLaunchAnimationsEnabled()) {
|
new StatusBarLaunchAnimatorController(
|
||||||
animationController = new StatusBarLaunchAnimatorController(
|
mNotificationAnimationProvider.getAnimatorController(row),
|
||||||
mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
|
mStatusBar, true /* isActivityIntent */);
|
||||||
true /* isActivityIntent */);
|
|
||||||
}
|
|
||||||
|
|
||||||
mActivityLaunchAnimator.startIntentWithAnimation(
|
mActivityLaunchAnimator.startIntentWithAnimation(
|
||||||
animationController,
|
animationController, mStatusBar.areLaunchAnimationsEnabled(),
|
||||||
(adapter) -> TaskStackBuilder.create(mContext)
|
(adapter) -> TaskStackBuilder.create(mContext)
|
||||||
.addNextIntentWithParentStack(intent)
|
.addNextIntentWithParentStack(intent)
|
||||||
.startActivities(getActivityOptions(
|
.startActivities(getActivityOptions(
|
||||||
mStatusBar.getDisplayId(),
|
mStatusBar.getDisplayId(),
|
||||||
adapter),
|
adapter),
|
||||||
new UserHandle(UserHandle.getUserId(appUid))));
|
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;
|
return true;
|
||||||
}, null, false /* afterKeyguardGone */);
|
}, null, false /* afterKeyguardGone */);
|
||||||
@@ -508,26 +493,16 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
tsb.addNextIntent(intent);
|
tsb.addNextIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivityLaunchAnimator.Controller animationController = null;
|
ActivityLaunchAnimator.Controller animationController =
|
||||||
if (mStatusBar.areLaunchAnimationsEnabled()) {
|
new StatusBarLaunchAnimatorController(
|
||||||
animationController = new StatusBarLaunchAnimatorController(
|
ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
|
||||||
ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
|
true /* isActivityIntent */);
|
||||||
true /* isActivityIntent */);
|
|
||||||
}
|
|
||||||
|
|
||||||
mActivityLaunchAnimator.startIntentWithAnimation(animationController,
|
mActivityLaunchAnimator.startIntentWithAnimation(animationController,
|
||||||
|
mStatusBar.areLaunchAnimationsEnabled(),
|
||||||
(adapter) -> tsb.startActivities(
|
(adapter) -> tsb.startActivities(
|
||||||
getActivityOptions(mStatusBar.getDisplayId(), adapter),
|
getActivityOptions(mStatusBar.getDisplayId(), adapter),
|
||||||
UserHandle.CURRENT));
|
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;
|
return true;
|
||||||
}, null, false /* afterKeyguardGone */);
|
}, null, false /* afterKeyguardGone */);
|
||||||
@@ -536,11 +511,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
private void removeHUN(ExpandableNotificationRow row) {
|
private void removeHUN(ExpandableNotificationRow row) {
|
||||||
String key = row.getEntry().getSbn().getKey();
|
String key = row.getEntry().getSbn().getKey();
|
||||||
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
|
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
|
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
|
||||||
// become canceled shortly by NoMan, but we can't assume that.
|
// become canceled shortly by NoMan, but we can't assume that.
|
||||||
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
|
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
|
||||||
|
|||||||
@@ -341,7 +341,6 @@ interface SmartActionInflater {
|
|||||||
activityStarter.startPendingIntentDismissingKeyguard(action.actionIntent, entry.row) {
|
activityStarter.startPendingIntentDismissingKeyguard(action.actionIntent, entry.row) {
|
||||||
smartReplyController
|
smartReplyController
|
||||||
.smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant)
|
.smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant)
|
||||||
headsUpManager.removeNotification(entry.key, true /* releaseImmediately */)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,13 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
private fun startIntentWithAnimation(
|
private fun startIntentWithAnimation(
|
||||||
controller: ActivityLaunchAnimator.Controller? = this.controller,
|
controller: ActivityLaunchAnimator.Controller? = this.controller,
|
||||||
|
animate: Boolean = true,
|
||||||
intentStarter: (RemoteAnimationAdapter?) -> Int
|
intentStarter: (RemoteAnimationAdapter?) -> Int
|
||||||
) {
|
) {
|
||||||
// We start in a new thread so that we can ensure that the callbacks are called in the main
|
// We start in a new thread so that we can ensure that the callbacks are called in the main
|
||||||
// thread.
|
// thread.
|
||||||
thread {
|
thread {
|
||||||
activityLaunchAnimator.startIntentWithAnimation(controller, intentStarter)
|
activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
|
||||||
}.join()
|
}.join()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +95,16 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
assertFalse(willAnimateCaptor.value)
|
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
|
@Test
|
||||||
fun doesNotStartIfAnimationIsCancelled() {
|
fun doesNotStartIfAnimationIsCancelled() {
|
||||||
val runner = activityLaunchAnimator.createRunner(controller)
|
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.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationPresenter;
|
import com.android.systemui.statusbar.NotificationPresenter;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.RemoteInputController;
|
import com.android.systemui.statusbar.RemoteInputController;
|
||||||
import com.android.systemui.statusbar.StatusBarState;
|
import com.android.systemui.statusbar.StatusBarState;
|
||||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
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.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
||||||
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
|
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.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
import com.android.systemui.util.time.FakeSystemClock;
|
import com.android.systemui.util.time.FakeSystemClock;
|
||||||
@@ -184,6 +186,14 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
|
when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
|
||||||
.thenReturn(null);
|
.thenReturn(null);
|
||||||
|
|
||||||
|
HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
|
||||||
|
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
|
||||||
|
new NotificationLaunchAnimatorControllerProvider(
|
||||||
|
mock(NotificationShadeWindowViewController.class), mock(
|
||||||
|
NotificationListContainer.class),
|
||||||
|
mock(NotificationShadeDepthController.class),
|
||||||
|
headsUpManager);
|
||||||
|
|
||||||
mNotificationActivityStarter =
|
mNotificationActivityStarter =
|
||||||
new StatusBarNotificationActivityStarter.Builder(
|
new StatusBarNotificationActivityStarter.Builder(
|
||||||
getContext(),
|
getContext(),
|
||||||
@@ -192,7 +202,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
mUiBgExecutor,
|
mUiBgExecutor,
|
||||||
mEntryManager,
|
mEntryManager,
|
||||||
mNotifPipeline,
|
mNotifPipeline,
|
||||||
mock(HeadsUpManagerPhone.class),
|
headsUpManager,
|
||||||
mActivityStarter,
|
mActivityStarter,
|
||||||
mClickNotifier,
|
mClickNotifier,
|
||||||
mock(StatusBarStateController.class),
|
mock(StatusBarStateController.class),
|
||||||
@@ -220,8 +230,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
.setNotificationPanelViewController(
|
.setNotificationPanelViewController(
|
||||||
mock(NotificationPanelViewController.class))
|
mock(NotificationPanelViewController.class))
|
||||||
.setActivityLaunchAnimator(mActivityLaunchAnimator)
|
.setActivityLaunchAnimator(mActivityLaunchAnimator)
|
||||||
.setNotificationAnimatorControllerProvider(
|
.setNotificationAnimatorControllerProvider(notificationAnimationProvider)
|
||||||
mock(NotificationLaunchAnimatorControllerProvider.class))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
|
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
|
||||||
@@ -259,7 +268,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
// Then
|
// Then
|
||||||
verify(mShadeController, atLeastOnce()).collapsePanel();
|
verify(mShadeController, atLeastOnce()).collapsePanel();
|
||||||
|
|
||||||
verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(eq(null), any());
|
verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
|
||||||
|
eq(false) /* animate */, any());
|
||||||
|
|
||||||
verify(mAssistManager).hideAssist();
|
verify(mAssistManager).hideAssist();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user