Merge "Add autofill app preference to Default Apps."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index de6be1a..0e572a6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8140,4 +8140,14 @@
     <!-- UI webview setting: WebView disabled-for-user explanatory text [CHAR LIMIT=30] -->
     <string name="webview_disabled_for_user">Disabled for user <xliff:g id="user" example="John Doe">%s</xliff:g>\n</string>
 
+    <!-- AutoFill strings -->
+    <!-- Preference label for the auto-fill app. [CHAR LIMIT=60] -->
+    <string name="autofill_app">Autofill app</string>
+    <!-- Keywords for the auto-fill feature. [CHAR LIMIT=NONE] -->
+    <string name="autofill_keywords">auto, fill, autofill</string>
+    <!-- Title of the warning dialog for setting the auto-fill app. [CHAR_LIMIT=NONE] -->
+    <string name="autofill_confirmation_message">
+        Make <xliff:g id="app_name">%1$s</xliff:g> your autofill app? <xliff:g id="app_name">%1$s</xliff:g> will be able to read your screen and fill fields in other apps.
+    </string>
+
 </resources>
diff --git a/res/xml/app_default_settings.xml b/res/xml/app_default_settings.xml
index 9b585c1..27200e7 100644
--- a/res/xml/app_default_settings.xml
+++ b/res/xml/app_default_settings.xml
@@ -26,12 +26,19 @@
         android:fragment="com.android.settings.applications.ManageAssist"
         android:order="-20"/>
 
+    <com.android.settings.applications.DefaultAutoFillPreference
+        android:key="default_autofill"
+        android:title="@string/autofill_app"
+        android:summary="@string/app_list_preference_none"
+        settings:keywords="@string/autofill_keywords"
+        android:order="-19"/>
+
     <Preference
         android:key="default_browser"
         android:title="@string/default_browser_title"
         android:summary="@string/default_browser_title_none"
         android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
-        android:order="-19">
+        android:order="-18">
         <extra android:name="for_work" android:value="false"/>
     </Preference>
 
@@ -40,35 +47,32 @@
         android:title="@string/home_app"
         android:summary="@string/no_default_home"
         settings:keywords="@string/keywords_home"
-        android:fragment="com.android.settings.applications.defaultapps.DefaultHomePicker"
-        android:order="-18"/>
+        android:order="-17"/>
 
     <Preference
         android:key="default_phone_app"
         android:title="@string/default_phone_title"
         android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
         settings:keywords="@string/keywords_default_phone_app"
-        android:order="-17"/>
+        android:order="-16"/>
 
     <Preference
         android:key="default_sms_app"
         android:title="@string/sms_application_title"
         android:fragment="com.android.settings.applications.defaultapps.DefaultSmsPicker"
         settings:keywords="@string/keywords_more_default_sms_app"
-        android:order="-16"/>
+        android:order="-15"/>
 
     <Preference
         android:key="default_emergency_app"
         android:title="@string/default_emergency_app"
         settings:keywords="@string/keywords_emergency_app"
-        android:fragment="com.android.settings.applications.defaultapps.DefaultEmergencyPicker"
-        android:order="-15"/>
+        android:order="-14"/>
 
     <Preference
         android:key="default_notification_asst_app"
         android:title="@string/default_notification_assistant"
-        android:fragment="com.android.settings.applications.defaultapps.DefaultNotificationAssistantPicker"
-        android:order="-14"/>
+        android:order="-13"/>
 
     <Preference
         android:key="domain_urls"
@@ -102,4 +106,4 @@
         android:fragment="com.android.settings.applications.SpecialAccessSettings"
         android:title="@string/special_access"/>
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java
index 4cf4996..8585454 100644
--- a/src/com/android/settings/AppListPreference.java
+++ b/src/com/android/settings/AppListPreference.java
@@ -61,6 +61,8 @@
     protected final boolean mForWork;
     protected final int mUserId;
 
+
+    private boolean mSavesState = true;
     private Drawable[] mEntryDrawables;
     private boolean mShowItemNone = false;
     private CharSequence[] mSummaries;
@@ -130,6 +132,10 @@
                 : UserHandle.myUserId();
     }
 
+    public void setSavesState(boolean savesState) {
+        mSavesState = savesState;
+    }
+
     public void setShowItemNone(boolean showItemNone) {
         mShowItemNone = showItemNone;
     }
