diff options
author | Justin Klaassen <justinklaassen@google.com> | 2018-01-03 13:39:41 -0500 |
---|---|---|
committer | Justin Klaassen <justinklaassen@google.com> | 2018-01-03 13:39:41 -0500 |
commit | 98fe7819c6d14f4f464a5cac047f9e82dee5da58 (patch) | |
tree | a6b8b93eb21e205b27590ab5e2a1fb9efe27f892 /com/android/server/autofill/Session.java | |
parent | 4217cf85c20565a3446a662a7f07f26137b26b7f (diff) | |
download | android-28-98fe7819c6d14f4f464a5cac047f9e82dee5da58.tar.gz |
Import Android SDK Platform P [4524038]
/google/data/ro/projects/android/fetch_artifact \
--bid 4524038 \
--target sdk_phone_armv7-win_sdk \
sdk-repo-linux-sources-4524038.zip
AndroidVersion.ApiLevel has been modified to appear as 28
Change-Id: Ic193bf1cf0cae78d4f2bfb4fbddfe42025c5c3c2
Diffstat (limited to 'com/android/server/autofill/Session.java')
-rw-r--r-- | com/android/server/autofill/Session.java | 180 |
1 files changed, 124 insertions, 56 deletions
diff --git a/com/android/server/autofill/Session.java b/com/android/server/autofill/Session.java index 99b92b9c..01f90840 100644 --- a/com/android/server/autofill/Session.java +++ b/com/android/server/autofill/Session.java @@ -55,7 +55,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.service.autofill.AutofillService; import android.service.autofill.Dataset; -import android.service.autofill.FieldsDetection; +import android.service.autofill.FieldClassification.Match; import android.service.autofill.FillContext; import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; @@ -63,7 +63,9 @@ import android.service.autofill.InternalSanitizer; import android.service.autofill.InternalValidator; import android.service.autofill.SaveInfo; import android.service.autofill.SaveRequest; +import android.service.autofill.UserData; import android.service.autofill.ValueFinder; +import android.service.autofill.FieldClassification; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; @@ -126,6 +128,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** uid the session is for */ public final int uid; + /** Flags used to start the session */ + public final int mFlags; + @GuardedBy("mLock") @NonNull private IBinder mActivityToken; @@ -236,6 +241,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState structure.ensureData(); // Sanitize structure before it's sent to service. + final ComponentName componentNameFromApp = structure.getActivityComponent(); + if (!mComponentName.equals(componentNameFromApp)) { + Slog.w(TAG, "Activity " + mComponentName + " forged different component on " + + "AssistStructure: " + componentNameFromApp); + structure.setActivityComponent(mComponentName); + mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME, + componentNameFromApp == null ? "null" + : componentNameFromApp.flattenToShortString())); + } structure.sanitizeForParceling(true); // Flags used to start the session. @@ -429,8 +444,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId, @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken, @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory, - @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName) { + @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName, + int flags) { id = sessionId; + mFlags = flags; this.uid = uid; mStartTime = SystemClock.elapsedRealtime(); mService = service; @@ -444,7 +461,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mComponentName = componentName; mClient = IAutoFillManagerClient.Stub.asInterface(client); - writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED); + mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED) + .addTaggedData(MetricsEvent.FIELD_FLAGS, flags)); } /** @@ -480,7 +498,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response, - int serviceUid, @NonNull String servicePackageName) { + @NonNull String servicePackageName) { + final AutofillId[] fieldClassificationIds; + synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: " @@ -491,16 +511,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState processNullResponseLocked(requestFlags); return; } - } - // TODO(b/67867469): remove once feature is finished - if (response.getFieldsDetection() != null && !mService.isFieldDetectionEnabled()) { - Slog.w(TAG, "Ignoring " + response + " because field detection is disabled"); - processNullResponseLocked(requestFlags); - return; + fieldClassificationIds = response.getFieldClassificationIds(); + if (fieldClassificationIds != null && !mService.isFieldClassificationEnabledLocked()) { + Slog.w(TAG, "Ignoring " + response + " because field detection is disabled"); + processNullResponseLocked(requestFlags); + return; + } } - mService.setLastResponse(serviceUid, id, response); + mService.setLastResponse(id, response); int sessionFinishedState = 0; final long disableDuration = response.getDisableDuration(); @@ -536,6 +556,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState .setType(MetricsEvent.TYPE_SUCCESS) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, response.getDatasets() == null ? 0 : response.getDatasets().size()); + if (fieldClassificationIds != null) { + log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS, + fieldClassificationIds.length); + } mMetricsLogger.write(log); } @@ -882,7 +906,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Generates a {@link android.service.autofill.FillEventHistory.Event#TYPE_CONTEXT_COMMITTED} * when necessary. */ - public void logContextCommittedLocked() { + public void logContextCommitted() { + mHandlerCaller.getHandler().post(() -> { + synchronized (mLock) { + logContextCommittedLocked(); + } + }); + } + + private void logContextCommittedLocked() { final FillResponse lastResponse = getLastResponseLocked("logContextCommited()"); if (lastResponse == null) return; @@ -903,7 +935,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final FillResponse response = mResponses.valueAt(i); final List<Dataset> datasets = response.getDatasets(); if (datasets == null || datasets.isEmpty()) { - if (sVerbose) Slog.v(TAG, "logContextCommitted() no datasets at " + i); + if (sVerbose) Slog.v(TAG, "logContextCommitted() no datasets at " + i); } else { for (int j = 0; j < datasets.size(); j++) { final Dataset dataset = datasets.get(j); @@ -926,29 +958,30 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } } - final FieldsDetection fieldsDetection = lastResponse.getFieldsDetection(); + final AutofillId[] fieldClassificationIds = lastResponse.getFieldClassificationIds(); - if (!hasAtLeastOneDataset && fieldsDetection == null) { + if (!hasAtLeastOneDataset && fieldClassificationIds == null) { if (sVerbose) { Slog.v(TAG, "logContextCommittedLocked(): skipped (no datasets nor fields " - + "detection)"); + + "classification ids)"); } return; } - final AutofillId detectableFieldId; - final String detectableRemoteId; - String detectedRemoteId = null; - if (fieldsDetection == null) { - detectableFieldId = null; - detectableRemoteId = null; + final UserData userData = mService.getUserData(); + + final ArrayList<AutofillId> detectedFieldIds; + final ArrayList<FieldClassification> detectedFieldClassifications; + + if (userData != null) { + final int maxFieldsSize = UserData.getMaxFieldClassificationIdsSize(); + detectedFieldIds = new ArrayList<>(maxFieldsSize); + detectedFieldClassifications = new ArrayList<>(maxFieldsSize); } else { - detectableFieldId = fieldsDetection.getFieldId(); - detectableRemoteId = fieldsDetection.getRemoteId(); + detectedFieldIds = null; + detectedFieldClassifications = null; } - int detectedFieldScore = -1; - for (int i = 0; i < mViewStates.size(); i++) { final ViewState viewState = mViewStates.valueAt(i); final int state = viewState.getState(); @@ -991,8 +1024,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final AutofillValue currentValue = viewState.getCurrentValue(); if (currentValue == null) { if (sDebug) { - Slog.d(TAG, "logContextCommitted(): skipping view witout current value " - + "( " + viewState + ")"); + Slog.d(TAG, "logContextCommitted(): skipping view without current " + + "value ( " + viewState + ")"); } continue; } @@ -1053,18 +1086,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } // for j } - // Check if detectable field changed. - if (detectableFieldId != null && detectableFieldId.equals(viewState.id) - && currentValue.isText() && currentValue.getTextValue() != null) { - final String actualValue = currentValue.getTextValue().toString(); - final String expectedValue = fieldsDetection.getValue(); - if (actualValue.equalsIgnoreCase(expectedValue)) { - detectedRemoteId = detectableRemoteId; - detectedFieldScore = 0; - } else if (sVerbose) { - Slog.v(TAG, "Detection mismatch for field " + detectableFieldId); - } - // TODO(b/67867469): set score on partial hits + // Sets field classification score for field + if (userData!= null) { + setScore(detectedFieldIds, detectedFieldClassifications, userData, + viewState.id, currentValue); } } // else } // else @@ -1077,8 +1102,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + ", changedAutofillIds=" + changedFieldIds + ", changedDatasetIds=" + changedDatasetIds + ", manuallyFilledIds=" + manuallyFilledIds - + ", detectableFieldId=" + detectableFieldId - + ", detectedFieldScore=" + detectedFieldScore + + ", detectedFieldIds=" + detectedFieldIds + + ", detectedFieldClassifications=" + detectedFieldClassifications ); } @@ -1098,10 +1123,53 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - mService.logContextCommitted(id, mClientState, mSelectedDatasetIds, ignoredDatasets, + mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, - detectedRemoteId, detectedFieldScore); + detectedFieldIds, detectedFieldClassifications, mComponentName.getPackageName()); + } + + /** + * Adds the matches to {@code detectedFieldsIds} and {@code detectedFieldClassifications} for + * {@code fieldId} based on its {@code currentValue} and {@code userData}. + */ + private static void setScore(@NonNull ArrayList<AutofillId> detectedFieldIds, + @NonNull ArrayList<FieldClassification> detectedFieldClassifications, + @NonNull UserData userData, @NonNull AutofillId fieldId, + @NonNull AutofillValue currentValue) { + + final String[] userValues = userData.getValues(); + final String[] remoteIds = userData.getRemoteIds(); + + // Sanity check + if (userValues == null || remoteIds == null || userValues.length != remoteIds.length) { + final int valuesLength = userValues == null ? -1 : userValues.length; + final int idsLength = remoteIds == null ? -1 : remoteIds.length; + Slog.w(TAG, "setScores(): user data mismatch: values.length = " + + valuesLength + ", ids.length = " + idsLength); + return; + } + + ArrayList<Match> matches = null; + for (int i = 0; i < userValues.length; i++) { + String remoteId = remoteIds[i]; + final String value = userValues[i]; + final float score = userData.getScorer().getScore(currentValue, value); + if (score > 0) { + if (sVerbose) { + Slog.v(TAG, "adding score " + score + " at index " + i + " and id " + fieldId); + } + if (matches == null) { + matches = new ArrayList<>(userValues.length); + } + matches.add(new Match(remoteId, score)); + } + else if (sVerbose) Slog.v(TAG, "skipping score 0 at index " + i + " and id " + fieldId); + } + if (matches != null) { + detectedFieldIds.add(fieldId); + detectedFieldClassifications.add(new FieldClassification(matches)); + } } /** @@ -1299,7 +1367,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (sDebug) Slog.d(TAG, "Good news, everyone! All checks passed, show save UI!"); - mService.logSaveShown(id, mClientState); + + // Use handler so logContextCommitted() is logged first + mHandlerCaller.getHandler().post(() -> mService.logSaveShown(id, mClientState)); + final IAutoFillManagerClient client = getClient(); mPendingSaveUi = new PendingUi(mActivityToken, id, client); getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(), @@ -1499,7 +1570,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * * <p>A new request will be started in 2 scenarios: * <ol> - * <li>If the user manually requested autofill after the view was already filled. + * <li>If the user manually requested autofill. * <li>If the view is part of a new partition. * </ol> * @@ -1507,14 +1578,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * @param viewState The view that is entered. * @param flags The flag that was passed by the AutofillManager. */ - private void requestNewFillResponseIfNecessaryLocked(@NonNull AutofillId id, + private void requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id, @NonNull ViewState viewState, int flags) { - // First check if this is a manual request after view was autofilled. - final int state = viewState.getState(); - final boolean restart = (state & STATE_AUTOFILLED) != 0 - && (flags & FLAG_MANUAL_REQUEST) != 0; - if (restart) { - if (sDebug) Slog.d(TAG, "Re-starting session on view " + id); + if ((flags & FLAG_MANUAL_REQUEST) != 0) { + if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags); viewState.setState(STATE_RESTARTED_SESSION); requestNewFillResponseLocked(flags); return; @@ -1607,7 +1674,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL); mViewStates.put(id, viewState); - // TODO(b/67867469): for optimization purposes, should also ignore if change is + // TODO(b/70407264): for optimization purposes, should also ignore if change is // detectable, and batch-send them when the session is finished (but that will // require tracking detectable fields on AutofillManager) if (isIgnored) { @@ -1667,9 +1734,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState break; case ACTION_VIEW_ENTERED: if (sVerbose && virtualBounds != null) { - Slog.w(TAG, "entered on virtual child " + id + ": " + virtualBounds); + Slog.v(TAG, "entered on virtual child " + id + ": " + virtualBounds); } - requestNewFillResponseIfNecessaryLocked(id, viewState, flags); + requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags); // Remove the UI if the ViewState has changed. if (mCurrentViewId != viewState.id) { @@ -2071,6 +2138,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final String prefix2 = prefix + " "; pw.print(prefix); pw.print("id: "); pw.println(id); pw.print(prefix); pw.print("uid: "); pw.println(uid); + pw.print(prefix); pw.print("flags: "); pw.println(mFlags); pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName); pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); pw.print(prefix); pw.print("mStartTime: "); pw.println(mStartTime); |