diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index db9d9234aeb86..97c9fa58622fb 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -376,6 +376,11 @@ public abstract class ActivityManagerInternal { */ public abstract boolean isRecentsComponentHomeActivity(int userId); + /** + * Cancels any currently running recents animation. + */ + public abstract void cancelRecentsAnimation(boolean restoreHomeStackPosition); + /** * Whether an UID is active or idle. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 1b02e152ec11a..22a48f0b03094 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -269,13 +269,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { } if (mCode != 0) { if (doIt) { - // If there was a pending remote recents animation, then we need to - // cancel the animation now before we handle the button itself. In the case - // where we are going home and the recents animation has already started, - // just cancel the recents animation, leaving the home stack in place - boolean isHomeKey = mCode == KEYCODE_HOME; - ActivityManagerWrapper.getInstance().cancelRecentsAnimation(!isHomeKey); - sendEvent(KeyEvent.ACTION_UP, 0); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6951c500d5c38..6718d9558ffbd 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -26632,6 +26632,11 @@ public class ActivityManagerService extends IActivityManager.Stub return getRecentTasks().isRecentsComponentHomeActivity(userId); } + @Override + public void cancelRecentsAnimation(boolean restoreHomeStackPosition) { + ActivityManagerService.this.cancelRecentsAnimation(restoreHomeStackPosition); + } + @Override public boolean isUidActive(int uid) { synchronized (ActivityManagerService.this) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 920e77f727714..bd4210c1b034b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -6091,6 +6091,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled) && event.getRepeatCount() == 0; + // Cancel any pending remote recents animations before handling the button itself. In the + // case where we are going home and the recents animation has already started, just cancel + // the recents animation, leaving the home stack in place for the pending start activity + if (isNavBarVirtKey && !down) { + boolean isHomeKey = keyCode == KeyEvent.KEYCODE_HOME; + mActivityManagerInternal.cancelRecentsAnimation(!isHomeKey); + } + // Handle special keys. switch (keyCode) { case KeyEvent.KEYCODE_BACK: { diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 08fa153a3bad0..79b230d45110a 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -369,7 +369,7 @@ public class RecentsAnimationController implements DeathRecipient { } void cancelAnimation(@ReorderMode int reorderMode, String reason) { - if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation()"); + if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason); synchronized (mService.getWindowManagerLock()) { if (mCanceled) { // We've already canceled the animation diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index 1b06b2fe1e7ea..67ef471031035 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -83,7 +83,8 @@ class RemoteAnimationController implements DeathRecipient { */ AnimationAdapter createAnimationAdapter(AppWindowToken appWindowToken, Point position, Rect stackBounds) { - if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimationAdapter(): token=" + appWindowToken); + if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimationAdapter(): token=" + + appWindowToken); final RemoteAnimationAdapterWrapper adapter = new RemoteAnimationAdapterWrapper( appWindowToken, position, stackBounds); mPendingAnimations.add(adapter); @@ -96,8 +97,9 @@ class RemoteAnimationController implements DeathRecipient { void goodToGo() { if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo()"); if (mPendingAnimations.isEmpty() || mCanceled) { - if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): Animation finished before good to go, canceled=" - + mCanceled + " mPendingAnimations=" + mPendingAnimations.size()); + if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): Animation finished already," + + " canceled=" + mCanceled + + " mPendingAnimations=" + mPendingAnimations.size()); onAnimationFinished(); return; } @@ -123,10 +125,6 @@ class RemoteAnimationController implements DeathRecipient { } if (DEBUG_REMOTE_ANIMATIONS) { Slog.d(TAG, "startAnimation(): Notify animation start:"); - for (int i = 0; i < mPendingAnimations.size(); i++) { - Slog.d(TAG, "\t" + mPendingAnimations.get(i).mAppWindowToken); - } - } else if (DEBUG_APP_TRANSITIONS) { writeStartDebugStatement(); } }); @@ -166,7 +164,8 @@ class RemoteAnimationController implements DeathRecipient { if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tAdd token=" + wrapper.mAppWindowToken); targets.add(target); } else { - if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tRemove token=" + wrapper.mAppWindowToken); + if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tRemove token=" + + wrapper.mAppWindowToken); // We can't really start an animation but we still need to make sure to finish the // pending animation that was started by SurfaceAnimator @@ -188,7 +187,8 @@ class RemoteAnimationController implements DeathRecipient { releaseFinishedCallback(); mService.openSurfaceTransaction(); try { - if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "onAnimationFinished(): Notify animation finished:"); + if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, + "onAnimationFinished(): Notify animation finished:"); for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { final RemoteAnimationAdapterWrapper adapter = mPendingAnimations.get(i); adapter.mCapturedFinishCallback.onAnimationFinished(adapter);