diff options
| author | Feng Cao <fengcao@google.com> | 2020-02-28 11:39:56 -0800 |
|---|---|---|
| committer | Feng Cao <fengcao@google.com> | 2020-03-02 21:18:16 -0800 |
| commit | 7c85eb79a7434f011c6ab903cc0b945758711baf (patch) | |
| tree | dcaee11167dbd38ba8308ac44c3d7f3e7ec7b044 /core/java/android/inputmethodservice/InputMethodService.java | |
| parent | 543ff5f068ad3e6ae9057e11d26f58934e597dea (diff) | |
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
Diffstat (limited to 'core/java/android/inputmethodservice/InputMethodService.java')
| -rw-r--r-- | core/java/android/inputmethodservice/InputMethodService.java | 39 |
1 files changed, 33 insertions, 6 deletions
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) { |
