Loading core/java/android/inputmethodservice/IInputMethodWrapper.java +13 −13 Original line number Diff line number Diff line Loading @@ -225,12 +225,12 @@ class IInputMethodWrapper extends IInputMethod.Stub return; case DO_SHOW_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2; if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) { ImeTracker.forLogging().onProgress( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); inputMethod.showSoftInputWithToken( msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken); inputMethod.showSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1, statsToken); } else { ImeTracker.forLogging().onFailed( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); Loading @@ -240,12 +240,12 @@ class IInputMethodWrapper extends IInputMethod.Stub } case DO_HIDE_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2; if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) { ImeTracker.forLogging().onProgress( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken); inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1, statsToken); } else { ImeTracker.forLogging().onFailed( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); Loading Loading @@ -453,20 +453,20 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override public void showSoftInput(IBinder showInputToken, @NonNull ImeTracker.Token statsToken, public void showSoftInput(@NonNull ImeTracker.Token statsToken, @InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER); mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT, flags, showInputToken, resultReceiver, statsToken)); mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_SHOW_SOFT_INPUT, flags, resultReceiver, statsToken)); } @BinderThread @Override public void hideSoftInput(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver) { public void hideSoftInput(@NonNull ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER); mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT, flags, hideInputToken, resultReceiver, statsToken)); mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_HIDE_SOFT_INPUT, flags, resultReceiver, statsToken)); } @BinderThread Loading core/java/android/inputmethodservice/InputMethodService.java +14 −66 Original line number Diff line number Diff line Loading @@ -87,7 +87,6 @@ import android.database.ContentObserver; import android.graphics.Rect; import android.graphics.Region; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -649,26 +648,6 @@ public class InputMethodService extends AbstractInputMethodService { // committed by commitHandwritingDelegationTextIfAvailable(). private CharSequence mHandwritingDelegationText; /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput} * The original app window token is passed from client app window. * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique * placeholder token to identify this window. * This placeholder token is only valid for a single call to * {@link InputMethodImpl#showSoftInput}, after which it is set null until next call. */ private IBinder mCurShowInputToken; /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#hideSoftInput} * The original app window token is passed from client app window. * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique * placeholder token to identify this window. * This placeholder token is only valid for a single call to * {@link InputMethodImpl#hideSoftInput}, after which it is set {@code null} until next call. */ private IBinder mCurHideInputToken; /** * The token tracking the current IME request. * Loading Loading @@ -881,14 +860,12 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, IBinder hideInputToken, @NonNull ImeTracker.Token statsToken) { @NonNull ImeTracker.Token statsToken) { mSystemCallingHideSoftInput = true; mCurHideInputToken = hideInputToken; mCurStatsToken = statsToken; try { hideSoftInput(flags, resultReceiver); } finally { mCurHideInputToken = null; mSystemCallingHideSoftInput = false; } } Loading Loading @@ -936,14 +913,12 @@ public class InputMethodService extends AbstractInputMethodService { : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (android.view.inputmethod.Flags.refactorInsetsController()) { // After the IME window was hidden, we can remove its surface scheduleImeSurfaceRemoval(); // The hide request first finishes the animation and then proceeds to the server // side, finally reaching here, marking this the end state. ImeTracker.forLogging().onHidden(statsToken); } } /** * {@inheritDoc} Loading @@ -952,15 +927,12 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void showSoftInputWithToken(@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver, IBinder showInputToken, @NonNull ImeTracker.Token statsToken) { ResultReceiver resultReceiver, @NonNull ImeTracker.Token statsToken) { mSystemCallingShowSoftInput = true; mCurShowInputToken = showInputToken; mCurStatsToken = statsToken; try { showSoftInput(flags, resultReceiver); } finally { mCurShowInputToken = null; mSystemCallingShowSoftInput = false; } } Loading Loading @@ -3108,12 +3080,10 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_SHOW_WINDOW); if (android.view.inputmethod.Flags.refactorInsetsController()) { // The ImeInsetsSourceProvider need the statsToken when dispatching the control // (whenever the IME has drawn and its window is visible). Therefore, sending the // statsToken here first. notifyPreImeWindowVisibilityChanged(true /* visible */, statsToken); } ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", mDumper, null /* icProto */); Loading @@ -3132,9 +3102,6 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); mDecorViewWasVisible = true; if (!android.view.inputmethod.Flags.refactorInsetsController()) { applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */, statsToken); } cancelImeSurfaceRemoval(); mInShowWindow = false; Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Loading Loading @@ -3266,21 +3233,6 @@ public class InputMethodService extends AbstractInputMethodService { if (doShowInput) startExtractingText(false); } /** * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}. * * @param setVisible {@code true} to make it visible, false to hide it. * @param statsToken the token tracking the current IME request. */ private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible, @NonNull ImeTracker.Token statsToken) { ImeTracing.getInstance().triggerServiceDump( "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper, null /* icProto */); mPrivOps.applyImeVisibilityAsync(setVisible ? mCurShowInputToken : mCurHideInputToken, setVisible, statsToken); } /** * Notifies the ImeInsetsSourceProvider before the IME visibility changes. * Loading Loading @@ -3336,13 +3288,9 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper, null /* icProto */); setImeWindowVisibility(0 /* vis */); if (android.view.inputmethod.Flags.refactorInsetsController()) { // The ImeInsetsSourceProvider need the statsToken when dispatching the control. We // send the token here, so that another request in the provider can be cancelled. notifyPreImeWindowVisibilityChanged(false /* visible */, statsToken); } else { applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */, statsToken); } mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { Loading core/java/android/view/ImeBackAnimationController.java +4 −7 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ 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 @@ -151,13 +150,11 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { } 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/ImeFocusController.java +1 −3 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.UiThread; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; import com.android.internal.inputmethod.InputMethodDebug; Loading Loading @@ -151,8 +150,7 @@ public final class ImeFocusController { if (!mHasImeFocus || isInLocalFocusMode(windowAttribute)) { return InputMethodManager.DISPATCH_NOT_HANDLED; } if (Flags.refactorInsetsController() && event instanceof KeyEvent keyEvent && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (event instanceof KeyEvent keyEvent && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) { final var insetsController = mViewRootImpl.getInsetsController(); if (insetsController.getAnimationType(WindowInsets.Type.ime()) == InsetsController.ANIMATION_TYPE_HIDE Loading core/java/android/view/ImeInsetsSourceConsumer.javadeleted 100644 → 0 +0 −291 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.view; import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.ImeInsetsSourceConsumerProto.HAS_PENDING_REQUEST; import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER; import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.Flags; import android.view.inputmethod.ImeTracker; import android.view.inputmethod.InputMethodManager; import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.SoftInputShowHideReason; /** * Controls the visibility and animations of IME window insets source. * @hide */ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { /** * Tracks whether are requested to show during the hide animation or requested to hide during * the show animation. If this is true, we should not remove the surface. */ private boolean mHasPendingRequest; /** * Tracks whether we have an outstanding request from the IME to show, but weren't able to * execute it because we didn't have control yet, or we didn't have a leash on the control yet. */ private boolean mIsRequestedVisibleAwaitingLeash; public ImeInsetsSourceConsumer(int id, InsetsState state, InsetsController controller) { super(id, WindowInsets.Type.ime(), state, controller); } @Override public boolean onAnimationStateChanged(boolean running) { if (Flags.refactorInsetsController()) { return super.onAnimationStateChanged(running); } else { if (!running) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#onAnimationFinished", mController.getHost().getInputMethodManager(), null /* icProto */); } boolean insetsChanged = false; if (!running && isShowRequested() && mAnimationState == ANIMATION_STATE_HIDE) { // A user controlled hide animation may have ended in the shown state (e.g. // cancelled predictive back animation) -> Insets need to be reset to shown. insetsChanged |= applyLocalVisibilityOverride(); } insetsChanged |= super.onAnimationStateChanged(running); if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) { // IME predictive back animation switched from pre-commit to post-commit. insetsChanged |= applyLocalVisibilityOverride(); } if (!isShowRequested()) { mIsRequestedVisibleAwaitingLeash = false; if (!running && !mHasPendingRequest) { final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_ON_ANIMATION_STATE_CHANGED, mController.getHost().isHandlingPointerEvent() /* fromUser */); notifyHidden(statsToken); removeSurface(); } } // This method is called // (1) after the animation starts. // (2) after the animation ends (including the case of cancel). // (3) if the IME is not controllable (running == false in this case). // We should reset mHasPendingRequest in all cases. mHasPendingRequest = false; return insetsChanged; } } @Override public void onWindowFocusGained(boolean hasViewFocus) { super.onWindowFocusGained(hasViewFocus); if (!Flags.refactorInsetsController()) { getImm().registerImeConsumer(this); if ((mController.getRequestedVisibleTypes() & getType()) != 0 && !hasLeash()) { mIsRequestedVisibleAwaitingLeash = true; } } } @Override public void onWindowFocusLost() { super.onWindowFocusLost(); if (!Flags.refactorInsetsController()) { getImm().unregisterImeConsumer(this); mIsRequestedVisibleAwaitingLeash = false; } } @Override public boolean applyLocalVisibilityOverride() { if (!Flags.refactorInsetsController()) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#applyLocalVisibilityOverride", mController.getHost().getInputMethodManager(), null /* icProto */); } return super.applyLocalVisibilityOverride(); } /** * Request {@link InputMethodManager} to show the IME. * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}. */ @Override @ShowResult public int requestShow(boolean fromIme, @Nullable ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { if (fromIme) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#requestShow", mController.getHost().getInputMethodManager(), null /* icProto */); } onShowRequested(); // TODO: ResultReceiver for IME. // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag. ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW); if (!hasLeash()) { // If control or leash is null, schedule to show IME when both available. mIsRequestedVisibleAwaitingLeash = true; } // If we had a request before to show from IME (tracked with mImeRequestedShow), // reaching this code here means that we now got control, so we can start the // animation immediately. If client window is trying to control IME and IME is // already visible, it is immediate. if (fromIme || (mState.isSourceOrDefaultVisible(getId(), getType()) && hasLeash())) { return ShowResult.SHOW_IMMEDIATELY; } return getImm().requestImeShow(mController.getHost().getWindowToken(), statsToken) ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED; } else { return ShowResult.IME_SHOW_FAILED; } } void requestHide(boolean fromIme, @Nullable ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { if (!fromIme) { // Create a new token to track the hide request when we have control and leash, // as we use the passed in token for the insets animation already. final var notifyStatsToken = hasLeash() ? ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, mController.getHost().isHandlingPointerEvent() /* fromUser */) : statsToken; // The insets might be controlled by a remote target. Let the server know we are // requested to hide. notifyHidden(notifyStatsToken); } if (mAnimationState == ANIMATION_STATE_SHOW) { mHasPendingRequest = true; } } } /** * Notify {@link com.android.server.inputmethod.InputMethodManagerService} that * IME insets are hidden. * * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ private void notifyHidden(@NonNull ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN); getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken); mIsRequestedVisibleAwaitingLeash = false; Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } } @Override public void removeSurface() { if (Flags.refactorInsetsController()) { super.removeSurface(); } else { final IBinder window = mController.getHost().getWindowToken(); if (window != null) { getImm().removeImeSurface(window); } } } @Override public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes, int[] cancelTypes, int[] transientTypes) { if (Flags.refactorInsetsController()) { return super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } else { ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl", mController.getHost().getInputMethodManager(), null /* icProto */); if (!super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes)) { return false; } if (control == null && !mIsRequestedVisibleAwaitingLeash) { mController.setRequestedVisibleTypes(0 /* visibleTypes */, getType()); removeSurface(); } final boolean hasLeash = control != null && control.getLeash() != null; if (hasLeash) { mIsRequestedVisibleAwaitingLeash = false; } return true; } } @Override protected boolean isRequestedVisibleAwaitingControl() { return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingLeash; } /** * Checks whether the consumer has an insets source control with a leash. */ private boolean hasLeash() { final var control = getControl(); return control != null && control.getLeash() != null; } @Override public void onPerceptible(boolean perceptible) { super.onPerceptible(perceptible); if (!Flags.refactorInsetsController()) { final IBinder window = mController.getHost().getWindowToken(); if (window != null) { getImm().reportPerceptible(window, perceptible); } } } @Override public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); super.dumpDebug(proto, INSETS_SOURCE_CONSUMER); proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingLeash); proto.write(HAS_PENDING_REQUEST, mHasPendingRequest); proto.end(token); } /** * Called when {@link #requestShow(boolean, ImeTracker.Token)} or * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { if (mAnimationState == ANIMATION_STATE_HIDE || mController.isPredictiveBackImeHideAnimInProgress()) { mHasPendingRequest = true; } } private InputMethodManager getImm() { return mController.getHost().getInputMethodManager(); } } Loading
core/java/android/inputmethodservice/IInputMethodWrapper.java +13 −13 Original line number Diff line number Diff line Loading @@ -225,12 +225,12 @@ class IInputMethodWrapper extends IInputMethod.Stub return; case DO_SHOW_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2; if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) { ImeTracker.forLogging().onProgress( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); inputMethod.showSoftInputWithToken( msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken); inputMethod.showSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1, statsToken); } else { ImeTracker.forLogging().onFailed( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); Loading @@ -240,12 +240,12 @@ class IInputMethodWrapper extends IInputMethod.Stub } case DO_HIDE_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3; final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2; if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) { ImeTracker.forLogging().onProgress( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken); inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1, statsToken); } else { ImeTracker.forLogging().onFailed( statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); Loading Loading @@ -453,20 +453,20 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override public void showSoftInput(IBinder showInputToken, @NonNull ImeTracker.Token statsToken, public void showSoftInput(@NonNull ImeTracker.Token statsToken, @InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER); mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT, flags, showInputToken, resultReceiver, statsToken)); mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_SHOW_SOFT_INPUT, flags, resultReceiver, statsToken)); } @BinderThread @Override public void hideSoftInput(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver) { public void hideSoftInput(@NonNull ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER); mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT, flags, hideInputToken, resultReceiver, statsToken)); mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_HIDE_SOFT_INPUT, flags, resultReceiver, statsToken)); } @BinderThread Loading
core/java/android/inputmethodservice/InputMethodService.java +14 −66 Original line number Diff line number Diff line Loading @@ -87,7 +87,6 @@ import android.database.ContentObserver; import android.graphics.Rect; import android.graphics.Region; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -649,26 +648,6 @@ public class InputMethodService extends AbstractInputMethodService { // committed by commitHandwritingDelegationTextIfAvailable(). private CharSequence mHandwritingDelegationText; /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput} * The original app window token is passed from client app window. * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique * placeholder token to identify this window. * This placeholder token is only valid for a single call to * {@link InputMethodImpl#showSoftInput}, after which it is set null until next call. */ private IBinder mCurShowInputToken; /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#hideSoftInput} * The original app window token is passed from client app window. * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique * placeholder token to identify this window. * This placeholder token is only valid for a single call to * {@link InputMethodImpl#hideSoftInput}, after which it is set {@code null} until next call. */ private IBinder mCurHideInputToken; /** * The token tracking the current IME request. * Loading Loading @@ -881,14 +860,12 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, IBinder hideInputToken, @NonNull ImeTracker.Token statsToken) { @NonNull ImeTracker.Token statsToken) { mSystemCallingHideSoftInput = true; mCurHideInputToken = hideInputToken; mCurStatsToken = statsToken; try { hideSoftInput(flags, resultReceiver); } finally { mCurHideInputToken = null; mSystemCallingHideSoftInput = false; } } Loading Loading @@ -936,14 +913,12 @@ public class InputMethodService extends AbstractInputMethodService { : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (android.view.inputmethod.Flags.refactorInsetsController()) { // After the IME window was hidden, we can remove its surface scheduleImeSurfaceRemoval(); // The hide request first finishes the animation and then proceeds to the server // side, finally reaching here, marking this the end state. ImeTracker.forLogging().onHidden(statsToken); } } /** * {@inheritDoc} Loading @@ -952,15 +927,12 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void showSoftInputWithToken(@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver, IBinder showInputToken, @NonNull ImeTracker.Token statsToken) { ResultReceiver resultReceiver, @NonNull ImeTracker.Token statsToken) { mSystemCallingShowSoftInput = true; mCurShowInputToken = showInputToken; mCurStatsToken = statsToken; try { showSoftInput(flags, resultReceiver); } finally { mCurShowInputToken = null; mSystemCallingShowSoftInput = false; } } Loading Loading @@ -3108,12 +3080,10 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_SHOW_WINDOW); if (android.view.inputmethod.Flags.refactorInsetsController()) { // The ImeInsetsSourceProvider need the statsToken when dispatching the control // (whenever the IME has drawn and its window is visible). Therefore, sending the // statsToken here first. notifyPreImeWindowVisibilityChanged(true /* visible */, statsToken); } ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", mDumper, null /* icProto */); Loading @@ -3132,9 +3102,6 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); mDecorViewWasVisible = true; if (!android.view.inputmethod.Flags.refactorInsetsController()) { applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */, statsToken); } cancelImeSurfaceRemoval(); mInShowWindow = false; Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Loading Loading @@ -3266,21 +3233,6 @@ public class InputMethodService extends AbstractInputMethodService { if (doShowInput) startExtractingText(false); } /** * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}. * * @param setVisible {@code true} to make it visible, false to hide it. * @param statsToken the token tracking the current IME request. */ private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible, @NonNull ImeTracker.Token statsToken) { ImeTracing.getInstance().triggerServiceDump( "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper, null /* icProto */); mPrivOps.applyImeVisibilityAsync(setVisible ? mCurShowInputToken : mCurHideInputToken, setVisible, statsToken); } /** * Notifies the ImeInsetsSourceProvider before the IME visibility changes. * Loading Loading @@ -3336,13 +3288,9 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper, null /* icProto */); setImeWindowVisibility(0 /* vis */); if (android.view.inputmethod.Flags.refactorInsetsController()) { // The ImeInsetsSourceProvider need the statsToken when dispatching the control. We // send the token here, so that another request in the provider can be cancelled. notifyPreImeWindowVisibilityChanged(false /* visible */, statsToken); } else { applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */, statsToken); } mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { Loading
core/java/android/view/ImeBackAnimationController.java +4 −7 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ 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 @@ -151,13 +150,11 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { } 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/ImeFocusController.java +1 −3 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.UiThread; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; import com.android.internal.inputmethod.InputMethodDebug; Loading Loading @@ -151,8 +150,7 @@ public final class ImeFocusController { if (!mHasImeFocus || isInLocalFocusMode(windowAttribute)) { return InputMethodManager.DISPATCH_NOT_HANDLED; } if (Flags.refactorInsetsController() && event instanceof KeyEvent keyEvent && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (event instanceof KeyEvent keyEvent && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) { final var insetsController = mViewRootImpl.getInsetsController(); if (insetsController.getAnimationType(WindowInsets.Type.ime()) == InsetsController.ANIMATION_TYPE_HIDE Loading
core/java/android/view/ImeInsetsSourceConsumer.javadeleted 100644 → 0 +0 −291 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.view; import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.ImeInsetsSourceConsumerProto.HAS_PENDING_REQUEST; import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER; import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.Flags; import android.view.inputmethod.ImeTracker; import android.view.inputmethod.InputMethodManager; import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.SoftInputShowHideReason; /** * Controls the visibility and animations of IME window insets source. * @hide */ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { /** * Tracks whether are requested to show during the hide animation or requested to hide during * the show animation. If this is true, we should not remove the surface. */ private boolean mHasPendingRequest; /** * Tracks whether we have an outstanding request from the IME to show, but weren't able to * execute it because we didn't have control yet, or we didn't have a leash on the control yet. */ private boolean mIsRequestedVisibleAwaitingLeash; public ImeInsetsSourceConsumer(int id, InsetsState state, InsetsController controller) { super(id, WindowInsets.Type.ime(), state, controller); } @Override public boolean onAnimationStateChanged(boolean running) { if (Flags.refactorInsetsController()) { return super.onAnimationStateChanged(running); } else { if (!running) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#onAnimationFinished", mController.getHost().getInputMethodManager(), null /* icProto */); } boolean insetsChanged = false; if (!running && isShowRequested() && mAnimationState == ANIMATION_STATE_HIDE) { // A user controlled hide animation may have ended in the shown state (e.g. // cancelled predictive back animation) -> Insets need to be reset to shown. insetsChanged |= applyLocalVisibilityOverride(); } insetsChanged |= super.onAnimationStateChanged(running); if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) { // IME predictive back animation switched from pre-commit to post-commit. insetsChanged |= applyLocalVisibilityOverride(); } if (!isShowRequested()) { mIsRequestedVisibleAwaitingLeash = false; if (!running && !mHasPendingRequest) { final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_ON_ANIMATION_STATE_CHANGED, mController.getHost().isHandlingPointerEvent() /* fromUser */); notifyHidden(statsToken); removeSurface(); } } // This method is called // (1) after the animation starts. // (2) after the animation ends (including the case of cancel). // (3) if the IME is not controllable (running == false in this case). // We should reset mHasPendingRequest in all cases. mHasPendingRequest = false; return insetsChanged; } } @Override public void onWindowFocusGained(boolean hasViewFocus) { super.onWindowFocusGained(hasViewFocus); if (!Flags.refactorInsetsController()) { getImm().registerImeConsumer(this); if ((mController.getRequestedVisibleTypes() & getType()) != 0 && !hasLeash()) { mIsRequestedVisibleAwaitingLeash = true; } } } @Override public void onWindowFocusLost() { super.onWindowFocusLost(); if (!Flags.refactorInsetsController()) { getImm().unregisterImeConsumer(this); mIsRequestedVisibleAwaitingLeash = false; } } @Override public boolean applyLocalVisibilityOverride() { if (!Flags.refactorInsetsController()) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#applyLocalVisibilityOverride", mController.getHost().getInputMethodManager(), null /* icProto */); } return super.applyLocalVisibilityOverride(); } /** * Request {@link InputMethodManager} to show the IME. * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}. */ @Override @ShowResult public int requestShow(boolean fromIme, @Nullable ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { if (fromIme) { ImeTracing.getInstance().triggerClientDump( "ImeInsetsSourceConsumer#requestShow", mController.getHost().getInputMethodManager(), null /* icProto */); } onShowRequested(); // TODO: ResultReceiver for IME. // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag. ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW); if (!hasLeash()) { // If control or leash is null, schedule to show IME when both available. mIsRequestedVisibleAwaitingLeash = true; } // If we had a request before to show from IME (tracked with mImeRequestedShow), // reaching this code here means that we now got control, so we can start the // animation immediately. If client window is trying to control IME and IME is // already visible, it is immediate. if (fromIme || (mState.isSourceOrDefaultVisible(getId(), getType()) && hasLeash())) { return ShowResult.SHOW_IMMEDIATELY; } return getImm().requestImeShow(mController.getHost().getWindowToken(), statsToken) ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED; } else { return ShowResult.IME_SHOW_FAILED; } } void requestHide(boolean fromIme, @Nullable ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { if (!fromIme) { // Create a new token to track the hide request when we have control and leash, // as we use the passed in token for the insets animation already. final var notifyStatsToken = hasLeash() ? ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, mController.getHost().isHandlingPointerEvent() /* fromUser */) : statsToken; // The insets might be controlled by a remote target. Let the server know we are // requested to hide. notifyHidden(notifyStatsToken); } if (mAnimationState == ANIMATION_STATE_SHOW) { mHasPendingRequest = true; } } } /** * Notify {@link com.android.server.inputmethod.InputMethodManagerService} that * IME insets are hidden. * * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ private void notifyHidden(@NonNull ImeTracker.Token statsToken) { if (!Flags.refactorInsetsController()) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN); getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken); mIsRequestedVisibleAwaitingLeash = false; Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } } @Override public void removeSurface() { if (Flags.refactorInsetsController()) { super.removeSurface(); } else { final IBinder window = mController.getHost().getWindowToken(); if (window != null) { getImm().removeImeSurface(window); } } } @Override public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes, int[] cancelTypes, int[] transientTypes) { if (Flags.refactorInsetsController()) { return super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } else { ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl", mController.getHost().getInputMethodManager(), null /* icProto */); if (!super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes)) { return false; } if (control == null && !mIsRequestedVisibleAwaitingLeash) { mController.setRequestedVisibleTypes(0 /* visibleTypes */, getType()); removeSurface(); } final boolean hasLeash = control != null && control.getLeash() != null; if (hasLeash) { mIsRequestedVisibleAwaitingLeash = false; } return true; } } @Override protected boolean isRequestedVisibleAwaitingControl() { return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingLeash; } /** * Checks whether the consumer has an insets source control with a leash. */ private boolean hasLeash() { final var control = getControl(); return control != null && control.getLeash() != null; } @Override public void onPerceptible(boolean perceptible) { super.onPerceptible(perceptible); if (!Flags.refactorInsetsController()) { final IBinder window = mController.getHost().getWindowToken(); if (window != null) { getImm().reportPerceptible(window, perceptible); } } } @Override public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); super.dumpDebug(proto, INSETS_SOURCE_CONSUMER); proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingLeash); proto.write(HAS_PENDING_REQUEST, mHasPendingRequest); proto.end(token); } /** * Called when {@link #requestShow(boolean, ImeTracker.Token)} or * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { if (mAnimationState == ANIMATION_STATE_HIDE || mController.isPredictiveBackImeHideAnimInProgress()) { mHasPendingRequest = true; } } private InputMethodManager getImm() { return mController.getHost().getInputMethodManager(); } }