diff options
| -rw-r--r-- | api/current.txt | 19 | ||||
| -rw-r--r-- | api/system-current.txt | 19 | ||||
| -rw-r--r-- | api/test-current.txt | 19 | ||||
| -rw-r--r-- | core/java/android/service/autofill/AutofillService.java | 18 | ||||
| -rw-r--r-- | core/java/android/service/autofill/Dataset.java | 38 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillEventHistory.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillEventHistory.java | 208 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillManager.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/autofill/IAutoFillManager.aidl | 2 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/AutofillManagerService.java | 16 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java | 86 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/RemoteFillService.java | 10 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/Session.java | 11 |
13 files changed, 474 insertions, 7 deletions
diff --git a/api/current.txt b/api/current.txt index 8a25ab4e5b71..8b63b754ddb7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37037,6 +37037,7 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); method public final deprecated void disableSelf(); + method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); @@ -37059,6 +37060,7 @@ package android.service.autofill { ctor public Dataset.Builder(); method public android.service.autofill.Dataset build(); method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender); + method public android.service.autofill.Dataset.Builder setId(java.lang.String); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews); } @@ -37076,6 +37078,23 @@ package android.service.autofill { field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; } + public final class FillEventHistory implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; + } + + public static final class FillEventHistory.Event { + method public java.lang.String getDatasetId(); + method public int getType(); + field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 + field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 + field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 + field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 + } + public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); diff --git a/api/system-current.txt b/api/system-current.txt index 874917964717..806c49c8ee00 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40149,6 +40149,7 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); method public final deprecated void disableSelf(); + method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); @@ -40171,6 +40172,7 @@ package android.service.autofill { ctor public Dataset.Builder(); method public android.service.autofill.Dataset build(); method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender); + method public android.service.autofill.Dataset.Builder setId(java.lang.String); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews); } @@ -40188,6 +40190,23 @@ package android.service.autofill { field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; } + public final class FillEventHistory implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; + } + + public static final class FillEventHistory.Event { + method public java.lang.String getDatasetId(); + method public int getType(); + field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 + field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 + field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 + field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 + } + public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); diff --git a/api/test-current.txt b/api/test-current.txt index 7a73d4b62f77..ff46bb75d61d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -37190,6 +37190,7 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); method public final deprecated void disableSelf(); + method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); @@ -37212,6 +37213,7 @@ package android.service.autofill { ctor public Dataset.Builder(); method public android.service.autofill.Dataset build(); method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender); + method public android.service.autofill.Dataset.Builder setId(java.lang.String); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue); method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews); } @@ -37229,6 +37231,23 @@ package android.service.autofill { field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; } + public final class FillEventHistory implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; + } + + public static final class FillEventHistory.Event { + method public java.lang.String getDatasetId(); + method public int getType(); + field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 + field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 + field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 + field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 + } + public final class FillRequest implements android.os.Parcelable { method public int describeContents(); method public android.os.Bundle getClientState(); diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 5e49b8f0553f..8fcb87c5c0d0 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -285,4 +285,22 @@ public abstract class AutofillService extends Service { // TODO(b/33197203): Remove when GCore has migrated off this API getSystemService(AutofillManager.class).disableOwnedAutofillServices(); } + + /** + * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was + * returned. + * + * <p>The history is not persisted over reboots. + * + * @return The history or {@code null} if there are not events. + */ + @Nullable public final FillEventHistory getFillEventHistory() { + AutofillManager afm = getSystemService(AutofillManager.class); + + if (afm == null) { + return null; + } else { + return afm.getFillEventHistory(); + } + } } diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index e77bd0d753ac..e04fae7bc2b5 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -24,6 +24,7 @@ import android.content.IntentSender; import android.os.Parcel; import android.os.Parcelable; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.widget.RemoteViews; import com.android.internal.util.Preconditions; @@ -50,6 +51,7 @@ public final class Dataset implements Parcelable { private final ArrayList<RemoteViews> mFieldPresentations; private final RemoteViews mPresentation; private final IntentSender mAuthentication; + @Nullable String mId; private Dataset(Builder builder) { mFieldIds = builder.mFieldIds; @@ -57,6 +59,7 @@ public final class Dataset implements Parcelable { mFieldPresentations = builder.mFieldPresentations; mPresentation = builder.mPresentation; mAuthentication = builder.mAuthentication; + mId = builder.mId; } /** @hide */ @@ -89,7 +92,7 @@ public final class Dataset implements Parcelable { public String toString() { if (!DEBUG) return super.toString(); - return new StringBuilder("Dataset [") + return new StringBuilder("Dataset " + mId + " [") .append("fieldIds=").append(mFieldIds) .append(", fieldValues=").append(mFieldValues) .append(", fieldPresentations=") @@ -100,6 +103,17 @@ public final class Dataset implements Parcelable { } /** + * Gets the id of this dataset. + * + * @return The id of this dataset or {@code null} if not set + * + * @hide + */ + public String getId() { + return mId; + } + + /** * A builder for {@link Dataset} objects. You must to provide at least * one value for a field or set an authentication intent. */ @@ -110,6 +124,7 @@ public final class Dataset implements Parcelable { private RemoteViews mPresentation; private IntentSender mAuthentication; private boolean mDestroyed; + @Nullable private String mId; /** * Creates a new builder. @@ -173,6 +188,25 @@ public final class Dataset implements Parcelable { } /** + * Sets the id for the dataset. + * + * <p>The id of the last selected dataset can be read from + * {@link AutofillService#getFillEventHistory()}. If the id is not set it will not be clear + * if a dataset was selected as {@link AutofillService#getFillEventHistory()} uses + * {@code null} to indicate that no dataset was selected. + * + * @param id id for this dataset or {@code null} to unset. + + * @return This builder. + */ + public @NonNull Builder setId(@Nullable String id) { + throwIfDestroyed(); + + mId = id; + return this; + } + + /** * Sets the value of a field. * * @param id id returned by {@link @@ -269,6 +303,7 @@ public final class Dataset implements Parcelable { parcel.writeTypedArrayList(mFieldValues, flags); parcel.writeParcelableList(mFieldPresentations, flags); parcel.writeParcelable(mAuthentication, flags); + parcel.writeString(mId); } public static final Creator<Dataset> CREATOR = new Creator<Dataset>() { @@ -295,6 +330,7 @@ public final class Dataset implements Parcelable { builder.setValueAndPresentation(id, value, fieldPresentation); } builder.setAuthentication(parcel.readParcelable(null)); + builder.setId(parcel.readString()); return builder.build(); } diff --git a/core/java/android/service/autofill/FillEventHistory.aidl b/core/java/android/service/autofill/FillEventHistory.aidl new file mode 100644 index 000000000000..3c4852423d1b --- /dev/null +++ b/core/java/android/service/autofill/FillEventHistory.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +parcelable FillEventHistory; diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java new file mode 100644 index 000000000000..3d72fccece9c --- /dev/null +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.content.IntentSender; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.autofill.AutofillId; +import android.widget.RemoteViews; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +/** + * Describes what happened after the latest call to {@link FillCallback#onSuccess(FillResponse)}. + */ +public final class FillEventHistory implements Parcelable { + /** + * Not in parcel. The UID of the {@link AutofillService} that created the {@link FillResponse}. + */ + private final int mServiceUid; + + @Nullable private final Bundle mClientState; + @Nullable List<Event> mEvents; + + /** + * Gets the UID of the {@link AutofillService} that created the {@link FillResponse}. + * + * @return The UID of the {@link AutofillService} + * + * @hide + */ + public int getServiceUid() { + return mServiceUid; + } + + /** + * Returns the client state of the {@link FillResponse}. + * + * @return The client state set by the last {@link FillResponse} + */ + @Nullable public Bundle getClientState() { + return mClientState; + } + + /** + * Returns the events occurred after the latest call to + * {@link FillCallback#onSuccess(FillResponse)}. + * + * @return The list of events or {@code null} if non occurred. + */ + @Nullable public List<Event> getEvents() { + return mEvents; + } + + /** + * @hide + */ + public void addEvent(Event event) { + if (mEvents == null) { + mEvents = new ArrayList<>(1); + } + mEvents.add(event); + } + + /** + * @hide + */ + public FillEventHistory(int serviceUid, @Nullable Bundle clientState) { + mClientState = clientState; + mServiceUid = serviceUid; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeBundle(mClientState); + + if (mEvents == null) { + dest.writeInt(0); + } else { + dest.writeInt(mEvents.size()); + + int numEvents = mEvents.size(); + for (int i = 0; i < numEvents; i++) { + Event event = mEvents.get(i); + dest.writeInt(event.getType()); + dest.writeString(event.getDatasetId()); + } + } + } + + /** + * Description of an event that occured after the latest call to + * {@link FillCallback#onSuccess(FillResponse)}. + */ + public static final class Event { + /** + * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}. + */ + public static final int TYPE_DATASET_SELECTED = 0; + + /** + * A {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was + * selected. The dataset authenticated can be read from {@link #getDatasetId()}. + */ + public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; + + /** + * A {@link FillResponse.Builder#setAuthentication(AutofillId[], IntentSender, RemoteViews) + * fill response authentication} was selected. + */ + public static final int TYPE_AUTHENTICATION_SELECTED = 2; + + /** A save UI was shown. */ + public static final int TYPE_SAVE_SHOWN = 3; + + /** @hide */ + @IntDef( + value = {TYPE_DATASET_SELECTED, + TYPE_DATASET_AUTHENTICATION_SELECTED, + TYPE_AUTHENTICATION_SELECTED, + TYPE_SAVE_SHOWN}) + @Retention(RetentionPolicy.SOURCE) + @interface EventIds{} + + @EventIds private final int mEventType; + @Nullable private final String mDatasetId; + + /** + * Returns the type of the event. + * + * @return The type of the event + */ + public int getType() { + return mEventType; + } + + /** + * Returns the id of dataset the id was on. + * + * @return The id of dataset, or {@code null} the event is not associated with a dataset. + */ + @Nullable public String getDatasetId() { + return mDatasetId; + } + + /** + * Creates a new event. + * + * @param eventType The type of the event + * @param datasetId The dataset the event was on, or {@code null} if the event was on the + * whole response. + * + * @hide + */ + public Event(int eventType, String datasetId) { + mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_SAVE_SHOWN, + "eventType"); + mDatasetId = datasetId; + } + } + + public static final Parcelable.Creator<FillEventHistory> CREATOR = + new Parcelable.Creator<FillEventHistory>() { + @Override + public FillEventHistory createFromParcel(Parcel parcel) { + FillEventHistory selection = new FillEventHistory(0, parcel.readBundle()); + + int numEvents = parcel.readInt(); + for (int i = 0; i < numEvents; i++) { + selection.addEvent(new Event(parcel.readInt(), parcel.readString())); + } + + return selection; + } + + @Override + public FillEventHistory[] newArray(int size) { + return new FillEventHistory[size]; + } + }; +} diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index f9f400d83b09..34e30564c10b 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -31,6 +31,8 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; import android.os.RemoteException; +import android.service.autofill.AutofillService; +import android.service.autofill.FillEventHistory; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -334,6 +336,20 @@ public final class AutofillManager { } /** + * Should always be called from {@link AutofillService#getFillEventHistory()}. + * + * @hide + */ + @Nullable public FillEventHistory getFillEventHistory() { + try { + return mService.getFillEventHistory(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return null; + } + } + + /** * Explicitly requests a new autofill context. * * <p>Normally, the autofill context is automatically started when autofillable views are diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 68b3ccabc8be..df777c4a6869 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -19,6 +19,7 @@ package android.view.autofill; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; +import android.service.autofill.FillEventHistory; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; import android.view.autofill.IAutoFillManagerClient; @@ -33,6 +34,7 @@ interface IAutoFillManager { int startSession(IBinder activityToken, IBinder windowToken, in IBinder appCallback, in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags, String packageName); + FillEventHistory getFillEventHistory(); boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback); void setWindow(int sessionId, in IBinder windowToken); void updateSession(int sessionId, in AutofillId id, in Rect bounds, diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index d6f525655d56..6ef33e396998 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -48,6 +48,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; +import android.service.autofill.FillEventHistory; import android.util.LocalLog; import android.util.Log; import android.util.Slog; @@ -398,6 +399,21 @@ public final class AutofillManagerService extends SystemService { } @Override + public FillEventHistory getFillEventHistory() throws RemoteException { + UserHandle user = getCallingUserHandle(); + int uid = getCallingUid(); + + synchronized (mLock) { + AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier()); + if (service != null) { + return service.getFillEventHistory(uid); + } + } + + return null; + } + + @Override public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback) throws RemoteException { activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 57ef6d01a96b..e274e18e1b31 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -48,7 +48,9 @@ import android.os.UserManager; import android.provider.Settings; import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; +import android.service.autofill.FillEventHistory; import android.service.autofill.FillRequest; +import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.LocalLog; @@ -122,6 +124,10 @@ final class AutofillManagerServiceImpl { @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); + /** The last selection */ + @GuardedBy("mLock") + private FillEventHistory mEventHistory; + /** * Receiver of assist data from the app's {@link Activity}. */ @@ -500,6 +506,72 @@ final class AutofillManagerServiceImpl { return mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()); } + /** + * Initializes the last fill selection after an autofill service returned a new + * {@link FillResponse}. + */ + void setLastResponse(int serviceUid, @NonNull FillResponse response) { + synchronized (mLock) { + mEventHistory = new FillEventHistory(serviceUid, response.getClientState()); + } + } + + /** + * Updates the last fill selection when an authentication was selected. + */ + void setAuthenticationSelected() { + synchronized (mLock) { + mEventHistory.addEvent( + new FillEventHistory.Event(FillEventHistory.Event.TYPE_AUTHENTICATION_SELECTED, null)); + } + } + + /** + * Updates the last fill selection when an dataset authentication was selected. + */ + void setDatasetAuthenticationSelected(@Nullable String selectedDataset) { + synchronized (mLock) { + mEventHistory.addEvent(new FillEventHistory.Event( + FillEventHistory.Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset)); + } + } + + /** + * Updates the last fill selection when an save Ui is shown. + */ + void setSaveShown() { + synchronized (mLock) { + mEventHistory.addEvent(new FillEventHistory.Event(FillEventHistory.Event.TYPE_SAVE_SHOWN, null)); + } + } + + /** + * Updates the last fill response when a dataset was selected. + */ + void setDatasetSelected(@Nullable String selectedDataset) { + synchronized (mLock) { + mEventHistory.addEvent( + new FillEventHistory.Event(FillEventHistory.Event.TYPE_DATASET_SELECTED, selectedDataset)); + } + } + + /** + * Gets the fill event history. + * + * @param callingUid The calling uid + * + * @return The history or {@code null} if there is none. + */ + FillEventHistory getFillEventHistory(int callingUid) { + synchronized (mLock) { + if (mEventHistory != null && mEventHistory.getServiceUid() == callingUid) { + return mEventHistory; + } + } + + return null; + } + void dumpLocked(String prefix, PrintWriter pw) { final String prefix2 = prefix + " "; @@ -528,6 +600,20 @@ final class AutofillManagerServiceImpl { mSessions.valueAt(i).dumpLocked(prefix2, pw); } } + + if (mEventHistory == null || mEventHistory.getEvents().size() == 0) { + pw.print(prefix); pw.println("No event on last fill response"); + } else { + pw.print(prefix); pw.println("Events of last fill response:"); + pw.print(prefix); + + int numEvents = mEventHistory.getEvents().size(); + for (int i = 0; i < numEvents; i++) { + FillEventHistory.Event event = mEventHistory.getEvents().get(i); + pw.println(" " + i + ": eventType=" + event.getType() + " datasetId=" + + event.getDatasetId()); + } + } } void destroySessionsLocked() { diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 3badcfcb61cd..4d0f38042276 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -87,7 +87,7 @@ final class RemoteFillService implements DeathRecipient { private PendingRequest mPendingRequest; public interface FillServiceCallbacks { - void onFillRequestSuccess(@Nullable FillResponse response, + void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, @NonNull String servicePackageName, int requestId); void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); @@ -252,11 +252,11 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, - FillResponse response, int requestId) { + int callingUid, FillResponse response, int requestId) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { - mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName(), - requestId); + mCallbacks.onFillRequestSuccess(response, callingUid, + mComponentName.getPackageName(), requestId); } }); } @@ -424,7 +424,7 @@ final class RemoteFillService implements DeathRecipient { RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { remoteService.dispatchOnFillRequestSuccess( - PendingFillRequest.this, response, requestId); + PendingFillRequest.this, getCallingUid(), response, requestId); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index c92c52fde8eb..2b9961428a29 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -229,7 +229,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override - public void onFillRequestSuccess(@Nullable FillResponse response, + public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, @NonNull String servicePackageName, int requestId) { if (response == null) { if ((mFlags & FLAG_MANUAL_REQUEST) != 0) { @@ -241,6 +241,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } + mService.setLastResponse(serviceUid, response); + if ((response.getDatasets() == null || response.getDatasets().isEmpty()) && response.getAuthentication() == null) { // Response is "empty" from an UI point of view, need to notify client. @@ -314,6 +316,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { fillInIntent = createAuthFillInIntent(mStructure, extras); } + + mService.setAuthenticationSelected(); + mHandlerCaller.getHandler().post(() -> startAuthentication(intent, fillInIntent)); } @@ -542,6 +547,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } if (atLeastOneChanged) { + mService.setSaveShown(); getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName); return false; } @@ -882,12 +888,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { // Autofill it directly... if (dataset.getAuthentication() == null) { + mService.setDatasetSelected(dataset.getId()); + autoFillApp(dataset); return; } // ...or handle authentication. // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already + mService.setDatasetAuthenticationSelected(dataset.getId()); mDatasetWaitingAuth = dataset; setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH); final Intent fillInIntent = createAuthFillInIntent(mStructure, null); |