Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c09acb1 authored by Felipe Leme's avatar Felipe Leme Committed by android-build-merger
Browse files

Merge "Don't show Save UI when values filled by user belong to a dataset."...

Merge "Don't show Save UI when values filled by user belong to a dataset." into oc-mr1-dev am: e802d18f
am: 40ebd6cb

Change-Id: I27a29b2eb54532bf09fb6cd5d37ea53f85e922a0
parents e467c32b 40ebd6cb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.Parcelable;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;
+3 −0
Original line number Diff line number Diff line
@@ -118,6 +118,9 @@ import java.util.Arrays;
 *   <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
 *       (i.e., it's neither the same value passed in a {@link Dataset}, nor the initial value
 *       presented in the view).
 *   <li>There is no {@link Dataset} in the last {@link FillResponse} that completely matches the
 *       screen state (i.e., all required and optional fields in the dataset have the same value as
 *       the fields in the screen).
 *   <li>The user explicitly tapped the UI affordance asking to save data for autofill.
 * </ul>
 *
+17 −0
Original line number Diff line number Diff line
@@ -16,11 +16,16 @@

package com.android.server.autofill;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
@@ -82,4 +87,16 @@ public final class Helper {
        }
        return array;
    }

    @NonNull
    static ArrayMap<AutofillId, AutofillValue> getFields(@NonNull Dataset dataset) {
        final ArrayList<AutofillId> ids = dataset.getFieldIds();
        final ArrayList<AutofillValue> values = dataset.getFieldValues();
        final int size = ids == null ? 0 : ids.size();
        final ArrayMap<AutofillId, AutofillValue> fields = new ArrayMap<>(size);
        for (int i = 0; i < size; i++) {
            fields.put(ids.get(i), values.get(i));
        }
        return fields;
    }
}
+64 −9
Original line number Diff line number Diff line
@@ -804,15 +804,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        /*
         * The Save dialog is only shown if all conditions below are met:
         *
         * - saveInfo is not null
         * - autofillValue of all required ids is not null
         * - saveInfo is not null.
         * - autofillValue of all required ids is not null.
         * - autofillValue of at least one id (required or optional) has changed.
         * - there is no Dataset in the last FillResponse whose values of all dataset fields matches
         *   the current values of all fields in the screen.
         */

        if (saveInfo == null) {
            return true;
        }

        // Cache used to make sure changed fields do not belong to a dataset.
        final ArrayMap<AutofillId, AutofillValue> currentValues = new ArrayMap<>();
        final ArraySet<AutofillId> allIds = new ArraySet<>();

        final AutofillId[] requiredIds = saveInfo.getRequiredIds();
        boolean allRequiredAreNotEmpty = true;
        boolean atLeastOneChanged = false;
@@ -823,6 +828,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    Slog.w(TAG, "null autofill id on " + Arrays.toString(requiredIds));
                    continue;
                }
                allIds.add(id);
                final ViewState viewState = mViewStates.get(id);
                if (viewState == null) {
                    Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
@@ -841,18 +847,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                        value = initialValue;
                    } else {
                        if (sDebug) {
                            Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
                            Slog.d(TAG, "empty value for required " + id );
                        }
                        allRequiredAreNotEmpty = false;
                        break;
                    }
                }
                currentValues.put(id, value);
                final AutofillValue filledValue = viewState.getAutofilledValue();

                if (!value.equals(filledValue)) {
                    if (sDebug) {
                        Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": "
                                + filledValue + " => " + value);
                        Slog.d(TAG, "found a change on required " + id + ": " + filledValue
                                + " => " + value);
                    }
                    atLeastOneChanged = true;
                }
@@ -865,22 +872,34 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                // No change on required ids yet, look for changes on optional ids.
                for (int i = 0; i < optionalIds.length; i++) {
                    final AutofillId id = optionalIds[i];
                    allIds.add(id);
                    final ViewState viewState = mViewStates.get(id);
                    if (viewState == null) {
                        Slog.w(TAG, "showSaveLocked(): no ViewState for optional " + id);
                        Slog.w(TAG, "no ViewState for optional " + id);
                        continue;
                    }
                    if ((viewState.getState() & ViewState.STATE_CHANGED) != 0) {
                        final AutofillValue currentValue = viewState.getCurrentValue();
                        currentValues.put(id, currentValue);
                        final AutofillValue filledValue = viewState.getAutofilledValue();
                        if (currentValue != null && !currentValue.equals(filledValue)) {
                            if (sDebug) {
                                Slog.d(TAG, "finishSessionLocked(): found a change on optional "
                                        + id + ": " + filledValue + " => " + currentValue);
                                Slog.d(TAG, "found a change on optional " + id + ": " + filledValue
                                        + " => " + currentValue);
                            }
                            atLeastOneChanged = true;
                            break;
                        }
                    } else {
                        // Update current values cache based on initial value
                        final AutofillValue initialValue = getValueFromContexts(id);
                        if (sDebug) {
                            Slog.d(TAG, "no current value for " + id + "; initial value is "
                                    + initialValue);
                        }
                        if (initialValue != null) {
                            currentValues.put(id, initialValue);
                        }
                    }
                }
            }
@@ -907,6 +926,42 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    }
                }

                // Make sure the service doesn't have the fields already by checking the datasets
                // content.
                final ArrayList<Dataset> datasets = response.getDatasets();
                if (datasets != null) {
                    datasets_loop: for (int i = 0; i < datasets.size(); i++) {
                        final Dataset dataset = datasets.get(i);
                        final ArrayMap<AutofillId, AutofillValue> datasetValues =
                                Helper.getFields(dataset);
                        if (sVerbose) {
                            Slog.v(TAG, "Checking if saved fields match contents of dataset #" + i
                                    + ": " + dataset + "; allIds=" + allIds);
                        }
                        for (int j = 0; j < allIds.size(); j++) {
                            final AutofillId id = allIds.valueAt(j);
                            final AutofillValue currentValue = currentValues.get(id);
                            if (currentValue == null) {
                                if (sDebug) {
                                    Slog.d(TAG, "dataset has value for field that is null: " + id);
                                }
                                continue datasets_loop;
                            }
                            final AutofillValue datasetValue = datasetValues.get(id);
                            if (!currentValue.equals(datasetValue)) {
                                if (sDebug) Slog.d(TAG, "found a change on id " + id);
                                continue datasets_loop;
                            }
                            if (sVerbose) Slog.v(TAG, "no changes for id " + id);
                        }
                        if (sDebug) {
                            Slog.d(TAG, "ignoring Save UI because all fields match contents of "
                                    + "dataset #" + i + ": " + dataset);
                        }
                        return true;
                    }
                }

                if (sDebug) Slog.d(TAG, "Good news, everyone! All checks passed, show save UI!");
                mService.setSaveShown(id);
                getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo,