Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +141 −154 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.os.UserHandle; import android.provider.Settings.Global; import android.provider.Settings.Global; import android.util.Log; import android.util.Log; import android.util.SparseArray; import android.util.SparseArray; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.IWindowFocusObserver; import android.view.IWindowFocusObserver; import android.view.InputDevice; import android.view.InputDevice; Loading Loading @@ -69,7 +68,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * Controls the window animation run when a user initiates a back gesture. * Controls the window animation run when a user initiates a back gesture. */ */ public class BackAnimationController implements RemoteCallable<BackAnimationController> { public class BackAnimationController implements RemoteCallable<BackAnimationController> { private static final String TAG = "BackAnimationController"; private static final String TAG = "ShellBackPreview"; private static final int SETTING_VALUE_OFF = 0; private static final int SETTING_VALUE_OFF = 0; private static final int SETTING_VALUE_ON = 1; private static final int SETTING_VALUE_ON = 1; public static final boolean IS_ENABLED = public static final boolean IS_ENABLED = Loading @@ -82,16 +81,15 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont /** Predictive back animation developer option */ /** Predictive back animation developer option */ private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false); private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false); /** /** * Max duration to wait for a transition to finish before accepting another gesture start * Max duration to wait for an animation to finish before triggering the real back. * request. */ */ private static final long MAX_TRANSITION_DURATION = 2000; private static final long MAX_ANIMATION_DURATION = 2000; /** True when a back gesture is ongoing */ /** True when a back gesture is ongoing */ private boolean mBackGestureStarted = false; private boolean mBackGestureStarted = false; /** Tracks if an uninterruptible transition is in progress */ /** Tracks if an uninterruptible animation is in progress */ private boolean mTransitionInProgress = false; private boolean mPostCommitAnimationInProgress = false; /** Tracks if we should start the back gesture on the next motion move event */ /** Tracks if we should start the back gesture on the next motion move event */ private boolean mShouldStartOnNextMoveEvent = false; private boolean mShouldStartOnNextMoveEvent = false; /** @see #setTriggerBack(boolean) */ /** @see #setTriggerBack(boolean) */ Loading @@ -105,9 +103,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final ShellController mShellController; private final ShellController mShellController; private final ShellExecutor mShellExecutor; private final ShellExecutor mShellExecutor; private final Handler mBgHandler; private final Handler mBgHandler; private final Runnable mResetTransitionRunnable = () -> { private final Runnable mAnimationTimeoutRunnable = () -> { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Transition didn't finish in %d ms. Resetting...", ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation didn't finish in %d ms. Resetting...", MAX_TRANSITION_DURATION); MAX_ANIMATION_DURATION); onBackAnimationFinished(); onBackAnimationFinished(); }; }; Loading @@ -119,6 +117,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>(); private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>(); private IOnBackInvokedCallback mActiveCallback; @VisibleForTesting @VisibleForTesting final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() { final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() { @Override @Override Loading @@ -126,9 +126,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Override @Override public void focusLost(IBinder inputToken) { public void focusLost(IBinder inputToken) { mShellExecutor.execute(() -> { mShellExecutor.execute(() -> { if (!mBackGestureStarted || mTransitionInProgress) { if (!mBackGestureStarted || mPostCommitAnimationInProgress) { // If an uninterruptible transition is already in progress, we should ignore // If an uninterruptible animation is already in progress, we should ignore // this due to the transition may cause focus lost. (alpha = 0) // this due to it may cause focus lost. (alpha = 0) return; return; } } ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus."); ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus."); Loading Loading @@ -180,26 +180,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } private void initBackAnimationRunners() { private void initBackAnimationRunners() { final IOnBackInvokedCallback dummyCallback = new IOnBackInvokedCallback.Default(); final IRemoteAnimationRunner dummyRunner = new IRemoteAnimationRunner.Default() { @Override public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException { // Animation missing. Simply finish animation. finishedCallback.onAnimationFinished(); } }; final BackAnimationRunner dummyBackRunner = new BackAnimationRunner(dummyCallback, dummyRunner); final CrossTaskBackAnimation crossTaskAnimation = new CrossTaskBackAnimation(mContext); final CrossTaskBackAnimation crossTaskAnimation = new CrossTaskBackAnimation(mContext); mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK, mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK, new BackAnimationRunner(crossTaskAnimation.mCallback, crossTaskAnimation.mRunner)); new BackAnimationRunner(crossTaskAnimation.mCallback, crossTaskAnimation.mRunner)); // TODO (238474994): register cross activity animation when it's completed. // TODO (238474994): register cross activity animation when it's completed. mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY, dummyBackRunner); // TODO (236760237): register dialog close animation when it's completed. // TODO (236760237): register dialog close animation when it's completed. mAnimationDefinition.set(BackNavigationInfo.TYPE_DIALOG_CLOSE, dummyBackRunner); } } private void setupAnimationDeveloperSettingsObserver( private void setupAnimationDeveloperSettingsObserver( Loading @@ -222,10 +207,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private void updateEnableAnimationFromSetting() { private void updateEnableAnimationFromSetting() { int settingValue = Global.getInt(mContext.getContentResolver(), int settingValue = Global.getInt(mContext.getContentResolver(), Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); boolean isEnabled = settingValue == SETTING_VALUE_ON; boolean isEnabled = settingValue == SETTING_VALUE_ON && IS_U_ANIMATION_ENABLED; mEnableAnimations.set(isEnabled); mEnableAnimations.set(isEnabled); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", isEnabled); isEnabled); } } public BackAnimation getBackAnimationImpl() { public BackAnimation getBackAnimationImpl() { Loading Loading @@ -279,7 +263,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont public void setBackToLauncherCallback(IOnBackInvokedCallback callback, public void setBackToLauncherCallback(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { IRemoteAnimationRunner runner) { executeRemoteCallWithTaskPermission(mController, "setBackToLauncherCallback", executeRemoteCallWithTaskPermission(mController, "setBackToLauncherCallback", (controller) -> controller.setBackToLauncherCallback(callback, runner)); (controller) -> controller.registerAnimation( BackNavigationInfo.TYPE_RETURN_TO_HOME, new BackAnimationRunner(callback, runner))); } } @Override @Override Loading @@ -294,44 +280,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } @VisibleForTesting void registerAnimation(@BackNavigationInfo.BackTargetType int type, void setBackToLauncherCallback(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { @NonNull BackAnimationRunner runner) { mAnimationDefinition.set(BackNavigationInfo.TYPE_RETURN_TO_HOME, mAnimationDefinition.set(type, runner); new BackAnimationRunner(callback, runner)); } } private void clearBackToLauncherCallback() { private void clearBackToLauncherCallback() { mAnimationDefinition.remove(BackNavigationInfo.TYPE_RETURN_TO_HOME); mAnimationDefinition.remove(BackNavigationInfo.TYPE_RETURN_TO_HOME); } } @VisibleForTesting void onBackAnimationFinished() { if (!mTransitionInProgress) { return; } ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: onBackAnimationFinished()"); // Trigger real back. if (mBackNavigationInfo != null) { IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback(); if (mTriggerBack) { dispatchOnBackInvoked(callback); } else { dispatchOnBackCancelled(callback); } } finishBackNavigation(); } /** /** * Called when a new motion event needs to be transferred to this * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} * {@link BackAnimationController} */ */ public void onMotionEvent(float touchX, float touchY, int keyAction, public void onMotionEvent(float touchX, float touchY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { @BackEvent.SwipeEdge int swipeEdge) { if (mTransitionInProgress) { if (mPostCommitAnimationInProgress) { return; return; } } Loading @@ -348,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont onGestureStarted(touchX, touchY, swipeEdge); onGestureStarted(touchX, touchY, swipeEdge); mShouldStartOnNextMoveEvent = false; mShouldStartOnNextMoveEvent = false; } } onMove(touchX, touchY, swipeEdge); onMove(); } else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) { } else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Finishing gesture with event action: %d", keyAction); "Finishing gesture with event action: %d", keyAction); Loading Loading @@ -386,30 +350,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } final int backType = backNavigationInfo.getType(); final int backType = backNavigationInfo.getType(); final IOnBackInvokedCallback targetCallback; final boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); final boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); if (shouldDispatchToAnimator) { if (shouldDispatchToAnimator) { mActiveCallback = mAnimationDefinition.get(backType).getCallback(); mAnimationDefinition.get(backType).startGesture(); mAnimationDefinition.get(backType).startGesture(); } else { } else { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback(); dispatchOnBackStarted(targetCallback, mTouchTracker.createStartEvent(null)); dispatchOnBackStarted(mActiveCallback, mTouchTracker.createStartEvent(null)); } } } } private void onMove(float touchX, float touchY, @BackEvent.SwipeEdge int swipeEdge) { private void onMove() { if (!mBackGestureStarted || mBackNavigationInfo == null || !mEnableAnimations.get()) { if (!mBackGestureStarted || mBackNavigationInfo == null || !mEnableAnimations.get()) { return; return; } } final BackEvent backEvent = mTouchTracker.createProgressEvent(); final BackEvent backEvent = mTouchTracker.createProgressEvent(); dispatchOnBackProgressed(mActiveCallback, backEvent); int backType = mBackNavigationInfo.getType(); IOnBackInvokedCallback targetCallback; if (shouldDispatchToAnimator(backType)) { targetCallback = mAnimationDefinition.get(backType).getCallback(); } else { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); } dispatchOnBackProgressed(targetCallback, backEvent); } } private void injectBackKey() { private void injectBackKey() { Loading @@ -431,57 +387,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } private void onGestureFinished(boolean fromTouch) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack); if (!mBackGestureStarted) { finishBackNavigation(); return; } if (fromTouch) { // Let touch reset the flag otherwise it will start a new back navigation and refresh // the info when received a new move event. mBackGestureStarted = false; } if (mTransitionInProgress) { return; } if (mBackNavigationInfo == null) { // No focus window found or core are running recents animation, inject back key as // legacy behavior. if (mTriggerBack) { injectBackKey(); } finishBackNavigation(); return; } int backType = mBackNavigationInfo.getType(); boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); final BackAnimationRunner runner = mAnimationDefinition.get(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToAnimator ? runner.getCallback() : mBackNavigationInfo.getOnBackInvokedCallback(); if (shouldDispatchToAnimator) { if (runner.onGestureFinished(mTriggerBack)) { Log.w(TAG, "Gesture released, but animation didn't ready."); return; } startTransition(); } if (mTriggerBack) { dispatchOnBackInvoked(targetCallback); } else { dispatchOnBackCancelled(targetCallback); } if (!shouldDispatchToAnimator) { // Animation callback missing. Simply finish animation. finishBackNavigation(); } } private boolean shouldDispatchToAnimator(int backType) { private boolean shouldDispatchToAnimator(int backType) { return mEnableAnimations.get() return mEnableAnimations.get() && mBackNavigationInfo != null && mBackNavigationInfo != null Loading @@ -495,7 +400,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackStarted(backEvent); callback.onBackStarted(backEvent); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -519,7 +424,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackCancelled(); callback.onBackCancelled(); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -533,7 +438,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackProgressed(backEvent); callback.onBackProgressed(backEvent); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -541,17 +446,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } private boolean shouldDispatchAnimation(IOnBackInvokedCallback callback) { return (IS_U_ANIMATION_ENABLED || callback == mAnimationDefinition.get( BackNavigationInfo.TYPE_RETURN_TO_HOME).getCallback()) && mEnableAnimations.get(); } /** /** * Sets to true when the back gesture has passed the triggering threshold, false otherwise. * Sets to true when the back gesture has passed the triggering threshold, false otherwise. */ */ public void setTriggerBack(boolean triggerBack) { public void setTriggerBack(boolean triggerBack) { if (mTransitionInProgress) { if (mPostCommitAnimationInProgress) { return; return; } } mTriggerBack = triggerBack; mTriggerBack = triggerBack; Loading @@ -562,6 +461,109 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTouchTracker.setProgressThreshold(progressThreshold); mTouchTracker.setProgressThreshold(progressThreshold); } } /** * Called when the gesture is released, then it could start the post commit animation. */ private void onGestureFinished(boolean fromTouch) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack); if (!mBackGestureStarted) { finishBackNavigation(); return; } if (fromTouch) { // Let touch reset the flag otherwise it will start a new back navigation and refresh // the info when received a new move event. mBackGestureStarted = false; } if (mPostCommitAnimationInProgress) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation is still running"); return; } if (mBackNavigationInfo == null) { // No focus window found or core are running recents animation, inject back key as // legacy behavior. if (mTriggerBack) { injectBackKey(); } finishBackNavigation(); return; } final int backType = mBackNavigationInfo.getType(); // Directly finish back navigation if no animator defined. if (!shouldDispatchToAnimator(backType)) { if (mTriggerBack) { dispatchOnBackInvoked(mActiveCallback); } else { dispatchOnBackCancelled(mActiveCallback); } // Animation missing. Simply finish back navigation. finishBackNavigation(); return; } final BackAnimationRunner runner = mAnimationDefinition.get(backType); if (runner.isWaitingAnimation()) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready."); return; } startPostCommitAnimation(); } /** * Start the phase 2 animation when gesture is released. * Callback to {@link #onBackAnimationFinished} when it is finished or timeout. */ private void startPostCommitAnimation() { if (mPostCommitAnimationInProgress) { return; } ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startPostCommitAnimation()"); mPostCommitAnimationInProgress = true; mShellExecutor.executeDelayed(mAnimationTimeoutRunnable, MAX_ANIMATION_DURATION); // The next callback should be {@link #onBackAnimationFinished}. if (mTriggerBack) { dispatchOnBackInvoked(mActiveCallback); } else { dispatchOnBackCancelled(mActiveCallback); } } /** * Called when the post commit animation is completed or timeout. * This will trigger the real {@link IOnBackInvokedCallback} behavior. */ @VisibleForTesting void onBackAnimationFinished() { if (!mPostCommitAnimationInProgress) { return; } // Stop timeout runner. mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); mPostCommitAnimationInProgress = false; ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: onBackAnimationFinished()"); // Trigger the real back. if (mBackNavigationInfo != null) { IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback(); if (mTriggerBack) { dispatchOnBackInvoked(callback); } else { dispatchOnBackCancelled(callback); } } finishBackNavigation(); } /** * This should be called after the whole back navigation is completed. */ @VisibleForTesting @VisibleForTesting void finishBackNavigation() { void finishBackNavigation() { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); Loading @@ -571,10 +573,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTriggerBack = false; mTriggerBack = false; mShouldStartOnNextMoveEvent = false; mShouldStartOnNextMoveEvent = false; mTouchTracker.reset(); mTouchTracker.reset(); mActiveCallback = null; if (backNavigationInfo == null) { if (backNavigationInfo == null) { return; return; } } stopTransition(); if (mBackAnimationFinishedCallback != null) { if (mBackAnimationFinishedCallback != null) { try { try { mBackAnimationFinishedCallback.onAnimationFinished(triggerBack); mBackAnimationFinishedCallback.onAnimationFinished(triggerBack); Loading @@ -586,19 +588,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backNavigationInfo.onBackNavigationFinished(triggerBack); backNavigationInfo.onBackNavigationFinished(triggerBack); } } private void startTransition() { if (mTransitionInProgress) { return; } mTransitionInProgress = true; mShellExecutor.executeDelayed(mResetTransitionRunnable, MAX_TRANSITION_DURATION); } void stopTransition() { mShellExecutor.removeCallbacks(mResetTransitionRunnable); mTransitionInProgress = false; } private void createAdapter() { private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override @Override Loading @@ -624,20 +613,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation(apps, wallpapers, nonApps, runner.startAnimation(apps, wallpapers, nonApps, BackAnimationController.this::onBackAnimationFinished); BackAnimationController.this::onBackAnimationFinished); if (apps.length >= 1) { if (apps.length >= 1) { final int backType = mBackNavigationInfo.getType(); IOnBackInvokedCallback targetCallback = mAnimationDefinition.get(backType) .getCallback(); dispatchOnBackStarted( dispatchOnBackStarted( targetCallback, mTouchTracker.createStartEvent(apps[0])); mActiveCallback, mTouchTracker.createStartEvent(apps[0])); } } if (!mBackGestureStarted) { if (!mBackGestureStarted) { // if the down -> up gesture happened before animation start, we have to // if the down -> up gesture happened before animation start, we have to // trigger the uninterruptible transition to finish the back animation. // trigger the uninterruptible transition to finish the back animation. final BackEvent backFinish = mTouchTracker.createProgressEvent(1); final BackEvent backFinish = mTouchTracker.createProgressEvent(); startTransition(); dispatchOnBackProgressed(mActiveCallback, backFinish); runner.consumeIfGestureFinished(backFinish); startPostCommitAnimation(); } } }); }); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java +5 −23 Original line number Original line Diff line number Diff line Loading @@ -18,12 +18,12 @@ package com.android.wm.shell.back; import static android.view.WindowManager.TRANSIT_OLD_UNSET; import static android.view.WindowManager.TRANSIT_OLD_UNSET; import android.annotation.NonNull; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.RemoteAnimationTarget; import android.window.BackEvent; import android.window.IBackAnimationRunner; import android.window.IBackAnimationRunner; import android.window.IOnBackInvokedCallback; import android.window.IOnBackInvokedCallback; Loading @@ -38,11 +38,11 @@ class BackAnimationRunner { private final IOnBackInvokedCallback mCallback; private final IOnBackInvokedCallback mCallback; private final IRemoteAnimationRunner mRunner; private final IRemoteAnimationRunner mRunner; private boolean mTriggerBack; // Whether we are waiting to receive onAnimationStart // Whether we are waiting to receive onAnimationStart private boolean mWaitingAnimation; private boolean mWaitingAnimation; BackAnimationRunner(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { BackAnimationRunner(@NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner) { mCallback = callback; mCallback = callback; mRunner = runner; mRunner = runner; } } Loading Loading @@ -83,25 +83,7 @@ class BackAnimationRunner { mWaitingAnimation = true; mWaitingAnimation = true; } } boolean onGestureFinished(boolean triggerBack) { boolean isWaitingAnimation() { if (mWaitingAnimation) { return mWaitingAnimation; mTriggerBack = triggerBack; return true; } return false; } void consumeIfGestureFinished(final BackEvent backFinish) { Log.d(TAG, "Start transition due to gesture is finished"); try { mCallback.onBackProgressed(backFinish); if (mTriggerBack) { mCallback.onBackInvoked(); } else { mCallback.onBackCancelled(); } } catch (RemoteException e) { Log.e(TAG, "dispatch error: ", e); } } } } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +90 −60 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +141 −154 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.os.UserHandle; import android.provider.Settings.Global; import android.provider.Settings.Global; import android.util.Log; import android.util.Log; import android.util.SparseArray; import android.util.SparseArray; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.IWindowFocusObserver; import android.view.IWindowFocusObserver; import android.view.InputDevice; import android.view.InputDevice; Loading Loading @@ -69,7 +68,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * Controls the window animation run when a user initiates a back gesture. * Controls the window animation run when a user initiates a back gesture. */ */ public class BackAnimationController implements RemoteCallable<BackAnimationController> { public class BackAnimationController implements RemoteCallable<BackAnimationController> { private static final String TAG = "BackAnimationController"; private static final String TAG = "ShellBackPreview"; private static final int SETTING_VALUE_OFF = 0; private static final int SETTING_VALUE_OFF = 0; private static final int SETTING_VALUE_ON = 1; private static final int SETTING_VALUE_ON = 1; public static final boolean IS_ENABLED = public static final boolean IS_ENABLED = Loading @@ -82,16 +81,15 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont /** Predictive back animation developer option */ /** Predictive back animation developer option */ private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false); private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false); /** /** * Max duration to wait for a transition to finish before accepting another gesture start * Max duration to wait for an animation to finish before triggering the real back. * request. */ */ private static final long MAX_TRANSITION_DURATION = 2000; private static final long MAX_ANIMATION_DURATION = 2000; /** True when a back gesture is ongoing */ /** True when a back gesture is ongoing */ private boolean mBackGestureStarted = false; private boolean mBackGestureStarted = false; /** Tracks if an uninterruptible transition is in progress */ /** Tracks if an uninterruptible animation is in progress */ private boolean mTransitionInProgress = false; private boolean mPostCommitAnimationInProgress = false; /** Tracks if we should start the back gesture on the next motion move event */ /** Tracks if we should start the back gesture on the next motion move event */ private boolean mShouldStartOnNextMoveEvent = false; private boolean mShouldStartOnNextMoveEvent = false; /** @see #setTriggerBack(boolean) */ /** @see #setTriggerBack(boolean) */ Loading @@ -105,9 +103,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final ShellController mShellController; private final ShellController mShellController; private final ShellExecutor mShellExecutor; private final ShellExecutor mShellExecutor; private final Handler mBgHandler; private final Handler mBgHandler; private final Runnable mResetTransitionRunnable = () -> { private final Runnable mAnimationTimeoutRunnable = () -> { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Transition didn't finish in %d ms. Resetting...", ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation didn't finish in %d ms. Resetting...", MAX_TRANSITION_DURATION); MAX_ANIMATION_DURATION); onBackAnimationFinished(); onBackAnimationFinished(); }; }; Loading @@ -119,6 +117,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>(); private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>(); private IOnBackInvokedCallback mActiveCallback; @VisibleForTesting @VisibleForTesting final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() { final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() { @Override @Override Loading @@ -126,9 +126,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Override @Override public void focusLost(IBinder inputToken) { public void focusLost(IBinder inputToken) { mShellExecutor.execute(() -> { mShellExecutor.execute(() -> { if (!mBackGestureStarted || mTransitionInProgress) { if (!mBackGestureStarted || mPostCommitAnimationInProgress) { // If an uninterruptible transition is already in progress, we should ignore // If an uninterruptible animation is already in progress, we should ignore // this due to the transition may cause focus lost. (alpha = 0) // this due to it may cause focus lost. (alpha = 0) return; return; } } ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus."); ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus."); Loading Loading @@ -180,26 +180,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } private void initBackAnimationRunners() { private void initBackAnimationRunners() { final IOnBackInvokedCallback dummyCallback = new IOnBackInvokedCallback.Default(); final IRemoteAnimationRunner dummyRunner = new IRemoteAnimationRunner.Default() { @Override public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException { // Animation missing. Simply finish animation. finishedCallback.onAnimationFinished(); } }; final BackAnimationRunner dummyBackRunner = new BackAnimationRunner(dummyCallback, dummyRunner); final CrossTaskBackAnimation crossTaskAnimation = new CrossTaskBackAnimation(mContext); final CrossTaskBackAnimation crossTaskAnimation = new CrossTaskBackAnimation(mContext); mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK, mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK, new BackAnimationRunner(crossTaskAnimation.mCallback, crossTaskAnimation.mRunner)); new BackAnimationRunner(crossTaskAnimation.mCallback, crossTaskAnimation.mRunner)); // TODO (238474994): register cross activity animation when it's completed. // TODO (238474994): register cross activity animation when it's completed. mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY, dummyBackRunner); // TODO (236760237): register dialog close animation when it's completed. // TODO (236760237): register dialog close animation when it's completed. mAnimationDefinition.set(BackNavigationInfo.TYPE_DIALOG_CLOSE, dummyBackRunner); } } private void setupAnimationDeveloperSettingsObserver( private void setupAnimationDeveloperSettingsObserver( Loading @@ -222,10 +207,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private void updateEnableAnimationFromSetting() { private void updateEnableAnimationFromSetting() { int settingValue = Global.getInt(mContext.getContentResolver(), int settingValue = Global.getInt(mContext.getContentResolver(), Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); boolean isEnabled = settingValue == SETTING_VALUE_ON; boolean isEnabled = settingValue == SETTING_VALUE_ON && IS_U_ANIMATION_ENABLED; mEnableAnimations.set(isEnabled); mEnableAnimations.set(isEnabled); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", isEnabled); isEnabled); } } public BackAnimation getBackAnimationImpl() { public BackAnimation getBackAnimationImpl() { Loading Loading @@ -279,7 +263,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont public void setBackToLauncherCallback(IOnBackInvokedCallback callback, public void setBackToLauncherCallback(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { IRemoteAnimationRunner runner) { executeRemoteCallWithTaskPermission(mController, "setBackToLauncherCallback", executeRemoteCallWithTaskPermission(mController, "setBackToLauncherCallback", (controller) -> controller.setBackToLauncherCallback(callback, runner)); (controller) -> controller.registerAnimation( BackNavigationInfo.TYPE_RETURN_TO_HOME, new BackAnimationRunner(callback, runner))); } } @Override @Override Loading @@ -294,44 +280,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } @VisibleForTesting void registerAnimation(@BackNavigationInfo.BackTargetType int type, void setBackToLauncherCallback(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { @NonNull BackAnimationRunner runner) { mAnimationDefinition.set(BackNavigationInfo.TYPE_RETURN_TO_HOME, mAnimationDefinition.set(type, runner); new BackAnimationRunner(callback, runner)); } } private void clearBackToLauncherCallback() { private void clearBackToLauncherCallback() { mAnimationDefinition.remove(BackNavigationInfo.TYPE_RETURN_TO_HOME); mAnimationDefinition.remove(BackNavigationInfo.TYPE_RETURN_TO_HOME); } } @VisibleForTesting void onBackAnimationFinished() { if (!mTransitionInProgress) { return; } ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: onBackAnimationFinished()"); // Trigger real back. if (mBackNavigationInfo != null) { IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback(); if (mTriggerBack) { dispatchOnBackInvoked(callback); } else { dispatchOnBackCancelled(callback); } } finishBackNavigation(); } /** /** * Called when a new motion event needs to be transferred to this * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} * {@link BackAnimationController} */ */ public void onMotionEvent(float touchX, float touchY, int keyAction, public void onMotionEvent(float touchX, float touchY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { @BackEvent.SwipeEdge int swipeEdge) { if (mTransitionInProgress) { if (mPostCommitAnimationInProgress) { return; return; } } Loading @@ -348,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont onGestureStarted(touchX, touchY, swipeEdge); onGestureStarted(touchX, touchY, swipeEdge); mShouldStartOnNextMoveEvent = false; mShouldStartOnNextMoveEvent = false; } } onMove(touchX, touchY, swipeEdge); onMove(); } else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) { } else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Finishing gesture with event action: %d", keyAction); "Finishing gesture with event action: %d", keyAction); Loading Loading @@ -386,30 +350,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } final int backType = backNavigationInfo.getType(); final int backType = backNavigationInfo.getType(); final IOnBackInvokedCallback targetCallback; final boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); final boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); if (shouldDispatchToAnimator) { if (shouldDispatchToAnimator) { mActiveCallback = mAnimationDefinition.get(backType).getCallback(); mAnimationDefinition.get(backType).startGesture(); mAnimationDefinition.get(backType).startGesture(); } else { } else { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback(); dispatchOnBackStarted(targetCallback, mTouchTracker.createStartEvent(null)); dispatchOnBackStarted(mActiveCallback, mTouchTracker.createStartEvent(null)); } } } } private void onMove(float touchX, float touchY, @BackEvent.SwipeEdge int swipeEdge) { private void onMove() { if (!mBackGestureStarted || mBackNavigationInfo == null || !mEnableAnimations.get()) { if (!mBackGestureStarted || mBackNavigationInfo == null || !mEnableAnimations.get()) { return; return; } } final BackEvent backEvent = mTouchTracker.createProgressEvent(); final BackEvent backEvent = mTouchTracker.createProgressEvent(); dispatchOnBackProgressed(mActiveCallback, backEvent); int backType = mBackNavigationInfo.getType(); IOnBackInvokedCallback targetCallback; if (shouldDispatchToAnimator(backType)) { targetCallback = mAnimationDefinition.get(backType).getCallback(); } else { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); } dispatchOnBackProgressed(targetCallback, backEvent); } } private void injectBackKey() { private void injectBackKey() { Loading @@ -431,57 +387,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } private void onGestureFinished(boolean fromTouch) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack); if (!mBackGestureStarted) { finishBackNavigation(); return; } if (fromTouch) { // Let touch reset the flag otherwise it will start a new back navigation and refresh // the info when received a new move event. mBackGestureStarted = false; } if (mTransitionInProgress) { return; } if (mBackNavigationInfo == null) { // No focus window found or core are running recents animation, inject back key as // legacy behavior. if (mTriggerBack) { injectBackKey(); } finishBackNavigation(); return; } int backType = mBackNavigationInfo.getType(); boolean shouldDispatchToAnimator = shouldDispatchToAnimator(backType); final BackAnimationRunner runner = mAnimationDefinition.get(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToAnimator ? runner.getCallback() : mBackNavigationInfo.getOnBackInvokedCallback(); if (shouldDispatchToAnimator) { if (runner.onGestureFinished(mTriggerBack)) { Log.w(TAG, "Gesture released, but animation didn't ready."); return; } startTransition(); } if (mTriggerBack) { dispatchOnBackInvoked(targetCallback); } else { dispatchOnBackCancelled(targetCallback); } if (!shouldDispatchToAnimator) { // Animation callback missing. Simply finish animation. finishBackNavigation(); } } private boolean shouldDispatchToAnimator(int backType) { private boolean shouldDispatchToAnimator(int backType) { return mEnableAnimations.get() return mEnableAnimations.get() && mBackNavigationInfo != null && mBackNavigationInfo != null Loading @@ -495,7 +400,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackStarted(backEvent); callback.onBackStarted(backEvent); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -519,7 +424,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackCancelled(); callback.onBackCancelled(); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -533,7 +438,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; return; } } try { try { if (shouldDispatchAnimation(callback)) { if (mEnableAnimations.get()) { callback.onBackProgressed(backEvent); callback.onBackProgressed(backEvent); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -541,17 +446,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } } private boolean shouldDispatchAnimation(IOnBackInvokedCallback callback) { return (IS_U_ANIMATION_ENABLED || callback == mAnimationDefinition.get( BackNavigationInfo.TYPE_RETURN_TO_HOME).getCallback()) && mEnableAnimations.get(); } /** /** * Sets to true when the back gesture has passed the triggering threshold, false otherwise. * Sets to true when the back gesture has passed the triggering threshold, false otherwise. */ */ public void setTriggerBack(boolean triggerBack) { public void setTriggerBack(boolean triggerBack) { if (mTransitionInProgress) { if (mPostCommitAnimationInProgress) { return; return; } } mTriggerBack = triggerBack; mTriggerBack = triggerBack; Loading @@ -562,6 +461,109 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTouchTracker.setProgressThreshold(progressThreshold); mTouchTracker.setProgressThreshold(progressThreshold); } } /** * Called when the gesture is released, then it could start the post commit animation. */ private void onGestureFinished(boolean fromTouch) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack); if (!mBackGestureStarted) { finishBackNavigation(); return; } if (fromTouch) { // Let touch reset the flag otherwise it will start a new back navigation and refresh // the info when received a new move event. mBackGestureStarted = false; } if (mPostCommitAnimationInProgress) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation is still running"); return; } if (mBackNavigationInfo == null) { // No focus window found or core are running recents animation, inject back key as // legacy behavior. if (mTriggerBack) { injectBackKey(); } finishBackNavigation(); return; } final int backType = mBackNavigationInfo.getType(); // Directly finish back navigation if no animator defined. if (!shouldDispatchToAnimator(backType)) { if (mTriggerBack) { dispatchOnBackInvoked(mActiveCallback); } else { dispatchOnBackCancelled(mActiveCallback); } // Animation missing. Simply finish back navigation. finishBackNavigation(); return; } final BackAnimationRunner runner = mAnimationDefinition.get(backType); if (runner.isWaitingAnimation()) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready."); return; } startPostCommitAnimation(); } /** * Start the phase 2 animation when gesture is released. * Callback to {@link #onBackAnimationFinished} when it is finished or timeout. */ private void startPostCommitAnimation() { if (mPostCommitAnimationInProgress) { return; } ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startPostCommitAnimation()"); mPostCommitAnimationInProgress = true; mShellExecutor.executeDelayed(mAnimationTimeoutRunnable, MAX_ANIMATION_DURATION); // The next callback should be {@link #onBackAnimationFinished}. if (mTriggerBack) { dispatchOnBackInvoked(mActiveCallback); } else { dispatchOnBackCancelled(mActiveCallback); } } /** * Called when the post commit animation is completed or timeout. * This will trigger the real {@link IOnBackInvokedCallback} behavior. */ @VisibleForTesting void onBackAnimationFinished() { if (!mPostCommitAnimationInProgress) { return; } // Stop timeout runner. mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); mPostCommitAnimationInProgress = false; ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: onBackAnimationFinished()"); // Trigger the real back. if (mBackNavigationInfo != null) { IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback(); if (mTriggerBack) { dispatchOnBackInvoked(callback); } else { dispatchOnBackCancelled(callback); } } finishBackNavigation(); } /** * This should be called after the whole back navigation is completed. */ @VisibleForTesting @VisibleForTesting void finishBackNavigation() { void finishBackNavigation() { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); Loading @@ -571,10 +573,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTriggerBack = false; mTriggerBack = false; mShouldStartOnNextMoveEvent = false; mShouldStartOnNextMoveEvent = false; mTouchTracker.reset(); mTouchTracker.reset(); mActiveCallback = null; if (backNavigationInfo == null) { if (backNavigationInfo == null) { return; return; } } stopTransition(); if (mBackAnimationFinishedCallback != null) { if (mBackAnimationFinishedCallback != null) { try { try { mBackAnimationFinishedCallback.onAnimationFinished(triggerBack); mBackAnimationFinishedCallback.onAnimationFinished(triggerBack); Loading @@ -586,19 +588,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backNavigationInfo.onBackNavigationFinished(triggerBack); backNavigationInfo.onBackNavigationFinished(triggerBack); } } private void startTransition() { if (mTransitionInProgress) { return; } mTransitionInProgress = true; mShellExecutor.executeDelayed(mResetTransitionRunnable, MAX_TRANSITION_DURATION); } void stopTransition() { mShellExecutor.removeCallbacks(mResetTransitionRunnable); mTransitionInProgress = false; } private void createAdapter() { private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override @Override Loading @@ -624,20 +613,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation(apps, wallpapers, nonApps, runner.startAnimation(apps, wallpapers, nonApps, BackAnimationController.this::onBackAnimationFinished); BackAnimationController.this::onBackAnimationFinished); if (apps.length >= 1) { if (apps.length >= 1) { final int backType = mBackNavigationInfo.getType(); IOnBackInvokedCallback targetCallback = mAnimationDefinition.get(backType) .getCallback(); dispatchOnBackStarted( dispatchOnBackStarted( targetCallback, mTouchTracker.createStartEvent(apps[0])); mActiveCallback, mTouchTracker.createStartEvent(apps[0])); } } if (!mBackGestureStarted) { if (!mBackGestureStarted) { // if the down -> up gesture happened before animation start, we have to // if the down -> up gesture happened before animation start, we have to // trigger the uninterruptible transition to finish the back animation. // trigger the uninterruptible transition to finish the back animation. final BackEvent backFinish = mTouchTracker.createProgressEvent(1); final BackEvent backFinish = mTouchTracker.createProgressEvent(); startTransition(); dispatchOnBackProgressed(mActiveCallback, backFinish); runner.consumeIfGestureFinished(backFinish); startPostCommitAnimation(); } } }); }); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java +5 −23 Original line number Original line Diff line number Diff line Loading @@ -18,12 +18,12 @@ package com.android.wm.shell.back; import static android.view.WindowManager.TRANSIT_OLD_UNSET; import static android.view.WindowManager.TRANSIT_OLD_UNSET; import android.annotation.NonNull; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.RemoteAnimationTarget; import android.window.BackEvent; import android.window.IBackAnimationRunner; import android.window.IBackAnimationRunner; import android.window.IOnBackInvokedCallback; import android.window.IOnBackInvokedCallback; Loading @@ -38,11 +38,11 @@ class BackAnimationRunner { private final IOnBackInvokedCallback mCallback; private final IOnBackInvokedCallback mCallback; private final IRemoteAnimationRunner mRunner; private final IRemoteAnimationRunner mRunner; private boolean mTriggerBack; // Whether we are waiting to receive onAnimationStart // Whether we are waiting to receive onAnimationStart private boolean mWaitingAnimation; private boolean mWaitingAnimation; BackAnimationRunner(IOnBackInvokedCallback callback, IRemoteAnimationRunner runner) { BackAnimationRunner(@NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner) { mCallback = callback; mCallback = callback; mRunner = runner; mRunner = runner; } } Loading Loading @@ -83,25 +83,7 @@ class BackAnimationRunner { mWaitingAnimation = true; mWaitingAnimation = true; } } boolean onGestureFinished(boolean triggerBack) { boolean isWaitingAnimation() { if (mWaitingAnimation) { return mWaitingAnimation; mTriggerBack = triggerBack; return true; } return false; } void consumeIfGestureFinished(final BackEvent backFinish) { Log.d(TAG, "Start transition due to gesture is finished"); try { mCallback.onBackProgressed(backFinish); if (mTriggerBack) { mCallback.onBackInvoked(); } else { mCallback.onBackCancelled(); } } catch (RemoteException e) { Log.e(TAG, "dispatch error: ", e); } } } } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +90 −60 File changed.Preview size limit exceeded, changes collapsed. Show changes