From 7c85eb79a7434f011c6ab903cc0b945758711baf Mon Sep 17 00:00:00 2001 From: Feng Cao Date: Fri, 28 Feb 2020 11:39:56 -0800 Subject: Notify autofill with the IME start/finish input view events * autofill will cache the inline suggestions response until it receives a start input view event from IME * the data flow from IMS point of view is: IMS#startViews and IMS#doStartInput (before calling onStartInputView) -> [async] InlineSuggestionsRequestCallback#onInputMethodStartInputView() --- process boundary --- -> IMMS.InlineSuggestionsRequestCallbackDecorator #onInputMethodStartInputView() -> InlineSuggestionSession.InlineSuggestionsRequestCallbackImpl #onInputMethodStartInputView() * similar data flow for IMS#finishViews() * this CL should not block IME's UI thread because it's only issuing a new async IPC from IMS start/finish input view call that's running on the UI thread. * there should not be performance impact on IMEs if autofill inline integration is not active Test: manual verification, atest EditorInfoTest Test: atest android.autofillservice.cts.inline, with two failing cases: InlineAugmentedLoginActivityTest#testAugmentedAutoFill_twoDatasetThenFilledSecond and InlineAugmentedLoginActivityTest#testAugmentedAutoFill_oneDatasetThenFilled due to the test itself being broken, I'll fix the test in a separate patch Bug: 149522488 Bug: 149442582 Change-Id: I2faa3577b9f95a122f26a6d7fa7822a769a51e34 --- .../inputmethodservice/InputMethodService.java | 39 ++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'core/java/android/inputmethodservice/InputMethodService.java') diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index d27d1382e09d..9e639346de73 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -444,6 +444,16 @@ public class InputMethodService extends AbstractInputMethodService { final Insets mTmpInsets = new Insets(); final int[] mTmpLocation = new int[2]; + /** + * We use a separate {@code mInlineLock} to make sure {@code mInlineSuggestionSession} is + * only accessed synchronously. Although when the lock is introduced, all the calls are from + * the main thread so the lock is not really necessarily (but for the same reason it also + * doesn't hurt), it's still being added as a safety guard to make sure in the future we + * don't add more code causing race condition when updating the {@code + * mInlineSuggestionSession}. + */ + private final Object mInlineLock = new Object(); + @GuardedBy("mInlineLock") @Nullable private InlineSuggestionSession mInlineSuggestionSession; @@ -822,13 +832,15 @@ public class InputMethodService extends AbstractInputMethodService { return; } - if (mInlineSuggestionSession != null) { - mInlineSuggestionSession.invalidateSession(); + synchronized (mInlineLock) { + if (mInlineSuggestionSession != null) { + mInlineSuggestionSession.invalidateSession(); + } + mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(), + callback, this::getEditorInfoPackageName, this::getEditorInfoAutofillId, + () -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()), + this::getHostInputToken, this::onInlineSuggestionsResponse, mInputViewStarted); } - mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(), - callback, this::getEditorInfoPackageName, this::getEditorInfoAutofillId, - () -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()), - this::getHostInputToken, this::onInlineSuggestionsResponse); } @Nullable @@ -2193,6 +2205,11 @@ public class InputMethodService extends AbstractInputMethodService { if (!mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); mInputViewStarted = true; + synchronized (mInlineLock) { + if (mInlineSuggestionSession != null) { + mInlineSuggestionSession.notifyOnStartInputView(getEditorInfoAutofillId()); + } + } onStartInputView(mInputEditorInfo, false); } } else if (!mCandidatesViewStarted) { @@ -2233,6 +2250,11 @@ public class InputMethodService extends AbstractInputMethodService { private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); + synchronized (mInlineLock) { + if (mInlineSuggestionSession != null) { + mInlineSuggestionSession.notifyOnFinishInputView(getEditorInfoAutofillId()); + } + } onFinishInputView(finishingInput); } else if (mCandidatesViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView"); @@ -2345,6 +2367,11 @@ public class InputMethodService extends AbstractInputMethodService { if (mShowInputRequested) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); mInputViewStarted = true; + synchronized (mInlineLock) { + if (mInlineSuggestionSession != null) { + mInlineSuggestionSession.notifyOnStartInputView(getEditorInfoAutofillId()); + } + } onStartInputView(mInputEditorInfo, restarting); startExtractingText(true); } else if (mCandidatesVisibility == View.VISIBLE) { -- cgit v1.2.3