summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jordan Demeulenaere <jdemeulenaere@google.com> 2021-05-20 11:20:42 +0200
committer Jordan Demeulenaere <jdemeulenaere@google.com> 2021-05-21 17:25:56 +0200
commit4e8dfa69621fc79dcf61ea766bb6fa5ccb5e8ea5 (patch)
tree938ebe6d8c00fde2127cc120e43b4b148c32182d
parent63a1453832f1023c65dee59b7075949810a086c1 (diff)
Register the remote animation before starting an intent.
This CL calls IActivityTaskManager#registerRemoteAnimationForNextActivityStart before starting an intent for which the launch should be animated. This allows to also animate trampoline launches. This CL also adds a bit of logging to ActivityLaunchAnimator. Bug: 184726377 Test: Manual Change-Id: I4a3b95ed5e93e870d6ae0989d9c1ec771c9e85fc
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java2
5 files changed, 50 insertions, 11 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 1cf0c5f52bb4..dafcb0fb1525 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -4,12 +4,14 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.ActivityManager
+import android.app.ActivityTaskManager
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.Log
import android.util.MathUtils
import android.view.IRemoteAnimationFinishedCallback
import android.view.IRemoteAnimationRunner
@@ -30,6 +32,8 @@ import kotlin.math.roundToInt
* nicely into the starting window.
*/
class ActivityLaunchAnimator(context: Context) {
+ private val TAG = this::class.java.simpleName
+
companion object {
const val ANIMATION_DURATION = 500L
const val ANIMATION_DURATION_FADE_OUT_CONTENT = 183L
@@ -78,29 +82,49 @@ class ActivityLaunchAnimator(context: Context) {
* If [controller] is null or [animate] is false, then the intent will be started and no
* animation will run.
*
+ * If possible, you should pass the [packageName] of the intent that will be started so that
+ * trampoline activity launches will also be animated.
+ *
* This method will throw any exception thrown by [intentStarter].
*/
@JvmOverloads
- inline fun startIntentWithAnimation(
+ fun startIntentWithAnimation(
controller: Controller?,
animate: Boolean = true,
+ packageName: String? = null,
intentStarter: (RemoteAnimationAdapter?) -> Int
) {
if (controller == null || !animate) {
+ Log.d(TAG, "Starting intent with no animation")
intentStarter(null)
controller?.callOnIntentStartedOnMainThread(willAnimate = false)
return
}
+ Log.d(TAG, "Starting intent with a launch animation")
val runner = Runner(controller)
val animationAdapter = RemoteAnimationAdapter(
runner,
ANIMATION_DURATION,
ANIMATION_DURATION - 150 /* statusBarTransitionDelay */
)
+
+ // Register the remote animation for the given package to also animate trampoline
+ // activity launches.
+ if (packageName != null) {
+ try {
+ ActivityTaskManager.getService().registerRemoteAnimationForNextActivityStart(
+ packageName, animationAdapter)
+ } catch (e: RemoteException) {
+ Log.w(TAG, "Unable to register the remote animation", e)
+ }
+ }
+
val launchResult = intentStarter(animationAdapter)
val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
launchResult == ActivityManager.START_SUCCESS
+
+ Log.d(TAG, "launchResult=$launchResult willAnimate=$willAnimate")
controller.callOnIntentStartedOnMainThread(willAnimate)
// If we expect an animation, post a timeout to cancel it in case the remote animation is
@@ -110,7 +134,6 @@ class ActivityLaunchAnimator(context: Context) {
}
}
- @PublishedApi
internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
if (Looper.myLooper() != Looper.getMainLooper()) {
this.launchContainer.context.mainExecutor.execute {
@@ -125,15 +148,21 @@ class ActivityLaunchAnimator(context: Context) {
* 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].
+ *
+ * If possible, you should pass the [packageName] of the intent that will be started so that
+ * trampoline activity launches will also be animated.
*/
@Throws(PendingIntent.CanceledException::class)
@JvmOverloads
fun startPendingIntentWithAnimation(
controller: Controller?,
animate: Boolean = true,
+ packageName: String? = null,
intentStarter: PendingIntentStarter
) {
- startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
+ startIntentWithAnimation(controller, animate, packageName) {
+ intentStarter.startPendingIntent(it)
+ }
}
/** Create a new animation [Runner] controlled by [controller]. */
@@ -278,7 +307,7 @@ class ActivityLaunchAnimator(context: Context) {
@VisibleForTesting
inner class Runner(private val controller: Controller) : IRemoteAnimationRunner.Stub() {
private val launchContainer = controller.launchContainer
- @PublishedApi internal val context = launchContainer.context
+ private val context = launchContainer.context
private val transactionApplier = SyncRtSurfaceTransactionApplier(launchContainer)
private var animator: ValueAnimator? = null
@@ -294,7 +323,6 @@ class ActivityLaunchAnimator(context: Context) {
// posting it.
private var onTimeout = Runnable { onAnimationTimedOut() }
- @PublishedApi
internal fun postTimeout() {
launchContainer.postDelayed(onTimeout, LAUNCH_TIMEOUT)
}
@@ -336,11 +364,13 @@ class ActivityLaunchAnimator(context: Context) {
remoteAnimationNonAppTargets: Array<out RemoteAnimationTarget>,
iCallback: IRemoteAnimationFinishedCallback
) {
+ Log.d(TAG, "Remote animation started")
val window = remoteAnimationTargets.firstOrNull {
it.mode == RemoteAnimationTarget.MODE_OPENING
}
if (window == null) {
+ Log.d(TAG, "Aborting the animation as no window is opening")
removeTimeout()
invokeCallback(iCallback)
controller.onLaunchAnimationCancelled()
@@ -399,10 +429,12 @@ class ActivityLaunchAnimator(context: Context) {
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
+ Log.d(TAG, "Animation started")
controller.onLaunchAnimationStart(isExpandingFullyAbove)
}
override fun onAnimationEnd(animation: Animator?) {
+ Log.d(TAG, "Animation ended")
invokeCallback(iCallback)
controller.onLaunchAnimationEnd(isExpandingFullyAbove)
}
@@ -496,6 +528,7 @@ class ActivityLaunchAnimator(context: Context) {
return
}
+ Log.d(TAG, "Remote animation timed out")
timedOut = true
controller.onLaunchAnimationCancelled()
}
@@ -505,6 +538,7 @@ class ActivityLaunchAnimator(context: Context) {
return
}
+ Log.d(TAG, "Remote animation was cancelled")
cancelled = true
removeTimeout()
context.mainExecutor.execute {
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 ec012bfde9b8..f046b402da38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2801,7 +2801,7 @@ public class StatusBar extends SystemUI implements DemoMode,
int[] result = new int[]{ActivityManager.START_CANCELED};
mActivityLaunchAnimator.startIntentWithAnimation(animController,
- areLaunchAnimationsEnabled(), (adapter) -> {
+ areLaunchAnimationsEnabled(), intent.getPackage(), (adapter) -> {
ActivityOptions options = new ActivityOptions(
getActivityOptions(mDisplayId, adapter));
options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -4563,7 +4563,7 @@ public class StatusBar extends SystemUI implements DemoMode,
animationController, this, intent.isActivity()) : null;
mActivityLaunchAnimator.startPendingIntentWithAnimation(
- controller, areLaunchAnimationsEnabled(),
+ controller, areLaunchAnimationsEnabled(), intent.getCreatorPackage(),
(animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
null, getActivityOptions(mDisplayId, animationAdapter)));
} catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index ab58aae6857e..5cd4e13bdcce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -437,7 +437,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
!wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
- (adapter) -> {
+ intent.getCreatorPackage(), (adapter) -> {
long eventTime = row.getAndResetLastActionUpTime();
Bundle options = eventTime > 0
? getActivityOptions(
@@ -469,6 +469,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mActivityLaunchAnimator.startIntentWithAnimation(
animationController, mStatusBar.areLaunchAnimationsEnabled(),
+ intent.getPackage(),
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
@@ -499,7 +500,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController,
- mStatusBar.areLaunchAnimationsEnabled(),
+ mStatusBar.areLaunchAnimationsEnabled(), intent.getPackage(),
(adapter) -> tsb.startActivities(
getActivityOptions(mStatusBar.getDisplayId(), adapter),
UserHandle.CURRENT));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 897d78b2ba0e..0753d05dc888 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -51,7 +51,11 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
// We start in a new thread so that we can ensure that the callbacks are called in the main
// thread.
thread {
- activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
+ activityLaunchAnimator.startIntentWithAnimation(
+ controller = controller,
+ animate = animate,
+ intentStarter = intentStarter
+ )
}.join()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index be86af585fc5..407afbe1f33e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -269,7 +269,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mShadeController, atLeastOnce()).collapsePanel();
verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
- eq(false) /* animate */, any());
+ eq(false) /* animate */, any(), any());
verify(mAssistManager).hideAssist();