Add autofill app preference to Default Apps.
Add an option to AppListPreference to disable saving/restoring state.
Bug: 34396007
Test: Manual verification
Change-Id: I80103bd3d4e8fadfa30b7d3631d24c1b159da0dd
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7a3be0c..15a4373 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8126,4 +8126,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;
+ }
+}