diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | api/test-current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/service/autofill/AutofillService.java | 7 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillCallback.java | 7 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillContext.java | 11 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillRequest.java | 25 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillResponse.java | 32 | ||||
| -rw-r--r-- | core/java/android/service/autofill/IFillCallback.aidl | 2 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/RemoteFillService.java | 26 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/Session.java | 209 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java | 10 |
12 files changed, 238 insertions, 97 deletions
diff --git a/api/current.txt b/api/current.txt index bd3d07a46549..58d617a00e7c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37084,9 +37084,9 @@ package android.service.autofill { public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); + method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts(); method public int getFlags(); method public int getId(); - method public android.app.assist.AssistStructure getStructure(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 diff --git a/api/system-current.txt b/api/system-current.txt index bcbd248c69e4..3723e7ea286a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40199,9 +40199,9 @@ package android.service.autofill { public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); + method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts(); method public int getFlags(); method public int getId(); - method public android.app.assist.AssistStructure getStructure(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 diff --git a/api/test-current.txt b/api/test-current.txt index 3ee9cb674b2d..9f7441c9124e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -37238,9 +37238,9 @@ package android.service.autofill { public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); + method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts(); method public int getFlags(); method public int getId(); - method public android.app.assist.AssistStructure getStructure(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index cb47c104ed9f..edb90983ae3e 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -34,6 +34,7 @@ import android.view.autofill.AutofillManager; import com.android.internal.os.SomeArgs; +import java.util.ArrayList; import java.util.List; /** @@ -118,8 +119,10 @@ public abstract class AutofillService extends Service { try { onFillRequest(request, cancellation, fillCallback); } catch (AbstractMethodError e) { - onFillRequest(request.getStructure(), request.getClientState(), - request.getFlags(), cancellation, fillCallback); + final ArrayList<FillContext> contexts = request.getFillContexts(); + onFillRequest(contexts.get(contexts.size() - 1).getStructure(), + request.getClientState(), request.getFlags(), cancellation, + fillCallback); } break; } case MSG_ON_SAVE_REQUEST: { diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java index 7774bdd4c410..105cd3867463 100644 --- a/core/java/android/service/autofill/FillCallback.java +++ b/core/java/android/service/autofill/FillCallback.java @@ -47,8 +47,13 @@ public final class FillCallback { public void onSuccess(@Nullable FillResponse response) { assertNotCalled(); mCalled = true; + + if (response != null) { + response.setRequestId(mRequestId); + } + try { - mCallback.onSuccess(response, mRequestId); + mCallback.onSuccess(response); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java index 2efa08c00969..8a28c45d145f 100644 --- a/core/java/android/service/autofill/FillContext.java +++ b/core/java/android/service/autofill/FillContext.java @@ -16,6 +16,8 @@ package android.service.autofill; +import static android.view.autofill.Helper.DEBUG; + import android.annotation.NonNull; import android.app.assist.AssistStructure; import android.os.Bundle; @@ -71,6 +73,15 @@ public final class FillContext implements Parcelable { } @Override + public String toString() { + if (!DEBUG) { + return super.toString(); + } else { + return "FillContext [mRequestId=" + mRequestId + "]"; + } + } + + @Override public int describeContents() { return 0; } diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index 49f348c79ef2..8ac399c776ec 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -19,16 +19,16 @@ package android.service.autofill; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.assist.AssistStructure; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Parcel; import android.os.Parcelable; + import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.ArrayList; /** * This class represents a request to an {@link AutofillService autofill provider} @@ -45,6 +45,9 @@ public final class FillRequest implements Parcelable { public static final int FLAG_MANUAL_REQUEST = 0x1; /** @hide */ + public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE; + + /** @hide */ @IntDef( flag = true, value = {FLAG_MANUAL_REQUEST}) @@ -53,22 +56,24 @@ public final class FillRequest implements Parcelable { private final int mId; private final @RequestFlags int mFlags; - private final @NonNull AssistStructure mStructure; + private final @NonNull ArrayList<FillContext> mContexts; private final @Nullable Bundle mClientState; private FillRequest(@NonNull Parcel parcel) { mId = parcel.readInt(); - mStructure = parcel.readParcelable(null); + mContexts = new ArrayList<>(); + parcel.readParcelableList(mContexts, null); + mClientState = parcel.readBundle(); mFlags = parcel.readInt(); } /** @hide */ - public FillRequest(int id, @NonNull AssistStructure structure, + public FillRequest(int id, @NonNull ArrayList<FillContext> contexts, @Nullable Bundle clientState, @RequestFlags int flags) { mId = id; mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST); - mStructure = Preconditions.checkNotNull(structure, "structure"); + mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts"); mClientState = clientState; } @@ -89,10 +94,10 @@ public final class FillRequest implements Parcelable { } /** - * @return The structure capturing the UI state. + * @return The contexts associated with each previous fill request. */ - public @NonNull AssistStructure getStructure() { - return mStructure; + public @NonNull ArrayList<FillContext> getFillContexts() { + return mContexts; } /** @@ -117,7 +122,7 @@ public final class FillRequest implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mId); - parcel.writeParcelable(mStructure, flags); + parcel.writeParcelableList(mContexts, flags); parcel.writeBundle(mClientState); parcel.writeInt(mFlags); } diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 2afb1f4fc9be..5c8f3cec9c59 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -16,6 +16,7 @@ package android.service.autofill; +import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static android.view.autofill.Helper.DEBUG; import android.annotation.NonNull; @@ -138,6 +139,7 @@ public final class FillResponse implements Parcelable { private final @Nullable IntentSender mAuthentication; private final @Nullable AutofillId[] mAuthenticationIds; private final @Nullable AutofillId[] mIgnoredIds; + private int mRequestId; private FillResponse(@NonNull Builder builder) { mDatasets = builder.mDatasets; @@ -147,6 +149,7 @@ public final class FillResponse implements Parcelable { mAuthentication = builder.mAuthentication; mAuthenticationIds = builder.mAuthenticationIds; mIgnoredIds = builder.mIgnoredIds; + mRequestId = INVALID_REQUEST_ID; } /** @hide */ @@ -185,6 +188,24 @@ public final class FillResponse implements Parcelable { } /** + * Associates a {@link FillResponse} to a request. + * + * <p>Set inside of the {@link FillCallback} code, not the {@link AutofillService}. + * + * @param requestId The id of the request to associate the response to. + * + * @hide + */ + public void setRequestId(int requestId) { + mRequestId = requestId; + } + + /** @hide */ + public int getRequestId() { + return mRequestId; + } + + /** * Builder for {@link FillResponse} objects. You must to provide at least * one dataset or set an authentication intent with a presentation view. */ @@ -376,7 +397,8 @@ public final class FillResponse implements Parcelable { if (!DEBUG) return super.toString(); return new StringBuilder( - "FillResponse: [datasets=").append(mDatasets) + "FillResponse : [mRequestId=" + mRequestId) + .append(", datasets=").append(mDatasets) .append(", saveInfo=").append(mSaveInfo) .append(", clientState=").append(mClientState != null) .append(", hasPresentation=").append(mPresentation != null) @@ -385,6 +407,7 @@ public final class FillResponse implements Parcelable { ? mAuthenticationIds.length : "N/A") .append(", ignoredIdsSize=").append(mIgnoredIds != null ? mIgnoredIds.length : "N/A") + .append("]") .toString(); } @@ -406,6 +429,7 @@ public final class FillResponse implements Parcelable { parcel.writeParcelable(mAuthentication, flags); parcel.writeParcelable(mPresentation, flags); parcel.writeParcelableArray(mIgnoredIds, flags); + parcel.writeInt(mRequestId); } public static final Parcelable.Creator<FillResponse> CREATOR = @@ -426,7 +450,11 @@ public final class FillResponse implements Parcelable { builder.setAuthentication(parcel.readParcelableArray(null, AutofillId.class), parcel.readParcelable(null), parcel.readParcelable(null)); builder.setIgnoredIds(parcel.readParcelableArray(null, AutofillId.class)); - return builder.build(); + final FillResponse response = builder.build(); + + response.setRequestId(parcel.readInt()); + + return response; } @Override diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl index 688ac84b9cd8..2bb3e9acd3e1 100644 --- a/core/java/android/service/autofill/IFillCallback.aidl +++ b/core/java/android/service/autofill/IFillCallback.aidl @@ -27,6 +27,6 @@ import android.service.autofill.FillResponse; */ interface IFillCallback { void onCancellable(in ICancellationSignal cancellation); - void onSuccess(in FillResponse response, int requestId); + void onSuccess(in FillResponse response); void onFailure(CharSequence message); } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 432a092a9874..2aeb07e1057b 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -16,6 +16,8 @@ package com.android.server.autofill; +import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; + import static com.android.server.autofill.Helper.DEBUG; import android.annotation.NonNull; @@ -88,7 +90,7 @@ final class RemoteFillService implements DeathRecipient { public interface FillServiceCallbacks { void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, - @NonNull String servicePackageName, int requestId); + @NonNull String servicePackageName); void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); void onSaveRequestSuccess(@NonNull String servicePackageName); @@ -139,16 +141,26 @@ final class RemoteFillService implements DeathRecipient { * * <p>This can be used when the request is unnecessary or will be superceeded by a request that * will soon be queued. + * + * @return the id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if no + * {@link PendingFillRequest} was canceled. */ - public void cancelCurrentRequest() { + public int cancelCurrentRequest() { if (mDestroyed) { - return; + return INVALID_REQUEST_ID; } + int requestId = INVALID_REQUEST_ID; if (mPendingRequest != null) { + if (mPendingRequest instanceof PendingFillRequest) { + requestId = ((PendingFillRequest) mPendingRequest).mRequest.getId(); + } + mPendingRequest.cancel(); mPendingRequest = null; } + + return requestId; } public void onFillRequest(@NonNull FillRequest request) { @@ -269,11 +281,11 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, - int callingUid, FillResponse response, int requestId) { + int callingUid, FillResponse response) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { mCallbacks.onFillRequestSuccess(response, callingUid, - mComponentName.getPackageName(), requestId); + mComponentName.getPackageName()); } }); } @@ -437,11 +449,11 @@ final class RemoteFillService implements DeathRecipient { } @Override - public void onSuccess(FillResponse response, int requestId) { + public void onSuccess(FillResponse response) { RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { remoteService.dispatchOnFillRequestSuccess( - PendingFillRequest.this, getCallingUid(), response, requestId); + PendingFillRequest.this, getCallingUid(), response); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index a00a397ece08..ac1f34d90b07 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -18,6 +18,7 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; +import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS; import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE; import static android.view.autofill.AutofillManager.FLAG_START_SESSION; @@ -152,11 +153,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private Dataset mDatasetWaitingAuth; /** - * Assist structure sent by the app; it will be updated (sanitized, change values for save) - * before sent to {@link AutofillService}. + * Contexts read from the app; they will be updated (sanitized, change values for save) before + * sent to {@link AutofillService}. Ordered by the time they we read. */ @GuardedBy("mLock") - private AssistStructure mStructure; + private ArrayList<FillContext> mContexts; /** * Whether the client has an {@link android.view.autofill.AutofillManager.AutofillCallback}. @@ -203,6 +204,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.d(TAG, "New structure for requestId " + requestId + ": " + structure); } + final FillRequest request; synchronized (mLock) { // TODO(b/35708678): Must fetch the data so it's available later on handleSave(), // even if if the activity is gone by then, but structure .ensureData() gives a @@ -214,12 +216,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Sanitize structure before it's sent to service. structure.sanitizeForParceling(true); - mStructure = structure; - } + if (mContexts == null) { + mContexts = new ArrayList<>(1); + } + mContexts.add(new FillContext(requestId, structure)); + + cancelCurrentRequestLocked(); + + final int numContexts = mContexts.size(); + for (int i = 0; i < numContexts; i++) { + fillStructureWithAllowedValues(mContexts.get(i).getStructure()); + } - fillStructureWithAllowedValues(mStructure); + request = new FillRequest(requestId, mContexts, mClientState, mFlags); + } - FillRequest request = new FillRequest(requestId, mStructure, mClientState, mFlags); mRemoteFillService.onFillRequest(request); } }; @@ -259,10 +270,35 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } /** + * Cancels the last request sent to the {@link #mRemoteFillService}. + */ + private void cancelCurrentRequestLocked() { + int canceledRequest = mRemoteFillService.cancelCurrentRequest(); + + // Remove the FillContext as there will never be a response for the service + if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) { + int numContexts = mContexts.size(); + + // It is most likely the last context, hence search backwards + for (int i = numContexts - 1; i >= 0; i--) { + if (mContexts.get(i).getRequestId() == canceledRequest) { + mContexts.remove(i); + break; + } + } + } + + } + + /** * Reads a new structure and then request a new fill response from the fill service. */ private void requestNewFillResponseLocked() { - final int requestId = sIdCounter.getAndIncrement(); + int requestId; + + do { + requestId = sIdCounter.getAndIncrement(); + } while (requestId == INVALID_REQUEST_ID); if (DEBUG) { Slog.d(TAG, "Requesting structure for requestId " + requestId); @@ -273,7 +309,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // enhanced as the focus change can be much faster than the taking of the assist structure. // Hence remove the currently queued request and replace it with the one queued after the // structure is taken. This causes only one fill request per bust of focus changes. - mRemoteFillService.cancelCurrentRequest(); + cancelCurrentRequestLocked(); try { final Bundle receiverExtras = new Bundle(); @@ -354,7 +390,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, - @NonNull String servicePackageName, int requestId) { + @NonNull String servicePackageName) { if (response == null) { if ((mFlags & FLAG_MANUAL_REQUEST) != 0) { getUiForShowing().showError(R.string.autofill_error_cannot_autofill); @@ -377,7 +413,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // TODO(b/37424539): proper implementation mResponseWaitingAuth = response; } - processResponseLocked(response, requestId); + processResponseLocked(response); } final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) @@ -433,12 +469,37 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState removeSelf(); } + /** + * Gets the {@link FillContext} for a request. + * + * @param requestId The id of the request + * + * @return The context or {@code null} if there is no context + */ + @Nullable private FillContext getFillContextByRequestIdLocked(int requestId) { + if (mContexts == null) { + return null; + } + + int numContexts = mContexts.size(); + for (int i = 0; i < numContexts; i++) { + FillContext context = mContexts.get(i); + + if (context.getRequestId() == requestId) { + return context; + } + } + + return null; + } + // FillServiceCallbacks @Override - public void authenticate(IntentSender intent, Bundle extras) { + public void authenticate(int requestId, IntentSender intent, Bundle extras) { final Intent fillInIntent; synchronized (mLock) { - fillInIntent = createAuthFillInIntent(mStructure, extras); + fillInIntent = createAuthFillInIntent( + getFillContextByRequestIdLocked(requestId).getStructure(), extras); } mService.setAuthenticationSelected(); @@ -454,8 +515,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // AutoFillUiCallback @Override - public void fill(Dataset dataset) { - mHandlerCaller.getHandler().post(() -> autoFill(dataset)); + public void fill(int requestId, Dataset dataset) { + mHandlerCaller.getHandler().post(() -> autoFill(requestId, dataset)); } // AutoFillUiCallback @@ -530,12 +591,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final Parcelable result = data.getParcelable( AutofillManager.EXTRA_AUTHENTICATION_RESULT); if (result instanceof FillResponse) { + FillResponse response = (FillResponse) result; + mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName); final int requestIndex = mResponses.indexOfValue(mResponseWaitingAuth); mResponseWaitingAuth = null; if (requestIndex >= 0) { - final int requestId = mResponses.keyAt(requestIndex); - processResponseLocked((FillResponse) result, requestId); + response.setRequestId(mResponses.keyAt(requestIndex)); + processResponseLocked(response); } else { Slog.e(TAG, "Error cannot find id for auth response"); } @@ -547,7 +610,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (index >= 0) { response.getDatasets().set(index, dataset); mDatasetWaitingAuth = null; - autoFill(dataset); + autoFill(mResponses.keyAt(i), dataset); resetViewStatesLocked(dataset, ViewState.STATE_WAITING_DATASET_AUTH); return; } @@ -566,8 +629,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * @return {@code true} if session is done, or {@code false} if it's pending user action. */ public boolean showSaveLocked() { - if (mStructure == null) { - Slog.d(TAG, "showSaveLocked(): no mStructure"); + if (mContexts == null) { + Slog.d(TAG, "showSaveLocked(): no contexts"); return true; } if (mResponses == null) { @@ -589,7 +652,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final FillResponse response = mResponses.valueAt(lastResponseIdx); final SaveInfo saveInfo = response.getSaveInfo(); if (DEBUG) { - Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts + ", mViewStates=" + mViewStates); } @@ -689,43 +752,49 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates); } - for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { - final AutofillValue value = entry.getValue().getCurrentValue(); - if (value == null) { - if (VERBOSE) { - Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey()); - } - continue; - } - final AutofillId id = entry.getKey(); - final ViewNode node = findViewNodeById(mStructure, id); - if (node == null) { - Slog.w(TAG, "callSaveLocked(): did not find node with id " + id); - continue; - } + int numContexts = mContexts.size(); + + for (int i = 0; i < numContexts; i++) { + FillContext context = mContexts.get(i); + if (VERBOSE) { - Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value); + Slog.v(TAG, "callSaveLocked(): updating " + context); } - node.updateAutofillValue(value); - } + for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { + final AutofillValue value = entry.getValue().getCurrentValue(); + if (value == null) { + if (VERBOSE) { + Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey()); + } + continue; + } + final AutofillId id = entry.getKey(); + final ViewNode node = findViewNodeById(context.getStructure(), id); + if (node == null) { + Slog.w(TAG, "callSaveLocked(): did not find node with id " + id); + continue; + } + if (VERBOSE) { + Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value); + } - // Sanitize structure before it's sent to service. - mStructure.sanitizeForParceling(false); + node.updateAutofillValue(value); + } - if (VERBOSE) { - Slog.v(TAG, "Dumping " + mStructure + " before calling service.save()"); - mStructure.dump(); + // Sanitize structure before it's sent to service. + context.getStructure().sanitizeForParceling(false); + + if (VERBOSE) { + Slog.v(TAG, "Dumping structure of " + context + " before calling service.save()"); + context.getStructure().dump(); + } } - // TODO(b/37426206): Implement partitioning properly - final int lastResponseIdx = getLastResponseIndex(); - final int requestId = mResponses.keyAt(lastResponseIdx); - final FillContext fillContext = new FillContext(requestId, mStructure); - final ArrayList<FillContext> fillContexts = new ArrayList<>(1); - fillContexts.add(fillContext); + // Remove pending fill requests as the session is finished. + cancelCurrentRequestLocked(); - final SaveRequest saveRequest = new SaveRequest(fillContexts, mClientState); + final SaveRequest saveRequest = new SaveRequest(mContexts, mClientState); mRemoteFillService.onSaveRequest(saveRequest); } @@ -921,7 +990,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private void processResponseLocked(FillResponse response, int requestId) { + private void processResponseLocked(@NonNull FillResponse response) { if (DEBUG) { Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response); } @@ -929,10 +998,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (mResponses == null) { mResponses = new SparseArray<>(4); } - mResponses.put(requestId, response); - if (response != null) { - mClientState = response.getClientState(); - } + mResponses.put(response.getRequestId(), response); + mClientState = response.getClientState(); setViewStatesLocked(response, ViewState.STATE_FILLABLE); updateTrackedIdsLocked(); @@ -944,7 +1011,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if ((mFlags & FLAG_MANUAL_REQUEST) != 0 && response.getDatasets() != null && response.getDatasets().size() == 1) { Slog.d(TAG, "autofilling manual request directly"); - autoFill(response.getDatasets().get(0)); + autoFill(response.getRequestId(), response.getDatasets().get(0)); return; } @@ -1033,7 +1100,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - void autoFill(Dataset dataset) { + void autoFill(int requestId, Dataset dataset) { synchronized (mLock) { // Autofill it directly... if (dataset.getAuthentication() == null) { @@ -1048,7 +1115,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.setDatasetAuthenticationSelected(dataset.getId()); mDatasetWaitingAuth = dataset; setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH); - final Intent fillInIntent = createAuthFillInIntent(mStructure, null); + final Intent fillInIntent = createAuthFillInIntent( + getFillContextByRequestIdLocked(requestId).getStructure(), null); startAuthentication(dataset.getAuthentication(), fillInIntent); } } @@ -1095,16 +1163,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); entry.getValue().dump(prefix2, pw); } - if (VERBOSE) { - pw.print(prefix); pw.print("mStructure: " ); - // TODO: add method on AssistStructure to dump on pw - if (mStructure != null) { - pw.println("look at logcat" ); - mStructure.dump(); // dumps to logcat - } else { - pw.println("null"); + + pw.print(prefix); pw.print("mContexts: " ); + if (mContexts != null) { + int numContexts = mContexts.size(); + for (int i = 0; i < numContexts; i++) { + FillContext context = mContexts.get(i); + + pw.print(prefix2); pw.print(context); + if (VERBOSE) { + pw.println(context.getStructure() + " (look at logcat)"); + + // TODO: add method on AssistStructure to dump on pw + context.getStructure().dump(); + } } + } else { + pw.println("null"); } + pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback); pw.print(prefix); pw.print("mClientState: "); pw.println( Helper.bundleToString(mClientState)); diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index ab6a3a7cd78b..0556c6711888 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -60,8 +60,8 @@ public final class AutoFillUI { private final MetricsLogger mMetricsLogger = new MetricsLogger(); public interface AutoFillUiCallback { - void authenticate(@NonNull IntentSender intent, @Nullable Bundle extras); - void fill(@NonNull Dataset dataset); + void authenticate(int requestId, @NonNull IntentSender intent, @Nullable Bundle extras); + void fill(int requestId, @NonNull Dataset dataset); void save(); void cancelSave(); void requestShowFillUi(AutofillId id, int width, int height, @@ -161,8 +161,8 @@ public final class AutoFillUI { log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL); hideFillUiUiThread(); if (mCallback != null) { - mCallback.authenticate(response.getAuthentication(), - response.getClientState()); + mCallback.authenticate(response.getRequestId(), + response.getAuthentication(), response.getClientState()); } } @@ -171,7 +171,7 @@ public final class AutoFillUI { log.setType(MetricsProto.MetricsEvent.TYPE_ACTION); hideFillUiUiThread(); if (mCallback != null) { - mCallback.fill(dataset); + mCallback.fill(response.getRequestId(), dataset); } } |