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

Commit debea0b4 authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

Merge changes from topics "bug_80100983", "fix_save_logic"

* changes:
  Changed Autofill Save UI to show UPDATE instead of SAVE when necessary.
  Fixed Autofill SaveUI logic so it considers all optional savable ids.
parents ab91392a c9f32596
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -4936,10 +4936,29 @@
         by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
         data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
    <string name="autofill_save_title_with_3types">Save <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, and <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%4$s</xliff:g>&lt;/b>?</string>

    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
         by an autofill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
    <string name="autofill_update_title">Update to &lt;b><xliff:g id="label" example="MyPass">%1$s</xliff:g>&lt;/b>?</string>
    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
         by an autofill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
    <string name="autofill_update_title_with_type">Update <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%2$s</xliff:g>&lt;/b>?</string>
    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
         by an autofill service, and the service does knows what the activity represents, and it represents 2 types of
         data (for example, password and credit card info) [CHAR LIMIT=NONE] -->
    <string name="autofill_update_title_with_2types">Update <xliff:g id="type" example="Password">%1$s</xliff:g> and <xliff:g id="type" example="Credit Card">%2$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%3$s</xliff:g>&lt;/b>?</string>
    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
         by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
         data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
    <string name="autofill_update_title_with_3types">Update <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, and <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%4$s</xliff:g>&lt;/b>?</string>


    <!-- Label for the autofill save button [CHAR LIMIT=NONE] -->
    <string name="autofill_save_yes">Save</string>
    <!-- Label for the autofill cancel button [CHAR LIMIT=NONE] -->
    <string name="autofill_save_no">No thanks</string>
    <!-- Label for the autofill update button [CHAR LIMIT=NONE] -->
    <string name="autofill_update_yes">Update</string>

    <!-- Label for the type of data being saved for autofill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
    <string name="autofill_save_type_password">password</string>
+5 −0
Original line number Diff line number Diff line
@@ -3108,6 +3108,11 @@
  <java-symbol type="plurals" name="autofill_picker_some_suggestions" />
  <java-symbol type="string" name="autofill" />
  <java-symbol type="string" name="autofill_picker_accessibility_title " />
  <java-symbol type="string" name="autofill_update_title" />
  <java-symbol type="string" name="autofill_update_title_with_type" />
  <java-symbol type="string" name="autofill_update_title_with_2types" />
  <java-symbol type="string" name="autofill_update_title_with_3types" />
  <java-symbol type="string" name="autofill_update_yes" />
  <java-symbol type="string" name="autofill_save_accessibility_title " />
  <java-symbol type="string" name="autofill_save_title" />
  <java-symbol type="string" name="autofill_save_title_with_type" />
