Merge changes from topic "150757314" into rvc-dev
* changes: Fixed deadlock in InlineSuggestionSession. Revert "Revert "Do not block autofill on waiting for the IME response""
This commit is contained in:
committed by
Android (Google) Code Review
commit
07dbadcd14
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -38,11 +39,8 @@ import com.android.server.inputmethod.InputMethodManagerInternal;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CancellationException;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.function.Consumer;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains an autofill inline suggestion session that communicates with the IME.
|
* Maintains an autofill inline suggestion session that communicates with the IME.
|
||||||
@@ -64,12 +62,12 @@ import java.util.concurrent.TimeoutException;
|
|||||||
* side flow.
|
* side flow.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This class is thread safe.
|
* This class should hold the same lock as {@link Session} as they call into each other.
|
||||||
*/
|
*/
|
||||||
final class InlineSuggestionSession {
|
final class InlineSuggestionSession {
|
||||||
|
|
||||||
private static final String TAG = "AfInlineSuggestionSession";
|
private static final String TAG = "AfInlineSuggestionSession";
|
||||||
private static final int INLINE_REQUEST_TIMEOUT_MS = 1000;
|
private static final int INLINE_REQUEST_TIMEOUT_MS = 200;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final InputMethodManagerInternal mInputMethodManagerInternal;
|
private final InputMethodManagerInternal mInputMethodManagerInternal;
|
||||||
@@ -80,6 +78,8 @@ final class InlineSuggestionSession {
|
|||||||
private final Object mLock;
|
private final Object mLock;
|
||||||
@NonNull
|
@NonNull
|
||||||
private final ImeStatusListener mImeStatusListener;
|
private final ImeStatusListener mImeStatusListener;
|
||||||
|
@NonNull
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To avoid the race condition, one should not access {@code mPendingImeResponse} without
|
* To avoid the race condition, one should not access {@code mPendingImeResponse} without
|
||||||
@@ -105,11 +105,12 @@ final class InlineSuggestionSession {
|
|||||||
private boolean mImeInputViewStarted = false;
|
private boolean mImeInputViewStarted = false;
|
||||||
|
|
||||||
InlineSuggestionSession(InputMethodManagerInternal inputMethodManagerInternal,
|
InlineSuggestionSession(InputMethodManagerInternal inputMethodManagerInternal,
|
||||||
int userId, ComponentName componentName) {
|
int userId, ComponentName componentName, Handler handler, Object lock) {
|
||||||
mInputMethodManagerInternal = inputMethodManagerInternal;
|
mInputMethodManagerInternal = inputMethodManagerInternal;
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
mComponentName = componentName;
|
mComponentName = componentName;
|
||||||
mLock = new Object();
|
mHandler = handler;
|
||||||
|
mLock = lock;
|
||||||
mImeStatusListener = new ImeStatusListener() {
|
mImeStatusListener = new ImeStatusListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onInputMethodStartInputView(AutofillId imeFieldId) {
|
public void onInputMethodStartInputView(AutofillId imeFieldId) {
|
||||||
@@ -137,7 +138,8 @@ final class InlineSuggestionSession {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreateInlineSuggestionsRequest(@NonNull AutofillId autofillId) {
|
public void onCreateInlineSuggestionsRequest(@NonNull AutofillId autofillId,
|
||||||
|
@NonNull Consumer<InlineSuggestionsRequest> requestConsumer) {
|
||||||
if (sDebug) Log.d(TAG, "onCreateInlineSuggestionsRequest called for " + autofillId);
|
if (sDebug) Log.d(TAG, "onCreateInlineSuggestionsRequest called for " + autofillId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -154,26 +156,16 @@ final class InlineSuggestionSession {
|
|||||||
mUserId,
|
mUserId,
|
||||||
new InlineSuggestionsRequestInfo(mComponentName, autofillId, new Bundle()),
|
new InlineSuggestionsRequestInfo(mComponentName, autofillId, new Bundle()),
|
||||||
new InlineSuggestionsRequestCallbackImpl(mPendingImeResponse,
|
new InlineSuggestionsRequestCallbackImpl(mPendingImeResponse,
|
||||||
mImeStatusListener));
|
mImeStatusListener, requestConsumer, mHandler, mLock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<InlineSuggestionsRequest> waitAndGetInlineSuggestionsRequest() {
|
public Optional<InlineSuggestionsRequest> getInlineSuggestionsRequest() {
|
||||||
final CompletableFuture<ImeResponse> pendingImeResponse = getPendingImeResponse();
|
final CompletableFuture<ImeResponse> pendingImeResponse = getPendingImeResponse();
|
||||||
if (pendingImeResponse == null) {
|
if (pendingImeResponse == null || !pendingImeResponse.isDone()) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
try {
|
return Optional.ofNullable(pendingImeResponse.getNow(null)).map(ImeResponse::getRequest);
|
||||||
return Optional.ofNullable(pendingImeResponse.get(INLINE_REQUEST_TIMEOUT_MS,
|
|
||||||
TimeUnit.MILLISECONDS)).map(ImeResponse::getRequest);
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
Log.w(TAG, "Exception getting inline suggestions request in time: " + e);
|
|
||||||
} catch (CancellationException e) {
|
|
||||||
Log.w(TAG, "Inline suggestions request cancelled");
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hideInlineSuggestionsUi(@NonNull AutofillId autofillId) {
|
public boolean hideInlineSuggestionsUi(@NonNull AutofillId autofillId) {
|
||||||
@@ -200,8 +192,7 @@ final class InlineSuggestionSession {
|
|||||||
if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked without IMS request");
|
if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked without IMS request");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// There is no need to wait on the CompletableFuture since it should have been completed
|
// There is no need to wait on the CompletableFuture since it should have been completed.
|
||||||
// when {@link #waitAndGetInlineSuggestionsRequest()} was called.
|
|
||||||
ImeResponse imeResponse = completedImsResponse.getNow(null);
|
ImeResponse imeResponse = completedImsResponse.getNow(null);
|
||||||
if (imeResponse == null) {
|
if (imeResponse == null) {
|
||||||
if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked with pending IMS response");
|
if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked with pending IMS response");
|
||||||
@@ -249,20 +240,48 @@ final class InlineSuggestionSession {
|
|||||||
private static final class InlineSuggestionsRequestCallbackImpl
|
private static final class InlineSuggestionsRequestCallbackImpl
|
||||||
extends IInlineSuggestionsRequestCallback.Stub {
|
extends IInlineSuggestionsRequestCallback.Stub {
|
||||||
|
|
||||||
|
private final Object mLock;
|
||||||
|
@GuardedBy("mLock")
|
||||||
private final CompletableFuture<ImeResponse> mResponse;
|
private final CompletableFuture<ImeResponse> mResponse;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final Consumer<InlineSuggestionsRequest> mRequestConsumer;
|
||||||
private final ImeStatusListener mImeStatusListener;
|
private final ImeStatusListener mImeStatusListener;
|
||||||
|
private final Handler mHandler;
|
||||||
|
private final Runnable mTimeoutCallback;
|
||||||
|
|
||||||
private InlineSuggestionsRequestCallbackImpl(CompletableFuture<ImeResponse> response,
|
private InlineSuggestionsRequestCallbackImpl(CompletableFuture<ImeResponse> response,
|
||||||
ImeStatusListener imeStatusListener) {
|
ImeStatusListener imeStatusListener,
|
||||||
|
Consumer<InlineSuggestionsRequest> requestConsumer,
|
||||||
|
Handler handler, Object lock) {
|
||||||
mResponse = response;
|
mResponse = response;
|
||||||
mImeStatusListener = imeStatusListener;
|
mImeStatusListener = imeStatusListener;
|
||||||
|
mRequestConsumer = requestConsumer;
|
||||||
|
mLock = lock;
|
||||||
|
|
||||||
|
mHandler = handler;
|
||||||
|
mTimeoutCallback = () -> {
|
||||||
|
Log.w(TAG, "Timed out waiting for IME callback InlineSuggestionsRequest.");
|
||||||
|
completeIfNot(null);
|
||||||
|
};
|
||||||
|
mHandler.postDelayed(mTimeoutCallback, INLINE_REQUEST_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void completeIfNot(@Nullable ImeResponse response) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mResponse.isDone()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mResponse.complete(response);
|
||||||
|
mRequestConsumer.accept(response == null ? null : response.mRequest);
|
||||||
|
mHandler.removeCallbacks(mTimeoutCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@BinderThread
|
@BinderThread
|
||||||
@Override
|
@Override
|
||||||
public void onInlineSuggestionsUnsupported() throws RemoteException {
|
public void onInlineSuggestionsUnsupported() throws RemoteException {
|
||||||
if (sDebug) Log.d(TAG, "onInlineSuggestionsUnsupported() called.");
|
if (sDebug) Log.d(TAG, "onInlineSuggestionsUnsupported() called.");
|
||||||
mResponse.complete(null);
|
completeIfNot(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BinderThread
|
@BinderThread
|
||||||
@@ -281,9 +300,9 @@ final class InlineSuggestionSession {
|
|||||||
mImeStatusListener.onInputMethodFinishInputView(imeFieldId);
|
mImeStatusListener.onInputMethodFinishInputView(imeFieldId);
|
||||||
}
|
}
|
||||||
if (request != null && callback != null) {
|
if (request != null && callback != null) {
|
||||||
mResponse.complete(new ImeResponse(request, callback));
|
completeIfNot(new ImeResponse(request, callback));
|
||||||
} else {
|
} else {
|
||||||
mResponse.complete(null);
|
completeIfNot(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,9 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A session for a given activity.
|
* A session for a given activity.
|
||||||
@@ -307,7 +309,47 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
/**
|
/**
|
||||||
* Receiver of assist data from the app's {@link Activity}.
|
* Receiver of assist data from the app's {@link Activity}.
|
||||||
*/
|
*/
|
||||||
private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() {
|
private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl();
|
||||||
|
|
||||||
|
private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private InlineSuggestionsRequest mPendingInlineSuggestionsRequest;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private FillRequest mPendingFillRequest;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private CountDownLatch mCountDownLatch;
|
||||||
|
|
||||||
|
@Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(
|
||||||
|
boolean isInlineRequest) {
|
||||||
|
mCountDownLatch = new CountDownLatch(isInlineRequest ? 2 : 1);
|
||||||
|
mPendingFillRequest = null;
|
||||||
|
mPendingInlineSuggestionsRequest = null;
|
||||||
|
return isInlineRequest ? (inlineSuggestionsRequest) -> {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
|
||||||
|
mCountDownLatch.countDown();
|
||||||
|
maybeRequestFillLocked();
|
||||||
|
}
|
||||||
|
} : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void maybeRequestFillLocked() {
|
||||||
|
if (mCountDownLatch == null || mCountDownLatch.getCount() > 0
|
||||||
|
|| mPendingFillRequest == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mPendingInlineSuggestionsRequest != null) {
|
||||||
|
mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
|
||||||
|
mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(),
|
||||||
|
mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
|
||||||
|
}
|
||||||
|
mRemoteFillService.onFillRequest(mPendingFillRequest);
|
||||||
|
mPendingInlineSuggestionsRequest = null;
|
||||||
|
mPendingFillRequest = null;
|
||||||
|
mCountDownLatch = null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onHandleAssistData(Bundle resultData) throws RemoteException {
|
public void onHandleAssistData(Bundle resultData) throws RemoteException {
|
||||||
if (mRemoteFillService == null) {
|
if (mRemoteFillService == null) {
|
||||||
@@ -402,17 +444,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
|
|
||||||
final ArrayList<FillContext> contexts =
|
final ArrayList<FillContext> contexts =
|
||||||
mergePreviousSessionLocked(/* forSave= */ false);
|
mergePreviousSessionLocked(/* forSave= */ false);
|
||||||
|
|
||||||
final Optional<InlineSuggestionsRequest> inlineSuggestionsRequest =
|
|
||||||
mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest();
|
|
||||||
request = new FillRequest(requestId, contexts, mClientState, flags,
|
request = new FillRequest(requestId, contexts, mClientState, flags,
|
||||||
inlineSuggestionsRequest.orElse(null));
|
/*inlineSuggestionsRequest=*/null);
|
||||||
|
|
||||||
|
mPendingFillRequest = request;
|
||||||
|
mCountDownLatch.countDown();
|
||||||
|
maybeRequestFillLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mActivityToken != null) {
|
if (mActivityToken != null) {
|
||||||
mService.sendActivityAssistDataToContentCapture(mActivityToken, resultData);
|
mService.sendActivityAssistDataToContentCapture(mActivityToken, resultData);
|
||||||
}
|
}
|
||||||
mRemoteFillService.onFillRequest(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -605,9 +647,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
private void maybeRequestInlineSuggestionsRequestThenFillLocked(@NonNull ViewState viewState,
|
private void maybeRequestInlineSuggestionsRequestThenFillLocked(@NonNull ViewState viewState,
|
||||||
int newState, int flags) {
|
int newState, int flags) {
|
||||||
if (isInlineSuggestionsEnabledLocked()) {
|
if (isInlineSuggestionsEnabledLocked()) {
|
||||||
mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId);
|
Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
|
||||||
|
mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ true);
|
||||||
|
if (inlineSuggestionsRequestConsumer != null) {
|
||||||
|
mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId,
|
||||||
|
inlineSuggestionsRequestConsumer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestNewFillResponseLocked(viewState, newState, flags);
|
requestNewFillResponseLocked(viewState, newState, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,7 +756,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
setClientLocked(client);
|
setClientLocked(client);
|
||||||
|
|
||||||
mInlineSuggestionSession = new InlineSuggestionSession(inputMethodManagerInternal, userId,
|
mInlineSuggestionSession = new InlineSuggestionSession(inputMethodManagerInternal, userId,
|
||||||
componentName);
|
componentName, handler, mLock);
|
||||||
|
|
||||||
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
|
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
|
||||||
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
|
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
|
||||||
@@ -2663,7 +2711,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
private boolean requestShowInlineSuggestionsLocked(@NonNull FillResponse response,
|
private boolean requestShowInlineSuggestionsLocked(@NonNull FillResponse response,
|
||||||
@Nullable String filterText) {
|
@Nullable String filterText) {
|
||||||
final Optional<InlineSuggestionsRequest> inlineSuggestionsRequest =
|
final Optional<InlineSuggestionsRequest> inlineSuggestionsRequest =
|
||||||
mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest();
|
mInlineSuggestionSession.getInlineSuggestionsRequest();
|
||||||
if (!inlineSuggestionsRequest.isPresent()) {
|
if (!inlineSuggestionsRequest.isPresent()) {
|
||||||
Log.w(TAG, "InlineSuggestionsRequest unavailable");
|
Log.w(TAG, "InlineSuggestionsRequest unavailable");
|
||||||
return false;
|
return false;
|
||||||
@@ -2896,6 +2944,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
/**
|
/**
|
||||||
* Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
|
* Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
|
||||||
*
|
*
|
||||||
|
* <p> The request may not have been sent when this method returns as it may be waiting for
|
||||||
|
* the inline suggestion request asynchronously.
|
||||||
|
*
|
||||||
* @return callback to destroy the autofill UI, or {@code null} if not supported.
|
* @return callback to destroy the autofill UI, or {@code null} if not supported.
|
||||||
*/
|
*/
|
||||||
// TODO(b/123099468): might need to call it in other places, like when the service returns a
|
// TODO(b/123099468): might need to call it in other places, like when the service returns a
|
||||||
@@ -2978,6 +3029,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
|
|
||||||
final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId);
|
final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId);
|
||||||
|
|
||||||
|
final Consumer<InlineSuggestionsRequest> requestAugmentedAutofill =
|
||||||
|
(inlineSuggestionsRequest) -> {
|
||||||
|
remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName,
|
||||||
|
focusedId,
|
||||||
|
currentValue, inlineSuggestionsRequest,
|
||||||
|
/*inlineSuggestionsCallback=*/
|
||||||
|
response -> mInlineSuggestionSession.onInlineSuggestionsResponse(
|
||||||
|
mCurrentViewId, response),
|
||||||
|
/*onErrorCallback=*/ () -> {
|
||||||
|
synchronized (mLock) {
|
||||||
|
cancelAugmentedAutofillLocked();
|
||||||
|
}
|
||||||
|
}, mService.getRemoteInlineSuggestionRenderServiceLocked());
|
||||||
|
};
|
||||||
|
|
||||||
// There are 3 cases when augmented autofill should ask IME for a new request:
|
// There are 3 cases when augmented autofill should ask IME for a new request:
|
||||||
// 1. standard autofill provider is None
|
// 1. standard autofill provider is None
|
||||||
// 2. standard autofill provider doesn't support inline (and returns null response)
|
// 2. standard autofill provider doesn't support inline (and returns null response)
|
||||||
@@ -2985,21 +3051,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
// doesn't want autofill
|
// doesn't want autofill
|
||||||
if (mForAugmentedAutofillOnly || !isInlineSuggestionsEnabledLocked()) {
|
if (mForAugmentedAutofillOnly || !isInlineSuggestionsEnabledLocked()) {
|
||||||
if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
|
if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
|
||||||
mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId);
|
mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId,
|
||||||
|
/*requestConsumer=*/ requestAugmentedAutofill);
|
||||||
|
} else {
|
||||||
|
requestAugmentedAutofill.accept(
|
||||||
|
mInlineSuggestionSession.getInlineSuggestionsRequest().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<InlineSuggestionsRequest> inlineSuggestionsRequest =
|
|
||||||
mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest();
|
|
||||||
remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, focusedId,
|
|
||||||
currentValue, inlineSuggestionsRequest.orElse(null),
|
|
||||||
response -> mInlineSuggestionSession.onInlineSuggestionsResponse(
|
|
||||||
mCurrentViewId, response),
|
|
||||||
() -> {
|
|
||||||
synchronized (mLock) {
|
|
||||||
cancelAugmentedAutofillLocked();
|
|
||||||
}
|
|
||||||
}, mService.getRemoteInlineSuggestionRenderServiceLocked());
|
|
||||||
|
|
||||||
if (mAugmentedAutofillDestroyer == null) {
|
if (mAugmentedAutofillDestroyer == null) {
|
||||||
mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
|
mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user