Merge changes from topics 'bug_62802026_take_2', 'bug_62802026' into oc-dev
* changes: Don't add FillEventHistory events to the wrong session. Fixed how FillEventHistory is reset and clarified javadoc.
This commit is contained in:
committed by
Android (Google) Code Review
commit
4f7fd183eb
@@ -208,12 +208,22 @@ public abstract class AutofillService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was
|
* Gets the events that happened after the last
|
||||||
* returned.
|
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
|
||||||
|
* call.
|
||||||
*
|
*
|
||||||
* <p>The history is not persisted over reboots.
|
* <p>This method is typically used to keep track of previous user actions to optimize further
|
||||||
|
* requests. For example, the service might return email addresses in alphabetical order by
|
||||||
|
* default, but change that order based on the address the user picked on previous requests.
|
||||||
*
|
*
|
||||||
* @return The history or {@code null} if there are not events.
|
* <p>The history is not persisted over reboots, and it's cleared every time the service
|
||||||
|
* replies to a {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} by calling
|
||||||
|
* {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)}
|
||||||
|
* (if the service doesn't call any of these methods, the history will clear out after some
|
||||||
|
* pre-defined time). Hence, the service should call {@link #getFillEventHistory()} before
|
||||||
|
* finishing the {@link FillCallback}.
|
||||||
|
*
|
||||||
|
* @return The history or {@code null} if there are no events.
|
||||||
*/
|
*/
|
||||||
@Nullable public final FillEventHistory getFillEventHistory() {
|
@Nullable public final FillEventHistory getFillEventHistory() {
|
||||||
AutofillManager afm = getSystemService(AutofillManager.class);
|
AutofillManager afm = getSystemService(AutofillManager.class);
|
||||||
|
|||||||
@@ -33,7 +33,20 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes what happened after the latest call to {@link FillCallback#onSuccess(FillResponse)}.
|
* Describes what happened after the last
|
||||||
|
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
|
||||||
|
* call.
|
||||||
|
*
|
||||||
|
* <p>This history is typically used to keep track of previous user actions to optimize further
|
||||||
|
* requests. For example, the service might return email addresses in alphabetical order by
|
||||||
|
* default, but change that order based on the address the user picked on previous requests.
|
||||||
|
*
|
||||||
|
* <p>The history is not persisted over reboots, and it's cleared every time the service
|
||||||
|
* replies to a
|
||||||
|
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
|
||||||
|
* by calling {@link FillCallback#onSuccess(FillResponse)} or
|
||||||
|
* {@link FillCallback#onFailure(CharSequence)} (if the service doesn't call any of these methods,
|
||||||
|
* the history will clear out after some pre-defined time).
|
||||||
*/
|
*/
|
||||||
public final class FillEventHistory implements Parcelable {
|
public final class FillEventHistory implements Parcelable {
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +54,11 @@ public final class FillEventHistory implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
private final int mServiceUid;
|
private final int mServiceUid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not in parcel. The ID of the autofill session that created the {@link FillResponse}.
|
||||||
|
*/
|
||||||
|
private final int mSessionId;
|
||||||
|
|
||||||
@Nullable private final Bundle mClientState;
|
@Nullable private final Bundle mClientState;
|
||||||
@Nullable List<Event> mEvents;
|
@Nullable List<Event> mEvents;
|
||||||
|
|
||||||
@@ -55,10 +73,17 @@ public final class FillEventHistory implements Parcelable {
|
|||||||
return mServiceUid;
|
return mServiceUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public int getSessionId() {
|
||||||
|
return mSessionId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the client state of the {@link FillResponse}.
|
* Returns the client state set in the previous {@link FillResponse}.
|
||||||
*
|
*
|
||||||
* @return The client state set by the last {@link FillResponse}
|
* <p><b>NOTE: </b>the state is associated with the app that was autofilled in the previous
|
||||||
|
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
|
||||||
|
* , which is not necessary the same app being autofilled now.
|
||||||
*/
|
*/
|
||||||
@Nullable public Bundle getClientState() {
|
@Nullable public Bundle getClientState() {
|
||||||
return mClientState;
|
return mClientState;
|
||||||
@@ -87,9 +112,10 @@ public final class FillEventHistory implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public FillEventHistory(int serviceUid, @Nullable Bundle clientState) {
|
public FillEventHistory(int serviceUid, int sessionId, @Nullable Bundle clientState) {
|
||||||
mClientState = clientState;
|
mClientState = clientState;
|
||||||
mServiceUid = serviceUid;
|
mServiceUid = serviceUid;
|
||||||
|
mSessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,7 +216,7 @@ public final class FillEventHistory implements Parcelable {
|
|||||||
new Parcelable.Creator<FillEventHistory>() {
|
new Parcelable.Creator<FillEventHistory>() {
|
||||||
@Override
|
@Override
|
||||||
public FillEventHistory createFromParcel(Parcel parcel) {
|
public FillEventHistory createFromParcel(Parcel parcel) {
|
||||||
FillEventHistory selection = new FillEventHistory(0, parcel.readBundle());
|
FillEventHistory selection = new FillEventHistory(0, 0, parcel.readBundle());
|
||||||
|
|
||||||
int numEvents = parcel.readInt();
|
int numEvents = parcel.readInt();
|
||||||
for (int i = 0; i < numEvents; i++) {
|
for (int i = 0; i < numEvents; i++) {
|
||||||
|
|||||||
@@ -489,48 +489,80 @@ final class AutofillManagerServiceImpl {
|
|||||||
* Initializes the last fill selection after an autofill service returned a new
|
* Initializes the last fill selection after an autofill service returned a new
|
||||||
* {@link FillResponse}.
|
* {@link FillResponse}.
|
||||||
*/
|
*/
|
||||||
void setLastResponse(int serviceUid, @NonNull FillResponse response) {
|
void setLastResponse(int serviceUid, int sessionId, @NonNull FillResponse response) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mEventHistory = new FillEventHistory(serviceUid, response.getClientState());
|
mEventHistory = new FillEventHistory(serviceUid, sessionId, response.getClientState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the last fill selection.
|
||||||
|
*/
|
||||||
|
void resetLastResponse() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mEventHistory = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidEventLocked(String method, int sessionId) {
|
||||||
|
if (mEventHistory == null) {
|
||||||
|
Slog.w(TAG, method + ": not logging event because history is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (sessionId != mEventHistory.getSessionId()) {
|
||||||
|
if (sDebug) {
|
||||||
|
Slog.d(TAG, method + ": not logging event for session " + sessionId
|
||||||
|
+ " because tracked session is " + mEventHistory.getSessionId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the last fill selection when an authentication was selected.
|
* Updates the last fill selection when an authentication was selected.
|
||||||
*/
|
*/
|
||||||
void setAuthenticationSelected() {
|
void setAuthenticationSelected(int sessionId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (isValidEventLocked("setAuthenticationSelected()", sessionId)) {
|
||||||
mEventHistory.addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null));
|
mEventHistory.addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the last fill selection when an dataset authentication was selected.
|
* Updates the last fill selection when an dataset authentication was selected.
|
||||||
*/
|
*/
|
||||||
void setDatasetAuthenticationSelected(@Nullable String selectedDataset) {
|
void setDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (isValidEventLocked("setDatasetAuthenticationSelected()", sessionId)) {
|
||||||
mEventHistory.addEvent(
|
mEventHistory.addEvent(
|
||||||
new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
|
new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the last fill selection when an save Ui is shown.
|
* Updates the last fill selection when an save Ui is shown.
|
||||||
*/
|
*/
|
||||||
void setSaveShown() {
|
void setSaveShown(int sessionId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (isValidEventLocked("setSaveShown()", sessionId)) {
|
||||||
mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null));
|
mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the last fill response when a dataset was selected.
|
* Updates the last fill response when a dataset was selected.
|
||||||
*/
|
*/
|
||||||
void setDatasetSelected(@Nullable String selectedDataset) {
|
void setDatasetSelected(@Nullable String selectedDataset, int sessionId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (isValidEventLocked("setDatasetSelected()", sessionId)) {
|
||||||
mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset));
|
mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the fill event history.
|
* Gets the fill event history.
|
||||||
|
|||||||
@@ -427,6 +427,7 @@ final class RemoteFillService implements DeathRecipient {
|
|||||||
mCompleted = true;
|
mCompleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out");
|
||||||
final RemoteFillService remoteService = mWeakService.get();
|
final RemoteFillService remoteService = mWeakService.get();
|
||||||
if (remoteService != null) {
|
if (remoteService != null) {
|
||||||
fail(remoteService);
|
fail(remoteService);
|
||||||
|
|||||||
@@ -407,13 +407,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
if ((requestFlags & FLAG_MANUAL_REQUEST) != 0) {
|
if ((requestFlags & FLAG_MANUAL_REQUEST) != 0) {
|
||||||
getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
|
getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
|
||||||
}
|
}
|
||||||
|
mService.resetLastResponse();
|
||||||
// Nothing to be done, but need to notify client.
|
// Nothing to be done, but need to notify client.
|
||||||
notifyUnavailableToClient();
|
notifyUnavailableToClient();
|
||||||
removeSelf();
|
removeSelf();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mService.setLastResponse(serviceUid, response);
|
mService.setLastResponse(serviceUid, id, response);
|
||||||
|
|
||||||
if ((response.getDatasets() == null || response.getDatasets().isEmpty())
|
if ((response.getDatasets() == null || response.getDatasets().isEmpty())
|
||||||
&& response.getAuthentication() == null) {
|
&& response.getAuthentication() == null) {
|
||||||
@@ -444,6 +445,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
+ id + " destroyed");
|
+ id + " destroyed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mService.resetLastResponse();
|
||||||
}
|
}
|
||||||
LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
|
LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
|
||||||
.setType(MetricsEvent.TYPE_FAILURE)
|
.setType(MetricsEvent.TYPE_FAILURE)
|
||||||
@@ -542,7 +544,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
getFillContextByRequestIdLocked(requestId).getStructure(), extras);
|
getFillContextByRequestIdLocked(requestId).getStructure(), extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
mService.setAuthenticationSelected();
|
mService.setAuthenticationSelected(id);
|
||||||
|
|
||||||
final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex);
|
final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex);
|
||||||
mHandlerCaller.getHandler().post(() -> startAuthentication(authenticationId,
|
mHandlerCaller.getHandler().post(() -> startAuthentication(authenticationId,
|
||||||
@@ -831,7 +833,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
}
|
}
|
||||||
if (atLeastOneChanged) {
|
if (atLeastOneChanged) {
|
||||||
if (sDebug) Slog.d(TAG, "at least one field changed - showing save UI");
|
if (sDebug) Slog.d(TAG, "at least one field changed - showing save UI");
|
||||||
mService.setSaveShown();
|
mService.setSaveShown(id);
|
||||||
getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName,
|
getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
@@ -1362,14 +1364,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
}
|
}
|
||||||
// Autofill it directly...
|
// Autofill it directly...
|
||||||
if (dataset.getAuthentication() == null) {
|
if (dataset.getAuthentication() == null) {
|
||||||
mService.setDatasetSelected(dataset.getId());
|
mService.setDatasetSelected(dataset.getId(), id);
|
||||||
|
|
||||||
autoFillApp(dataset);
|
autoFillApp(dataset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...or handle authentication.
|
// ...or handle authentication.
|
||||||
mService.setDatasetAuthenticationSelected(dataset.getId());
|
mService.setDatasetAuthenticationSelected(dataset.getId(), id);
|
||||||
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
|
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
|
||||||
final Intent fillInIntent = createAuthFillInIntent(
|
final Intent fillInIntent = createAuthFillInIntent(
|
||||||
getFillContextByRequestIdLocked(requestId).getStructure(), mClientState);
|
getFillContextByRequestIdLocked(requestId).getStructure(), mClientState);
|
||||||
|
|||||||
Reference in New Issue
Block a user