summaryrefslogtreecommitdiff
path: root/com/android/server/autofill/Session.java
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2018-01-03 13:39:41 -0500
committerJustin Klaassen <justinklaassen@google.com>2018-01-03 13:39:41 -0500
commit98fe7819c6d14f4f464a5cac047f9e82dee5da58 (patch)
treea6b8b93eb21e205b27590ab5e2a1fb9efe27f892 /com/android/server/autofill/Session.java
parent4217cf85c20565a3446a662a7f07f26137b26b7f (diff)
downloadandroid-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.java180
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);