From 1619482379abbfb6a8feb725c15c77273e9b1c29 Mon Sep 17 00:00:00 2001 From: Cosmin Băieș Date: Thu, 10 Nov 2022 16:12:44 +0000 Subject: Revert^2 "Input latency & reliability tracking" 1f4fd2d21e4316e21f74c80c5c11cd266832346a Change-Id: I096456e9cd7449836b373ff392f2e9df58b3e661 --- .../wm/shell/common/DisplayImeController.java | 34 +++++++++++++++++----- .../wm/shell/common/DisplayInsetsController.java | 23 ++++++++++----- .../com/android/wm/shell/common/SystemWindows.java | 4 ++- .../wm/shell/common/DisplayImeControllerTest.java | 2 +- .../shell/common/DisplayInsetsControllerTest.java | 10 +++++-- 5 files changed, 53 insertions(+), 20 deletions(-) (limited to 'libs') diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index bb7c4134aaaf..6140b1fd971b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.res.Configuration; import android.graphics.Point; @@ -38,6 +39,7 @@ import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; +import android.view.inputmethod.ImeTracker; import android.view.inputmethod.InputMethodManagerGlobal; import androidx.annotation.VisibleForTesting; @@ -112,7 +114,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } if (mDisplayController.getDisplayLayout(displayId).rotation() != pd.mRotation && isImeShowing(displayId)) { - pd.startAnimation(true, false /* forceRestart */); + pd.startAnimation(true, false /* forceRestart */, null /* statsToken */); } } @@ -244,7 +246,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged mInsetsState.set(insetsState, true /* copySources */); if (mImeShowing && !newFrame.equals(oldFrame) && newSource.isVisible()) { if (DEBUG) Slog.d(TAG, "insetsChanged when IME showing, restart animation"); - startAnimation(mImeShowing, true /* forceRestart */); + startAnimation(mImeShowing, true /* forceRestart */, null /* statsToken */); } } @@ -280,7 +282,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged !haveSameLeash(mImeSourceControl, imeSourceControl); if (mAnimation != null) { if (positionChanged) { - startAnimation(mImeShowing, true /* forceRestart */); + startAnimation(mImeShowing, true /* forceRestart */, null /* statsToken */); } } else { if (leashChanged) { @@ -312,21 +314,22 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } @Override - public void showInsets(int types, boolean fromIme) { + public void showInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { if ((types & WindowInsets.Type.ime()) == 0) { return; } if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); - startAnimation(true /* show */, false /* forceRestart */); + startAnimation(true /* show */, false /* forceRestart */, statsToken); } @Override - public void hideInsets(int types, boolean fromIme) { + public void hideInsets(@InsetsType int types, boolean fromIme) { if ((types & WindowInsets.Type.ime()) == 0) { return; } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); - startAnimation(false /* show */, false /* forceRestart */); + startAnimation(false /* show */, false /* forceRestart */, null /* statsToken */); } @Override @@ -367,9 +370,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged .navBarFrameHeight(); } - private void startAnimation(final boolean show, final boolean forceRestart) { + private void startAnimation(final boolean show, final boolean forceRestart, + @Nullable ImeTracker.Token statsToken) { final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); if (imeSource == null || mImeSourceControl == null) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE); return; } final Rect newFrame = imeSource.getFrame(); @@ -392,6 +397,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } if (!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show) || (mAnimationDirection == DIRECTION_HIDE && !show)) { + ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE); return; } boolean seek = false; @@ -435,8 +441,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged mTransactionPool.release(t); }); mAnimation.setInterpolator(INTERPOLATOR); + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE); mAnimation.addListener(new AnimatorListenerAdapter() { private boolean mCancelled = false; + @Nullable + private final ImeTracker.Token mStatsToken = statsToken; @Override public void onAnimationStart(Animator animation) { @@ -456,6 +465,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged t.setAlpha(mImeSourceControl.getLeash(), alpha); if (mAnimationDirection == DIRECTION_SHOW) { t.show(mImeSourceControl.getLeash()); + ImeTracker.get().onProgress(mStatsToken, + ImeTracker.PHASE_WM_ANIMATION_RUNNING); } t.apply(); mTransactionPool.release(t); @@ -482,6 +493,13 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged t.apply(); mTransactionPool.release(t); + if (mAnimationDirection == DIRECTION_SHOW && mCancelled) { + ImeTracker.get().onFailed(mStatsToken, + ImeTracker.PHASE_WM_ANIMATION_RUNNING); + } else if (!mCancelled) { + ImeTracker.get().onShown(mStatsToken); + } + mAnimationDirection = DIRECTION_NONE; mAnimation = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java index 8d4a09d8f371..f78ed22adc7c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java @@ -16,6 +16,7 @@ package com.android.wm.shell.common; +import android.annotation.Nullable; import android.content.ComponentName; import android.os.RemoteException; import android.util.Slog; @@ -25,6 +26,7 @@ import android.view.IWindowManager; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.WindowInsets.Type.InsetsType; +import android.view.inputmethod.ImeTracker; import androidx.annotation.BinderThread; @@ -156,17 +158,20 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan } } - private void showInsets(int types, boolean fromIme) { + private void showInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { CopyOnWriteArrayList listeners = mListeners.get(mDisplayId); if (listeners == null) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER); return; } + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER); for (OnInsetsChangedListener listener : listeners) { - listener.showInsets(types, fromIme); + listener.showInsets(types, fromIme, statsToken); } } - private void hideInsets(int types, boolean fromIme) { + private void hideInsets(@InsetsType int types, boolean fromIme) { CopyOnWriteArrayList listeners = mListeners.get(mDisplayId); if (listeners == null) { return; @@ -214,14 +219,15 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan } @Override - public void showInsets(int types, boolean fromIme) throws RemoteException { + public void showInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) throws RemoteException { mMainExecutor.execute(() -> { - PerDisplay.this.showInsets(types, fromIme); + PerDisplay.this.showInsets(types, fromIme, statsToken); }); } @Override - public void hideInsets(int types, boolean fromIme) throws RemoteException { + public void hideInsets(@InsetsType int types, boolean fromIme) throws RemoteException { mMainExecutor.execute(() -> { PerDisplay.this.hideInsets(types, fromIme); }); @@ -263,8 +269,11 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan * * @param types {@link InsetsType} to show * @param fromIme true if this request originated from IME (InputMethodService). + * @param statsToken the token tracking the current IME show request + * or {@code null} otherwise. */ - default void showInsets(@InsetsType int types, boolean fromIme) {} + default void showInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) {} /** * Called when a set of insets source window should be hidden by policy. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index e270edb800bd..4f45eb8993c9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -19,6 +19,7 @@ package com.android.wm.shell.common; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.graphics.Region; @@ -46,6 +47,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowlessWindowManager; +import android.view.inputmethod.ImeTracker; import android.window.ClientWindowFrames; import com.android.internal.os.IResultReceiver; @@ -351,7 +353,7 @@ public class SystemWindows { InsetsSourceControl[] activeControls) {} @Override - public void showInsets(int types, boolean fromIme) {} + public void showInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) {} @Override public void hideInsets(int types, boolean fromIme) {} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java index a6f19e7d11d3..f207024958a4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java @@ -97,7 +97,7 @@ public class DisplayImeControllerTest extends ShellTestCase { @Test public void showInsets_schedulesNoWorkOnExecutor() { - mPerDisplay.showInsets(ime(), true); + mPerDisplay.showInsets(ime(), true, null /* statsToken */); verifyZeroInteractions(mExecutor); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java index 39db328ef0e0..a676402efe9a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.annotation.Nullable; import android.content.ComponentName; import android.os.RemoteException; import android.util.SparseArray; @@ -33,6 +34,7 @@ import android.view.IWindowManager; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.WindowInsets; +import android.view.inputmethod.ImeTracker; import androidx.test.filters.SmallTest; @@ -111,7 +113,8 @@ public class DisplayInsetsControllerTest extends ShellTestCase { WindowInsets.Type.defaultVisible()); mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).insetsChanged(null); mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).insetsControlChanged(null, null); - mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).showInsets(0, false); + mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).showInsets(0, false, + null /* statsToken */); mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).hideInsets(0, false); mExecutor.flushAll(); @@ -131,7 +134,8 @@ public class DisplayInsetsControllerTest extends ShellTestCase { WindowInsets.Type.defaultVisible()); mInsetsControllersByDisplayId.get(SECOND_DISPLAY).insetsChanged(null); mInsetsControllersByDisplayId.get(SECOND_DISPLAY).insetsControlChanged(null, null); - mInsetsControllersByDisplayId.get(SECOND_DISPLAY).showInsets(0, false); + mInsetsControllersByDisplayId.get(SECOND_DISPLAY).showInsets(0, false, + null /* statsToken */); mInsetsControllersByDisplayId.get(SECOND_DISPLAY).hideInsets(0, false); mExecutor.flushAll(); @@ -191,7 +195,7 @@ public class DisplayInsetsControllerTest extends ShellTestCase { } @Override - public void showInsets(int types, boolean fromIme) { + public void showInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) { showInsetsCount++; } -- cgit v1.2.3-59-g8ed1b From 44ff0dd9eb26d429620dddff3511a84f184986a2 Mon Sep 17 00:00:00 2001 From: Cosmin Băieș Date: Thu, 10 Nov 2022 16:12:44 +0000 Subject: Revert^2 "Input latency & reliability tracking - hide flow" d638a60aae20b5aabd8af057ea5cf4c622907694 Test: atest CtsSystemApiSignatureTestCases:android.signature.cts.api.system.SignatureTest#testRuntimeCompatibilityWithCurrentApi Change-Id: I1ee7224b40fa3f4b744311eb4145fa13a87d835a --- .../inputmethodservice/IInputMethodWrapper.java | 14 +- .../inputmethodservice/InputMethodService.java | 15 +- .../view/IDisplayWindowInsetsController.aidl | 2 +- core/java/android/view/IWindow.aidl | 3 +- .../android/view/InsetsAnimationControlRunner.java | 2 +- core/java/android/view/InsetsController.java | 31 ++- core/java/android/view/ViewRootImpl.java | 19 +- .../IInputMethodManagerGlobalInvoker.java | 7 +- core/java/android/view/inputmethod/ImeTracker.java | 245 +++++++++++++++------ .../java/android/view/inputmethod/InputMethod.java | 9 +- .../view/inputmethod/InputMethodManager.java | 44 +++- .../android/internal/inputmethod/IInputMethod.aidl | 3 +- .../InputMethodPrivilegedOperations.java | 2 +- .../com/android/internal/view/BaseIWindow.java | 3 +- .../android/internal/view/IInputMethodManager.aidl | 3 +- .../android/view/ImeInsetsSourceConsumerTest.java | 2 +- .../src/android/view/InsetsControllerTest.java | 4 +- .../wm/shell/common/DisplayImeController.java | 24 +- .../wm/shell/common/DisplayInsetsController.java | 17 +- .../com/android/wm/shell/common/SystemWindows.java | 2 +- .../wm/shell/common/DisplayImeControllerTest.java | 4 +- .../shell/common/DisplayInsetsControllerTest.java | 8 +- .../server/inputmethod/IInputMethodInvoker.java | 5 +- .../inputmethod/InputMethodManagerService.java | 161 ++++++++------ .../java/com/android/server/wm/DisplayContent.java | 17 +- .../android/server/wm/ImeInsetsSourceProvider.java | 9 +- .../com/android/server/wm/InsetsControlTarget.java | 4 +- .../android/server/wm/WindowManagerInternal.java | 4 +- .../android/server/wm/WindowManagerService.java | 16 +- .../java/com/android/server/wm/WindowState.java | 17 +- .../InputMethodManagerServiceTestBase.java | 2 +- .../src/com/android/server/wm/TestIWindow.java | 3 +- .../src/com/android/server/wm/WindowTestsBase.java | 3 +- 33 files changed, 475 insertions(+), 229 deletions(-) (limited to 'libs') diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index fde8f0c506a1..d55367f19a70 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -234,9 +234,13 @@ class IInputMethodWrapper extends IInputMethod.Stub } case DO_HIDE_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; + final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3; if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) { + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2, - (IBinder) args.arg1); + (IBinder) args.arg1, statsToken); + } else { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH); } args.recycle(); return; @@ -431,9 +435,11 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override - public void hideSoftInput(IBinder hideInputToken, int flags, ResultReceiver resultReceiver) { - mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_HIDE_SOFT_INPUT, - flags, hideInputToken, resultReceiver)); + public void hideSoftInput(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken, + int flags, ResultReceiver resultReceiver) { + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER); + mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT, + flags, hideInputToken, resultReceiver, statsToken)); } @BinderThread diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 07eb5f21abf6..bf4fc4a72fdc 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -670,7 +670,7 @@ public class InputMethodService extends AbstractInputMethodService { */ private IBinder mCurHideInputToken; - /** The token tracking the current IME show request or {@code null} otherwise. */ + /** The token tracking the current IME request or {@code null} otherwise. */ @Nullable private ImeTracker.Token mCurStatsToken; @@ -875,10 +875,12 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, - IBinder hideInputToken) { + IBinder hideInputToken, @Nullable ImeTracker.Token statsToken) { mSystemCallingHideSoftInput = true; mCurHideInputToken = hideInputToken; + mCurStatsToken = statsToken; hideSoftInput(flags, resultReceiver); + mCurStatsToken = null; mCurHideInputToken = null; mSystemCallingHideSoftInput = false; } @@ -889,6 +891,7 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void hideSoftInput(int flags, ResultReceiver resultReceiver) { + ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT); if (DEBUG) Log.v(TAG, "hideSoftInput()"); if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R && !mSystemCallingHideSoftInput) { @@ -930,9 +933,9 @@ public class InputMethodService extends AbstractInputMethodService { try { showSoftInput(flags, resultReceiver); } finally { + mCurStatsToken = null; mCurShowInputToken = null; mSystemCallingShowSoftInput = false; - mCurStatsToken = null; } } @@ -2939,10 +2942,8 @@ public class InputMethodService extends AbstractInputMethodService { ImeTracing.getInstance().triggerServiceDump( "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper, null /* icProto */); - if (setVisible) { - ImeTracker.get().onProgress(mCurStatsToken, - ImeTracker.PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER); - } + ImeTracker.get().onProgress(mCurStatsToken, + ImeTracker.PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER); mPrivOps.applyImeVisibilityAsync(setVisible ? mCurShowInputToken : mCurHideInputToken, setVisible, mCurStatsToken); } diff --git a/core/java/android/view/IDisplayWindowInsetsController.aidl b/core/java/android/view/IDisplayWindowInsetsController.aidl index 1b62bb5c519a..91270d4160f5 100644 --- a/core/java/android/view/IDisplayWindowInsetsController.aidl +++ b/core/java/android/view/IDisplayWindowInsetsController.aidl @@ -54,5 +54,5 @@ oneway interface IDisplayWindowInsetsController { /** * @see IWindow#hideInsets */ - void hideInsets(int types, boolean fromIme); + void hideInsets(int types, boolean fromIme, in @nullable ImeTracker.Token statsToken); } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 16526d19b4c1..8e16f24b154f 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -78,8 +78,9 @@ oneway interface IWindow { * * @param types internal insets types (WindowInsets.Type.InsetsType) to hide * @param fromIme true if this request originated from IME (InputMethodService). + * @param statsToken the token tracking the current IME hide request or {@code null} otherwise. */ - void hideInsets(int types, boolean fromIme); + void hideInsets(int types, boolean fromIme, in @nullable ImeTracker.Token statsToken); void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); diff --git a/core/java/android/view/InsetsAnimationControlRunner.java b/core/java/android/view/InsetsAnimationControlRunner.java index 86238964edb7..cf40e7e4d308 100644 --- a/core/java/android/view/InsetsAnimationControlRunner.java +++ b/core/java/android/view/InsetsAnimationControlRunner.java @@ -76,7 +76,7 @@ public interface InsetsAnimationControlRunner { @AnimationType int getAnimationType(); /** - * @return The token tracking the current IME show request or {@code null} otherwise. + * @return The token tracking the current IME request or {@code null} otherwise. */ @Nullable ImeTracker.Token getStatsToken(); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 276310ef9b00..fbd82266246b 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1029,11 +1029,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void hide(@InsetsType int types) { - hide(types, false /* fromIme */); + hide(types, false /* fromIme */, null /* statsToken */); } @VisibleForTesting - public void hide(@InsetsType int types, boolean fromIme) { + public void hide(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { if (fromIme) { ImeTracing.getInstance().triggerClientDump("InsetsController#hide", mHost.getInputMethodManager(), null /* icProto */); @@ -1046,16 +1047,25 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if ((types & type) == 0) { continue; } - final @AnimationType int animationType = getAnimationType(type); + @AnimationType final int animationType = getAnimationType(type); final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0; + final boolean isImeAnimation = type == ime(); if (!requestedVisible && animationType == ANIMATION_TYPE_NONE || animationType == ANIMATION_TYPE_HIDE) { - // no-op: already hidden or animating out. + // no-op: already hidden or animating out (because window visibility is + // applied before starting animation). + if (isImeAnimation) { + ImeTracker.get().onCancelled(statsToken, + ImeTracker.PHASE_CLIENT_APPLY_ANIMATION); + } continue; } + if (isImeAnimation) { + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION); + } typesReady |= type; } - applyAnimation(typesReady, false /* show */, fromIme /* fromIme */, null /* statsToken */); + applyAnimation(typesReady, false /* show */, fromIme, statsToken); } @Override @@ -1337,9 +1347,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation showDirectly(runner.getTypes(), true /* fromIme */); ImeTracker.get().onShown(statsToken); } else { - ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW); + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE); hideDirectly(runner.getTypes(), true /* animationFinished */, runner.getAnimationType(), true /* fromIme */); + ImeTracker.get().onHidden(statsToken); } } @@ -1364,7 +1376,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) { if (invokeCallback) { - ImeTracker.get().onFailed(control.getStatsToken(), + ImeTracker.get().onCancelled(control.getStatsToken(), ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL); control.cancel(); } else { @@ -1527,9 +1539,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken); } - private void hideDirectly( - @InsetsType int types, boolean animationFinished, @AnimationType int animationType, - boolean fromIme) { + private void hideDirectly(@InsetsType int types, boolean animationFinished, + @AnimationType int animationType, boolean fromIme) { if ((types & ime()) != 0) { ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly", mHost.getInputMethodManager(), null /* icProto */); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b5e9b657cfac..b088514c6989 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -5663,7 +5663,10 @@ public final class ViewRootImpl implements ViewParent, break; } case MSG_HIDE_INSETS: { - mInsetsController.hide(msg.arg1, msg.arg2 == 1); + final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj; + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_CLIENT_HANDLE_HIDE_INSETS); + mInsetsController.hide(msg.arg1, msg.arg2 == 1, statsToken); break; } case MSG_WINDOW_MOVED: @@ -8820,8 +8823,9 @@ public final class ViewRootImpl implements ViewParent, mHandler.obtainMessage(MSG_SHOW_INSETS, types, fromIme ? 1 : 0, statsToken).sendToTarget(); } - private void hideInsets(@InsetsType int types, boolean fromIme) { - mHandler.obtainMessage(MSG_HIDE_INSETS, types, fromIme ? 1 : 0).sendToTarget(); + private void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { + mHandler.obtainMessage(MSG_HIDE_INSETS, types, fromIme ? 1 : 0, statsToken).sendToTarget(); } public void dispatchMoved(int newX, int newY) { @@ -10202,8 +10206,8 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) { - + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (fromIme) { ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#hideInsets", @@ -10211,7 +10215,10 @@ public final class ViewRootImpl implements ViewParent, null /* icProto */); } if (viewAncestor != null) { - viewAncestor.hideInsets(types, fromIme); + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS); + viewAncestor.hideInsets(types, fromIme, statsToken); + } else { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS); } } diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java index e1a5b4c1558b..6eae63afcba7 100644 --- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java +++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java @@ -292,14 +292,15 @@ final class IInputMethodManagerGlobalInvoker { @AnyThread static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken, - int flags, @Nullable ResultReceiver resultReceiver, - @SoftInputShowHideReason int reason) { + @Nullable ImeTracker.Token statsToken, int flags, + @Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { final IInputMethodManager service = getService(); if (service == null) { return false; } try { - return service.hideSoftInput(client, windowToken, flags, resultReceiver, reason); + return service.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver, + reason); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java index 818a7290c40d..f4ecdff12c7a 100644 --- a/core/java/android/view/inputmethod/ImeTracker.java +++ b/core/java/android/view/inputmethod/ImeTracker.java @@ -27,9 +27,8 @@ import android.os.Binder; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; -import android.os.ResultReceiver; +import android.os.SystemProperties; import android.util.Log; -import android.view.View; import com.android.internal.inputmethod.InputMethodDebug; import com.android.internal.inputmethod.SoftInputShowHideReason; @@ -47,33 +46,46 @@ public interface ImeTracker { String TAG = "ImeTracker"; - /** The origin of the IME show request. */ + /** + * The origin of the IME request + * + * The name follows the format {@code PHASE_x_...} where {@code x} denotes + * where the origin is (i.e. {@code PHASE_SERVER_...} occurs in the server). + */ @IntDef(prefix = { "ORIGIN_" }, value = { - ORIGIN_SHOW_SOFT_INPUT, - ORIGIN_START_INPUT + ORIGIN_CLIENT_SHOW_SOFT_INPUT, + ORIGIN_CLIENT_HIDE_SOFT_INPUT, + ORIGIN_SERVER_START_INPUT, + ORIGIN_SERVER_HIDE_INPUT }) @Retention(RetentionPolicy.SOURCE) @interface Origin {} /** - * The IME is already started. - * - * @see InputMethodManager#showSoftInput(View, int, ResultReceiver) + * The IME show request originated in the client. */ - int ORIGIN_SHOW_SOFT_INPUT = 0; + int ORIGIN_CLIENT_SHOW_SOFT_INPUT = 0; /** - * The IME must be started. - * - * @see com.android.server.inputmethod.InputMethodManagerService#showCurrentInputImplicitLocked + * The IME hide request originated in the client. + */ + int ORIGIN_CLIENT_HIDE_SOFT_INPUT = 1; + + /** + * The IME show request originated in the server. + */ + int ORIGIN_SERVER_START_INPUT = 2; + + /** + * The IME hide request originated in the server. */ - int ORIGIN_START_INPUT = 1; + int ORIGIN_SERVER_HIDE_INPUT = 3; /** - * The current phase of the IME show request. + * The current phase of the IME request. * * The name follows the format {@code PHASE_x_...} where {@code x} denotes - * where the phase occurs (i.e. {@code PHASE_WM_...} takes place in the WindowManager). + * where the phase is (i.e. {@code PHASE_SERVER_...} occurs in the server). */ @IntDef(prefix = { "PHASE_" }, value = { PHASE_CLIENT_VIEW_SERVED, @@ -81,107 +93,152 @@ public interface ImeTracker { PHASE_SERVER_CLIENT_FOCUSED, PHASE_SERVER_ACCESSIBILITY, PHASE_SERVER_SYSTEM_READY, + PHASE_SERVER_HIDE_IMPLICIT, + PHASE_SERVER_HIDE_NOT_ALWAYS, + PHASE_SERVER_WAIT_IME, PHASE_SERVER_HAS_IME, + PHASE_SERVER_SHOULD_HIDE, PHASE_IME_WRAPPER, PHASE_IME_WRAPPER_DISPATCH, PHASE_IME_SHOW_SOFT_INPUT, + PHASE_IME_HIDE_SOFT_INPUT, PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE, PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER, PHASE_SERVER_APPLY_IME_VISIBILITY, PHASE_WM_SHOW_IME_RUNNER, PHASE_WM_SHOW_IME_READY, - PHASE_WM_REMOTE_INSETS_CONTROL_TARGET, + PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET, + PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS, + PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS, + PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS, + PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS, PHASE_WM_REMOTE_INSETS_CONTROLLER, PHASE_WM_ANIMATION_CREATE, PHASE_WM_ANIMATION_RUNNING, PHASE_CLIENT_SHOW_INSETS, + PHASE_CLIENT_HIDE_INSETS, PHASE_CLIENT_HANDLE_SHOW_INSETS, + PHASE_CLIENT_HANDLE_HIDE_INSETS, PHASE_CLIENT_APPLY_ANIMATION, PHASE_CLIENT_CONTROL_ANIMATION, PHASE_CLIENT_ANIMATION_RUNNING, PHASE_CLIENT_ANIMATION_CANCEL, - PHASE_CLIENT_ANIMATION_FINISHED_SHOW + PHASE_CLIENT_ANIMATION_FINISHED_SHOW, + PHASE_CLIENT_ANIMATION_FINISHED_HIDE }) @Retention(RetentionPolicy.SOURCE) @interface Phase {} /** The view that requested the IME has been served by the IMM. */ - int PHASE_CLIENT_VIEW_SERVED = 1; + int PHASE_CLIENT_VIEW_SERVED = 0; /** The IME client that requested the IME has window manager focus. */ - int PHASE_SERVER_CLIENT_KNOWN = 2; + int PHASE_SERVER_CLIENT_KNOWN = 1; /** The IME client that requested the IME has IME focus. */ - int PHASE_SERVER_CLIENT_FOCUSED = 3; + int PHASE_SERVER_CLIENT_FOCUSED = 2; /** The IME request complies with the current accessibility settings. */ - int PHASE_SERVER_ACCESSIBILITY = 4; + int PHASE_SERVER_ACCESSIBILITY = 3; /** The server is ready to run third party code. */ - int PHASE_SERVER_SYSTEM_READY = 5; + int PHASE_SERVER_SYSTEM_READY = 4; + + /** Checked the implicit hide request against any explicit show requests. */ + int PHASE_SERVER_HIDE_IMPLICIT = 5; + + /** Checked the not-always hide request against any forced show requests. */ + int PHASE_SERVER_HIDE_NOT_ALWAYS = 6; /** The server is waiting for a connection to the IME. */ - int PHASE_SERVER_WAIT_IME = 6; + int PHASE_SERVER_WAIT_IME = 7; /** The server has a connection to the IME. */ - int PHASE_SERVER_HAS_IME = 7; + int PHASE_SERVER_HAS_IME = 8; + + /** The server decided the IME should be hidden. */ + int PHASE_SERVER_SHOULD_HIDE = 9; /** Reached the IME wrapper. */ - int PHASE_IME_WRAPPER = 8; + int PHASE_IME_WRAPPER = 10; /** Dispatched from the IME wrapper to the IME. */ - int PHASE_IME_WRAPPER_DISPATCH = 9; + int PHASE_IME_WRAPPER_DISPATCH = 11; + + /** Reached the IME' showSoftInput method. */ + int PHASE_IME_SHOW_SOFT_INPUT = 12; - /** Reached the IME. */ - int PHASE_IME_SHOW_SOFT_INPUT = 10; + /** Reached the IME' hideSoftInput method. */ + int PHASE_IME_HIDE_SOFT_INPUT = 13; /** The server decided the IME should be shown. */ - int PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE = 11; + int PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE = 14; /** Requested applying the IME visibility in the insets source consumer. */ - int PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER = 12; + int PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER = 15; /** Applied the IME visibility. */ - int PHASE_SERVER_APPLY_IME_VISIBILITY = 13; + int PHASE_SERVER_APPLY_IME_VISIBILITY = 16; /** Created the show IME runner. */ - int PHASE_WM_SHOW_IME_RUNNER = 14; + int PHASE_WM_SHOW_IME_RUNNER = 17; /** Ready to show IME. */ - int PHASE_WM_SHOW_IME_READY = 15; + int PHASE_WM_SHOW_IME_READY = 18; - /** Reached the remote insets control target. */ - int PHASE_WM_REMOTE_INSETS_CONTROL_TARGET = 16; + /** The Window Manager has a connection to the IME insets control target. */ + int PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET = 19; + + /** Reached the window insets control target's show insets method. */ + int PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS = 20; + + /** Reached the window insets control target's hide insets method. */ + int PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS = 21; + + /** Reached the remote insets control target's show insets method. */ + int PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS = 22; + + /** Reached the remote insets control target's hide insets method. */ + int PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS = 23; /** Reached the remote insets controller. */ - int PHASE_WM_REMOTE_INSETS_CONTROLLER = 17; + int PHASE_WM_REMOTE_INSETS_CONTROLLER = 24; /** Created the IME window insets show animation. */ - int PHASE_WM_ANIMATION_CREATE = 18; + int PHASE_WM_ANIMATION_CREATE = 25; /** Started the IME window insets show animation. */ - int PHASE_WM_ANIMATION_RUNNING = 19; + int PHASE_WM_ANIMATION_RUNNING = 26; - /** Reached the client. */ - int PHASE_CLIENT_SHOW_INSETS = 20; + /** Reached the client's show insets method. */ + int PHASE_CLIENT_SHOW_INSETS = 27; - /** Handled the IME window insets show request. */ - int PHASE_CLIENT_HANDLE_SHOW_INSETS = 21; + /** Reached the client's hide insets method. */ + int PHASE_CLIENT_HIDE_INSETS = 28; + + /** Handling the IME window insets show request. */ + int PHASE_CLIENT_HANDLE_SHOW_INSETS = 29; + + /** Handling the IME window insets hide request. */ + int PHASE_CLIENT_HANDLE_HIDE_INSETS = 30; /** Applied the IME window insets show animation. */ - int PHASE_CLIENT_APPLY_ANIMATION = 22; + int PHASE_CLIENT_APPLY_ANIMATION = 31; /** Started the IME window insets show animation. */ - int PHASE_CLIENT_CONTROL_ANIMATION = 23; + int PHASE_CLIENT_CONTROL_ANIMATION = 32; /** Queued the IME window insets show animation. */ - int PHASE_CLIENT_ANIMATION_RUNNING = 24; + int PHASE_CLIENT_ANIMATION_RUNNING = 33; /** Cancelled the IME window insets show animation. */ - int PHASE_CLIENT_ANIMATION_CANCEL = 25; + int PHASE_CLIENT_ANIMATION_CANCEL = 34; /** Finished the IME window insets show animation. */ - int PHASE_CLIENT_ANIMATION_FINISHED_SHOW = 26; + int PHASE_CLIENT_ANIMATION_FINISHED_SHOW = 35; + + /** Finished the IME window insets hide animation. */ + int PHASE_CLIENT_ANIMATION_FINISHED_HIDE = 36; /** * Called when an IME show request is created. @@ -194,34 +251,44 @@ public interface ImeTracker { @SoftInputShowHideReason int reason); /** - * Called when an IME show request progresses to a further phase. + * Called when an IME hide request is created. * - * @param token the token tracking the current IME show request or {@code null} otherwise. - * @param phase the new phase the IME show request reached. + * @param token the token tracking the current IME hide request or {@code null} otherwise. + * @param origin the origin of the IME hide request. + * @param reason the reason why the IME hide request was created. + */ + void onRequestHide(@Nullable Token token, @Origin int origin, + @SoftInputShowHideReason int reason); + + /** + * Called when an IME request progresses to a further phase. + * + * @param token the token tracking the current IME request or {@code null} otherwise. + * @param phase the new phase the IME request reached. */ void onProgress(@Nullable Token token, @Phase int phase); /** - * Called when an IME show request failed. + * Called when an IME request fails. * - * @param token the token tracking the current IME show request or {@code null} otherwise. - * @param phase the phase the IME show request failed at. + * @param token the token tracking the current IME request or {@code null} otherwise. + * @param phase the phase the IME request failed at. */ void onFailed(@Nullable Token token, @Phase int phase); /** - * Called when an IME show request reached a flow that is not yet implemented. + * Called when an IME request reached a flow that is not yet implemented. * - * @param token the token tracking the current IME show request or {@code null} otherwise. - * @param phase the phase the IME show request was currently at. + * @param token the token tracking the current IME request or {@code null} otherwise. + * @param phase the phase the IME request was currently at. */ void onTodo(@Nullable Token token, @Phase int phase); /** - * Called when an IME show request is cancelled. + * Called when an IME request is cancelled. * - * @param token the token tracking the current IME show request or {@code null} otherwise. - * @param phase the phase the IME show request was cancelled at. + * @param token the token tracking the current IME request or {@code null} otherwise. + * @param phase the phase the IME request was cancelled at. */ void onCancelled(@Nullable Token token, @Phase int phase); @@ -232,6 +299,13 @@ public interface ImeTracker { */ void onShown(@Nullable Token token); + /** + * Called when the IME hide request is successful. + * + * @param token the token tracking the current IME hide request or {@code null} otherwise. + */ + void onHidden(@Nullable Token token); + /** * Get the singleton instance of this class. * @@ -239,19 +313,30 @@ public interface ImeTracker { */ @NonNull static ImeTracker get() { - return LOGGER; + return SystemProperties.getBoolean("persist.debug.imetracker", false) + ? LOGGER + : NOOP_LOGGER; } /** The singleton IME tracker instance. */ ImeTracker LOGGER = new ImeTracker() { @Override - public void onRequestShow(@Nullable Token token, int origin, int reason) { + public void onRequestShow(@Nullable Token token, int origin, + @SoftInputShowHideReason int reason) { if (token == null) return; Log.i(TAG, token.mTag + ": onRequestShow at " + originToString(origin) + " reason " + InputMethodDebug.softInputDisplayReasonToString(reason)); } + @Override + public void onRequestHide(@Nullable Token token, int origin, + @SoftInputShowHideReason int reason) { + if (token == null) return; + Log.i(TAG, token.mTag + ": onRequestHide at " + originToString(origin) + + " reason " + InputMethodDebug.softInputDisplayReasonToString(reason)); + } + @Override public void onProgress(@Nullable Token token, int phase) { if (token == null) return; @@ -281,9 +366,45 @@ public interface ImeTracker { if (token == null) return; Log.i(TAG, token.mTag + ": onShown"); } + + @Override + public void onHidden(@Nullable Token token) { + if (token == null) return; + Log.i(TAG, token.mTag + ": onHidden"); + } + }; + + /** The singleton no-op IME tracker instance. */ + ImeTracker NOOP_LOGGER = new ImeTracker() { + + @Override + public void onRequestShow(@Nullable Token token, int origin, + @SoftInputShowHideReason int reason) {} + + @Override + public void onRequestHide(@Nullable Token token, int origin, + @SoftInputShowHideReason int reason) {} + + @Override + public void onProgress(@Nullable Token token, int phase) {} + + @Override + public void onFailed(@Nullable Token token, int phase) {} + + @Override + public void onTodo(@Nullable Token token, int phase) {} + + @Override + public void onCancelled(@Nullable Token token, int phase) {} + + @Override + public void onShown(@Nullable Token token) {} + + @Override + public void onHidden(@Nullable Token token) {} }; - /** A token that tracks the progress of an IME show request. */ + /** A token that tracks the progress of an IME request. */ class Token implements Parcelable { private final IBinder mBinder; diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java index 13a7c8b1a1ad..92380ed7a7bc 100644 --- a/core/java/android/view/inputmethod/InputMethod.java +++ b/core/java/android/view/inputmethod/InputMethod.java @@ -304,7 +304,7 @@ public interface InputMethod { * @hide */ @MainThread - default public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver, + public default void showSoftInputWithToken(int flags, ResultReceiver resultReceiver, IBinder showInputToken, @Nullable ImeTracker.Token statsToken) { showSoftInput(flags, resultReceiver); } @@ -339,11 +339,14 @@ public interface InputMethod { * @param hideInputToken an opaque {@link android.os.Binder} token to identify which API call * of {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}} is associated * with this callback. + * @param statsToken the token tracking the current IME hide request or {@code null} otherwise. * @hide */ @MainThread - public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, - IBinder hideInputToken); + public default void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver, + IBinder hideInputToken, @Nullable ImeTracker.Token statsToken) { + hideSoftInput(flags, resultReceiver); + } /** * Request that any soft input part of the input method be hidden from the user. diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 8a286ae99198..8aba526e6d3d 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2002,7 +2002,8 @@ public final class InputMethodManager { private boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { final ImeTracker.Token statsToken = new ImeTracker.Token(); - ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_SHOW_SOFT_INPUT, reason); + ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, + reason); ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this, null /* icProto */); @@ -2051,7 +2052,7 @@ public final class InputMethodManager { public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) { synchronized (mH) { final ImeTracker.Token statsToken = new ImeTracker.Token(); - ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_SHOW_SOFT_INPUT, + ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, SoftInputShowHideReason.SHOW_SOFT_INPUT); Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be" @@ -2141,17 +2142,24 @@ public final class InputMethodManager { private boolean hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { + final ImeTracker.Token statsToken = new ImeTracker.Token(); + ImeTracker.get().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, + reason); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow", this, null /* icProto */); checkFocus(); synchronized (mH) { final View servedView = getServedViewLocked(); if (servedView == null || servedView.getWindowToken() != windowToken) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); return false; } - return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, flags, - resultReceiver, reason); + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); + + return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken, + flags, resultReceiver, reason); } } @@ -2779,14 +2787,23 @@ public final class InputMethodManager { @UnsupportedAppUsage void closeCurrentInput() { + final ImeTracker.Token statsToken = new ImeTracker.Token(); + ImeTracker.get().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, + SoftInputShowHideReason.HIDE_SOFT_INPUT); + synchronized (mH) { if (mCurRootView == null || mCurRootView.getView() == null) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); Log.w(TAG, "No current root view, ignoring closeCurrentInput()"); return; } + + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); + IInputMethodManagerGlobalInvoker.hideSoftInput( mClient, mCurRootView.getView().getWindowToken(), + statsToken, HIDE_NOT_ALWAYS, null, SoftInputShowHideReason.HIDE_SOFT_INPUT); @@ -2855,15 +2872,24 @@ public final class InputMethodManager { * @hide */ public void notifyImeHidden(IBinder windowToken) { + final ImeTracker.Token statsToken = new ImeTracker.Token(); + ImeTracker.get().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, + SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this, null /* icProto */); synchronized (mH) { - if (isImeSessionAvailableLocked() && mCurRootView != null - && mCurRootView.getWindowToken() == windowToken) { - IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, 0 /* flags */, - null /* resultReceiver */, - SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API); + if (!isImeSessionAvailableLocked() || mCurRootView == null + || mCurRootView.getWindowToken() != windowToken) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); + return; } + + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); + + IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken, + 0 /* flags */, null /* resultReceiver */, + SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API); } } diff --git a/core/java/com/android/internal/inputmethod/IInputMethod.aidl b/core/java/com/android/internal/inputmethod/IInputMethod.aidl index 058fca53f9bd..1e3714eb342d 100644 --- a/core/java/com/android/internal/inputmethod/IInputMethod.aidl +++ b/core/java/com/android/internal/inputmethod/IInputMethod.aidl @@ -73,7 +73,8 @@ oneway interface IInputMethod { void showSoftInput(in IBinder showInputToken, in @nullable ImeTracker.Token statsToken, int flags, in ResultReceiver resultReceiver); - void hideSoftInput(in IBinder hideInputToken, int flags, in ResultReceiver resultReceiver); + void hideSoftInput(in IBinder hideInputToken, in @nullable ImeTracker.Token statsToken, + int flags, in ResultReceiver resultReceiver); void updateEditorToolType(int toolType); diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java index 59fa1381c1d7..66e3333acf7c 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java @@ -384,7 +384,7 @@ public final class InputMethodPrivilegedOperations { * {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, * int)} * @param setVisible {@code true} to set IME visible, else hidden. - * @param statsToken the token tracking the current IME show request or {@code null} otherwise. + * @param statsToken the token tracking the current IME request or {@code null} otherwise. */ @AnyThread public void applyImeVisibilityAsync(IBinder showOrHideInputToken, boolean setVisible, diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 195f5847184e..2ac43099c741 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -73,7 +73,8 @@ public class BaseIWindow extends IWindow.Stub { } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) { + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { } @Override diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 361b83dca509..00bc3f2ae530 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -58,7 +58,8 @@ interface IInputMethodManager { boolean showSoftInput(in IInputMethodClient client, @nullable IBinder windowToken, in @nullable ImeTracker.Token statsToken, int flags, int lastClickToolType, in @nullable ResultReceiver resultReceiver, int reason); - boolean hideSoftInput(in IInputMethodClient client, @nullable IBinder windowToken, int flags, + boolean hideSoftInput(in IInputMethodClient client, @nullable IBinder windowToken, + in @nullable ImeTracker.Token statsToken, int flags, in @nullable ResultReceiver resultReceiver, int reason); // If windowToken is null, this just does startInput(). Otherwise this reports that a window // has gained focus, and if 'editorInfo' is non-null then also does startInput. diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java index 5002f377289d..0bf133fe01b6 100644 --- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java @@ -104,7 +104,7 @@ public class ImeInsetsSourceConsumerTest { assertTrue((mController.getRequestedVisibleTypes() & WindowInsets.Type.ime()) != 0); // test if setVisibility can hide IME - mController.hide(WindowInsets.Type.ime(), true /* fromIme */); + mController.hide(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */); mController.cancelExistingAnimations(); assertFalse((mController.getRequestedVisibleTypes() & WindowInsets.Type.ime()) != 0); }); diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index d5b37f3581ac..c6fa778763a8 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -267,7 +267,7 @@ public class InsetsControllerTest { final @InsetsType int types = navigationBars() | statusBars() | ime(); assertEquals(types, mController.getRequestedVisibleTypes() & types); - mController.hide(ime(), true /* fromIme */); + mController.hide(ime(), true /* fromIme */, null /* statsToken */); mController.hide(all()); mController.cancelExistingAnimations(); assertEquals(0, mController.getRequestedVisibleTypes() & types); @@ -285,7 +285,7 @@ public class InsetsControllerTest { mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */); mController.cancelExistingAnimations(); assertTrue(isRequestedVisible(mController, ime())); - mController.hide(ime(), true /* fromIme */); + mController.hide(ime(), true /* fromIme */, null /* statsToken */); mController.cancelExistingAnimations(); assertFalse(isRequestedVisible(mController, ime())); mController.getSourceConsumer(ITYPE_IME).onWindowFocusLost(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index 6140b1fd971b..d9b4f475a50c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -324,12 +324,13 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) { + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { if ((types & WindowInsets.Type.ime()) == 0) { return; } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); - startAnimation(false /* show */, false /* forceRestart */, null /* statsToken */); + startAnimation(false /* show */, false /* forceRestart */, statsToken); } @Override @@ -395,7 +396,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged + (mAnimationDirection == DIRECTION_SHOW ? "SHOW" : (mAnimationDirection == DIRECTION_HIDE ? "HIDE" : "NONE"))); } - if (!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show) + if ((!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show)) || (mAnimationDirection == DIRECTION_HIDE && !show)) { ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE); return; @@ -464,9 +465,9 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged : 1.f; t.setAlpha(mImeSourceControl.getLeash(), alpha); if (mAnimationDirection == DIRECTION_SHOW) { - t.show(mImeSourceControl.getLeash()); ImeTracker.get().onProgress(mStatsToken, ImeTracker.PHASE_WM_ANIMATION_RUNNING); + t.show(mImeSourceControl.getLeash()); } t.apply(); mTransactionPool.release(t); @@ -487,19 +488,20 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } dispatchEndPositioning(mDisplayId, mCancelled, t); if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { + ImeTracker.get().onProgress(mStatsToken, + ImeTracker.PHASE_WM_ANIMATION_RUNNING); t.hide(mImeSourceControl.getLeash()); removeImeSurface(); + ImeTracker.get().onHidden(mStatsToken); + } else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) { + ImeTracker.get().onShown(mStatsToken); + } else if (mCancelled) { + ImeTracker.get().onCancelled(mStatsToken, + ImeTracker.PHASE_WM_ANIMATION_RUNNING); } t.apply(); mTransactionPool.release(t); - if (mAnimationDirection == DIRECTION_SHOW && mCancelled) { - ImeTracker.get().onFailed(mStatsToken, - ImeTracker.PHASE_WM_ANIMATION_RUNNING); - } else if (!mCancelled) { - ImeTracker.get().onShown(mStatsToken); - } - mAnimationDirection = DIRECTION_NONE; mAnimation = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java index f78ed22adc7c..8759301f695b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java @@ -171,13 +171,16 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan } } - private void hideInsets(@InsetsType int types, boolean fromIme) { + private void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { CopyOnWriteArrayList listeners = mListeners.get(mDisplayId); if (listeners == null) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER); return; } + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER); for (OnInsetsChangedListener listener : listeners) { - listener.hideInsets(types, fromIme); + listener.hideInsets(types, fromIme, statsToken); } } @@ -227,9 +230,10 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) throws RemoteException { + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) throws RemoteException { mMainExecutor.execute(() -> { - PerDisplay.this.hideInsets(types, fromIme); + PerDisplay.this.hideInsets(types, fromIme, statsToken); }); } } @@ -280,7 +284,10 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan * * @param types {@link InsetsType} to hide * @param fromIme true if this request originated from IME (InputMethodService). + * @param statsToken the token tracking the current IME hide request + * or {@code null} otherwise. */ - default void hideInsets(@InsetsType int types, boolean fromIme) {} + default void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) {} } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 4f45eb8993c9..af13bf54f691 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -356,7 +356,7 @@ public class SystemWindows { public void showInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) {} @Override - public void hideInsets(int types, boolean fromIme) {} + public void hideInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) {} @Override public void moved(int newX, int newY) {} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java index f207024958a4..40f2e88f34fd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java @@ -97,13 +97,13 @@ public class DisplayImeControllerTest extends ShellTestCase { @Test public void showInsets_schedulesNoWorkOnExecutor() { - mPerDisplay.showInsets(ime(), true, null /* statsToken */); + mPerDisplay.showInsets(ime(), true /* fromIme */, null /* statsToken */); verifyZeroInteractions(mExecutor); } @Test public void hideInsets_schedulesNoWorkOnExecutor() { - mPerDisplay.hideInsets(ime(), true); + mPerDisplay.hideInsets(ime(), true /* fromIme */, null /* statsToken */); verifyZeroInteractions(mExecutor); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java index a676402efe9a..956f1cd419c2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java @@ -115,7 +115,8 @@ public class DisplayInsetsControllerTest extends ShellTestCase { mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).insetsControlChanged(null, null); mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).showInsets(0, false, null /* statsToken */); - mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).hideInsets(0, false); + mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).hideInsets(0, false, + null /* statsToken */); mExecutor.flushAll(); assertTrue(defaultListener.topFocusedWindowChangedCount == 1); @@ -136,7 +137,8 @@ public class DisplayInsetsControllerTest extends ShellTestCase { mInsetsControllersByDisplayId.get(SECOND_DISPLAY).insetsControlChanged(null, null); mInsetsControllersByDisplayId.get(SECOND_DISPLAY).showInsets(0, false, null /* statsToken */); - mInsetsControllersByDisplayId.get(SECOND_DISPLAY).hideInsets(0, false); + mInsetsControllersByDisplayId.get(SECOND_DISPLAY).hideInsets(0, false, + null /* statsToken */); mExecutor.flushAll(); assertTrue(defaultListener.topFocusedWindowChangedCount == 1); @@ -200,7 +202,7 @@ public class DisplayInsetsControllerTest extends ShellTestCase { } @Override - public void hideInsets(int types, boolean fromIme) { + public void hideInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) { hideInsetsCount++; } } diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java index 0cb5eb7a5d39..015e5768d505 100644 --- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java +++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java @@ -212,9 +212,10 @@ final class IInputMethodInvoker { // TODO(b/192412909): Convert this back to void method @AnyThread - boolean hideSoftInput(IBinder hideInputToken, int flags, ResultReceiver resultReceiver) { + boolean hideSoftInput(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken, int flags, + ResultReceiver resultReceiver) { try { - mTarget.hideSoftInput(hideInputToken, flags, resultReceiver); + mTarget.hideSoftInput(hideInputToken, statsToken, flags, resultReceiver); } catch (RemoteException e) { logRemoteException(e); return false; diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index ae470115f068..27d966e8673e 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -643,7 +643,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub */ private boolean mInputShown; - /** The token tracking the current IME show request or {@code null} otherwise. */ + /** The token tracking the current IME request or {@code null} otherwise. */ @Nullable private ImeTracker.Token mCurStatsToken; @@ -766,7 +766,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub *
* If this bit is ON, some of IME view, e.g. software input, candidate view, is visible. *
- * dt>{@link InputMethodService#IME_INVISIBLE} + *
{@link InputMethodService#IME_INVISIBLE}
*
If this bit is ON, IME is ready with views from last EditorInfo but is * currently invisible. *
@@ -1193,13 +1193,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } else if (accessibilityRequestingNoImeUri.equals(uri)) { final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser( mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, mUserId); + Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0 /* def */, mUserId); mAccessibilityRequestingNoSoftKeyboard = (accessibilitySoftKeyboardSetting & AccessibilityService.SHOW_MODE_MASK) == AccessibilityService.SHOW_MODE_HIDDEN; if (mAccessibilityRequestingNoSoftKeyboard) { final boolean showRequested = mShowRequested; - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, + 0 /* flags */, null /* resultReceiver */, SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE); mShowRequested = showRequested; } else if (mShowRequested) { @@ -1669,8 +1670,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } // Hide soft input before user switch task since switch task may block main handler a while // and delayed the hideCurrentInputLocked(). - hideCurrentInputLocked( - mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_SWITCH_USER); + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_SWITCH_USER); final UserSwitchHandlerTask task = new UserSwitchHandlerTask(this, userId, clientToBeReset); mUserSwitchHandlerTask = task; @@ -2225,7 +2226,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } final ClientDeathRecipient deathRecipient = new ClientDeathRecipient(this, client); try { - client.asBinder().linkToDeath(deathRecipient, 0); + client.asBinder().linkToDeath(deathRecipient, 0 /* flags */); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -2250,7 +2251,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { ClientState cs = mClients.remove(client.asBinder()); if (cs != null) { - client.asBinder().unlinkToDeath(cs.mClientDeathRecipient, 0); + client.asBinder().unlinkToDeath(cs.mClientDeathRecipient, 0 /* flags */); clearClientSessionLocked(cs); clearClientSessionForAccessibilityLocked(cs); @@ -2263,8 +2264,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } if (mCurClient == cs) { - hideCurrentInputLocked( - mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_REMOVE_CLIENT); + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_REMOVE_CLIENT); if (mBoundToMethod) { mBoundToMethod = false; IInputMethodInvoker curMethod = getCurMethodLocked(); @@ -2385,21 +2386,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub navButtonFlags, mCurImeDispatcher); if (mShowRequested) { if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); - final ImeTracker.Token statsToken; - if (mCurStatsToken != null) { - statsToken = mCurStatsToken; - mCurStatsToken = null; - } else { - String packageName = null; - if (mCurEditorInfo != null) { - packageName = mCurEditorInfo.packageName; - } - statsToken = new ImeTracker.Token(packageName); - ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_START_INPUT, - SoftInputShowHideReason.ATTACH_NEW_INPUT); - } - showCurrentInputLocked(mCurFocusedWindow, statsToken, - getAppShowFlagsLocked(), null, SoftInputShowHideReason.ATTACH_NEW_INPUT); + // Re-use current statsToken, if it exists. + final ImeTracker.Token statsToken = mCurStatsToken; + mCurStatsToken = null; + showCurrentInputLocked(mCurFocusedWindow, statsToken, getAppShowFlagsLocked(), + null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT); } String curId = getCurIdLocked(); @@ -2518,7 +2509,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (mDisplayIdToShowIme == INVALID_DISPLAY) { mImeHiddenByDisplayPolicy = true; - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE); return InputBindResult.NO_IME; } @@ -3290,6 +3282,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub "InputMethodManagerService#showSoftInput"); synchronized (ImfLock.class) { if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED); return false; } final long ident = Binder.clearCallingIdentity(); @@ -3379,6 +3372,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private boolean showCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken, int flags, int lastClickToolType, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { + // Create statsToken is none exists. + if (statsToken == null) { + String packageName = null; + if (mCurEditorInfo != null) { + packageName = mCurEditorInfo.packageName; + } + statsToken = new ImeTracker.Token(packageName); + ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_SERVER_START_INPUT, + reason); + } + mShowRequested = true; if (mAccessibilityRequestingNoSoftKeyboard || mImeHiddenByDisplayPolicy) { ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY); @@ -3433,13 +3437,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags, - ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { + public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, + @Nullable ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver, + @SoftInputShowHideReason int reason) { int uid = Binder.getCallingUid(); ImeTracing.getInstance().triggerManagerServiceDump( "InputMethodManagerService#hideSoftInput"); synchronized (ImfLock.class) { - if (!canInteractWithImeLocked(uid, client, "hideSoftInput", null /* statsToken */)) { + if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) { + if (mInputShown) { + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED); + } else { + ImeTracker.get().onCancelled(statsToken, + ImeTracker.PHASE_SERVER_CLIENT_FOCUSED); + } return false; } final long ident = Binder.clearCallingIdentity(); @@ -3447,7 +3458,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput"); if (DEBUG) Slog.v(TAG, "Client requesting input be hidden"); return InputMethodManagerService.this.hideCurrentInputLocked(windowToken, - flags, resultReceiver, reason); + statsToken, flags, resultReceiver, reason); } finally { Binder.restoreCallingIdentity(ident); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); @@ -3456,17 +3467,32 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("ImfLock.class") - boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver, - @SoftInputShowHideReason int reason) { + boolean hideCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken, + int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { + // Create statsToken is none exists. + if (statsToken == null) { + String packageName = null; + if (mCurEditorInfo != null) { + packageName = mCurEditorInfo.packageName; + } + statsToken = new ImeTracker.Token(packageName); + ImeTracker.get().onRequestHide(statsToken, ImeTracker.ORIGIN_SERVER_HIDE_INPUT, reason); + } + if ((flags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0 && (mShowExplicitlyRequested || mShowForced)) { if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide"); + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT); return false; } + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT); + if (mShowForced && (flags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) { if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide"); + ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS); return false; } + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS); // There is a chance that IMM#hideSoftInput() is called in a transient state where // IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting @@ -3477,8 +3503,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // IMMS#InputShown indicates that the software keyboard is shown. // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested. IInputMethodInvoker curMethod = getCurMethodLocked(); - final boolean shouldHideSoftInput = (curMethod != null) && (mInputShown - || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0); + final boolean shouldHideSoftInput = (curMethod != null) + && (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0); boolean res; if (shouldHideSoftInput) { final Binder hideInputToken = new Binder(); @@ -3487,17 +3513,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // delivered to the IME process as an IPC. Hence the inconsistency between // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in // the final state. + ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE); if (DEBUG) { Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken + ", " + resultReceiver + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); } // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not. - if (curMethod.hideSoftInput(hideInputToken, 0 /* flags */, resultReceiver)) { + if (curMethod.hideSoftInput(hideInputToken, statsToken, 0 /* flags */, + resultReceiver)) { onShowHideSoftInputRequested(false /* show */, windowToken, reason); } res = true; } else { + ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE); res = false; } mBindingController.setCurrentMethodNotVisible(); @@ -3505,8 +3534,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mShowRequested = false; mShowExplicitlyRequested = false; mShowForced = false; - // TODO: fail with HIDE phase here - ImeTracker.get().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME); + // Cancel existing statsToken for show IME as we got a hide request. + ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME); mCurStatsToken = null; return res; } @@ -3665,8 +3694,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Slog.w(TAG, "If you need to impersonate a foreground user/profile from" + " a background user, use EditorInfo.targetInputMethodUser with" + " INTERACT_ACROSS_USERS_FULL permission."); - hideCurrentInputLocked( - mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_INVALID_USER); + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_INVALID_USER); return InputBindResult.INVALID_USER; } @@ -3747,8 +3776,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // be behind any soft input window, so hide the // soft input window if it is shown. if (DEBUG) Slog.v(TAG, "Unspecified window will hide input"); - hideCurrentInputLocked( - mCurFocusedWindow, InputMethodManager.HIDE_NOT_ALWAYS, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, + InputMethodManager.HIDE_NOT_ALWAYS, null /* resultReceiver */, SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW); // If focused display changed, we should unbind current method @@ -3790,14 +3819,16 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub case LayoutParams.SOFT_INPUT_STATE_HIDDEN: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward"); - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV); } break; case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN: if (!sameWindowFocused) { if (DEBUG) Slog.v(TAG, "Window asks to hide input"); - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE); } break; @@ -3856,7 +3887,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // an editor upon refocusing a window. if (startInputByWinGainedFocus) { if (DEBUG) Slog.v(TAG, "Same window without editor will hide input"); - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, + 0 /* flags */, null /* resultReceiver */, SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR); } } @@ -3870,7 +3902,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // 2) SOFT_INPUT_STATE_VISIBLE state without an editor // 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor if (DEBUG) Slog.v(TAG, "Window without editor will hide input"); - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR); } res = startInputUncheckedLocked(cs, inputContext, @@ -3887,14 +3920,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private void showCurrentInputImplicitLocked(@NonNull IBinder windowToken, @SoftInputShowHideReason int reason) { - String packageName = null; - if (mCurEditorInfo != null) { - packageName = mCurEditorInfo.packageName; - } - final ImeTracker.Token statsToken = new ImeTracker.Token(packageName); - ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_START_INPUT, reason); - showCurrentInputLocked(windowToken, statsToken, InputMethodManager.SHOW_IMPLICIT, null, - reason); + showCurrentInputLocked(windowToken, null /* statsToken */, InputMethodManager.SHOW_IMPLICIT, + null /* resultReceiver */, reason); } @GuardedBy("ImfLock.class") @@ -3912,7 +3939,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN); if (!isImeClientFocused(mCurFocusedWindow, cs)) { - ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED); Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client)); return false; } @@ -4716,9 +4742,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } if (!setVisible) { if (mCurClient != null) { + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY); + mWindowManagerInternal.hideIme( mHideRequestWindowMap.get(windowToken), - mCurClient.mSelfReportedDisplayId); + mCurClient.mSelfReportedDisplayId, statsToken); + } else { + ImeTracker.get().onFailed(statsToken, + ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY); } } else { ImeTracker.get().onProgress(statsToken, @@ -4792,7 +4824,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } final long ident = Binder.clearCallingIdentity(); try { - hideCurrentInputLocked(mLastImeTargetWindow, flags, null, reason); + hideCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags, + null /* resultReceiver */, reason); } finally { Binder.restoreCallingIdentity(ident); } @@ -4809,14 +4842,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } final long ident = Binder.clearCallingIdentity(); try { - String packageName = null; - if (mCurEditorInfo != null) { - packageName = mCurEditorInfo.packageName; - } - final ImeTracker.Token statsToken = new ImeTracker.Token(packageName); - ImeTracker.get().onRequestShow(statsToken, ImeTracker.ORIGIN_START_INPUT, - SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME); - showCurrentInputLocked(mLastImeTargetWindow, statsToken, flags, null, + showCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags, + null /* resultReceiver */, SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME); } finally { Binder.restoreCallingIdentity(ident); @@ -4907,7 +4934,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub case MSG_HIDE_CURRENT_INPUT_METHOD: synchronized (ImfLock.class) { final @SoftInputShowHideReason int reason = (int) msg.obj; - hideCurrentInputLocked(mCurFocusedWindow, 0, null, reason); + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, + null /* resultReceiver */, reason); } return true; @@ -6394,7 +6422,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final String nextIme; final List nextEnabledImes; if (userId == mSettings.getCurrentUserId()) { - hideCurrentInputLocked(mCurFocusedWindow, 0, null, + hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, + 0 /* flags */, null /* resultReceiver */, SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND); mBindingController.unbindCurrentMethod(); // Reset the current IME diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2311b2a47da3..12efe0dc074f 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -6713,7 +6713,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mRemoteInsetsController.insetsControlChanged(stateController.getRawInsetsState(), stateController.getControlsForDispatch(this)); } catch (RemoteException e) { - Slog.w(TAG, "Failed to deliver inset state change", e); + Slog.w(TAG, "Failed to deliver inset control state change", e); } } @@ -6722,21 +6722,26 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @Nullable ImeTracker.Token statsToken) { try { ImeTracker.get().onProgress(statsToken, - ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET); + ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS); mRemoteInsetsController.showInsets(types, fromIme, statsToken); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver showInsets", e); ImeTracker.get().onFailed(statsToken, - ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET); + ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS); } } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) { + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { try { - mRemoteInsetsController.hideInsets(types, fromIme); + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS); + mRemoteInsetsController.hideInsets(types, fromIme, statsToken); } catch (RemoteException e) { - Slog.w(TAG, "Failed to deliver showInsets", e); + Slog.w(TAG, "Failed to deliver hideInsets", e); + ImeTracker.get().onFailed(statsToken, + ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS); } } diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 5680d1700078..7fd093fffe95 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -51,7 +51,7 @@ import java.io.PrintWriter; */ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider { - /** The token tracking the current IME show request or {@code null} otherwise. */ + /** The token tracking the current IME request or {@code null} otherwise. */ @Nullable private ImeTracker.Token mImeRequesterStatsToken; private InsetsControlTarget mImeRequester; @@ -171,7 +171,7 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider * when {@link android.inputmethodservice.InputMethodService} requests to show IME * on {@param imeTarget}. * - * @param imeTarget imeTarget on which IME request is coming from. + * @param imeTarget imeTarget on which IME show request is coming from. * @param statsToken the token tracking the current IME show request or {@code null} otherwise. */ void scheduleShowImePostLayout(InsetsControlTarget imeTarget, @@ -255,9 +255,8 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider mImeRequester = null; mIsImeLayoutDrawn = false; mShowImeRunner = null; - if (mImeRequesterStatsToken != null) { - ImeTracker.get().onFailed(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER); - } + ImeTracker.get().onCancelled(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER); + mImeRequesterStatsToken = null; } @VisibleForTesting diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java index 6aaa1c0e3087..8ecbc177896c 100644 --- a/services/core/java/com/android/server/wm/InsetsControlTarget.java +++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java @@ -70,8 +70,10 @@ interface InsetsControlTarget { * * @param types to specify which types of insets source window should be hidden. * @param fromIme {@code true} if IME hide request originated from {@link InputMethodService}. + * @param statsToken the token tracking the current IME hide request or {@code null} otherwise. */ - default void hideInsets(@InsetsType int types, boolean fromIme) { + default void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 9cc5e82712ae..bab3a0553e63 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -740,8 +740,10 @@ public abstract class WindowManagerInternal { * * @param imeTargetWindowToken token of the (IME target) window on which IME should be hidden. * @param displayId the id of the display the IME is on. + * @param statsToken the token tracking the current IME hide request or {@code null} otherwise. */ - public abstract void hideIme(IBinder imeTargetWindowToken, int displayId); + public abstract void hideIme(IBinder imeTargetWindowToken, int displayId, + @Nullable ImeTracker.Token statsToken); /** * Tell window manager about a package that should be running with a restricted range of diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a3889ee9805a..5485df6f6a34 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8025,8 +8025,8 @@ public class WindowManagerService extends IWindowManager.Stub Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0); final InsetsControlTarget controlTarget = imeTarget.getImeControlTarget(); imeTarget = controlTarget.getWindow(); - // If InsetsControlTarget doesn't have a window, its using remoteControlTarget which - // is controlled by default display + // If InsetsControlTarget doesn't have a window, it's using remoteControlTarget + // which is controlled by default display final DisplayContent dc = imeTarget != null ? imeTarget.getDisplayContent() : getDefaultDisplayContentLocked(); dc.getInsetsStateController().getImeSourceProvider() @@ -8035,7 +8035,8 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void hideIme(IBinder imeTargetWindowToken, int displayId) { + public void hideIme(IBinder imeTargetWindowToken, int displayId, + @Nullable ImeTracker.Token statsToken) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.hideIme"); synchronized (mGlobalLock) { WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); @@ -8051,10 +8052,15 @@ public class WindowManagerService extends IWindowManager.Stub dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout(); } if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) { + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ", dc.getImeTarget(IME_TARGET_CONTROL)); - dc.getImeTarget(IME_TARGET_CONTROL).hideInsets( - WindowInsets.Type.ime(), true /* fromIme */); + dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(WindowInsets.Type.ime(), + true /* fromIme */, statsToken); + } else { + ImeTracker.get().onFailed(statsToken, + ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); } if (dc != null) { dc.getInsetsStateController().getImeSourceProvider().setImeShowing(false); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 62a7a01561c4..b4c377745aba 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4016,7 +4016,7 @@ class WindowState extends WindowContainer implements WindowManagerP mClient.insetsControlChanged(getCompatInsetsState(), stateController.getControlsForDispatch(this)); } catch (RemoteException e) { - Slog.w(TAG, "Failed to deliver inset state change to w=" + this, e); + Slog.w(TAG, "Failed to deliver inset control state change to w=" + this, e); } } @@ -4029,18 +4029,27 @@ class WindowState extends WindowContainer implements WindowManagerP public void showInsets(@InsetsType int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) { try { + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS); mClient.showInsets(types, fromIme, statsToken); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver showInsets", e); + ImeTracker.get().onFailed(statsToken, + ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS); } } @Override - public void hideInsets(@InsetsType int types, boolean fromIme) { + public void hideInsets(@InsetsType int types, boolean fromIme, + @Nullable ImeTracker.Token statsToken) { try { - mClient.hideInsets(types, fromIme); + ImeTracker.get().onProgress(statsToken, + ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS); + mClient.hideInsets(types, fromIme, statsToken); } catch (RemoteException e) { - Slog.w(TAG, "Failed to deliver showInsets", e); + Slog.w(TAG, "Failed to deliver hideInsets", e); + ImeTracker.get().onFailed(statsToken, + ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS); } } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java index 1f0d58504242..640bde330cee 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java @@ -254,6 +254,6 @@ public class InputMethodManagerServiceTestBase { .setCurrentMethodNotVisible(); } verify(mMockInputMethod, times(hideSoftInput ? 1 : 0)) - .hideSoftInput(any(), anyInt(), any()); + .hideSoftInput(any(), any(), anyInt(), any()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index dfbbfb7d8cfd..6e72bf360295 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -124,6 +124,7 @@ public class TestIWindow extends IWindow.Stub { } @Override - public void hideInsets(int types, boolean fromIme) throws RemoteException { + public void hideInsets(int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) + throws RemoteException { } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 100388dbb8df..ab042d15963b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -854,7 +854,8 @@ class WindowTestsBase extends SystemServiceTestsBase { } @Override - public void hideInsets(int i, boolean b) throws RemoteException { + public void hideInsets(int i, boolean b, @Nullable ImeTracker.Token t) + throws RemoteException { } @Override -- cgit v1.2.3-59-g8ed1b