diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java index 0de523c5f3f62..c4ff4ac6c981c 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -313,6 +313,7 @@ final class InputMethodBindingController { mSupportsStylusHw); mService.scheduleNotifyImeUidToAudioService(mCurMethodUid); mService.reRequestCurrentClientSessionLocked(); + mService.performOnCreateInlineSuggestionsRequestLocked(); } // reset Handwriting event receiver. diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 3c3140551bc31..bcebcb4c74d4d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -286,6 +286,30 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @NonNull private final Set mNonPreemptibleInputMethods; + private static final class CreateInlineSuggestionsRequest { + @NonNull final InlineSuggestionsRequestInfo mRequestInfo; + @NonNull final IInlineSuggestionsRequestCallback mCallback; + @NonNull final String mPackageName; + + CreateInlineSuggestionsRequest( + @NonNull InlineSuggestionsRequestInfo requestInfo, + @NonNull IInlineSuggestionsRequestCallback callback, + @NonNull String packageName) { + mRequestInfo = requestInfo; + mCallback = callback; + mPackageName = packageName; + } + } + + /** + * If a request to create inline autofill suggestions comes in while the IME is unbound + * due to {@link #mPreventImeStartupUnlessTextEditor}, this is where it is stored, so + * that it may be fulfilled once the IME rebinds. + */ + @GuardedBy("ImfLock.class") + @Nullable + private CreateInlineSuggestionsRequest mPendingInlineSuggestionsRequest; + @UserIdInt private int mLastSwitchUserId; @@ -2137,16 +2161,24 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId, InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback, boolean touchExplorationEnabled) { + clearPendingInlineSuggestionsRequestLocked(); final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked()); try { - IInputMethodInvoker curMethod = getCurMethodLocked(); - if (userId == mSettings.getCurrentUserId() && curMethod != null + if (userId == mSettings.getCurrentUserId() && imi != null && isInlineSuggestionsEnabled(imi, touchExplorationEnabled)) { - final IInlineSuggestionsRequestCallback callbackImpl = - new InlineSuggestionsRequestCallbackDecorator(callback, - imi.getPackageName(), mCurTokenDisplayId, getCurTokenLocked(), - this); - curMethod.onCreateInlineSuggestionsRequest(requestInfo, callbackImpl); + mPendingInlineSuggestionsRequest = new CreateInlineSuggestionsRequest( + requestInfo, callback, imi.getPackageName()); + if (getCurMethodLocked() != null) { + // In the normal case when the IME is connected, we can make the request here. + performOnCreateInlineSuggestionsRequestLocked(); + } else { + // Otherwise, the next time the IME connection is established, + // InputMethodBindingController.mMainConnection#onServiceConnected() will call + // into #performOnCreateInlineSuggestionsRequestLocked() to make the request. + if (DEBUG) { + Slog.d(TAG, "IME not connected. Delaying inline suggestions request."); + } + } } else { callback.onInlineSuggestionsUnsupported(); } @@ -2155,6 +2187,34 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } } + @GuardedBy("ImfLock.class") + void performOnCreateInlineSuggestionsRequestLocked() { + if (mPendingInlineSuggestionsRequest == null) { + return; + } + IInputMethodInvoker curMethod = getCurMethodLocked(); + if (DEBUG) { + Slog.d(TAG, "Performing onCreateInlineSuggestionsRequest. mCurMethod = " + curMethod); + } + if (curMethod != null) { + final IInlineSuggestionsRequestCallback callback = + new InlineSuggestionsRequestCallbackDecorator( + mPendingInlineSuggestionsRequest.mCallback, + mPendingInlineSuggestionsRequest.mPackageName, + mCurTokenDisplayId, getCurTokenLocked(), this); + curMethod.onCreateInlineSuggestionsRequest( + mPendingInlineSuggestionsRequest.mRequestInfo, callback); + } else { + Slog.w(TAG, "No IME connected! Abandoning inline suggestions creation request."); + } + clearPendingInlineSuggestionsRequestLocked(); + } + + @GuardedBy("ImfLock.class") + private void clearPendingInlineSuggestionsRequestLocked() { + mPendingInlineSuggestionsRequest = null; + } + private static boolean isInlineSuggestionsEnabled(InputMethodInfo imi, boolean touchExplorationEnabled) { return imi.isInlineSuggestionsEnabled()