Merge "Dataset authentication for Augmented Autofill" into rvc-dev

This commit is contained in:
Nikita Dubrovsky
2020-06-17 03:20:39 +00:00
committed by Android (Google) Code Review
5 changed files with 113 additions and 6 deletions

View File

@@ -815,6 +815,19 @@ final class AutofillManagerServiceImpl
}
}
void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset,
@Nullable Bundle clientState) {
synchronized (mLock) {
if (mAugmentedAutofillEventHistory == null
|| mAugmentedAutofillEventHistory.getSessionId() != sessionId) {
return;
}
mAugmentedAutofillEventHistory.addEvent(
new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset,
clientState, null, null, null, null, null, null, null, null));
}
}
void logAugmentedAutofillSelected(int sessionId, @Nullable String suggestionId,
@Nullable Bundle clientState) {
synchronized (mLock) {
@@ -1198,6 +1211,14 @@ final class AutofillManagerServiceImpl
suggestionId, clientState);
}
@Override
public void logAugmentedAutofillAuthenticationSelected(int sessionId,
String suggestionId, Bundle clientState) {
AutofillManagerServiceImpl.this
.logAugmentedAutofillAuthenticationSelected(
sessionId, suggestionId, clientState);
}
@Override
public void onServiceDied(@NonNull RemoteAugmentedAutofillService service) {
Slog.w(TAG, "remote augmented autofill service died");

View File

@@ -263,7 +263,28 @@ final class RemoteAugmentedAutofillService
request, inlineSuggestionsData, focusedId, filterText,
new InlineFillUi.InlineSuggestionUiCallback() {
@Override
public void autofill(Dataset dataset) {
public void autofill(Dataset dataset, int datasetIndex) {
if (dataset.getAuthentication() != null) {
mCallbacks.logAugmentedAutofillAuthenticationSelected(sessionId,
dataset.getId(), clientState);
final IntentSender action = dataset.getAuthentication();
final int authenticationId =
AutofillManager.makeAuthenticationId(
Session.AUGMENTED_AUTOFILL_REQUEST_ID,
datasetIndex);
final Intent fillInIntent = new Intent();
fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE,
clientState);
try {
client.authenticate(sessionId, authenticationId, action,
fillInIntent, false);
} catch (RemoteException e) {
Slog.w(TAG, "Error starting auth flow");
inlineSuggestionsCallback.apply(
InlineFillUi.emptyUi(focusedId));
}
return;
}
mCallbacks.logAugmentedAutofillSelected(sessionId,
dataset.getId(), clientState);
try {
@@ -319,5 +340,8 @@ final class RemoteAugmentedAutofillService
void logAugmentedAutofillSelected(int sessionId, @Nullable String suggestionId,
@Nullable Bundle clientState);
void logAugmentedAutofillAuthenticationSelected(int sessionId,
@Nullable String suggestionId, @Nullable Bundle clientState);
}
}

View File

@@ -144,7 +144,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final MetricsLogger mMetricsLogger = new MetricsLogger();
private static AtomicInteger sIdCounter = new AtomicInteger();
static final int AUGMENTED_AUTOFILL_REQUEST_ID = 1;
private static AtomicInteger sIdCounter = new AtomicInteger(2);
/**
* ID of the session.
@@ -736,7 +738,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
viewState.setState(newState);
int requestId;
// TODO(b/158623971): Update this to prevent possible overflow
do {
requestId = sIdCounter.getAndIncrement();
} while (requestId == INVALID_REQUEST_ID);
@@ -1344,6 +1346,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ id + " destroyed");
return;
}
final int requestId = AutofillManager.getRequestIdFromAuthenticationId(authenticationId);
if (requestId == AUGMENTED_AUTOFILL_REQUEST_ID) {
setAuthenticationResultForAugmentedAutofillLocked(data, authenticationId);
return;
}
if (mResponses == null) {
// Typically happens when app explicitly called cancel() while the service was showing
// the auth UI.
@@ -1351,7 +1358,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
removeSelf();
return;
}
final int requestId = AutofillManager.getRequestIdFromAuthenticationId(authenticationId);
final FillResponse authenticatedResponse = mResponses.get(requestId);
if (authenticatedResponse == null || data == null) {
Slog.w(TAG, "no authenticated response");
@@ -1410,6 +1416,58 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
@GuardedBy("mLock")
void setAuthenticationResultForAugmentedAutofillLocked(Bundle data, int authId) {
final Dataset dataset = (data == null) ? null :
data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (sDebug) {
Slog.d(TAG, "Auth result for augmented autofill: sessionId=" + id
+ ", authId=" + authId + ", dataset=" + dataset);
}
if (dataset == null
|| dataset.getFieldIds().size() != 1
|| dataset.getFieldIds().get(0) == null
|| dataset.getFieldValues().size() != 1
|| dataset.getFieldValues().get(0) == null) {
if (sDebug) {
Slog.d(TAG, "Rejecting empty/invalid auth result");
}
mService.resetLastAugmentedAutofillResponse();
removeSelfLocked();
return;
}
final List<AutofillId> fieldIds = dataset.getFieldIds();
final List<AutofillValue> autofillValues = dataset.getFieldValues();
final AutofillId fieldId = fieldIds.get(0);
final AutofillValue value = autofillValues.get(0);
// Update state to ensure that after filling the field here we don't end up firing another
// autofill request that will end up showing the same suggestions to the user again. When
// the auth activity came up, the field for which the suggestions were shown lost focus and
// mCurrentViewId was cleared. We need to set mCurrentViewId back to the id of the field
// that we are filling.
fieldId.setSessionId(id);
mCurrentViewId = fieldId;
// Notify the Augmented Autofill provider of the dataset that was selected.
final Bundle clientState = data.getBundle(AutofillManager.EXTRA_CLIENT_STATE);
mService.logAugmentedAutofillSelected(id, dataset.getId(), clientState);
// Fill the value into the field.
if (sDebug) {
Slog.d(TAG, "Filling after auth: fieldId=" + fieldId + ", value=" + value);
}
try {
mClient.autofill(id, fieldIds, autofillValues, true);
} catch (RemoteException e) {
Slog.w(TAG, "Error filling after auth: fieldId=" + fieldId + ", value=" + value
+ ", error=" + e);
}
// Clear the suggestions since the user already accepted one of them.
mInlineSessionController.setInlineFillUiLocked(InlineFillUi.emptyUi(fieldId));
}
@GuardedBy("mLock")
void setHasCallbackLocked(boolean hasIt) {
if (mDestroyed) {
@@ -2506,6 +2564,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ actionAsString(action) + ", flags=" + flags);
}
ViewState viewState = mViewStates.get(id);
if (sVerbose) {
Slog.v(TAG, "updateLocked(" + this.id + "): mCurrentViewId=" + mCurrentViewId
+ ", mExpiredResponse=" + mExpiredResponse + ", viewState=" + viewState);
}
if (viewState == null) {
if (action == ACTION_START_SESSION || action == ACTION_VALUE_CHANGED

View File

@@ -290,7 +290,7 @@ public final class InlineFillUi {
/**
* Callback to autofill a dataset to the client app.
*/
void autofill(@NonNull Dataset dataset);
void autofill(@NonNull Dataset dataset, int datasetIndex);
/**
* Callback to start Intent in client app.

View File

@@ -109,7 +109,7 @@ final class InlineSuggestionFactory {
return createInlineSuggestionsInternal(/* isAugmented= */ true, request,
datasets, autofillId, onErrorCallback,
(dataset, datasetIndex) ->
inlineSuggestionUiCallback.autofill(dataset),
inlineSuggestionUiCallback.autofill(dataset, datasetIndex),
(intentSender) ->
inlineSuggestionUiCallback.startIntentSender(intentSender, new Intent()),
remoteRenderService);