Merge "Add <autofill-service> that declares AutoFillService metadata."
diff --git a/api/current.txt b/api/current.txt
index cc8e709..4e7d2dc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35271,6 +35271,7 @@
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
diff --git a/api/system-current.txt b/api/system-current.txt
index d5d84a0..0acfea2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -38170,6 +38170,7 @@
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
diff --git a/api/test-current.txt b/api/test-current.txt
index 7933890..8abaf84 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -35390,6 +35390,7 @@
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index c2e980c..805d8e5 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -61,6 +61,19 @@
     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
 
+    /**
+     * Name under which a AutoFillService component publishes information about itself.
+     * This meta-data should reference an XML resource containing a
+     * <code>&lt;{@link
+     * android.R.styleable#AutoFillService autofill-service}&gt;</code> tag.
+     * This is a a sample XML file configuring an AutoFillService:
+     * <pre> &lt;autofill-service
+     *     android:settingsActivity="foo.bar.SettingsActivity"
+     *     . . .
+     * /&gt;</pre>
+     */
+    public static final String SERVICE_META_DATA = "android.autofill";
+
     // Internal bundle keys.
     /** @hide */ public static final String KEY_CALLBACK = "callback";
     /** @hide */ public static final String KEY_SAVABLE_IDS = "savable_ids";
diff --git a/core/java/android/service/autofill/AutoFillServiceInfo.java b/core/java/android/service/autofill/AutoFillServiceInfo.java
index fe21615..ab86580 100644
--- a/core/java/android/service/autofill/AutoFillServiceInfo.java
+++ b/core/java/android/service/autofill/AutoFillServiceInfo.java
@@ -16,20 +16,34 @@
 package android.service.autofill;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
 import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
 
 /** @hide */
 public final class AutoFillServiceInfo {
+    static final String TAG = "AutoFillServiceInfo";
 
     private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
             throws PackageManager.NameNotFoundException {
         try {
-            final ServiceInfo si =
-                    AppGlobals.getPackageManager().getServiceInfo(comp, 0, userHandle);
+            ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(
+                    comp,
+                    PackageManager.GET_META_DATA,
+                    userHandle);
             if (si != null) {
                 return si;
             }
@@ -38,11 +52,21 @@
         throw new PackageManager.NameNotFoundException(comp.toString());
     }
 
+    @Nullable
     private String mParseError;
 
+    @Nullable
     private ServiceInfo mServiceInfo;
+    @Nullable
+    private String mSettingsActivity;
 
-    private  AutoFillServiceInfo(ServiceInfo si) {
+    public AutoFillServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
+            throws PackageManager.NameNotFoundException {
+        this(pm, getServiceInfoOrThrow(comp, userHandle));
+    }
+
+    public AutoFillServiceInfo(PackageManager pm, ServiceInfo si)
+            throws PackageManager.NameNotFoundException{
         if (si == null) {
             mParseError = "Service not available";
             return;
@@ -53,19 +77,57 @@
             return;
         }
 
+        XmlResourceParser parser = null;
+        try {
+            parser = si.loadXmlMetaData(pm, AutoFillService.SERVICE_META_DATA);
+            if (parser == null) {
+                mParseError = "No " + AutoFillService.SERVICE_META_DATA
+                        + " meta-data for " + si.packageName;
+                return;
+            }
+
+            Resources res = pm.getResourcesForApplication(si.applicationInfo);
+
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+            }
+
+            String nodeName = parser.getName();
+            if (!"autofill-service".equals(nodeName)) {
+                mParseError = "Meta-data does not start with autofill-service tag";
+                return;
+            }
+
+            TypedArray array = res.obtainAttributes(attrs,
+                    com.android.internal.R.styleable.AutoFillService);
+            mSettingsActivity = array.getString(
+                    com.android.internal.R.styleable.AutoFillService_settingsActivity);
+            array.recycle();
+        } catch (XmlPullParserException | IOException | PackageManager.NameNotFoundException e) {
+            mParseError = "Error parsing auto fill service meta-data: " + e;
+            Log.w(TAG, "error parsing auto fill service meta-data", e);
+            return;
+        } finally {
+            if (parser != null) parser.close();
+        }
         mServiceInfo = si;
     }
 
-    public AutoFillServiceInfo(ComponentName comp, int userHandle)
-            throws PackageManager.NameNotFoundException {
-        this(getServiceInfoOrThrow(comp, userHandle));
-    }
-
+    @Nullable
     public String getParseError() {
         return mParseError;
     }
 
+    @Nullable
     public ServiceInfo getServiceInfo() {
         return mServiceInfo;
     }
+
+    @Nullable
+    public String getSettingsActivity() {
+        return mSettingsActivity;
+    }
 }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8e9959f..a5c1a94 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7617,6 +7617,21 @@
     </declare-styleable>
 
     <!-- =============================== -->
+    <!-- AutoFill attributes -->
+    <!-- =============================== -->
+    <eat-comment />
+
+    <!-- Use <code>autofill-service</code> as the root tag of the XML resource that describes a
+         {@link android.service.autofill.AutoFillService}, which is referenced from its
+         {@link android.service.autofill#SERVICE_META_DATA} meta-data entry.
+    -->
+    <declare-styleable name="AutoFillService">
+        <!-- Fully qualified class name of an activity that allows the user to modify
+             the settings for this service. -->
+        <attr name="settingsActivity" />
+    </declare-styleable>
+
+    <!-- =============================== -->
     <!-- Contacts meta-data attributes -->
     <!-- =============================== -->
     <eat-comment />
@@ -8430,7 +8445,7 @@
     <!-- @hide Attributes which will be read by the Activity to intialize the
                base activity TaskDescription. -->
     <declare-styleable name="ActivityTaskDescription">
-        <!-- @hide From Theme.colorPrimary, used for the TaskDescription primary 
+        <!-- @hide From Theme.colorPrimary, used for the TaskDescription primary
                    color. -->
         <attr name="colorPrimary" />
         <!-- @hide From Theme.colorBackground, used for the TaskDescription background
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 3de8a8b..ae21b07 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -202,7 +202,7 @@
 
         final AutoFillServiceInfo info;
         try {
-            info = new AutoFillServiceInfo(component, mUserId);
+            info = new AutoFillServiceInfo(context.getPackageManager(), component, mUserId);
         } catch (PackageManager.NameNotFoundException e) {
             Slog.w(TAG, "Auto-fill service not found: " + component, e);
             mInfo = null;