Loading core/java/android/window/BackEvent.java +6 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,12 @@ public final class BackEvent { @SwipeEdge private final int mSwipeEdge; /** @hide */ public static BackEvent fromBackMotionEvent(BackMotionEvent backMotionEvent) { return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge()); } /** * Creates a new {@link BackEvent} instance. * Loading core/java/android/window/ImeOnBackInvokedDispatcher.java +84 −102 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.view.ViewRootImpl; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.function.Consumer; /** * A {@link OnBackInvokedDispatcher} for IME that forwards {@link OnBackInvokedCallback} Loading @@ -52,17 +53,8 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc static final String RESULT_KEY_PRIORITY = "priority"; static final int RESULT_CODE_REGISTER = 0; static final int RESULT_CODE_UNREGISTER = 1; static final int RESULT_CODE_START_DISPATCHING = 2; static final int RESULT_CODE_STOP_DISPATCHING = 3; @NonNull private final ResultReceiver mResultReceiver; @NonNull private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator(); @NonNull private final BackTouchTracker mTouchTracker = new BackTouchTracker(); // The handler to run callbacks on. This should be on the same thread // the ViewRootImpl holding IME's WindowOnBackInvokedDispatcher is created on. private Handler mHandler; public ImeOnBackInvokedDispatcher(Handler handler) { mResultReceiver = new ResultReceiver(handler) { Loading @@ -89,10 +81,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mResultReceiver = in.readTypedObject(ResultReceiver.CREATOR); } void setHandler(@NonNull Handler handler) { mHandler = handler; } @Override public void registerOnBackInvokedCallback( @OnBackInvokedDispatcher.Priority int priority, Loading @@ -103,14 +91,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc // This is necessary because the callback is sent to and registered from // the app process, which may treat the IME callback as weakly referenced. This will not // cause a memory leak because the app side already clears the reference correctly. final IOnBackInvokedCallback iCallback = new ImeOnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, this, mHandler != null ? mHandler : Handler.getMain(), false /* useWeakRef */); final IOnBackInvokedCallback iCallback = new ImeOnBackInvokedCallbackWrapper(callback); bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder()); bundle.putInt(RESULT_KEY_PRIORITY, priority); bundle.putInt(RESULT_KEY_ID, callback.hashCode()); Loading @@ -135,12 +116,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc dest.writeTypedObject(mResultReceiver, flags); } /** Sets the progress thresholds for touch tracking */ public void setProgressThresholds(float linearDistance, float maxDistance, float nonLinearFactor) { mTouchTracker.setProgressThresholds(linearDistance, maxDistance, nonLinearFactor); } @NonNull public static final Parcelable.Creator<ImeOnBackInvokedDispatcher> CREATOR = new Parcelable.Creator<ImeOnBackInvokedDispatcher>() { Loading @@ -162,15 +137,10 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc int priority = resultData.getInt(RESULT_KEY_PRIORITY); final IOnBackInvokedCallback callback = IOnBackInvokedCallback.Stub.asInterface( resultData.getBinder(RESULT_KEY_CALLBACK)); registerReceivedCallback( callback, priority, callbackId, receivingDispatcher); registerReceivedCallback(callback, priority, callbackId, receivingDispatcher); } else if (resultCode == RESULT_CODE_UNREGISTER) { final int callbackId = resultData.getInt(RESULT_KEY_ID); unregisterReceivedCallback(callbackId, receivingDispatcher); } else if (resultCode == RESULT_CODE_START_DISPATCHING) { receiveStartDispatching(receivingDispatcher); } else if (resultCode == RESULT_CODE_STOP_DISPATCHING) { receiveStopDispatching(receivingDispatcher); } } Loading Loading @@ -212,63 +182,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mImeCallbacks.remove(callback); } static class ImeOnBackInvokedCallbackWrapper extends WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper { @NonNull private final ImeOnBackInvokedDispatcher mDispatcher; ImeOnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull ImeOnBackInvokedDispatcher dispatcher, @NonNull Handler handler, boolean useWeakRef) { super(callback, touchTracker, progressAnimator, handler, useWeakRef); mDispatcher = dispatcher; } @Override public void onBackStarted(BackMotionEvent backEvent) { super.onBackStarted(backEvent); mDispatcher.sendStartDispatching(); } @Override public void onBackCancelled() { super.onBackCancelled(); mDispatcher.sendStopDispatching(); } @Override public void onBackInvoked() throws RemoteException { super.onBackInvoked(); mDispatcher.sendStopDispatching(); } } /** Notifies the app process that we've stopped dispatching to an IME callback */ private void sendStopDispatching() { mResultReceiver.send(RESULT_CODE_STOP_DISPATCHING, null /* unused bundle */); } /** Notifies the app process that we've started dispatching to an IME callback */ private void sendStartDispatching() { mResultReceiver.send(RESULT_CODE_START_DISPATCHING, null /* unused bundle */); } /** Receives IME's message that dispatching has started. */ private void receiveStopDispatching( @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) { receivingDispatcher.onStopImeDispatching(); } /** Receives IME's message that dispatching has stopped. */ private void receiveStartDispatching( @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) { receivingDispatcher.onStartImeDispatching(); } /** Clears all registered callbacks on the instance. */ public void clear() { // Unregister previously registered callbacks if there's any. Loading @@ -278,14 +191,10 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc } } mImeCallbacks.clear(); // We should also stop running animations since all callbacks have been removed. // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler. Handler.getMain().post(mProgressAnimator::reset); sendStopDispatching(); } @VisibleForTesting(visibility = PACKAGE) public static class ImeOnBackInvokedCallback implements OnBackInvokedCallback { public static class ImeOnBackInvokedCallback implements OnBackAnimationCallback { @NonNull private final IOnBackInvokedCallback mIOnBackInvokedCallback; /** Loading @@ -302,12 +211,43 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mPriority = priority; } @Override public void onBackStarted(@NonNull BackEvent backEvent) { try { mIOnBackInvokedCallback.onBackStarted( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackProgressed(@NonNull BackEvent backEvent) { try { mIOnBackInvokedCallback.onBackProgressed( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackInvoked() { try { if (mIOnBackInvokedCallback != null) { mIOnBackInvokedCallback.onBackInvoked(); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackCancelled() { try { mIOnBackInvokedCallback.onBackCancelled(); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } Loading @@ -317,10 +257,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc return mId; } IOnBackInvokedCallback getIOnBackInvokedCallback() { return mIOnBackInvokedCallback; } @Override public String toString() { return "ImeCallback=ImeOnBackInvokedCallback@" + mId Loading Loading @@ -358,4 +294,50 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc } } } /** * Wrapper class that wraps an OnBackInvokedCallback. This is used when a callback is sent from * the IME process to the app process. */ private class ImeOnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { private final OnBackInvokedCallback mCallback; ImeOnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) { mCallback = callback; } @Override public void onBackStarted(BackMotionEvent backMotionEvent) { maybeRunOnAnimationCallback((animationCallback) -> animationCallback.onBackStarted( BackEvent.fromBackMotionEvent(backMotionEvent))); } @Override public void onBackProgressed(BackMotionEvent backMotionEvent) { maybeRunOnAnimationCallback((animationCallback) -> animationCallback.onBackProgressed( BackEvent.fromBackMotionEvent(backMotionEvent))); } @Override public void onBackCancelled() { maybeRunOnAnimationCallback(OnBackAnimationCallback::onBackCancelled); } @Override public void onBackInvoked() { mCallback.onBackInvoked(); } @Override public void setTriggerBack(boolean triggerBack) { // no-op } private void maybeRunOnAnimationCallback(Consumer<OnBackAnimationCallback> block) { if (mCallback instanceof OnBackAnimationCallback) { block.accept((OnBackAnimationCallback) mCallback); } } } } core/java/android/window/WindowOnBackInvokedDispatcher.java +18 −88 Original line number Diff line number Diff line Loading @@ -105,7 +105,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { // The threshold for back swipe full progress. private float mBackSwipeLinearThreshold; private float mNonLinearProgressFactor; private boolean mImeDispatchingActive; public WindowOnBackInvokedDispatcher(@NonNull Context context, Looper looper) { mChecker = new Checker(context); Loading Loading @@ -176,18 +175,19 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.registerOnBackInvokedCallback(priority, callback); return; } if ((callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) && !isOnBackInvokedCallbackEnabled()) { if (callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) { // Fall back to compat back key injection if legacy back behaviour should be used. return; if (!isOnBackInvokedCallbackEnabled()) return; if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback && mImeBackAnimationController != null) { // register ImeBackAnimationController instead to play predictive back animation callback = mImeBackAnimationController; } } if (!mOnBackInvokedCallbacks.containsKey(priority)) { mOnBackInvokedCallbacks.put(priority, new ArrayList<>()); } if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { callback = mImeBackAnimationController; } ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority); // If callback has already been added, remove it and re-add it. Loading Loading @@ -250,7 +250,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { */ public boolean isBackGestureInProgress() { synchronized (mLock) { return mTouchTracker.isActive() || mImeDispatchingActive; return mTouchTracker.isActive(); } } Loading Loading @@ -308,16 +308,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { OnBackInvokedCallbackInfo callbackInfo = null; if (callback != null) { int priority = mAllCallbacks.get(callback); final IOnBackInvokedCallback iCallback = callback instanceof ImeOnBackInvokedDispatcher .ImeOnBackInvokedCallback ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) callback).getIOnBackInvokedCallback() : new OnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, mHandler); final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, mHandler); callbackInfo = new OnBackInvokedCallbackInfo( iCallback, priority, Loading Loading @@ -367,10 +359,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { float linearDistance = Math.min(maxDistance, mBackSwipeLinearThreshold); mTouchTracker.setProgressThresholds( linearDistance, maxDistance, mNonLinearProgressFactor); if (mImeDispatcher != null) { mImeDispatcher.setProgressThresholds( linearDistance, maxDistance, mNonLinearProgressFactor); } } /** Loading Loading @@ -402,46 +390,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } /** * Called when we start dispatching to a callback registered from IME. */ public void onStartImeDispatching() { synchronized (mLock) { mImeDispatchingActive = true; } } /** * Called when we stop dispatching to a callback registered from IME. */ public void onStopImeDispatching() { synchronized (mLock) { mImeDispatchingActive = false; } } static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { static class CallbackRef { final WeakReference<OnBackInvokedCallback> mWeakRef; final OnBackInvokedCallback mStrongRef; CallbackRef(@NonNull OnBackInvokedCallback callback, boolean useWeakRef) { if (useWeakRef) { mWeakRef = new WeakReference<>(callback); mStrongRef = null; } else { mStrongRef = callback; mWeakRef = null; } } OnBackInvokedCallback get() { if (mStrongRef != null) { return mStrongRef; } return mWeakRef.get(); } } final CallbackRef mCallbackRef; private static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { @NonNull private final WeakReference<OnBackInvokedCallback> mCallback; @NonNull private final BackProgressAnimator mProgressAnimator; @NonNull Loading @@ -454,19 +405,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull Handler handler) { mCallbackRef = new CallbackRef(callback, true /* useWeakRef */); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; } OnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull Handler handler, boolean useWeakRef) { mCallbackRef = new CallbackRef(callback, useWeakRef); mCallback = new WeakReference<>(callback); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; Loading @@ -489,11 +428,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getSwipeEdge()); if (callback != null) { callback.onBackStarted(new BackEvent( backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), backEvent.getSwipeEdge())); callback.onBackStarted(BackEvent.fromBackMotionEvent(backEvent)); mProgressAnimator.onBackStarted(backEvent, callback::onBackProgressed); } }); Loading @@ -519,7 +454,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { boolean isInProgress = mProgressAnimator.isBackAnimationInProgress(); mProgressAnimator.reset(); // TODO(b/333957271): Re-introduce auto fling progress generation. final OnBackInvokedCallback callback = mCallbackRef.get(); final OnBackInvokedCallback callback = mCallback.get(); if (callback == null) { Log.d(TAG, "Trying to call onBackInvoked() on a null callback reference."); return; Loading @@ -539,7 +474,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @Nullable private OnBackAnimationCallback getBackAnimationCallback() { OnBackInvokedCallback callback = mCallbackRef.get(); OnBackInvokedCallback callback = mCallback.get(); return callback instanceof OnBackAnimationCallback ? (OnBackAnimationCallback) callback : null; } Loading Loading @@ -569,11 +504,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { public void setImeOnBackInvokedDispatcher( @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { mImeDispatcher = imeDispatcher; mImeDispatcher.setHandler(mHandler); mImeDispatcher.setProgressThresholds( mTouchTracker.getLinearDistance(), mTouchTracker.getMaxDistance(), mTouchTracker.getNonLinearFactor()); } /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/ Loading Loading
core/java/android/window/BackEvent.java +6 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,12 @@ public final class BackEvent { @SwipeEdge private final int mSwipeEdge; /** @hide */ public static BackEvent fromBackMotionEvent(BackMotionEvent backMotionEvent) { return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge()); } /** * Creates a new {@link BackEvent} instance. * Loading
core/java/android/window/ImeOnBackInvokedDispatcher.java +84 −102 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.view.ViewRootImpl; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.function.Consumer; /** * A {@link OnBackInvokedDispatcher} for IME that forwards {@link OnBackInvokedCallback} Loading @@ -52,17 +53,8 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc static final String RESULT_KEY_PRIORITY = "priority"; static final int RESULT_CODE_REGISTER = 0; static final int RESULT_CODE_UNREGISTER = 1; static final int RESULT_CODE_START_DISPATCHING = 2; static final int RESULT_CODE_STOP_DISPATCHING = 3; @NonNull private final ResultReceiver mResultReceiver; @NonNull private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator(); @NonNull private final BackTouchTracker mTouchTracker = new BackTouchTracker(); // The handler to run callbacks on. This should be on the same thread // the ViewRootImpl holding IME's WindowOnBackInvokedDispatcher is created on. private Handler mHandler; public ImeOnBackInvokedDispatcher(Handler handler) { mResultReceiver = new ResultReceiver(handler) { Loading @@ -89,10 +81,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mResultReceiver = in.readTypedObject(ResultReceiver.CREATOR); } void setHandler(@NonNull Handler handler) { mHandler = handler; } @Override public void registerOnBackInvokedCallback( @OnBackInvokedDispatcher.Priority int priority, Loading @@ -103,14 +91,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc // This is necessary because the callback is sent to and registered from // the app process, which may treat the IME callback as weakly referenced. This will not // cause a memory leak because the app side already clears the reference correctly. final IOnBackInvokedCallback iCallback = new ImeOnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, this, mHandler != null ? mHandler : Handler.getMain(), false /* useWeakRef */); final IOnBackInvokedCallback iCallback = new ImeOnBackInvokedCallbackWrapper(callback); bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder()); bundle.putInt(RESULT_KEY_PRIORITY, priority); bundle.putInt(RESULT_KEY_ID, callback.hashCode()); Loading @@ -135,12 +116,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc dest.writeTypedObject(mResultReceiver, flags); } /** Sets the progress thresholds for touch tracking */ public void setProgressThresholds(float linearDistance, float maxDistance, float nonLinearFactor) { mTouchTracker.setProgressThresholds(linearDistance, maxDistance, nonLinearFactor); } @NonNull public static final Parcelable.Creator<ImeOnBackInvokedDispatcher> CREATOR = new Parcelable.Creator<ImeOnBackInvokedDispatcher>() { Loading @@ -162,15 +137,10 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc int priority = resultData.getInt(RESULT_KEY_PRIORITY); final IOnBackInvokedCallback callback = IOnBackInvokedCallback.Stub.asInterface( resultData.getBinder(RESULT_KEY_CALLBACK)); registerReceivedCallback( callback, priority, callbackId, receivingDispatcher); registerReceivedCallback(callback, priority, callbackId, receivingDispatcher); } else if (resultCode == RESULT_CODE_UNREGISTER) { final int callbackId = resultData.getInt(RESULT_KEY_ID); unregisterReceivedCallback(callbackId, receivingDispatcher); } else if (resultCode == RESULT_CODE_START_DISPATCHING) { receiveStartDispatching(receivingDispatcher); } else if (resultCode == RESULT_CODE_STOP_DISPATCHING) { receiveStopDispatching(receivingDispatcher); } } Loading Loading @@ -212,63 +182,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mImeCallbacks.remove(callback); } static class ImeOnBackInvokedCallbackWrapper extends WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper { @NonNull private final ImeOnBackInvokedDispatcher mDispatcher; ImeOnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull ImeOnBackInvokedDispatcher dispatcher, @NonNull Handler handler, boolean useWeakRef) { super(callback, touchTracker, progressAnimator, handler, useWeakRef); mDispatcher = dispatcher; } @Override public void onBackStarted(BackMotionEvent backEvent) { super.onBackStarted(backEvent); mDispatcher.sendStartDispatching(); } @Override public void onBackCancelled() { super.onBackCancelled(); mDispatcher.sendStopDispatching(); } @Override public void onBackInvoked() throws RemoteException { super.onBackInvoked(); mDispatcher.sendStopDispatching(); } } /** Notifies the app process that we've stopped dispatching to an IME callback */ private void sendStopDispatching() { mResultReceiver.send(RESULT_CODE_STOP_DISPATCHING, null /* unused bundle */); } /** Notifies the app process that we've started dispatching to an IME callback */ private void sendStartDispatching() { mResultReceiver.send(RESULT_CODE_START_DISPATCHING, null /* unused bundle */); } /** Receives IME's message that dispatching has started. */ private void receiveStopDispatching( @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) { receivingDispatcher.onStopImeDispatching(); } /** Receives IME's message that dispatching has stopped. */ private void receiveStartDispatching( @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) { receivingDispatcher.onStartImeDispatching(); } /** Clears all registered callbacks on the instance. */ public void clear() { // Unregister previously registered callbacks if there's any. Loading @@ -278,14 +191,10 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc } } mImeCallbacks.clear(); // We should also stop running animations since all callbacks have been removed. // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler. Handler.getMain().post(mProgressAnimator::reset); sendStopDispatching(); } @VisibleForTesting(visibility = PACKAGE) public static class ImeOnBackInvokedCallback implements OnBackInvokedCallback { public static class ImeOnBackInvokedCallback implements OnBackAnimationCallback { @NonNull private final IOnBackInvokedCallback mIOnBackInvokedCallback; /** Loading @@ -302,12 +211,43 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mPriority = priority; } @Override public void onBackStarted(@NonNull BackEvent backEvent) { try { mIOnBackInvokedCallback.onBackStarted( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackProgressed(@NonNull BackEvent backEvent) { try { mIOnBackInvokedCallback.onBackProgressed( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackInvoked() { try { if (mIOnBackInvokedCallback != null) { mIOnBackInvokedCallback.onBackInvoked(); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } } @Override public void onBackCancelled() { try { mIOnBackInvokedCallback.onBackCancelled(); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); } Loading @@ -317,10 +257,6 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc return mId; } IOnBackInvokedCallback getIOnBackInvokedCallback() { return mIOnBackInvokedCallback; } @Override public String toString() { return "ImeCallback=ImeOnBackInvokedCallback@" + mId Loading Loading @@ -358,4 +294,50 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc } } } /** * Wrapper class that wraps an OnBackInvokedCallback. This is used when a callback is sent from * the IME process to the app process. */ private class ImeOnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { private final OnBackInvokedCallback mCallback; ImeOnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) { mCallback = callback; } @Override public void onBackStarted(BackMotionEvent backMotionEvent) { maybeRunOnAnimationCallback((animationCallback) -> animationCallback.onBackStarted( BackEvent.fromBackMotionEvent(backMotionEvent))); } @Override public void onBackProgressed(BackMotionEvent backMotionEvent) { maybeRunOnAnimationCallback((animationCallback) -> animationCallback.onBackProgressed( BackEvent.fromBackMotionEvent(backMotionEvent))); } @Override public void onBackCancelled() { maybeRunOnAnimationCallback(OnBackAnimationCallback::onBackCancelled); } @Override public void onBackInvoked() { mCallback.onBackInvoked(); } @Override public void setTriggerBack(boolean triggerBack) { // no-op } private void maybeRunOnAnimationCallback(Consumer<OnBackAnimationCallback> block) { if (mCallback instanceof OnBackAnimationCallback) { block.accept((OnBackAnimationCallback) mCallback); } } } }
core/java/android/window/WindowOnBackInvokedDispatcher.java +18 −88 Original line number Diff line number Diff line Loading @@ -105,7 +105,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { // The threshold for back swipe full progress. private float mBackSwipeLinearThreshold; private float mNonLinearProgressFactor; private boolean mImeDispatchingActive; public WindowOnBackInvokedDispatcher(@NonNull Context context, Looper looper) { mChecker = new Checker(context); Loading Loading @@ -176,18 +175,19 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.registerOnBackInvokedCallback(priority, callback); return; } if ((callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) && !isOnBackInvokedCallbackEnabled()) { if (callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) { // Fall back to compat back key injection if legacy back behaviour should be used. return; if (!isOnBackInvokedCallbackEnabled()) return; if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback && mImeBackAnimationController != null) { // register ImeBackAnimationController instead to play predictive back animation callback = mImeBackAnimationController; } } if (!mOnBackInvokedCallbacks.containsKey(priority)) { mOnBackInvokedCallbacks.put(priority, new ArrayList<>()); } if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { callback = mImeBackAnimationController; } ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority); // If callback has already been added, remove it and re-add it. Loading Loading @@ -250,7 +250,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { */ public boolean isBackGestureInProgress() { synchronized (mLock) { return mTouchTracker.isActive() || mImeDispatchingActive; return mTouchTracker.isActive(); } } Loading Loading @@ -308,16 +308,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { OnBackInvokedCallbackInfo callbackInfo = null; if (callback != null) { int priority = mAllCallbacks.get(callback); final IOnBackInvokedCallback iCallback = callback instanceof ImeOnBackInvokedDispatcher .ImeOnBackInvokedCallback ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) callback).getIOnBackInvokedCallback() : new OnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, mHandler); final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper( callback, mTouchTracker, mProgressAnimator, mHandler); callbackInfo = new OnBackInvokedCallbackInfo( iCallback, priority, Loading Loading @@ -367,10 +359,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { float linearDistance = Math.min(maxDistance, mBackSwipeLinearThreshold); mTouchTracker.setProgressThresholds( linearDistance, maxDistance, mNonLinearProgressFactor); if (mImeDispatcher != null) { mImeDispatcher.setProgressThresholds( linearDistance, maxDistance, mNonLinearProgressFactor); } } /** Loading Loading @@ -402,46 +390,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } /** * Called when we start dispatching to a callback registered from IME. */ public void onStartImeDispatching() { synchronized (mLock) { mImeDispatchingActive = true; } } /** * Called when we stop dispatching to a callback registered from IME. */ public void onStopImeDispatching() { synchronized (mLock) { mImeDispatchingActive = false; } } static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { static class CallbackRef { final WeakReference<OnBackInvokedCallback> mWeakRef; final OnBackInvokedCallback mStrongRef; CallbackRef(@NonNull OnBackInvokedCallback callback, boolean useWeakRef) { if (useWeakRef) { mWeakRef = new WeakReference<>(callback); mStrongRef = null; } else { mStrongRef = callback; mWeakRef = null; } } OnBackInvokedCallback get() { if (mStrongRef != null) { return mStrongRef; } return mWeakRef.get(); } } final CallbackRef mCallbackRef; private static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { @NonNull private final WeakReference<OnBackInvokedCallback> mCallback; @NonNull private final BackProgressAnimator mProgressAnimator; @NonNull Loading @@ -454,19 +405,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull Handler handler) { mCallbackRef = new CallbackRef(callback, true /* useWeakRef */); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; } OnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull Handler handler, boolean useWeakRef) { mCallbackRef = new CallbackRef(callback, useWeakRef); mCallback = new WeakReference<>(callback); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; Loading @@ -489,11 +428,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getSwipeEdge()); if (callback != null) { callback.onBackStarted(new BackEvent( backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getProgress(), backEvent.getSwipeEdge())); callback.onBackStarted(BackEvent.fromBackMotionEvent(backEvent)); mProgressAnimator.onBackStarted(backEvent, callback::onBackProgressed); } }); Loading @@ -519,7 +454,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { boolean isInProgress = mProgressAnimator.isBackAnimationInProgress(); mProgressAnimator.reset(); // TODO(b/333957271): Re-introduce auto fling progress generation. final OnBackInvokedCallback callback = mCallbackRef.get(); final OnBackInvokedCallback callback = mCallback.get(); if (callback == null) { Log.d(TAG, "Trying to call onBackInvoked() on a null callback reference."); return; Loading @@ -539,7 +474,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @Nullable private OnBackAnimationCallback getBackAnimationCallback() { OnBackInvokedCallback callback = mCallbackRef.get(); OnBackInvokedCallback callback = mCallback.get(); return callback instanceof OnBackAnimationCallback ? (OnBackAnimationCallback) callback : null; } Loading Loading @@ -569,11 +504,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { public void setImeOnBackInvokedDispatcher( @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { mImeDispatcher = imeDispatcher; mImeDispatcher.setHandler(mHandler); mImeDispatcher.setProgressThresholds( mTouchTracker.getLinearDistance(), mTouchTracker.getMaxDistance(), mTouchTracker.getNonLinearFactor()); } /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/ Loading