OSDN Git Service

TRON log important auto-fill events
authorPhilip P. Moltmann <moltmann@google.com>
Sat, 4 Mar 2017 01:22:57 +0000 (17:22 -0800)
committerPhilip P. Moltmann <moltmann@google.com>
Thu, 16 Mar 2017 22:41:33 +0000 (15:41 -0700)
Example log from
android.autofillservice.cts.LoginActivityTest#testAutoFill#testAutoFillOneDatasetAndSave
(translated from numbers of human readable string):

AUTOFILL_SESSION_STARTED
   package=android.autofillservice.cts
AUTOFILL_REQUEST
   type=TYPE_SUCCESS
   package=android.autofillservice.cts
   FIELD_AUTOFILL_SERVICE=android.autofillservice.cts
   FIELD_AUTOFILL_NUM_DATASETS=1
AUTOFILL_FILL_UI
   type=TYPE_ACTION
   package=android.autofillservice.cts
   FIELD_AUTOFILL_NUM_DATASETS=1
   FIELD_AUTOFILL_FILTERTEXT_LEN=0
AUTOFILL_DATASET_APPLIED
   package=android.autofillservice.cts
   FIELD_AUTOFILL_NUM_VALUES=2
   FIELD_AUTOFILL_NUM_VIEWS_FILLED=2
AUTOFILL_SAVE_UI
   package=android.autofillservice.cts
   FIELD_AUTOFILL_NUM_IDS=2
AUTOFILL_DATA_SAVE_REQUEST
   type=TYPE_SUCCESS
   package=android.autofillservice.cts
   FIELD_AUTOFILL_SERVICE=android.autofillservice.cts
AUTOFILL_SESSION_FINISHED
   package=android.autofillservice.cts

Test: Ran auto-fill tests and looked at event log.
Change-Id: I58aaa58e4435e7d04c8cd91878411943d3eb13de

20 files changed:
api/current.txt
api/system-current.txt
api/test-current.txt
core/java/android/app/Activity.java
core/java/android/view/View.java
core/java/android/view/autofill/AutofillManager.java
core/java/android/view/autofill/IAutoFillManager.aidl
core/java/android/widget/AbsSpinner.java
core/java/android/widget/CompoundButton.java
core/java/android/widget/DatePicker.java
core/java/android/widget/RadioGroup.java
core/java/android/widget/TextView.java
core/java/android/widget/TimePicker.java
proto/src/metrics_constants.proto
services/autofill/java/com/android/server/autofill/AutofillManagerService.java
services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
services/autofill/java/com/android/server/autofill/RemoteFillService.java
services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
services/autofill/java/com/android/server/autofill/ui/FillUi.java
services/autofill/java/com/android/server/autofill/ui/SaveUi.java