+5 −0
Original line number Diff line number Diff line
@@ -4084,6 +4084,8 @@ message MetricsEvent {
    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
    // NOTE: starting on OS Q, it also added the following fields:
    // FIELD_AUTOFILL_UPDATE: Whether the UI displayed "UPDATE" instead of "SAVE"
    AUTOFILL_SAVE_UI = 916;

    // Tag of a field for the number of saveable ids
@@ -6430,6 +6432,9 @@ message MetricsEvent {
    // OS: Q
    FACE_ENROLL_PREVIEW = 1554;

    // Field used to indicate whether a save request was used to update existing user data.
    FIELD_AUTOFILL_UPDATE = 1555;

    // ---- End Q Constants, all Q constants go above this line ----

    // Add new aosp constants above this line.
+44 −18
Original line number Diff line number Diff line
@@ -1474,11 +1474,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState

        // 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<>();
        // Savable (optional or required) ids that will be checked against the dataset ids.
        final ArraySet<AutofillId> savableIds = new ArraySet<>();

        final AutofillId[] requiredIds = saveInfo.getRequiredIds();
        boolean allRequiredAreNotEmpty = true;
        boolean atLeastOneChanged = false;
        // If an autofilled field is changed, we need to change isUpdate to true so the proper UI is
        // shown.
        boolean isUpdate = false;
        if (requiredIds != null) {
            for (int i = 0; i < requiredIds.length; i++) {
                final AutofillId id = requiredIds[i];
@@ -1486,7 +1490,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    Slog.w(TAG, "null autofill id on " + Arrays.toString(requiredIds));
                    continue;
                }
                allIds.add(id);
                savableIds.add(id);
                final ViewState viewState = mViewStates.get(id);
                if (viewState == null) {
                    Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
@@ -1536,6 +1540,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                            }
                            changed = false;
                        }
                    } else {
                        isUpdate = true;
                    }
                    if (changed) {
                        if (sDebug) {
@@ -1549,12 +1555,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        }

        final AutofillId[] optionalIds = saveInfo.getOptionalIds();
        if (sVerbose) {
            Slog.v(TAG, "allRequiredAreNotEmpty: " + allRequiredAreNotEmpty + " hasOptional: "
                    + (optionalIds != null));
        }
        if (allRequiredAreNotEmpty) {
            if (!atLeastOneChanged && optionalIds != null) {
            // Must look up all optional ids in 2 scenarios:
            // - if no required id changed but an optional id did, it should trigger save / update
            // - if at least one required id changed but it was not part of a filled dataset, we
            //   need to check if an optional id is part of a filled datased (in which case we show
            //   Update instead of Save)
            if (optionalIds!= null && (!atLeastOneChanged || !isUpdate)) {
                // 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);
                    savableIds.add(id);
                    final ViewState viewState = mViewStates.get(id);
                    if (viewState == null) {
                        Slog.w(TAG, "no ViewState for optional " + id);
@@ -1562,15 +1577,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    }
                    if ((viewState.getState() & ViewState.STATE_CHANGED) != 0) {
                        final AutofillValue currentValue = viewState.getCurrentValue();
                        currentValues.put(id, currentValue);
                        final AutofillValue value = getSanitizedValue(sanitizers, id, currentValue);
                        if (value == null) {
                            if (sDebug) {
                                Slog.d(TAG, "value of opt. field " + id + " failed sanitization");
                            }
                            continue;
                        }

                        currentValues.put(id, value);
                        final AutofillValue filledValue = viewState.getAutofilledValue();
                        if (currentValue != null && !currentValue.equals(filledValue)) {
                        if (value != null && !value.equals(filledValue)) {
                            if (sDebug) {
                                Slog.d(TAG, "found a change on optional " + id + ": " + filledValue
                                        + " => " + currentValue);
                                        + " => " + value);
                            }
                            if (filledValue != null) {
                                isUpdate = true;
                            }
                            atLeastOneChanged = true;
                            break;
                        }
                    } else  {
                        // Update current values cache based on initial value
@@ -1623,16 +1648,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                                Helper.getFields(dataset);
                        if (sVerbose) {
                            Slog.v(TAG, "Checking if saved fields match contents of dataset #" + i
                                    + ": " + dataset + "; allIds=" + allIds);
                                    + ": " + dataset + "; savableIds=" + savableIds);
                        }
                        for (int j = 0; j < allIds.size(); j++) {
                            final AutofillId id = allIds.valueAt(j);
                        savable_ids_loop: for (int j = 0; j < savableIds.size(); j++) {
                            final AutofillId id = savableIds.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;
                                continue savable_ids_loop;
                            }
                            final AutofillValue datasetValue = datasetValues.get(id);
                            if (!currentValue.equals(datasetValue)) {
@@ -1658,14 +1683,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                }

                // Use handler so logContextCommitted() is logged first
                mHandler.sendMessage(obtainMessage(
                        Session::logSaveShown, this));
                mHandler.sendMessage(obtainMessage(Session::logSaveShown, this));

                final IAutoFillManagerClient client = getClient();
                mPendingSaveUi = new PendingUi(mActivityToken, id, client);
                getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
                        mService.getServicePackageName(), saveInfo, this,
                        mComponentName, this, mPendingSaveUi, mCompatMode);
                        mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode);
                if (client != null) {
                    try {
                        client.setSaveUiState(id, true);
@@ -1715,12 +1739,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        return sanitizers;
    }

    // TODO: this method is called a few times in the save process, we should cache its results into
    // ViewState.
    @Nullable
    private AutofillValue getSanitizedValue(
            @Nullable ArrayMap<AutofillId, InternalSanitizer> sanitizers,
            @NonNull AutofillId id,
            @NonNull AutofillValue value) {
        if (sanitizers == null) return value;
            @Nullable AutofillValue value) {
        if (sanitizers == null || value == null) return value;

        final InternalSanitizer sanitizer = sanitizers.get(id);
        if (sanitizer == null) {
+7 −3
Original line number Diff line number Diff line
@@ -268,9 +268,10 @@ public final class AutoFillUI {
            @Nullable String servicePackageName, @NonNull SaveInfo info,
            @NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
            @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi,
            boolean compatMode) {
            boolean isUpdate, boolean compatMode) {
        if (sVerbose) {
            Slog.v(TAG, "showSaveUi() for " + componentName.toShortString() + ": " + info);
            Slog.v(TAG, "showSaveUi(update=" + isUpdate + ") for " + componentName.toShortString()
                    + ": " + info);
        }
        int numIds = 0;
        numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
@@ -280,6 +281,9 @@ public final class AutoFillUI {
                .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, componentName, servicePackageName,
                        pendingSaveUi.sessionId, compatMode)
                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
        if (isUpdate) {
            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_UPDATE, 1);
        }

        mHandler.post(() -> {
            if (callback != mCallback) {
@@ -328,7 +332,7 @@ public final class AutoFillUI {
                    }
                    mMetricsLogger.write(log);
                }
            }, compatMode);
            }, isUpdate, compatMode);
        });
    }

Loading