@@ -261,12 +267,16 @@
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
-        return new SavedState(getEntryValues(), getValue(), mSummaries, mShowItemNone, superState);
+        if (mSavesState) {
+            return new SavedState(getEntryValues(), getValue(), mSummaries, mShowItemNone, superState);
+        } else {
+            return superState;
+        }
     }
 
     @Override
     protected void onRestoreInstanceState(Parcelable state) {
-        if (state instanceof SavedState) {
+        if (mSavesState || state instanceof SavedState) {
             SavedState savedState = (SavedState) state;
             mShowItemNone = savedState.showItemNone;
             setPackageNames(savedState.entryValues, savedState.value);
diff --git a/src/com/android/settings/applications/DefaultAutoFillPreference.java b/src/com/android/settings/applications/DefaultAutoFillPreference.java
new file mode 100644
index 0000000..9ed2e19
--- /dev/null
+++ b/src/com/android/settings/applications/DefaultAutoFillPreference.java
@@ -0,0 +1,141 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Parcelable;
+import android.provider.Settings;
+import android.service.autofill.AutoFillService;
+import android.service.autofill.AutoFillServiceInfo;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.AppListPreferenceWithSettings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultAutoFillPreference extends AppListPreferenceWithSettings {
+    private static final String TAG = "DefaultAutoFill";
+
+    private static final String SETTING = Settings.Secure.AUTO_FILL_SERVICE;
+
+    public DefaultAutoFillPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        setSavesState(false);
+        setShowItemNone(true);
+
+        refreshData();
+    }
+
+    @Override
+    protected CharSequence getConfirmationMessage(String value) {
+        if (value == null || value.isEmpty()) {
+            return null;
+        }
+
+        int index = findIndexOfValue(value);
+        CharSequence[] entries = getEntries();
+        if (index < 0 || index >= entries.length) {
+            return null;
+        }
+
+        CharSequence entry = entries[index];
+        return getContext().getString(R.string.autofill_confirmation_message, entry);
+    }
+
+    @Override
+    protected boolean persistString(String value) {
+        Settings.Secure.putString(getContext().getContentResolver(), SETTING, value);
+        refreshData();
+        return true;
+    }
+
+    private void refreshData() {
+        ComponentName selectedComponent = getSelectedComponentName();
+        List<AutoFillServiceInfo> infos = getInfos();
+
+        AutoFillServiceInfo selectedInfo = null;
+        int numberOfComponents = infos.size();
+        ComponentName[] components = new ComponentName[numberOfComponents];
+        for (int i = 0; i < numberOfComponents; ++i) {
+            AutoFillServiceInfo info = infos.get(i);
+            ServiceInfo serviceInfo = info.getServiceInfo();
+            ComponentName component =
+                    new ComponentName(serviceInfo.packageName, serviceInfo.name);
+            components[i] = component;
+
+            if (component.equals(selectedComponent)) {
+                selectedInfo = info;
+            }
+        }
+
+        ComponentName selectedComponentSettings = null;
+        if (selectedInfo != null) {
+            String settingsActivity = selectedInfo.getSettingsActivity();
+            selectedComponentSettings = settingsActivity != null
+                    ? new ComponentName(selectedComponent.getPackageName(), settingsActivity)
+                    : null;
+        } else { // selected component not found
+            Log.w(TAG, "Selected AutoFillService not found " + selectedComponent);
+            selectedComponent = null;
+            selectedComponentSettings = null;
+        }
+
+        setComponentNames(components, selectedComponent);
+        setSettingsComponent(selectedComponentSettings);
+        setSummary(getEntry());
+    }
+
+    @Nullable
+    private ComponentName getSelectedComponentName() {
+        String componentString =
+                Settings.Secure.getString(getContext().getContentResolver(), SETTING);
+        if (componentString == null) {
+            return null;
+        }
+
+        return ComponentName.unflattenFromString(componentString);
+    }
+
+    private List<AutoFillServiceInfo> getInfos() {
+        PackageManager pm = getContext().getPackageManager();
+        List<ResolveInfo> resolveInfos = pm.queryIntentServices(
+                new Intent(AutoFillService.SERVICE_INTERFACE),
+                PackageManager.GET_META_DATA);
+        List<AutoFillServiceInfo> infos = new ArrayList<>(resolveInfos.size());
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+            AutoFillServiceInfo info = new AutoFillServiceInfo(pm, serviceInfo);
+            if (info.getParseError() == null) {
+                infos.add(info);
+            } else {
+                Log.i(TAG, "Invalid AutoFillService " + serviceInfo + ": " + info.getParseError());
+            }
+        }
+        return infos;
+    }
+}