diff options
3 files changed, 126 insertions, 105 deletions
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 41c209cc016a..570f968587b1 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -760,8 +760,8 @@ public final class AutofillManager { } } - private void requestShowFillUi(IBinder windowToken, AutofillId id, int width, int height, - Rect anchorBounds, IAutofillWindowPresenter presenter) { + private void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width, + int height, Rect anchorBounds, IAutofillWindowPresenter presenter) { final View anchor = findAchorView(windowToken, id); if (anchor == null) { return; @@ -769,9 +769,15 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { - if (getClientLocked().autofillCallbackRequestShowFillUi(anchor, width, height, - anchorBounds, presenter) && mCallback != null) { - callback = mCallback; + if (mSessionId == sessionId) { + AutofillClient client = getClientLocked(); + + if (client != null) { + if (client.autofillCallbackRequestShowFillUi(anchor, width, height, + anchorBounds, presenter) && mCallback != null) { + callback = mCallback; + } + } } } @@ -785,6 +791,23 @@ public final class AutofillManager { } } + private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { + synchronized (mLock) { + if (sessionId == mSessionId) { + AutofillClient client = getClientLocked(); + if (client != null) { + client.autofillCallbackAuthenticate(intent, fillInIntent); + } + } + } + } + + private void setState(boolean enabled) { + synchronized (mLock) { + mEnabled = enabled; + } + } + /** * Sets a view as autofilled if the current value is the {code targetValue}. * @@ -804,80 +827,92 @@ public final class AutofillManager { } } - private void handleAutofill(IBinder windowToken, List<AutofillId> ids, + private void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids, List<AutofillValue> values) { - final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken); - if (root == null) { - return; - } - - final int itemCount = ids.size(); - int numApplied = 0; - ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null; + synchronized (mLock) { + if (sessionId != mSessionId) { + return; + } - for (int i = 0; i < itemCount; i++) { - final AutofillId id = ids.get(i); - final AutofillValue value = values.get(i); - final int viewId = id.getViewId(); - final View view = root.findViewByAccessibilityIdTraversal(viewId); - if (view == null) { - Log.w(TAG, "autofill(): no View with id " + viewId); - continue; + final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken); + if (root == null) { + return; } - if (id.isVirtual()) { - if (virtualValues == null) { - // Most likely there will be just one view with virtual children. - virtualValues = new ArrayMap<>(1); - } - SparseArray<AutofillValue> valuesByParent = virtualValues.get(view); - if (valuesByParent == null) { - // We don't know the size yet, but usually it will be just a few fields... - valuesByParent = new SparseArray<>(5); - virtualValues.put(view, valuesByParent); + + final int itemCount = ids.size(); + int numApplied = 0; + ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null; + + for (int i = 0; i < itemCount; i++) { + final AutofillId id = ids.get(i); + final AutofillValue value = values.get(i); + final int viewId = id.getViewId(); + final View view = root.findViewByAccessibilityIdTraversal(viewId); + if (view == null) { + Log.w(TAG, "autofill(): no View with id " + viewId); + continue; } - valuesByParent.put(id.getVirtualChildId(), value); - } else { - synchronized (mLock) { + if (id.isVirtual()) { + if (virtualValues == null) { + // Most likely there will be just one view with virtual children. + virtualValues = new ArrayMap<>(1); + } + SparseArray<AutofillValue> valuesByParent = virtualValues.get(view); + if (valuesByParent == null) { + // We don't know the size yet, but usually it will be just a few fields... + valuesByParent = new SparseArray<>(5); + virtualValues.put(view, valuesByParent); + } + valuesByParent.put(id.getVirtualChildId(), value); + } else { // Mark the view as to be autofilled with 'value' if (mLastAutofilledData == null) { mLastAutofilledData = new ParcelableMap(itemCount - i); } mLastAutofilledData.put(id, value); - } - view.autofill(value); + view.autofill(value); - // Set as autofilled if the values match now, e.g. when the value was updated - // synchronously. - // If autofill happens async, the view is set to autofilled in notifyValueChanged. - setAutofilledIfValuesIs(view, value); + // Set as autofilled if the values match now, e.g. when the value was updated + // synchronously. + // If autofill happens async, the view is set to autofilled in + // notifyValueChanged. + setAutofilledIfValuesIs(view, value); - numApplied++; + numApplied++; + } } - } - if (virtualValues != null) { - for (int i = 0; i < virtualValues.size(); i++) { - final View parent = virtualValues.keyAt(i); - final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i); - parent.autofill(childrenValues); - numApplied += childrenValues.size(); + if (virtualValues != null) { + for (int i = 0; i < virtualValues.size(); i++) { + final View parent = virtualValues.keyAt(i); + final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i); + parent.autofill(childrenValues); + numApplied += childrenValues.size(); + } } - } - final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied); - mMetricsLogger.write(log); + final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED); + log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount); + log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, + numApplied); + mMetricsLogger.write(log); + } } - private void requestHideFillUi(IBinder windowToken, AutofillId id) { + private void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) { final View anchor = findAchorView(windowToken, id); AutofillCallback callback = null; synchronized (mLock) { - if (getClientLocked().autofillCallbackRequestHideFillUi() && mCallback != null) { - callback = mCallback; + if (mSessionId == sessionId) { + AutofillClient client = getClientLocked(); + + if (client != null) { + if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { + callback = mCallback; + } + } } } @@ -891,12 +926,14 @@ public final class AutofillManager { } } - private void notifyNoFillUi(IBinder windowToken, AutofillId id) { + private void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) { final View anchor = findAchorView(windowToken, id); - AutofillCallback callback; + AutofillCallback callback = null; synchronized (mLock) { - callback = mCallback; + if (mSessionId == sessionId && getClientLocked() != null) { + callback = mCallback; + } } if (callback != null) { @@ -999,73 +1036,57 @@ public final class AutofillManager { public void setState(boolean enabled) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - synchronized (afm.mLock) { - afm.mEnabled = enabled; - } - }); + afm.mContext.getMainThreadHandler().post(() -> afm.setState(enabled)); } } @Override - public void autofill(IBinder windowToken, List<AutofillId> ids, + public void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids, List<AutofillValue> values) { // TODO(b/33197203): must keep the dataset so subsequent calls pass the same // dataset.extras to service final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> - afm.handleAutofill(windowToken, ids, values)); + afm.mContext.getMainThreadHandler().post( + () -> afm.autofill(sessionId, windowToken, ids, values)); } } @Override - public void authenticate(IntentSender intent, Intent fillInIntent) { + public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.getClientLocked().autofillCallbackAuthenticate(intent, fillInIntent); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.authenticate(sessionId, intent, fillInIntent)); } } @Override - public void requestShowFillUi(IBinder windowToken, AutofillId id, + public void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width, int height, Rect anchorBounds, IAutofillWindowPresenter presenter) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.requestShowFillUi(windowToken, id, width, - height, anchorBounds, presenter); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.requestShowFillUi(sessionId, windowToken, id, width, height, + anchorBounds, presenter)); } } @Override - public void requestHideFillUi(IBinder windowToken, AutofillId id) { + public void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.requestHideFillUi(windowToken, id); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.requestHideFillUi(sessionId, windowToken, id)); } } @Override - public void notifyNoFillUi(IBinder windowToken, AutofillId id) { + public void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.notifyNoFillUi(windowToken, id); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.notifyNoFillUi(sessionId, windowToken, id)); } } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 176eaacb57ae..56f91ed6de9b 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -40,28 +40,29 @@ oneway interface IAutoFillManagerClient { /** * Autofills the activity with the contents of a dataset. */ - void autofill(in IBinder windowToken, in List<AutofillId> ids, in List<AutofillValue> values); + void autofill(int sessionId, in IBinder windowToken, in List<AutofillId> ids, + in List<AutofillValue> values); /** * Authenticates a fill response or a data set. */ - void authenticate(in IntentSender intent, in Intent fillInIntent); + void authenticate(int sessionId, in IntentSender intent, in Intent fillInIntent); /** * Requests showing the fill UI. */ - void requestShowFillUi(in IBinder windowToken, in AutofillId id, int width, + void requestShowFillUi(int sessionId, in IBinder windowToken, in AutofillId id, int width, int height, in Rect anchorBounds, in IAutofillWindowPresenter presenter); /** * Requests hiding the fill UI. */ - void requestHideFillUi(in IBinder windowToken, in AutofillId id); + void requestHideFillUi(int sessionId, in IBinder windowToken, in AutofillId id); /** * Notifies no fill UI will be shown. */ - void notifyNoFillUi(in IBinder windowToken, in AutofillId id); + void notifyNoFillUi(int sessionId, in IBinder windowToken, in AutofillId id); /** * Starts the provided intent sender diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 0b1381ebec89..1a311614214e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -343,9 +343,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (id.equals(mCurrentViewId)) { try { final ViewState view = mViewStates.get(id); - mClient.requestShowFillUi(mWindowToken, id, width, height, - view.getVirtualBounds(), - presenter); + mClient.requestShowFillUi(this.id, mWindowToken, id, width, height, + view.getVirtualBounds(), presenter); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to show fill UI", e); } @@ -363,7 +362,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void requestHideFillUi(AutofillId id) { synchronized (mLock) { try { - mClient.requestHideFillUi(mWindowToken, id); + mClient.requestHideFillUi(this.id, mWindowToken, id); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to hide fill UI", e); } @@ -716,7 +715,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (!mHasCallback) return; try { - mClient.notifyNoFillUi(mWindowToken, mCurrentViewId); + mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId); } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken + " id=" + mCurrentViewId, e); @@ -852,7 +851,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void startAuthentication(IntentSender intent, Intent fillInIntent) { try { synchronized (mLock) { - mClient.authenticate(intent, fillInIntent); + mClient.authenticate(id, intent, fillInIntent); } } catch (RemoteException e) { Slog.e(TAG, "Error launching auth intent", e); @@ -895,7 +894,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (DEBUG) { Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); } - mClient.autofill(mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); + mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED); } catch (RemoteException e) { Slog.w(TAG, "Error autofilling activity: " + e); |