summaryrefslogtreecommitdiff
path: root/core/java/android/inputmethodservice/InputMethodService.java
diff options
context:
space:
mode:
authorFeng Cao <fengcao@google.com>2020-02-28 11:39:56 -0800
committerFeng Cao <fengcao@google.com>2020-03-02 21:18:16 -0800
commit7c85eb79a7434f011c6ab903cc0b945758711baf (patch)
treedcaee11167dbd38ba8308ac44c3d7f3e7ec7b044 /core/java/android/inputmethodservice/InputMethodService.java
parent543ff5f068ad3e6ae9057e11d26f58934e597dea (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.java39
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) {