Loading core/java/android/view/ImeBackAnimationController.java +9 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.Log; import android.view.animation.BackGestureInterpolator; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.inputmethod.Flags; import android.view.inputmethod.ImeTracker; import android.window.BackEvent; import android.window.OnBackAnimationCallback; Loading Loading @@ -142,10 +143,16 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { // control has been cancelled by the system. This can happen in multi-window mode for // example (i.e. split-screen or activity-embedding) notifyHideIme(); return; } } else { startPostCommitAnim(/*hideIme*/ true); } if (Flags.refactorInsetsController()) { // Unregister all IME back callbacks so that back events are sent to the next callback // even while the hide animation is playing mInsetsController.getHost().getInputMethodManager().getImeOnBackInvokedDispatcher() .preliminaryClear(); } } private void setPreCommitProgress(float progress) { if (isHideAnimationInProgress()) return; Loading core/java/android/view/InsetsController.java +13 −0 Original line number Diff line number Diff line Loading @@ -1344,6 +1344,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean fromPredictiveBack) { final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; if (Flags.refactorInsetsController() && !fromPredictiveBack && !visible && (types & ime()) != 0 && (mRequestedVisibleTypes & ime()) != 0) { // Clear IME back callbacks if a IME hide animation is requested mHost.getInputMethodManager().getImeOnBackInvokedDispatcher().preliminaryClear(); } // Basically, we accept the requested visibilities from the upstream callers... setRequestedVisibleTypes(visible ? types : 0, types); Loading Loading @@ -1921,6 +1926,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @InsetsType int requestedVisibleTypes = (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask); if (mRequestedVisibleTypes != requestedVisibleTypes) { if (Flags.refactorInsetsController() && (mRequestedVisibleTypes & ime()) == 0 && (requestedVisibleTypes & ime()) != 0) { // In case the IME back callbacks have been preliminarily cleared before, let's // reregister them. This can happen if an IME hide animation was interrupted and the // IME is requested to be shown again. getHost().getInputMethodManager().getImeOnBackInvokedDispatcher() .undoPreliminaryClear(); } ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)", requestedVisibleTypes, mRequestedVisibleTypes); mRequestedVisibleTypes = requestedVisibleTypes; Loading core/java/android/view/inputmethod/InputMethodManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -3666,6 +3666,14 @@ public final class InputMethodManager { 0 /* startInputFlags */, 0 /* softInputMode */, 0 /* windowFlags */); } /** * Returns the ImeOnBackInvokedDispatcher. * @hide */ public ImeOnBackInvokedDispatcher getImeOnBackInvokedDispatcher() { return mImeDispatcher; } /** * Check the next served view if needs to start input. */ Loading core/java/android/window/ImeOnBackInvokedDispatcher.java +28 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,34 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mImeCallbacks.remove(callback); } /** * Unregisters all callbacks on the receiving dispatcher but keeps a reference of the callbacks * in case the clearance is reverted in * {@link ImeOnBackInvokedDispatcher#undoPreliminaryClear()}. */ public void preliminaryClear() { // Unregister previously registered callbacks if there's any. if (getReceivingDispatcher() != null) { for (ImeOnBackInvokedCallback callback : mImeCallbacks) { getReceivingDispatcher().unregisterOnBackInvokedCallback(callback); } } } /** * Reregisters all callbacks on the receiving dispatcher that have previously been cleared by * calling {@link ImeOnBackInvokedDispatcher#preliminaryClear()}. This can happen if an IME hide * animation is interrupted causing the IME to reappear. */ public void undoPreliminaryClear() { if (getReceivingDispatcher() != null) { for (ImeOnBackInvokedCallback callback : mImeCallbacks) { getReceivingDispatcher().registerOnBackInvokedCallbackUnchecked(callback, callback.mPriority); } } } /** Clears all registered callbacks on the instance. */ public void clear() { // Unregister previously registered callbacks if there's any. Loading core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -161,7 +161,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); // verify that ImeBackAnimationController does not take control over IME insets verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(), anyBoolean(), anyLong(), any(), anyInt(), anyBoolean()); Loading @@ -180,7 +180,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); // verify that ImeBackAnimationController does not take control over IME insets verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(), anyBoolean(), anyLong(), any(), anyInt(), anyBoolean()); Loading Loading @@ -300,7 +300,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); }); } Loading Loading
core/java/android/view/ImeBackAnimationController.java +9 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.Log; import android.view.animation.BackGestureInterpolator; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.inputmethod.Flags; import android.view.inputmethod.ImeTracker; import android.window.BackEvent; import android.window.OnBackAnimationCallback; Loading Loading @@ -142,10 +143,16 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { // control has been cancelled by the system. This can happen in multi-window mode for // example (i.e. split-screen or activity-embedding) notifyHideIme(); return; } } else { startPostCommitAnim(/*hideIme*/ true); } if (Flags.refactorInsetsController()) { // Unregister all IME back callbacks so that back events are sent to the next callback // even while the hide animation is playing mInsetsController.getHost().getInputMethodManager().getImeOnBackInvokedDispatcher() .preliminaryClear(); } } private void setPreCommitProgress(float progress) { if (isHideAnimationInProgress()) return; Loading
core/java/android/view/InsetsController.java +13 −0 Original line number Diff line number Diff line Loading @@ -1344,6 +1344,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean fromPredictiveBack) { final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; if (Flags.refactorInsetsController() && !fromPredictiveBack && !visible && (types & ime()) != 0 && (mRequestedVisibleTypes & ime()) != 0) { // Clear IME back callbacks if a IME hide animation is requested mHost.getInputMethodManager().getImeOnBackInvokedDispatcher().preliminaryClear(); } // Basically, we accept the requested visibilities from the upstream callers... setRequestedVisibleTypes(visible ? types : 0, types); Loading Loading @@ -1921,6 +1926,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @InsetsType int requestedVisibleTypes = (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask); if (mRequestedVisibleTypes != requestedVisibleTypes) { if (Flags.refactorInsetsController() && (mRequestedVisibleTypes & ime()) == 0 && (requestedVisibleTypes & ime()) != 0) { // In case the IME back callbacks have been preliminarily cleared before, let's // reregister them. This can happen if an IME hide animation was interrupted and the // IME is requested to be shown again. getHost().getInputMethodManager().getImeOnBackInvokedDispatcher() .undoPreliminaryClear(); } ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)", requestedVisibleTypes, mRequestedVisibleTypes); mRequestedVisibleTypes = requestedVisibleTypes; Loading
core/java/android/view/inputmethod/InputMethodManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -3666,6 +3666,14 @@ public final class InputMethodManager { 0 /* startInputFlags */, 0 /* softInputMode */, 0 /* windowFlags */); } /** * Returns the ImeOnBackInvokedDispatcher. * @hide */ public ImeOnBackInvokedDispatcher getImeOnBackInvokedDispatcher() { return mImeDispatcher; } /** * Check the next served view if needs to start input. */ Loading
core/java/android/window/ImeOnBackInvokedDispatcher.java +28 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,34 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc mImeCallbacks.remove(callback); } /** * Unregisters all callbacks on the receiving dispatcher but keeps a reference of the callbacks * in case the clearance is reverted in * {@link ImeOnBackInvokedDispatcher#undoPreliminaryClear()}. */ public void preliminaryClear() { // Unregister previously registered callbacks if there's any. if (getReceivingDispatcher() != null) { for (ImeOnBackInvokedCallback callback : mImeCallbacks) { getReceivingDispatcher().unregisterOnBackInvokedCallback(callback); } } } /** * Reregisters all callbacks on the receiving dispatcher that have previously been cleared by * calling {@link ImeOnBackInvokedDispatcher#preliminaryClear()}. This can happen if an IME hide * animation is interrupted causing the IME to reappear. */ public void undoPreliminaryClear() { if (getReceivingDispatcher() != null) { for (ImeOnBackInvokedCallback callback : mImeCallbacks) { getReceivingDispatcher().registerOnBackInvokedCallbackUnchecked(callback, callback.mPriority); } } } /** Clears all registered callbacks on the instance. */ public void clear() { // Unregister previously registered callbacks if there's any. Loading
core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -161,7 +161,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); // verify that ImeBackAnimationController does not take control over IME insets verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(), anyBoolean(), anyLong(), any(), anyInt(), anyBoolean()); Loading @@ -180,7 +180,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); // verify that ImeBackAnimationController does not take control over IME insets verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(), anyBoolean(), anyLong(), any(), anyInt(), anyBoolean()); Loading Loading @@ -300,7 +300,7 @@ public class ImeBackAnimationControllerTest { mBackAnimationController.onBackInvoked(); // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever // getInputMethodManager is called from ImeBackAnimationController) verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager(); verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager(); }); } Loading