index 9557ee5..8cb1262 100644 (file)
@@ -45076,8 +45076,8 @@ package android.view {
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
-    method public void autofill(android.view.autofill.AutofillValue);
-    method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+    method public boolean autofill(android.view.autofill.AutofillValue);
+    method public boolean autofillVirtual(int, android.view.autofill.AutofillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
index 6d01c6b..8d9c0c0 100644 (file)
@@ -48539,8 +48539,8 @@ package android.view {
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
-    method public void autofill(android.view.autofill.AutofillValue);
-    method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+    method public boolean autofill(android.view.autofill.AutofillValue);
+    method public boolean autofillVirtual(int, android.view.autofill.AutofillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
index 1d0a289..46f9085 100644 (file)
@@ -45436,8 +45436,8 @@ package android.view {
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
-    method public void autofill(android.view.autofill.AutofillValue);
-    method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+    method public boolean autofill(android.view.autofill.AutofillValue);
+    method public boolean autofillVirtual(int, android.view.autofill.AutofillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
index 78c29e8..e65c7c8 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.metrics.LogMaker;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -23,6 +24,8 @@ import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.policy.PhoneWindow;
 
 import android.annotation.CallSuper;
@@ -765,6 +768,7 @@ public class Activity extends ContextThemeWrapper
     /*package*/ Configuration mCurrentConfig;
     private SearchManager mSearchManager;
     private MenuInflater mMenuInflater;
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
     static final class NonConfigurationInstances {
         Object activity;
@@ -7188,6 +7192,8 @@ public class Activity extends ContextThemeWrapper
     public void autofill(List<AutofillId> ids, List<AutofillValue> values) {
         final View root = getWindow().getDecorView();
         final int itemCount = ids.size();
+        int numApplied = 0;
+
         for (int i = 0; i < itemCount; i++) {
             final AutofillId id = ids.get(i);
             final AutofillValue value = values.get(i);
@@ -7197,12 +7203,22 @@ public class Activity extends ContextThemeWrapper
                 Log.w(TAG, "autofill(): no View with id " + viewId);
                 continue;
             }
+            final boolean wasApplied;
             if (id.isVirtual()) {
-                view.autofillVirtual(id.getVirtualChildId(), value);
+                wasApplied = view.autofillVirtual(id.getVirtualChildId(), value);
             } else {
-                view.autofill(value);
+                wasApplied = view.autofill(value);
+            }
+
+            if (wasApplied) {
+                numApplied++;
             }
         }
+
+        LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
+        log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
+        log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
+        mMetricsLogger.write(log);
     }
 
     /** @hide */
index 80f6c32..6cddbac 100644 (file)
@@ -7445,8 +7445,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * </pre>
      *
      * @param value value to be autofilled.
+     *
+     * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
      */
-    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
+    public boolean autofill(@SuppressWarnings("unused") AutofillValue value) {
+        return false;
     }
 
     /**
@@ -7457,9 +7460,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      *
      * @param value value to be autofilled.
      * @param virtualId id identifying the virtual child inside the custom view.
+     *
+     * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
      */
-    public void autofillVirtual(@SuppressWarnings("unused") int virtualId,
+    public boolean autofillVirtual(@SuppressWarnings("unused") int virtualId,
             @SuppressWarnings("unused") AutofillValue value) {
+        return false;
     }
 
     /**
index f036b9c..244aba7 100644 (file)
@@ -83,7 +83,7 @@ public final class AutofillManager {
     /** @hide */ public static final int FLAG_VIEW_EXITED =   0x20000000;
     /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x10000000;
 
-    private final Rect mTempRect = new Rect();
+    @NonNull private final Rect mTempRect = new Rect();
 
     private final IAutoFillManager mService;
     private IAutoFillManagerClient mServiceClient;
@@ -371,8 +371,8 @@ public final class AutofillManager {
         return new AutofillId(parent.getAccessibilityViewId(), childId);
     }
 
-    private void startSession(AutofillId id, IBinder windowToken, Rect bounds,
-            AutofillValue value, int flags) {
+    private void startSession(@NonNull AutofillId id, @NonNull IBinder windowToken,
+            @NonNull Rect bounds, @NonNull AutofillValue value, int flags) {
         if (DEBUG) {
             Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
                     + ", flags=" + flags);
@@ -381,8 +381,8 @@ public final class AutofillManager {
         try {
             mService.startSession(mContext.getActivityToken(), windowToken,
                     mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
-                    mCallback != null, flags);
-            final AutofillClient client = getClient();
+                    mCallback != null, flags, mContext.getOpPackageName());
+            AutofillClient client = getClient();
             if (client != null) {
                 client.resetableStateAvailable();
             }
index 85b05e5..97210cc 100644 (file)
@@ -32,7 +32,7 @@ interface IAutoFillManager {
     boolean addClient(in IAutoFillManagerClient client, int userId);
     oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
             in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
-            boolean hasCallback, int flags);
+            boolean hasCallback, int flags, String packageName);
     oneway void updateSession(in IBinder activityToken, in AutofillId id, in Rect bounds,
             in AutofillValue value, int flags, int userId);
     oneway void finishSession(in IBinder activityToken, int userId);
index 020e80a..fae5742 100644 (file)
@@ -514,14 +514,15 @@ public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> {
     }
 
     @Override
-    public void autofill(AutofillValue value) {
-        if (!isEnabled()) return;
+    public boolean autofill(AutofillValue value) {
+        if (!isEnabled()) return false;
 
         if (value.isList()) {
             setSelection(value.getListValue());
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
         }
+        return true;
     }
 
     @Override
index 899a824..9dc61ab 100644 (file)
@@ -584,14 +584,16 @@ public abstract class CompoundButton extends Button implements Checkable {
     }
 
     @Override
-    public void autofill(AutofillValue value) {
-        if (!isEnabled()) return;
+    public boolean autofill(AutofillValue value) {
+        if (!isEnabled()) return false;
 
         if (value.isToggle()) {
             setChecked(value.getToggleValue());
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
         }
+
+        return true;
     }
 
     @Override
index f63573f..7d04f35 100644 (file)
@@ -775,14 +775,16 @@ public class DatePicker extends FrameLayout {
     }
 
     @Override
-    public void autofill(AutofillValue value) {
-        if (!isEnabled()) return;
+    public boolean autofill(AutofillValue value) {
+        if (!isEnabled()) return false;
 
         if (value.isDate()) {
             mDelegate.updateDate(value.getDateValue());
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
         }
+
+        return true;
     }
 
     @Override
index 5e8279a..a7574c7 100644 (file)
@@ -426,23 +426,24 @@ public class RadioGroup extends LinearLayout {
     }
 
     @Override
-    public void autofill(AutofillValue value) {
-        if (!isEnabled()) return;
+    public boolean autofill(AutofillValue value) {
+        if (!isEnabled()) return false;
 
         int index;
         if (value.isList()) {
             index = value.getListValue();
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
-            return;
+            return false;
         }
 
         final View child = getChildAt(index);
         if (child == null) {
             Log.w(VIEW_LOG_TAG, "RadioGroup.autoFill(): no child with index " + index);
-            return;
+            return false;
         }
         check(child.getId());
+        return true;
     }
 
     @Override
index c5c317d..26edc43 100644 (file)
@@ -10028,14 +10028,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     @Override
-    public void autofill(AutofillValue value) {
+    public boolean autofill(AutofillValue value) {
         if (value.isText()) {
             if (isTextEditable()) {
                 setText(value.getTextValue(), mBufferType, true, 0);
+                return true;
             }
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
         }
+
+        return false;
     }
 
     @Override
index cfa78b5..1e97e3b 100644 (file)
@@ -530,14 +530,16 @@ public class TimePicker extends FrameLayout {
     }
 
     @Override
-    public void autofill(AutofillValue value) {
-        if (!isEnabled()) return;
+    public boolean autofill(AutofillValue value) {
+        if (!isEnabled()) return false;
 
         if (value.isDate()) {
             mDelegate.setDate(value.getDateValue());
         } else {
             Log.w(LOG_TAG, value + " could not be autofilled into " + this);
         }
+
+        return true;
     }
 
     @Override
index f11f302..8a3b9af 100644 (file)
@@ -56,6 +56,12 @@ message MetricsEvent {
     // Type for APP_TRANSITION event: The transition brought an already existing activity to the
     // front.
     TYPE_TRANSITION_HOT_LAUNCH = 9;
+
+    // The action was successful
+    TYPE_SUCCESS = 10;
+
+    // The action failed
+    TYPE_FAILURE = 11;
   }
 
   // Known visual elements: views or controls.
@@ -3702,6 +3708,75 @@ message MetricsEvent {
     // OS: O
     APP_TRANSITION_IS_EPHEMERAL = 905;
 
+    // An autofill session was started
+    // Package: Package of app that is autofilled
+    AUTOFILL_SESSION_STARTED = 906;
+
+    // An autofill request was processed by a service
+    // Type TYPE_SUCCESS: The request succeeded
+    // Type TYPE_FAILURE: The request failed
+    // Package: Package of app that is autofilled
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_NUM_DATASET: The number of datasets returned (only in success case)
+    AUTOFILL_REQUEST = 907;
+
+    // Tag of a field for a package of an autofill service
+    FIELD_AUTOFILL_SERVICE = 908;
+
+    // Tag of a field for the number of datasets
+    FIELD_AUTOFILL_NUM_DATASETS = 909;
+
+    // An autofill dataset selection UI was shown
+    // Type TYPE_DISMISS: UI was explicityly canceled by the user
+    // Type TYPE_CLOSE: UI was destroyed without influence of the user
+    // Type TYPE_ACTION: dataset was selected
+    // Type TYPE_DETAIL: authentication was selected
+    // Package: Package of app that was autofilled
+    // Tag FIELD_AUTOFILL_FILTERTEXT_LEN: The length of the filter text
+    // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets shown
+    AUTOFILL_FILL_UI = 910;
+
+    // Tag of a field for the length of the filter text
+    FIELD_AUTOFILL_FILTERTEXT_LEN = 911;
+
+    // An autofill authentification succeeded
+    // Package: Package of app that was autofilled
+    AUTOFILL_AUTHENTICATED = 912;
+
+    // An activity was autofilled and all values could be applied
+    // Package: Package of app that is autofilled
+    // Tag FIELD_AUTOFILL_NUM_VALUES: Number of values that were suggested to be autofilled
+    // Tag FIELD_AUTOFILL_NUM_VIEWS_FILLED: Number of views that could be filled
+    AUTOFILL_DATASET_APPLIED = 913;
+
+    // Tag of a field for the number values to be filled in
+    FIELD_AUTOFILL_NUM_VALUES = 914;
+
+    // Tag of a field for the number of views that were filled
+    FIELD_AUTOFILL_NUM_VIEWS_FILLED = 915;
+
+    // An autofill save UI was shown
+    // Type TYPE_DISMISS: UI was explicityly canceled by the user
+    // Type TYPE_CLOSE: UI was destroyed without influence of the user
+    // Type TYPE_ACTION: data was saved
+    // Package: Package of app that was autofilled
+    // Tag FIELD_AUTOFILL_NUM_ID: The number of ids that are saved
+    AUTOFILL_SAVE_UI = 916;
+
+    // Tag of a field for the number of saveable ids
+    FIELD_AUTOFILL_NUM_IDS = 917;
+
+    // ACTION: An autofill service was reqiested to save data
+    // Type TYPE_SUCCESS: The request succeeded
+    // Type TYPE_FAILURE: The request failed
+    // Package: Package of app that was autofilled
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    AUTOFILL_DATA_SAVE_REQUEST = 918;
+
+    // An auto-fill session was finished
+    // Package: Package of app that was autofilled
+    AUTOFILL_SESSION_FINISHED = 919;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
index af1193d..c7ba1ff 100644 (file)
@@ -28,6 +28,7 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.graphics.Rect;
@@ -53,6 +54,7 @@ import android.view.autofill.IAutoFillManagerClient;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -316,13 +318,27 @@ public final class AutofillManagerService extends SystemService {
         @Override
         public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
                 AutofillId autofillId, Rect bounds, AutofillValue value, int userId,
-                boolean hasCallback, int flags) {
+                boolean hasCallback, int flags, String packageName) {
             // TODO(b/33197203): make sure it's called by resumed / focused activity
 
+            activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
+            appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
+            autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
+            bounds = Preconditions.checkNotNull(bounds, "bounds");
+            packageName = Preconditions.checkNotNull(packageName, "packageName");
+
+            Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");
+
+            try {
+                mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
+            } catch (PackageManager.NameNotFoundException e) {
+                throw new IllegalArgumentException(packageName + " is not a valid package", e);
+            }
+
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                 service.startSessionLocked(activityToken, windowToken, appCallback,
-                        autofillId, bounds, value, hasCallback, flags);
+                        autofillId, bounds, value, hasCallback, flags, packageName);
             }
         }
 
index 3e5ad82..3158786 100644 (file)
@@ -28,6 +28,7 @@ import static com.android.server.autofill.Helper.DEBUG;
 import static com.android.server.autofill.Helper.VERBOSE;
 import static com.android.server.autofill.Helper.findValue;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -43,6 +44,7 @@ import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
+import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -68,6 +70,8 @@ import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutoFillManagerClient;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.IResultReceiver;
 import com.android.server.autofill.ui.AutoFillUI;
@@ -92,6 +96,7 @@ final class AutofillManagerServiceImpl {
     private final Context mContext;
     private final Object mLock;
     private final AutoFillUI mUi;
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
     private RemoteCallbackList<IAutoFillManagerClient> mClients;
     private AutofillServiceInfo mInfo;
@@ -284,9 +289,10 @@ final class AutofillManagerServiceImpl {
         }
     }
 
-    void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
-            AutofillId autofillId,  Rect bounds, AutofillValue value, boolean hasCallback,
-            int flags) {
+    void startSessionLocked(@NonNull IBinder activityToken, @Nullable IBinder windowToken,
+            @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId, @NonNull Rect bounds,
+            @Nullable AutofillValue value, boolean hasCallback, int flags,
+            @NonNull String packageName) {
         if (!hasService()) {
             return;
         }
@@ -305,7 +311,7 @@ final class AutofillManagerServiceImpl {
         }
 
         final Session newSession = createSessionByTokenLocked(activityToken,
-                windowToken, appCallbackToken, hasCallback, flags);
+                windowToken, appCallbackToken, hasCallback, flags, packageName);
         newSession.updateLocked(autofillId, bounds, value, FLAG_START_SESSION);
     }
 
@@ -337,10 +343,11 @@ final class AutofillManagerServiceImpl {
         session.destroyLocked();
     }
 
-    private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
-            IBinder appCallbackToken, boolean hasCallback, int flags) {
+    private Session createSessionByTokenLocked(@NonNull IBinder activityToken,
+            @Nullable IBinder windowToken, @NonNull IBinder appCallbackToken, boolean hasCallback,
+            int flags, @NonNull String packageName) {
         final Session newSession = new Session(mContext, activityToken,
-                windowToken, appCallbackToken, hasCallback, flags);
+                windowToken, appCallbackToken, hasCallback, flags, packageName);
         mSessions.put(activityToken, newSession);
 
         /*
@@ -351,7 +358,6 @@ final class AutofillManagerServiceImpl {
          * - display disclosure if needed
          */
         try {
-            // TODO(b/33197203): add MetricsLogger call
             final Bundle receiverExtras = new Bundle();
             receiverExtras.putBinder(EXTRA_ACTIVITY_TOKEN, activityToken);
             final long identity = Binder.clearCallingIdentity();
@@ -371,7 +377,6 @@ final class AutofillManagerServiceImpl {
 
     void updateSessionLocked(IBinder activityToken, AutofillId autofillId, Rect bounds,
             AutofillValue value, int flags) {
-        // TODO(b/33197203): add MetricsLogger call
         final Session session = mSessions.get(activityToken);
         if (session == null) {
             if (VERBOSE) {
@@ -595,6 +600,9 @@ final class AutofillManagerServiceImpl {
         private final IBinder mActivityToken;
         private final IBinder mWindowToken;
 
+        /** Package name of the app that is auto-filled */
+        @NonNull private final String mPackageName;
+
         @GuardedBy("mLock")
         private final Map<AutofillId, ViewState> mViewStates = new ArrayMap<>();
 
@@ -634,15 +642,16 @@ final class AutofillManagerServiceImpl {
          * Flags used to start the session.
          */
         private int mFlags;
-
-        private Session(Context context, IBinder activityToken, IBinder windowToken,
-                IBinder client, boolean hasCallback, int flags) {
+        private Session(@NonNull Context context, @NonNull IBinder activityToken,
+                @Nullable IBinder windowToken, @NonNull IBinder client, boolean hasCallback,
+                int flags, @NonNull String packageName) {
             mRemoteFillService = new RemoteFillService(context,
                     mInfo.getServiceInfo().getComponentName(), mUserId, this);
             mActivityToken = activityToken;
             mWindowToken = windowToken;
             mHasCallback = hasCallback;
             mFlags = flags;
+            mPackageName = packageName;
 
             mClient = IAutoFillManagerClient.Stub.asInterface(client);
             try {
@@ -656,12 +665,14 @@ final class AutofillManagerServiceImpl {
             } catch (RemoteException e) {
                 Slog.w(TAG, "linkToDeath() on mClient failed: " + e);
             }
+
+            mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName);
         }
 
         // FillServiceCallbacks
         @Override
-        public void onFillRequestSuccess(FillResponse response) {
-            // TODO(b/33197203): add MetricsLogger call
+        public void onFillRequestSuccess(@Nullable FillResponse response,
+                @NonNull String servicePackageName) {
             if (response == null) {
                 removeSelf();
                 return;
@@ -669,28 +680,59 @@ final class AutofillManagerServiceImpl {
             synchronized (mLock) {
                 processResponseLocked(response);
             }
+
+            LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_REQUEST))
+                    .setType(MetricsProto.MetricsEvent.TYPE_SUCCESS)
+                    .setPackageName(mPackageName)
+                    .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+                            response.getDatasets() == null ? 0 : response.getDatasets().size())
+                    .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+                            servicePackageName);
+            mMetricsLogger.write(log);
         }
 
         // FillServiceCallbacks
         @Override
-        public void onFillRequestFailure(CharSequence message) {
-            // TODO(b/33197203): add MetricsLogger call
+        public void onFillRequestFailure(@Nullable CharSequence message,
+                @NonNull String servicePackageName) {
+            LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_REQUEST))
+                    .setType(MetricsProto.MetricsEvent.TYPE_FAILURE)
+                    .setPackageName(mPackageName)
+                    .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+                            servicePackageName);
+            mMetricsLogger.write(log);
+
             getUiForShowing().showError(message);
             removeSelf();
         }
 
         // FillServiceCallbacks
         @Override
-        public void onSaveRequestSuccess() {
-            // TODO(b/33197203): add MetricsLogger call
+        public void onSaveRequestSuccess(@NonNull String servicePackageName) {
+            LogMaker log = (new LogMaker(
+                    MetricsProto.MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
+                    .setType(MetricsProto.MetricsEvent.TYPE_SUCCESS)
+                    .setPackageName(mPackageName)
+                    .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+                            servicePackageName);
+            mMetricsLogger.write(log);
+
             // Nothing left to do...
             removeSelf();
         }
 
         // FillServiceCallbacks
         @Override
-        public void onSaveRequestFailure(CharSequence message) {
-            // TODO(b/33197203): add MetricsLogger call
+        public void onSaveRequestFailure(@Nullable CharSequence message,
+                @NonNull String servicePackageName) {
+            LogMaker log = (new LogMaker(
+                    MetricsProto.MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
+                    .setType(MetricsProto.MetricsEvent.TYPE_FAILURE)
+                    .setPackageName(mPackageName)
+                    .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+                            servicePackageName);
+            mMetricsLogger.write(log);
+
             getUiForShowing().showError(message);
             removeSelf();
         }
@@ -773,6 +815,9 @@ final class AutofillManagerServiceImpl {
                 Parcelable result = data.getParcelable(
                         AutofillManager.EXTRA_AUTHENTICATION_RESULT);
                 if (result instanceof FillResponse) {
+                    mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_AUTHENTICATED,
+                            mPackageName);
+
                     mCurrentResponse = (FillResponse) result;
                     processResponseLocked(mCurrentResponse);
                 } else if (result instanceof Dataset) {
@@ -894,7 +939,7 @@ final class AutofillManagerServiceImpl {
                 if (atLeastOneChanged) {
                     getUiForShowing().showSaveUi(
                             mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
-                            saveInfo);
+                            saveInfo, mPackageName);
                     return;
                 }
             }
@@ -1034,7 +1079,7 @@ final class AutofillManagerServiceImpl {
                 filterText = value.getTextValue().toString();
             }
 
-            getUiForShowing().showFillUi(filledId, response, bounds, filterText);
+            getUiForShowing().showFillUi(filledId, response, bounds, filterText, mPackageName);
         }
 
         private void notifyChangeToClient(AutofillId id, int event) {
@@ -1052,8 +1097,6 @@ final class AutofillManagerServiceImpl {
                     + "):" + response);
             }
 
-            // TODO(b/33197203): add MetricsLogger calls
-
             if (mCurrentViewState == null) {
                 // TODO(b/33197203): temporary sanity check; should never happen
                 Slog.w(TAG, "processResponseLocked(): mCurrentResponse is null");
@@ -1188,6 +1231,9 @@ final class AutofillManagerServiceImpl {
         private void destroyLocked() {
             mRemoteFillService.destroy();
             mUi.setCallback(null, null);
+
+            mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_SESSION_FINISHED,
+                    mPackageName);
         }
 
         private void removeSelf() {
index b1cc89b..c41ac05 100644 (file)
@@ -87,10 +87,10 @@ final class RemoteFillService implements DeathRecipient {
     private PendingRequest mPendingRequest;
 
     public interface FillServiceCallbacks {
-        void onFillRequestSuccess(FillResponse response);
-        void onFillRequestFailure(CharSequence message);
-        void onSaveRequestSuccess();
-        void onSaveRequestFailure(CharSequence message);
+        void onFillRequestSuccess(@Nullable FillResponse response, @NonNull String servicePackageName);
+        void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName);
+        void onSaveRequestSuccess(@NonNull String servicePackageName);
+        void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName);
         void onServiceDied(RemoteFillService service);
         void onDisableSelf();
     }
@@ -262,7 +262,7 @@ final class RemoteFillService implements DeathRecipient {
             FillResponse response) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestSuccess(response);
+                mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName());
             }
         });
     }
@@ -271,7 +271,7 @@ final class RemoteFillService implements DeathRecipient {
             CharSequence message) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestFailure(message);
+                mCallbacks.onFillRequestFailure(message, mComponentName.getPackageName());
             }
         });
     }
@@ -279,7 +279,7 @@ final class RemoteFillService implements DeathRecipient {
     private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onSaveRequestSuccess();
+                mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName());
             }
         });
     }
@@ -288,7 +288,7 @@ final class RemoteFillService implements DeathRecipient {
             CharSequence message) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onSaveRequestFailure(message);
+                mCallbacks.onSaveRequestFailure(message, mComponentName.getPackageName());
             }
         });
     }
index c7e59a3..56c78be 100644 (file)
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
 import android.content.Context;
 import android.content.IntentSender;
 import android.graphics.Rect;
+import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.IBinder;
 import android.service.autofill.Dataset;
@@ -34,6 +35,8 @@ import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.widget.Toast;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.server.UiThread;
 
 import java.io.PrintWriter;
@@ -60,6 +63,7 @@ public final class AutoFillUI {
     private @Nullable IBinder mWindowToken;
 
     private int mSaveTimeoutMs = (int) (5 * DateUtils.SECOND_IN_MILLIS);
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
     public interface AutoFillUiCallback {
         void authenticate(@NonNull IntentSender intent);
@@ -152,9 +156,17 @@ public final class AutoFillUI {
      * @param response the current fill response
      * @param anchorBounds bounds of the focused view
      * @param filterText text of the view to be filled
+     * @param packageName package name of the activity that is filled
      */
     public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
-            @NonNull Rect anchorBounds, @Nullable String filterText) {
+            @NonNull Rect anchorBounds, @Nullable String filterText, @NonNull String packageName) {
+        LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI))
+                .setPackageName(packageName)
+                .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
+                        filterText == null ? 0 : filterText.length())
+                .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+                        response.getDatasets() == null ? 0 : response.getDatasets().size());
+
         mHandler.post(() -> {
             if (!hasCallback()) {
                 return;
@@ -164,6 +176,7 @@ public final class AutoFillUI {
                     mWindowToken, anchorBounds, filterText, new FillUi.Callback() {
                 @Override
                 public void onResponsePicked(FillResponse response) {
+                    log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
                     hideFillUiUiThread();
                     if (mCallback != null) {
                         mCallback.authenticate(response.getAuthentication());
@@ -172,17 +185,25 @@ public final class AutoFillUI {
 
                 @Override
                 public void onDatasetPicked(Dataset dataset) {
+                    log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
                     hideFillUiUiThread();
                     if (mCallback != null) {
                         mCallback.fill(dataset);
                     }
-                    // TODO(b/33197203): add MetricsLogger call
                 }
 
                 @Override
                 public void onCanceled() {
+                    log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
                     hideFillUiUiThread();
-                    // TODO(b/33197203): add MetricsLogger call
+                }
+
+                @Override
+                public void onDestroy() {
+                    if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
+                        log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+                    }
+                    mMetricsLogger.write(log);
                 }
             });
             mCallback.onEvent(focusedId, EVENT_INPUT_SHOWN);
@@ -192,7 +213,16 @@ public final class AutoFillUI {
     /**
      * Shows the UI asking the user to save for autofill.
      */
-    public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
+    public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info,
+            @NonNull String packageName) {
+        int numIds = 0;
+        numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
+        numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
+
+        LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_SAVE_UI))
+                .setPackageName(packageName).addTaggedData(
+                        MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
+
         mHandler.post(() -> {
             if (!hasCallback()) {
                 return;
@@ -202,16 +232,16 @@ public final class AutoFillUI {
                     new SaveUi.OnSaveListener() {
                 @Override
                 public void onSave() {
+                    log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
                     hideSaveUiUiThread();
                     if (mCallback != null) {
                         mCallback.save();
                     }
-                    // TODO(b/33197203): add MetricsLogger call
                 }
 
                 @Override
                 public void onCancel(IntentSender listener) {
-                    // TODO(b/33197203): add MetricsLogger call
+                    log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
                     hideSaveUiUiThread();
                     if (listener != null) {
                         try {
@@ -225,6 +255,14 @@ public final class AutoFillUI {
                         mCallback.cancelSave();
                     }
                 }
+
+                @Override
+                public void onDestroy() {
+                    if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
+                        log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+                    }
+                    mMetricsLogger.write(log);
+                }
             }, mSaveTimeoutMs);
         });
     }
index a7d9fe9..fbf5d26 100644 (file)
@@ -50,6 +50,7 @@ final class FillUi {
         void onResponsePicked(@NonNull FillResponse response);
         void onDatasetPicked(@NonNull Dataset dataset);
         void onCanceled();
+        void onDestroy();
     }
 
     private final Rect mAnchorBounds = new Rect();
@@ -201,6 +202,7 @@ final class FillUi {
 
     public void destroy() {
         throwIfDestroyed();
+        mCallback.onDestroy();
         mWindow.hide();
         mDestroyed = true;
     }
index 3f409ad..644abe6 100644 (file)
@@ -40,6 +40,7 @@ final class SaveUi {
     public interface OnSaveListener {
         void onSave();
         void onCancel(IntentSender listener);
+        void onDestroy();
     }
 
     private final Handler mHandler = UiThread.getHandler();
@@ -122,6 +123,7 @@ final class SaveUi {
 
     void destroy() {
         throwIfDestroyed();
+        mListener.onDestroy();
         mHandler.removeCallbacksAndMessages(mListener);
         mDialog.dismiss();
         mDestroyed = true;