Loading core/java/android/inputmethodservice/InputMethodService.java +36 −2 Original line number Diff line number Diff line Loading @@ -974,6 +974,11 @@ public class InputMethodService extends AbstractInputMethodService { : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (android.view.inputmethod.Flags.refactorInsetsController()) { // 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); } } /** Loading Loading @@ -3104,6 +3109,13 @@ 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 */); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow"); Loading @@ -3127,7 +3139,9 @@ 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 @@ -3238,6 +3252,20 @@ public class InputMethodService extends AbstractInputMethodService { ? mCurShowInputToken : mCurHideInputToken, setVisible, statsToken); } /** * Notifies the ImeInsetsSourceProvider before the IME visibility changes. * * @param visible {@code true} if it became visible, {@code false} otherwise. * @param statsToken the token tracking the current IME request. */ private void notifyPreImeWindowVisibilityChanged(boolean visible, @NonNull ImeTracker.Token statsToken) { final var viewRootImpl = getWindow().getWindow().getDecorView().getViewRootImpl(); if (viewRootImpl != null) { viewRootImpl.notifyImeVisibilityChanged(visible, statsToken); } } private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); Loading Loading @@ -3279,7 +3307,13 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper, null /* icProto */); setImeWindowStatus(0, mBackDisposition); 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/IWindowSession.aidl +13 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.IWindow; import android.view.IWindowId; import android.view.MotionEvent; import android.view.WindowManager; import android.view.inputmethod.ImeTracker; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.Surface; Loading Loading @@ -276,7 +277,8 @@ interface IWindowSession { /** * Updates the requested visible types of insets. */ oneway void updateRequestedVisibleTypes(IWindow window, int requestedVisibleTypes); oneway void updateRequestedVisibleTypes(IWindow window, int requestedVisibleTypes, in @nullable ImeTracker.Token imeStatsToken); /** * Called when the system gesture exclusion has changed. Loading Loading @@ -369,4 +371,14 @@ interface IWindowSession { * @return {@code true} if the focus changes. Otherwise, {@code false}. */ boolean moveFocusToAdjacentWindow(IWindow fromWindow, int direction); /** * Notifies the statsToken and IME visibility to the ImeInsetsSourceProvider. * * @param window The window that is used to get the ImeInsetsSourceProvider. * @param visible {@code true} to make it visible, {@code false} to hide it. * @param statsToken the token tracking the current IME request. */ oneway void notifyImeWindowVisibilityChangedFromClient(IWindow window, boolean visible, in ImeTracker.Token statsToken); } core/java/android/view/InsetsController.java +56 −19 Original line number Diff line number Diff line Loading @@ -121,8 +121,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * The visibilities should be reported back to WM. * * @param types Bitwise flags of types requested visible. * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ void updateRequestedVisibleTypes(@InsetsType int types); void updateRequestedVisibleTypes(@InsetsType int types, @Nullable ImeTracker.Token statsToken); /** * @return Whether the host has any callbacks it wants to synchronize the animations with. Loading Loading @@ -974,6 +976,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation int consumedControlCount = 0; final @InsetsType int[] showTypes = new int[1]; final @InsetsType int[] hideTypes = new int[1]; ImeTracker.Token statsToken = null; // Ensure to update all existing source consumers for (int i = mSourceConsumers.size() - 1; i >= 0; i--) { Loading @@ -988,6 +991,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (control != null) { controllableTypes |= control.getType(); consumedControlCount++; if (Flags.refactorInsetsController()) { if (control.getId() == ID_IME) { statsToken = control.getImeStatsToken(); } } } // control may be null, but we still need to update the control to null if it got Loading Loading @@ -1021,34 +1030,31 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (Flags.refactorInsetsController()) { if (mPendingImeControlRequest != null && getImeSourceConsumer().getControl() != null && getImeSourceConsumer().getControl().getLeash() != null) { // TODO we need to pass the statsToken handlePendingControlRequest(null); handlePendingControlRequest(statsToken); } else { if (showTypes[0] != 0) { applyAnimation(showTypes[0], true /* show */, false /* fromIme */, null /* statsToken */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); } if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, null /* statsToken */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); } } } else { if (showTypes[0] != 0) { final var statsToken = final var newStatsToken = (showTypes[0] & ime()) == 0 ? null : ImeTracker.forLogging().onStart( ImeTracker.TYPE_SHOW, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, newStatsToken); } if (hideTypes[0] != 0) { final var statsToken = final var newStatsToken = (hideTypes[0] & ime()) == 0 ? null : ImeTracker.forLogging().onStart( ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, newStatsToken); } } Loading @@ -1065,7 +1071,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } // InsetsSourceConsumer#setControl might change the requested visibility. reportRequestedVisibleTypes(); // TODO(b/353463205) check this: if the requestedVisibleTypes for the IME were already // sent, the request would fail. Therefore, don't send the statsToken here. reportRequestedVisibleTypes(null /* statsToken */); } @VisibleForTesting(visibility = PACKAGE) Loading Loading @@ -1176,6 +1184,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady); if ((Flags.refactorInsetsController() || fromIme) && (typesReady & Type.ime()) != 0) { // TODO(b/353463205) check if this is needed here ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication); } applyAnimation(typesReady, true /* show */, fromIme, statsToken); Loading Loading @@ -1243,6 +1252,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // an animation again (mRequestedVisibleTypes are reported at the end of the IME // hide animation but set at the beginning) if ((mRequestedVisibleTypes & ime()) == 0) { ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_CLIENT_ALREADY_HIDDEN); continue; } } Loading Loading @@ -1346,7 +1357,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // We are finishing setting the requested visible types. Report them to the server // and/or the app. reportRequestedVisibleTypes(); reportRequestedVisibleTypes(statsToken); } private void controlAnimationUncheckedInner(@InsetsType int types, Loading Loading @@ -1396,8 +1407,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // Ime will not be contained in typesReady nor in controls, if we don't have a leash Pair<Integer, Integer> typesReadyPair = collectSourceControlsV2(types, controls); typesReady = typesReadyPair.first; @InsetsType int typesWithoutLeash = typesReadyPair.second; if (animationType == ANIMATION_TYPE_USER) { @InsetsType int typesWithoutLeash = typesReadyPair.second; // When using an app-driven animation, the IME won't have a leash (because the // window isn't created yet). If we have a control, but no leash, defers the // request until the leash gets created. Loading Loading @@ -1431,6 +1442,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } // We need to wait until all types are ready if (typesReady != types) { if (DEBUG) { Log.d(TAG, TextUtils.formatSimple( "not all types are ready yet, waiting. typesReady: %s, types: %s", typesReady, types)); } return; } } Loading Loading @@ -1728,9 +1744,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } else { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE); // The requestedVisibleTypes are only send at the end of the hide animation. // Therefore, the requested is not finished at this point. if (!Flags.refactorInsetsController()) { ImeTracker.forLogging().onHidden(statsToken); } reportRequestedVisibleTypes(); } reportRequestedVisibleTypes(shown ? null : runner.getStatsToken()); } @Override Loading Loading @@ -1787,7 +1807,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (mHost != null) { // if the (hide) animation is cancelled, the // requestedVisibleTypes should be reported at this point. reportRequestedVisibleTypes(); reportRequestedVisibleTypes(control.getStatsToken()); mHost.getInputMethodManager().removeImeSurface( mHost.getWindowToken()); } Loading Loading @@ -1923,8 +1943,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation /** * Called when finishing setting requested visible types or finishing setting controls. * * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ private void reportRequestedVisibleTypes() { private void reportRequestedVisibleTypes(@Nullable ImeTracker.Token statsToken) { final @InsetsType int typesToReport; if (Flags.refactorInsetsController()) { // If the IME is currently animating out, it is still visible, therefore we only Loading @@ -1941,8 +1963,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (WindowInsets.Type.hasCompatSystemBars(diff)) { mCompatSysUiVisibilityStaled = true; } if (Flags.refactorInsetsController()) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_REPORT_REQUESTED_VISIBLE_TYPES); } mReportedRequestedVisibleTypes = mRequestedVisibleTypes; mHost.updateRequestedVisibleTypes(mReportedRequestedVisibleTypes); mHost.updateRequestedVisibleTypes(mReportedRequestedVisibleTypes, statsToken); } else if (Flags.refactorInsetsController()) { if ((typesToReport & ime()) != 0 && mImeSourceConsumer != null) { InsetsSourceControl control = mImeSourceConsumer.getControl(); if (control != null && control.getLeash() == null) { // If the IME was requested twice, and we didn't receive the controls // yet, this request will not continue. It should be cancelled here, as // it would time out otherwise. ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_CLIENT_REPORT_REQUESTED_VISIBLE_TYPES); } } } updateCompatSysUiVisibility(); } Loading core/java/android/view/InsetsSourceControl.java +20 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.proto.ProtoOutputStream; import android.view.WindowInsets.Type.InsetsType; import android.view.inputmethod.ImeTracker; import java.io.PrintWriter; import java.util.Arrays; Loading @@ -56,6 +57,9 @@ public class InsetsSourceControl implements Parcelable { private boolean mSkipAnimationOnce; private int mParcelableFlags; /** The token tracking the current IME request */ private @Nullable ImeTracker.Token mImeStatsToken; public InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash, boolean initiallyVisible, Point surfacePosition, Insets insetsHint) { mId = id; Loading @@ -78,6 +82,7 @@ public class InsetsSourceControl implements Parcelable { mSurfacePosition = new Point(other.mSurfacePosition); mInsetsHint = other.mInsetsHint; mSkipAnimationOnce = other.getAndClearSkipAnimationOnce(); mImeStatsToken = other.getImeStatsToken(); } public InsetsSourceControl(Parcel in) { Loading @@ -88,6 +93,7 @@ public class InsetsSourceControl implements Parcelable { mSurfacePosition = in.readTypedObject(Point.CREATOR); mInsetsHint = in.readTypedObject(Insets.CREATOR); mSkipAnimationOnce = in.readBoolean(); mImeStatsToken = in.readTypedObject(ImeTracker.Token.CREATOR); } public int getId() { Loading Loading @@ -153,6 +159,15 @@ public class InsetsSourceControl implements Parcelable { return result; } @Nullable public ImeTracker.Token getImeStatsToken() { return mImeStatsToken; } public void setImeStatsToken(@Nullable ImeTracker.Token imeStatsToken) { mImeStatsToken = imeStatsToken; } public void setParcelableFlags(int parcelableFlags) { mParcelableFlags = parcelableFlags; } Loading @@ -171,6 +186,7 @@ public class InsetsSourceControl implements Parcelable { dest.writeTypedObject(mSurfacePosition, mParcelableFlags); dest.writeTypedObject(mInsetsHint, mParcelableFlags); dest.writeBoolean(mSkipAnimationOnce); dest.writeTypedObject(mImeStatsToken, mParcelableFlags); } public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) { Loading @@ -196,13 +212,14 @@ public class InsetsSourceControl implements Parcelable { && mInitiallyVisible == that.mInitiallyVisible && mSurfacePosition.equals(that.mSurfacePosition) && mInsetsHint.equals(that.mInsetsHint) && mSkipAnimationOnce == that.mSkipAnimationOnce; && mSkipAnimationOnce == that.mSkipAnimationOnce && Objects.equals(mImeStatsToken, that.mImeStatsToken); } @Override public int hashCode() { return Objects.hash(mId, mType, mLeash, mInitiallyVisible, mSurfacePosition, mInsetsHint, mSkipAnimationOnce); mSkipAnimationOnce, mImeStatsToken); } @Override Loading @@ -225,6 +242,7 @@ public class InsetsSourceControl implements Parcelable { pw.print(" mSurfacePosition="); pw.print(mSurfacePosition); pw.print(" mInsetsHint="); pw.print(mInsetsHint); pw.print(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce); pw.print(" mImeStatsToken="); pw.print(mImeStatsToken); pw.println(); } Loading core/java/android/view/ViewRootImpl.java +18 −0 Original line number Diff line number Diff line Loading @@ -10056,6 +10056,24 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } /** * Dispatches the statsToken and IME visibility to the ImeInsetsSourceProvider. * * @param visible {@code true} if it became visible, {@code false} otherwise. * @param statsToken the token tracking the current IME request. * * @hide */ public void notifyImeVisibilityChanged(boolean visible, @NonNull ImeTracker.Token statsToken) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_NOTIFY_IME_VISIBILITY_CHANGED); try { mWindowSession.notifyImeWindowVisibilityChangedFromClient(mWindow, visible, statsToken); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** * Represents a pending input event that is waiting in a queue. * Loading Loading
core/java/android/inputmethodservice/InputMethodService.java +36 −2 Original line number Diff line number Diff line Loading @@ -974,6 +974,11 @@ public class InputMethodService extends AbstractInputMethodService { : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (android.view.inputmethod.Flags.refactorInsetsController()) { // 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); } } /** Loading Loading @@ -3104,6 +3109,13 @@ 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 */); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow"); Loading @@ -3127,7 +3139,9 @@ 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 @@ -3238,6 +3252,20 @@ public class InputMethodService extends AbstractInputMethodService { ? mCurShowInputToken : mCurHideInputToken, setVisible, statsToken); } /** * Notifies the ImeInsetsSourceProvider before the IME visibility changes. * * @param visible {@code true} if it became visible, {@code false} otherwise. * @param statsToken the token tracking the current IME request. */ private void notifyPreImeWindowVisibilityChanged(boolean visible, @NonNull ImeTracker.Token statsToken) { final var viewRootImpl = getWindow().getWindow().getDecorView().getViewRootImpl(); if (viewRootImpl != null) { viewRootImpl.notifyImeVisibilityChanged(visible, statsToken); } } private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); Loading Loading @@ -3279,7 +3307,13 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper, null /* icProto */); setImeWindowStatus(0, mBackDisposition); 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/IWindowSession.aidl +13 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.IWindow; import android.view.IWindowId; import android.view.MotionEvent; import android.view.WindowManager; import android.view.inputmethod.ImeTracker; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.Surface; Loading Loading @@ -276,7 +277,8 @@ interface IWindowSession { /** * Updates the requested visible types of insets. */ oneway void updateRequestedVisibleTypes(IWindow window, int requestedVisibleTypes); oneway void updateRequestedVisibleTypes(IWindow window, int requestedVisibleTypes, in @nullable ImeTracker.Token imeStatsToken); /** * Called when the system gesture exclusion has changed. Loading Loading @@ -369,4 +371,14 @@ interface IWindowSession { * @return {@code true} if the focus changes. Otherwise, {@code false}. */ boolean moveFocusToAdjacentWindow(IWindow fromWindow, int direction); /** * Notifies the statsToken and IME visibility to the ImeInsetsSourceProvider. * * @param window The window that is used to get the ImeInsetsSourceProvider. * @param visible {@code true} to make it visible, {@code false} to hide it. * @param statsToken the token tracking the current IME request. */ oneway void notifyImeWindowVisibilityChangedFromClient(IWindow window, boolean visible, in ImeTracker.Token statsToken); }
core/java/android/view/InsetsController.java +56 −19 Original line number Diff line number Diff line Loading @@ -121,8 +121,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * The visibilities should be reported back to WM. * * @param types Bitwise flags of types requested visible. * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ void updateRequestedVisibleTypes(@InsetsType int types); void updateRequestedVisibleTypes(@InsetsType int types, @Nullable ImeTracker.Token statsToken); /** * @return Whether the host has any callbacks it wants to synchronize the animations with. Loading Loading @@ -974,6 +976,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation int consumedControlCount = 0; final @InsetsType int[] showTypes = new int[1]; final @InsetsType int[] hideTypes = new int[1]; ImeTracker.Token statsToken = null; // Ensure to update all existing source consumers for (int i = mSourceConsumers.size() - 1; i >= 0; i--) { Loading @@ -988,6 +991,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (control != null) { controllableTypes |= control.getType(); consumedControlCount++; if (Flags.refactorInsetsController()) { if (control.getId() == ID_IME) { statsToken = control.getImeStatsToken(); } } } // control may be null, but we still need to update the control to null if it got Loading Loading @@ -1021,34 +1030,31 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (Flags.refactorInsetsController()) { if (mPendingImeControlRequest != null && getImeSourceConsumer().getControl() != null && getImeSourceConsumer().getControl().getLeash() != null) { // TODO we need to pass the statsToken handlePendingControlRequest(null); handlePendingControlRequest(statsToken); } else { if (showTypes[0] != 0) { applyAnimation(showTypes[0], true /* show */, false /* fromIme */, null /* statsToken */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); } if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, null /* statsToken */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); } } } else { if (showTypes[0] != 0) { final var statsToken = final var newStatsToken = (showTypes[0] & ime()) == 0 ? null : ImeTracker.forLogging().onStart( ImeTracker.TYPE_SHOW, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, newStatsToken); } if (hideTypes[0] != 0) { final var statsToken = final var newStatsToken = (hideTypes[0] & ime()) == 0 ? null : ImeTracker.forLogging().onStart( ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, newStatsToken); } } Loading @@ -1065,7 +1071,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } // InsetsSourceConsumer#setControl might change the requested visibility. reportRequestedVisibleTypes(); // TODO(b/353463205) check this: if the requestedVisibleTypes for the IME were already // sent, the request would fail. Therefore, don't send the statsToken here. reportRequestedVisibleTypes(null /* statsToken */); } @VisibleForTesting(visibility = PACKAGE) Loading Loading @@ -1176,6 +1184,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady); if ((Flags.refactorInsetsController() || fromIme) && (typesReady & Type.ime()) != 0) { // TODO(b/353463205) check if this is needed here ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication); } applyAnimation(typesReady, true /* show */, fromIme, statsToken); Loading Loading @@ -1243,6 +1252,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // an animation again (mRequestedVisibleTypes are reported at the end of the IME // hide animation but set at the beginning) if ((mRequestedVisibleTypes & ime()) == 0) { ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_CLIENT_ALREADY_HIDDEN); continue; } } Loading Loading @@ -1346,7 +1357,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // We are finishing setting the requested visible types. Report them to the server // and/or the app. reportRequestedVisibleTypes(); reportRequestedVisibleTypes(statsToken); } private void controlAnimationUncheckedInner(@InsetsType int types, Loading Loading @@ -1396,8 +1407,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // Ime will not be contained in typesReady nor in controls, if we don't have a leash Pair<Integer, Integer> typesReadyPair = collectSourceControlsV2(types, controls); typesReady = typesReadyPair.first; @InsetsType int typesWithoutLeash = typesReadyPair.second; if (animationType == ANIMATION_TYPE_USER) { @InsetsType int typesWithoutLeash = typesReadyPair.second; // When using an app-driven animation, the IME won't have a leash (because the // window isn't created yet). If we have a control, but no leash, defers the // request until the leash gets created. Loading Loading @@ -1431,6 +1442,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } // We need to wait until all types are ready if (typesReady != types) { if (DEBUG) { Log.d(TAG, TextUtils.formatSimple( "not all types are ready yet, waiting. typesReady: %s, types: %s", typesReady, types)); } return; } } Loading Loading @@ -1728,9 +1744,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } else { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE); // The requestedVisibleTypes are only send at the end of the hide animation. // Therefore, the requested is not finished at this point. if (!Flags.refactorInsetsController()) { ImeTracker.forLogging().onHidden(statsToken); } reportRequestedVisibleTypes(); } reportRequestedVisibleTypes(shown ? null : runner.getStatsToken()); } @Override Loading Loading @@ -1787,7 +1807,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (mHost != null) { // if the (hide) animation is cancelled, the // requestedVisibleTypes should be reported at this point. reportRequestedVisibleTypes(); reportRequestedVisibleTypes(control.getStatsToken()); mHost.getInputMethodManager().removeImeSurface( mHost.getWindowToken()); } Loading Loading @@ -1923,8 +1943,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation /** * Called when finishing setting requested visible types or finishing setting controls. * * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ private void reportRequestedVisibleTypes() { private void reportRequestedVisibleTypes(@Nullable ImeTracker.Token statsToken) { final @InsetsType int typesToReport; if (Flags.refactorInsetsController()) { // If the IME is currently animating out, it is still visible, therefore we only Loading @@ -1941,8 +1963,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (WindowInsets.Type.hasCompatSystemBars(diff)) { mCompatSysUiVisibilityStaled = true; } if (Flags.refactorInsetsController()) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_REPORT_REQUESTED_VISIBLE_TYPES); } mReportedRequestedVisibleTypes = mRequestedVisibleTypes; mHost.updateRequestedVisibleTypes(mReportedRequestedVisibleTypes); mHost.updateRequestedVisibleTypes(mReportedRequestedVisibleTypes, statsToken); } else if (Flags.refactorInsetsController()) { if ((typesToReport & ime()) != 0 && mImeSourceConsumer != null) { InsetsSourceControl control = mImeSourceConsumer.getControl(); if (control != null && control.getLeash() == null) { // If the IME was requested twice, and we didn't receive the controls // yet, this request will not continue. It should be cancelled here, as // it would time out otherwise. ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_CLIENT_REPORT_REQUESTED_VISIBLE_TYPES); } } } updateCompatSysUiVisibility(); } Loading
core/java/android/view/InsetsSourceControl.java +20 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.proto.ProtoOutputStream; import android.view.WindowInsets.Type.InsetsType; import android.view.inputmethod.ImeTracker; import java.io.PrintWriter; import java.util.Arrays; Loading @@ -56,6 +57,9 @@ public class InsetsSourceControl implements Parcelable { private boolean mSkipAnimationOnce; private int mParcelableFlags; /** The token tracking the current IME request */ private @Nullable ImeTracker.Token mImeStatsToken; public InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash, boolean initiallyVisible, Point surfacePosition, Insets insetsHint) { mId = id; Loading @@ -78,6 +82,7 @@ public class InsetsSourceControl implements Parcelable { mSurfacePosition = new Point(other.mSurfacePosition); mInsetsHint = other.mInsetsHint; mSkipAnimationOnce = other.getAndClearSkipAnimationOnce(); mImeStatsToken = other.getImeStatsToken(); } public InsetsSourceControl(Parcel in) { Loading @@ -88,6 +93,7 @@ public class InsetsSourceControl implements Parcelable { mSurfacePosition = in.readTypedObject(Point.CREATOR); mInsetsHint = in.readTypedObject(Insets.CREATOR); mSkipAnimationOnce = in.readBoolean(); mImeStatsToken = in.readTypedObject(ImeTracker.Token.CREATOR); } public int getId() { Loading Loading @@ -153,6 +159,15 @@ public class InsetsSourceControl implements Parcelable { return result; } @Nullable public ImeTracker.Token getImeStatsToken() { return mImeStatsToken; } public void setImeStatsToken(@Nullable ImeTracker.Token imeStatsToken) { mImeStatsToken = imeStatsToken; } public void setParcelableFlags(int parcelableFlags) { mParcelableFlags = parcelableFlags; } Loading @@ -171,6 +186,7 @@ public class InsetsSourceControl implements Parcelable { dest.writeTypedObject(mSurfacePosition, mParcelableFlags); dest.writeTypedObject(mInsetsHint, mParcelableFlags); dest.writeBoolean(mSkipAnimationOnce); dest.writeTypedObject(mImeStatsToken, mParcelableFlags); } public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) { Loading @@ -196,13 +212,14 @@ public class InsetsSourceControl implements Parcelable { && mInitiallyVisible == that.mInitiallyVisible && mSurfacePosition.equals(that.mSurfacePosition) && mInsetsHint.equals(that.mInsetsHint) && mSkipAnimationOnce == that.mSkipAnimationOnce; && mSkipAnimationOnce == that.mSkipAnimationOnce && Objects.equals(mImeStatsToken, that.mImeStatsToken); } @Override public int hashCode() { return Objects.hash(mId, mType, mLeash, mInitiallyVisible, mSurfacePosition, mInsetsHint, mSkipAnimationOnce); mSkipAnimationOnce, mImeStatsToken); } @Override Loading @@ -225,6 +242,7 @@ public class InsetsSourceControl implements Parcelable { pw.print(" mSurfacePosition="); pw.print(mSurfacePosition); pw.print(" mInsetsHint="); pw.print(mInsetsHint); pw.print(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce); pw.print(" mImeStatsToken="); pw.print(mImeStatsToken); pw.println(); } Loading
core/java/android/view/ViewRootImpl.java +18 −0 Original line number Diff line number Diff line Loading @@ -10056,6 +10056,24 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } /** * Dispatches the statsToken and IME visibility to the ImeInsetsSourceProvider. * * @param visible {@code true} if it became visible, {@code false} otherwise. * @param statsToken the token tracking the current IME request. * * @hide */ public void notifyImeVisibilityChanged(boolean visible, @NonNull ImeTracker.Token statsToken) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_NOTIFY_IME_VISIBILITY_CHANGED); try { mWindowSession.notifyImeWindowVisibilityChangedFromClient(mWindow, visible, statsToken); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** * Represents a pending input event that is waiting in a queue. * Loading