From 19e38edfe60939c475b2eedd85aacfaf1eeb2ffa Mon Sep 17 00:00:00 2001 From: Simranjit Kohli Date: Thu, 10 Aug 2023 05:48:26 -0700 Subject: [PATCH] [Autofill PCC] Avoid duplicates suggestions with prefer_pcc Avoid the possibility of showing up duplicate suggestions with preferPCC. If the dataset is being picked up because the type is detected by the PCC, include other fields specified by the provider too (only if those autofill id's aren't detected by the PCC) This also removes empty datasets being created during processing. Bug: 293313411 Fixes: 295184051 Test: atest CtsAutoFillServiceTestCases Change-Id: I4a82d19350fe02ad5758682ba4d5535908a9a14a Merged-In: I4a82d19350fe02ad5758682ba4d5535908a9a14a --- .../com/android/server/autofill/Session.java | 139 +++++++++++++----- 1 file changed, 100 insertions(+), 39 deletions(-) diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 65e1916c27de4..d6702b7ecf9d1 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -1840,6 +1840,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + /** + * Computes datasets that are eligible to be shown based on provider detections. + * Datasets are populated in the provided container for them to be later merged with the + * PCC eligible datasets based on preference strategy. + * @param response + * @param container + */ private void computeDatasetsForProviderAndUpdateContainer( FillResponse response, DatasetComputationContainer container) { @DatasetEligibleReason int globalPickReason = PICK_REASON_UNKNOWN; @@ -1940,6 +1947,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState container.mAutofillIds = eligibleAutofillIds; } + /** + * Computes datasets that are eligible to be shown based on PCC detections. + * Datasets are populated in the provided container for them to be later merged with the + * provider eligible datasets based on preference strategy. + * @param response + * @param container + */ private void computeDatasetsForPccAndUpdateContainer( FillResponse response, DatasetComputationContainer container) { List datasets = response.getDatasets(); @@ -1974,11 +1988,33 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState ArrayList fieldFilters = new ArrayList<>(); Set datasetAutofillIds = new LinkedHashSet<>(); + boolean isDatasetAvailable = false; + Set additionalDatasetAutofillIds = new LinkedHashSet<>(); + Set additionalEligibleAutofillIds = new LinkedHashSet<>(); + for (int j = 0; j < dataset.getAutofillDatatypes().size(); j++) { if (dataset.getAutofillDatatypes().get(j) == null) { + // TODO : revisit pickReason logic if (dataset.getFieldIds() != null && dataset.getFieldIds().get(j) != null) { pickReason = PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER; } + // Check if the autofill id at this index is detected by PCC. + // If not, add that id here, otherwise, we can have duplicates when later + // merging with provider datasets. + // Howover, this doesn't make datasetAvailable for PCC on its own. + // For that, there has to be a datatype detected by PCC, and the dataset + // for that datatype provided by the provider. + AutofillId autofillId = dataset.getFieldIds().get(j); + if (!mClassificationState.mClassificationCombinedHintsMap + .containsKey(autofillId)) { + additionalEligibleAutofillIds.add(autofillId); + additionalDatasetAutofillIds.add(autofillId); + // For each of the field, copy over values. + copyFieldsFromDataset(dataset, j, autofillId, fieldIds, fieldValues, + fieldPresentations, fieldDialogPresentations, + fieldInlinePresentations, fieldInlineTooltipPresentations, + fieldFilters); + } continue; } String hint = dataset.getAutofillDatatypes().get(j); @@ -1986,22 +2022,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (hintsToAutofillIdMap.containsKey(hint)) { ArrayList tempIds = new ArrayList<>(hintsToAutofillIdMap.get(hint)); - + if (tempIds.isEmpty()) { + continue; + } + isDatasetAvailable = true; for (AutofillId autofillId : tempIds) { eligibleAutofillIds.add(autofillId); datasetAutofillIds.add(autofillId); // For each of the field, copy over values. - fieldIds.add(autofillId); - fieldValues.add(dataset.getFieldValues().get(j)); - // TODO(b/266379948): might need to make it more efficient by not - // copying over value if it didn't exist. This would require creating - // a getter for the presentations arraylist. - fieldPresentations.add(dataset.getFieldPresentation(j)); - fieldDialogPresentations.add(dataset.getFieldDialogPresentation(j)); - fieldInlinePresentations.add(dataset.getFieldInlinePresentation(j)); - fieldInlineTooltipPresentations.add( - dataset.getFieldInlineTooltipPresentation(j)); - fieldFilters.add(dataset.getFilter(j)); + copyFieldsFromDataset(dataset, j, autofillId, fieldIds, fieldValues, + fieldPresentations, fieldDialogPresentations, + fieldInlinePresentations, fieldInlineTooltipPresentations, + fieldFilters); } } // TODO(b/266379948): handle the case: @@ -2010,34 +2042,38 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // TODO(b/266379948): also handle the case where there could be more types in // the dataset, provided by the provider, however, they aren't applicable. } - Dataset newDataset = - new Dataset( - fieldIds, - fieldValues, - fieldPresentations, - fieldDialogPresentations, - fieldInlinePresentations, - fieldInlineTooltipPresentations, - fieldFilters, - new ArrayList<>(), - dataset.getFieldContent(), - null, - null, - null, - null, - dataset.getId(), - dataset.getAuthentication()); - newDataset.setEligibleReasonReason(pickReason); - eligibleDatasets.add(newDataset); - Set newDatasets; - for (AutofillId autofillId : datasetAutofillIds) { - if (map.containsKey(autofillId)) { - newDatasets = map.get(autofillId); - } else { - newDatasets = new LinkedHashSet<>(); + if (isDatasetAvailable) { + datasetAutofillIds.addAll(additionalDatasetAutofillIds); + eligibleAutofillIds.addAll(additionalEligibleAutofillIds); + Dataset newDataset = + new Dataset( + fieldIds, + fieldValues, + fieldPresentations, + fieldDialogPresentations, + fieldInlinePresentations, + fieldInlineTooltipPresentations, + fieldFilters, + new ArrayList<>(), + dataset.getFieldContent(), + null, + null, + null, + null, + dataset.getId(), + dataset.getAuthentication()); + newDataset.setEligibleReasonReason(pickReason); + eligibleDatasets.add(newDataset); + Set newDatasets; + for (AutofillId autofillId : datasetAutofillIds) { + if (map.containsKey(autofillId)) { + newDatasets = map.get(autofillId); + } else { + newDatasets = new LinkedHashSet<>(); + } + newDatasets.add(newDataset); + map.put(autofillId, newDatasets); } - newDatasets.add(newDataset); - map.put(autofillId, newDatasets); } } container.mAutofillIds = eligibleAutofillIds; @@ -2046,6 +2082,31 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + private void copyFieldsFromDataset( + Dataset dataset, + int index, + AutofillId autofillId, + ArrayList fieldIds, + ArrayList fieldValues, + ArrayList fieldPresentations, + ArrayList fieldDialogPresentations, + ArrayList fieldInlinePresentations, + ArrayList fieldInlineTooltipPresentations, + ArrayList fieldFilters) { + // copy over values + fieldIds.add(autofillId); + fieldValues.add(dataset.getFieldValues().get(index)); + // TODO(b/266379948): might need to make it more efficient by not + // copying over value if it didn't exist. This would require creating + // a getter for the presentations arraylist. + fieldPresentations.add(dataset.getFieldPresentation(index)); + fieldDialogPresentations.add(dataset.getFieldDialogPresentation(index)); + fieldInlinePresentations.add(dataset.getFieldInlinePresentation(index)); + fieldInlineTooltipPresentations.add( + dataset.getFieldInlineTooltipPresentation(index)); + fieldFilters.add(dataset.getFilter(index)); + } + // FillServiceCallbacks @Override @SuppressWarnings("GuardedBy")