Merge "Take new autofill structure for each partition" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f40d1cb773
@@ -66,10 +66,6 @@ public abstract class AutofillService extends Service {
|
||||
*/
|
||||
public static final String SERVICE_META_DATA = "android.autofill";
|
||||
|
||||
// Internal extras
|
||||
/** @hide */
|
||||
public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID";
|
||||
|
||||
// Handler messages.
|
||||
private static final int MSG_CONNECT = 1;
|
||||
private static final int MSG_DISCONNECT = 2;
|
||||
|
||||
@@ -39,8 +39,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
|
||||
*/
|
||||
public final class FillRequest implements Parcelable {
|
||||
private static AtomicInteger sIdCounter = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Indicates autofill was explicitly requested by the user.
|
||||
*/
|
||||
@@ -58,12 +56,6 @@ public final class FillRequest implements Parcelable {
|
||||
private final @NonNull AssistStructure mStructure;
|
||||
private final @Nullable Bundle mClientState;
|
||||
|
||||
/** @hide */
|
||||
public FillRequest(@NonNull AssistStructure structure,
|
||||
@Nullable Bundle clientState, @RequestFlags int flags) {
|
||||
this(sIdCounter.incrementAndGet(), structure, clientState, flags);
|
||||
}
|
||||
|
||||
private FillRequest(@NonNull Parcel parcel) {
|
||||
mId = parcel.readInt();
|
||||
mStructure = parcel.readParcelable(null);
|
||||
@@ -71,7 +63,8 @@ public final class FillRequest implements Parcelable {
|
||||
mFlags = parcel.readInt();
|
||||
}
|
||||
|
||||
private FillRequest(int id, @NonNull AssistStructure structure,
|
||||
/** @hide */
|
||||
public FillRequest(int id, @NonNull AssistStructure structure,
|
||||
@Nullable Bundle clientState, @RequestFlags int flags) {
|
||||
mId = id;
|
||||
mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package com.android.server.autofill;
|
||||
|
||||
import static android.service.autofill.AutofillService.EXTRA_SESSION_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;
|
||||
import static android.view.autofill.AutofillManager.NO_SESSION;
|
||||
|
||||
@@ -27,10 +24,7 @@ import static com.android.server.autofill.Helper.VERBOSE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.assist.AssistStructure;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -50,7 +44,6 @@ import android.service.autofill.AutofillService;
|
||||
import android.service.autofill.AutofillServiceInfo;
|
||||
import android.service.autofill.FillEventHistory;
|
||||
import android.service.autofill.FillEventHistory.Event;
|
||||
import android.service.autofill.FillRequest;
|
||||
import android.service.autofill.FillResponse;
|
||||
import android.service.autofill.IAutoFillService;
|
||||
import android.text.TextUtils;
|
||||
@@ -66,7 +59,6 @@ import android.view.autofill.IAutoFillManagerClient;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.os.HandlerCaller;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.server.autofill.ui.AutoFillUI;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -127,56 +119,6 @@ final class AutofillManagerServiceImpl {
|
||||
@GuardedBy("mLock")
|
||||
private FillEventHistory mEventHistory;
|
||||
|
||||
/**
|
||||
* Receiver of assist data from the app's {@link Activity}.
|
||||
*/
|
||||
private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
|
||||
@Override
|
||||
public void send(int resultCode, Bundle resultData) throws RemoteException {
|
||||
if (VERBOSE) {
|
||||
Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode);
|
||||
}
|
||||
|
||||
final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
|
||||
if (structure == null) {
|
||||
Slog.wtf(TAG, "no assist structure for id " + resultCode);
|
||||
return;
|
||||
}
|
||||
|
||||
final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS);
|
||||
if (receiverExtras == null) {
|
||||
Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver");
|
||||
return;
|
||||
}
|
||||
|
||||
final int sessionId = receiverExtras.getInt(EXTRA_SESSION_ID);
|
||||
final Session session;
|
||||
synchronized (mLock) {
|
||||
session = mSessions.get(sessionId);
|
||||
if (session == null) {
|
||||
Slog.w(TAG, "no server session for " + sessionId);
|
||||
return;
|
||||
}
|
||||
session.setStructureLocked(structure);
|
||||
}
|
||||
|
||||
|
||||
// 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 ONE_WAY warning because system_service could block on app calls.
|
||||
// We need to change AssistStructure so it provides a "one-way" writeToParcel()
|
||||
// method that sends all the data
|
||||
structure.ensureData();
|
||||
|
||||
// Sanitize structure before it's sent to service.
|
||||
structure.sanitizeForParceling(true);
|
||||
|
||||
// This is the first request, hence there is no Bundle to be sent as clientState
|
||||
final FillRequest request = new FillRequest(structure, null, session.mFlags);
|
||||
session.mRemoteFillService.onFillRequest(request);
|
||||
}
|
||||
};
|
||||
|
||||
AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory,
|
||||
int userId, AutoFillUI ui, boolean disabled) {
|
||||
mContext = context;
|
||||
@@ -393,21 +335,6 @@ final class AutofillManagerServiceImpl {
|
||||
mInfo.getServiceInfo().getComponentName(), packageName);
|
||||
mSessions.put(newSession.id, newSession);
|
||||
|
||||
try {
|
||||
final Bundle receiverExtras = new Bundle();
|
||||
receiverExtras.putInt(EXTRA_SESSION_ID, sessionId);
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!ActivityManager.getService().requestAutofillData(mAssistReceiver,
|
||||
receiverExtras, activityToken)) {
|
||||
Slog.w(TAG, "failed to request autofill data for " + activityToken);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should not happen, it's a local call.
|
||||
}
|
||||
return newSession;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
|
||||
package com.android.server.autofill;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.assist.AssistStructure;
|
||||
import android.app.assist.AssistStructure.ViewNode;
|
||||
import android.os.Bundle;
|
||||
import android.view.autofill.AutofillId;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
@@ -53,4 +58,37 @@ final class Helper {
|
||||
private Helper() {
|
||||
throw new UnsupportedOperationException("contains static members only");
|
||||
}
|
||||
|
||||
static ViewNode findViewNodeById(@NonNull AssistStructure structure, @NonNull AutofillId id) {
|
||||
final int size = structure.getWindowNodeCount();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final AssistStructure.WindowNode window = structure.getWindowNodeAt(i);
|
||||
final ViewNode root = window.getRootViewNode();
|
||||
if (id.equals(root.getAutofillId())) {
|
||||
return root;
|
||||
}
|
||||
final ViewNode child = findViewNodeById(root, id);
|
||||
if (child != null) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static ViewNode findViewNodeById(@NonNull ViewNode parent, @NonNull AutofillId id) {
|
||||
final int childrenSize = parent.getChildCount();
|
||||
if (childrenSize > 0) {
|
||||
for (int i = 0; i < childrenSize; i++) {
|
||||
final ViewNode child = parent.getChildAt(i);
|
||||
if (id.equals(child.getAutofillId())) {
|
||||
return child;
|
||||
}
|
||||
final ViewNode grandChild = findViewNodeById(child, id);
|
||||
if (grandChild != null && id.equals(grandChild.getAutofillId())) {
|
||||
return grandChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,23 @@ final class RemoteFillService implements DeathRecipient {
|
||||
mCallbacks.onServiceDied(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the currently pending request.
|
||||
*
|
||||
* <p>This can be used when the request is unnecessary or will be superceeded by a request that
|
||||
* will soon be queued.
|
||||
*/
|
||||
public void cancelCurrentRequest() {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPendingRequest != null) {
|
||||
mPendingRequest.cancel();
|
||||
mPendingRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void onFillRequest(@NonNull FillRequest request) {
|
||||
cancelScheduledUnbind();
|
||||
final PendingFillRequest pendingRequest = new PendingFillRequest(request, this);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package com.android.server.autofill;
|
||||
|
||||
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
|
||||
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;
|
||||
import static android.view.autofill.AutofillManager.FLAG_VALUE_CHANGED;
|
||||
import static android.view.autofill.AutofillManager.FLAG_VIEW_ENTERED;
|
||||
@@ -25,19 +27,22 @@ import static android.view.autofill.AutofillManager.FLAG_VIEW_EXITED;
|
||||
|
||||
import static com.android.server.autofill.Helper.DEBUG;
|
||||
import static com.android.server.autofill.Helper.VERBOSE;
|
||||
import static com.android.server.autofill.Helper.findViewNodeById;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.assist.AssistStructure;
|
||||
import android.app.assist.AssistStructure.AutofillOverlay;
|
||||
import android.app.assist.AssistStructure.ViewNode;
|
||||
import android.app.assist.AssistStructure.WindowNode;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.graphics.Rect;
|
||||
import android.metrics.LogMaker;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
@@ -64,14 +69,16 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.os.HandlerCaller;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.autofill.ui.AutoFillUI;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A session for a given activity.
|
||||
@@ -89,6 +96,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
AutoFillUI.AutoFillUiCallback {
|
||||
private static final String TAG = "AutofillSession";
|
||||
|
||||
private static final String EXTRA_REQUEST_ID = "android.service.autofill.extra.REQUEST_ID";
|
||||
|
||||
private final AutofillManagerServiceImpl mService;
|
||||
private final HandlerCaller mHandlerCaller;
|
||||
private final Object mLock;
|
||||
@@ -96,6 +105,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
|
||||
private final MetricsLogger mMetricsLogger = new MetricsLogger();
|
||||
|
||||
private static AtomicInteger sIdCounter = new AtomicInteger();
|
||||
|
||||
/** Id of the session */
|
||||
public final int id;
|
||||
|
||||
@@ -123,8 +134,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
@GuardedBy("mLock")
|
||||
private IAutoFillManagerClient mClient;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
RemoteFillService mRemoteFillService;
|
||||
private final RemoteFillService mRemoteFillService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private SparseArray<FillResponse> mResponses;
|
||||
@@ -163,7 +173,124 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
/**
|
||||
* Flags used to start the session.
|
||||
*/
|
||||
int mFlags;
|
||||
private final int mFlags;
|
||||
|
||||
/**
|
||||
* Receiver of assist data from the app's {@link Activity}.
|
||||
*/
|
||||
private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
|
||||
@Override
|
||||
public void send(int resultCode, Bundle resultData) throws RemoteException {
|
||||
if (VERBOSE) {
|
||||
Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode);
|
||||
}
|
||||
|
||||
final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
|
||||
if (structure == null) {
|
||||
Slog.wtf(TAG, "no assist structure for id " + resultCode);
|
||||
return;
|
||||
}
|
||||
|
||||
final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS);
|
||||
if (receiverExtras == null) {
|
||||
Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver");
|
||||
return;
|
||||
}
|
||||
|
||||
final int requestId = receiverExtras.getInt(EXTRA_REQUEST_ID);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "New structure for requestId " + requestId + ": " + structure);
|
||||
}
|
||||
|
||||
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
|
||||
// ONE_WAY warning because system_service could block on app calls. We need to
|
||||
// change AssistStructure so it provides a "one-way" writeToParcel() method that
|
||||
// sends all the data
|
||||
structure.ensureData();
|
||||
|
||||
// Sanitize structure before it's sent to service.
|
||||
structure.sanitizeForParceling(true);
|
||||
|
||||
mStructure = structure;
|
||||
}
|
||||
|
||||
fillStructureWithAllowedValues(mStructure);
|
||||
|
||||
FillRequest request = new FillRequest(requestId, mStructure, mClientState, mFlags);
|
||||
mRemoteFillService.onFillRequest(request);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates values of the nodes in the structure so that:
|
||||
* - proper node is focused
|
||||
* - autofillValue is sent back to service when it was previously autofilled
|
||||
*
|
||||
* @param structure The structure to be filled
|
||||
*/
|
||||
private void fillStructureWithAllowedValues(@NonNull AssistStructure structure) {
|
||||
final int numViewStates = mViewStates.size();
|
||||
for (int i = 0; i < numViewStates; i++) {
|
||||
final ViewState viewState = mViewStates.valueAt(i);
|
||||
|
||||
final ViewNode node = findViewNodeById(structure, viewState.id);
|
||||
if (node == null) {
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "fillStructureWithAllowedValues(): no node for " + viewState.id);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
final AutofillValue initialValue = viewState.getInitialValue();
|
||||
final AutofillValue filledValue = viewState.getAutofilledValue();
|
||||
final AutofillOverlay overlay = new AutofillOverlay();
|
||||
if (filledValue != null && !filledValue.equals(initialValue)) {
|
||||
overlay.value = filledValue;
|
||||
}
|
||||
if (mCurrentViewId != null) {
|
||||
overlay.focused = mCurrentViewId.equals(viewState.id);
|
||||
}
|
||||
|
||||
node.setAutofillOverlay(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a new structure and then request a new fill response from the fill service.
|
||||
*/
|
||||
private void requestNewFillResponseLocked() {
|
||||
final int requestId = sIdCounter.getAndIncrement();
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Requesting structure for requestId " + requestId);
|
||||
}
|
||||
|
||||
// If the focus changes very quickly before the first request is returned each focus change
|
||||
// triggers a new partition and we end up with many duplicate partitions. This is
|
||||
// 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();
|
||||
|
||||
try {
|
||||
final Bundle receiverExtras = new Bundle();
|
||||
receiverExtras.putInt(EXTRA_REQUEST_ID, requestId);
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!ActivityManager.getService().requestAutofillData(mAssistReceiver,
|
||||
receiverExtras, mActivityToken)) {
|
||||
Slog.w(TAG, "failed to request autofill data for " + mActivityToken);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should not happen, it's a local call.
|
||||
}
|
||||
}
|
||||
|
||||
Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui,
|
||||
@NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId,
|
||||
@@ -433,10 +560,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
mHasCallback = hasIt;
|
||||
}
|
||||
|
||||
public void setStructureLocked(AssistStructure structure) {
|
||||
mStructure = structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the save UI, when session can be saved.
|
||||
*
|
||||
@@ -575,7 +698,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
continue;
|
||||
}
|
||||
final AutofillId id = entry.getKey();
|
||||
final ViewNode node = findViewNodeByIdLocked(id);
|
||||
final ViewNode node = findViewNodeById(mStructure, id);
|
||||
if (node == null) {
|
||||
Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
|
||||
continue;
|
||||
@@ -606,24 +729,61 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
mRemoteFillService.onSaveRequest(saveRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a new partition should be started for an id.
|
||||
*
|
||||
* @param id The id of the view that is entered
|
||||
*
|
||||
* @return {@code true} iff a new partition should be started
|
||||
*/
|
||||
private boolean shouldStartNewPartitionLocked(@NonNull AutofillId id) {
|
||||
if (mResponses == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final int numResponses = mResponses.size();
|
||||
for (int responseNum = 0; responseNum < numResponses; responseNum++) {
|
||||
final FillResponse response = mResponses.valueAt(responseNum);
|
||||
|
||||
if (ArrayUtils.contains(response.getIgnoredIds(), id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final SaveInfo saveInfo = response.getSaveInfo();
|
||||
if (saveInfo != null) {
|
||||
if (ArrayUtils.contains(saveInfo.getOptionalIds(), id)
|
||||
|| ArrayUtils.contains(saveInfo.getRequiredIds(), id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final ArrayList<Dataset> datasets = response.getDatasets();
|
||||
if (datasets != null) {
|
||||
final int numDatasets = datasets.size();
|
||||
|
||||
for (int dataSetNum = 0; dataSetNum < numDatasets; dataSetNum++) {
|
||||
final ArrayList fields = datasets.get(dataSetNum).getFieldIds();
|
||||
|
||||
if (fields != null && fields.contains(id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
|
||||
ViewState viewState = mViewStates.get(id);
|
||||
|
||||
if (viewState == null) {
|
||||
if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED)) != 0) {
|
||||
if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED | FLAG_VIEW_ENTERED)) != 0) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags));
|
||||
}
|
||||
viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL);
|
||||
mViewStates.put(id, viewState);
|
||||
} else if (mStructure != null && (flags & FLAG_VIEW_ENTERED) != 0) {
|
||||
if (isIgnoredLocked(id)) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Not starting partition for ignored view id " + id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
viewState = startPartitionLocked(id, value);
|
||||
} else {
|
||||
if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id);
|
||||
return;
|
||||
@@ -635,6 +795,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
mCurrentViewId = viewState.id;
|
||||
viewState.update(value, virtualBounds);
|
||||
viewState.setState(ViewState.STATE_STARTED_SESSION);
|
||||
requestNewFillResponseLocked();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -664,6 +825,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
}
|
||||
|
||||
if ((flags & FLAG_VIEW_ENTERED) != 0) {
|
||||
if (shouldStartNewPartitionLocked(id)) {
|
||||
// TODO(b/37424539): proper implementation
|
||||
if (mResponseWaitingAuth != null && ((flags & FLAG_START_SESSION) == 0)) {
|
||||
viewState.setState(ViewState.STATE_WAITING_RESPONSE_AUTH);
|
||||
} else if ((flags & FLAG_START_SESSION) == 0){
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Starting partition for view id " + viewState.id);
|
||||
}
|
||||
viewState.setState(ViewState.STATE_STARTED_PARTITION);
|
||||
requestNewFillResponseLocked();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the UI if the ViewState has changed.
|
||||
if (mCurrentViewId != viewState.id) {
|
||||
mUi.hideFillUi(mCurrentViewId != null ? mCurrentViewId : null);
|
||||
@@ -687,49 +861,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags));
|
||||
}
|
||||
|
||||
private ViewState startPartitionLocked(AutofillId id, AutofillValue value) {
|
||||
// TODO(b/37424539): proper implementation
|
||||
if (mResponseWaitingAuth != null) {
|
||||
final ViewState viewState =
|
||||
new ViewState(this, id, value, this, ViewState.STATE_WAITING_RESPONSE_AUTH);
|
||||
mViewStates.put(id, viewState);
|
||||
return viewState;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Starting partition for view id " + id);
|
||||
}
|
||||
final ViewState newViewState =
|
||||
new ViewState(this, id, value, this,ViewState.STATE_STARTED_PARTITION);
|
||||
mViewStates.put(id, newViewState);
|
||||
|
||||
// Must update value of nodes so:
|
||||
// - proper node is focused
|
||||
// - autofillValue is sent back to service when it was previously autofilled
|
||||
for (int i = 0; i < mViewStates.size(); i++) {
|
||||
final ViewState viewState = mViewStates.valueAt(i);
|
||||
|
||||
final ViewNode node = findViewNodeByIdLocked(viewState.id);
|
||||
if (node == null) {
|
||||
Slog.w(TAG, "startPartitionLocked(): no node for " + viewState.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
final AutofillValue initialValue = viewState.getInitialValue();
|
||||
final AutofillValue filledValue = viewState.getAutofilledValue();
|
||||
final AutofillOverlay overlay = new AutofillOverlay();
|
||||
if (filledValue != null && !filledValue.equals(initialValue)) {
|
||||
overlay.value = filledValue;
|
||||
}
|
||||
overlay.focused = id.equals(viewState.id);
|
||||
node.setAutofillOverlay(overlay);
|
||||
}
|
||||
|
||||
FillRequest request = new FillRequest(mStructure, mClientState, 0);
|
||||
mRemoteFillService.onFillRequest(request);
|
||||
|
||||
return newViewState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFillReady(FillResponse response, AutofillId filledId,
|
||||
@Nullable AutofillValue value) {
|
||||
@@ -949,23 +1080,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIgnoredLocked(@NonNull AutofillId id) {
|
||||
if (mResponses == null) return false;
|
||||
|
||||
for (int i = mResponses.size() - 1; i >= 0; i--) {
|
||||
final FillResponse response = mResponses.valueAt(i);
|
||||
final AutofillId[] ignoredIds = response.getIgnoredIds();
|
||||
if (ignoredIds == null) continue;
|
||||
for (int j = 0; j < ignoredIds.length; j++) {
|
||||
final AutofillId ignoredId = ignoredIds[j];
|
||||
if (ignoredId != null && ignoredId.equals(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void dumpLocked(String prefix, PrintWriter pw) {
|
||||
pw.print(prefix); pw.print("id: "); pw.println(id);
|
||||
pw.print(prefix); pw.print("uid: "); pw.println(uid);
|
||||
@@ -1018,39 +1132,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
}
|
||||
}
|
||||
|
||||
private ViewNode findViewNodeByIdLocked(AutofillId id) {
|
||||
final int size = mStructure.getWindowNodeCount();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final WindowNode window = mStructure.getWindowNodeAt(i);
|
||||
final ViewNode root = window.getRootViewNode();
|
||||
if (id.equals(root.getAutofillId())) {
|
||||
return root;
|
||||
}
|
||||
final ViewNode child = findViewNodeByIdLocked(root, id);
|
||||
if (child != null) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ViewNode findViewNodeByIdLocked(ViewNode parent, AutofillId id) {
|
||||
final int childrenSize = parent.getChildCount();
|
||||
if (childrenSize > 0) {
|
||||
for (int i = 0; i < childrenSize; i++) {
|
||||
final ViewNode child = parent.getChildAt(i);
|
||||
if (id.equals(child.getAutofillId())) {
|
||||
return child;
|
||||
}
|
||||
final ViewNode grandChild = findViewNodeByIdLocked(child, id);
|
||||
if (grandChild != null && id.equals(grandChild.getAutofillId())) {
|
||||
return grandChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void destroyLocked() {
|
||||
mRemoteFillService.destroy();
|
||||
mUi.setCallback(null);
|
||||
|
||||
Reference in New Issue
Block a user