From d506ddfc3f289fc5998242fb8b0f9633bd7f4ad1 Mon Sep 17 00:00:00 2001 From: Jason Long Date: Wed, 18 Jan 2017 13:38:23 -0800 Subject: [PATCH] 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 --- res/values/strings.xml | 10 ++ res/xml/app_default_settings.xml | 24 +-- .../android/settings/AppListPreference.java | 14 +- .../DefaultAutoFillPreference.java | 141 ++++++++++++++++++ 4 files changed, 177 insertions(+), 12 deletions(-) create mode 100644 src/com/android/settings/applications/DefaultAutoFillPreference.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 7a3be0c75c2..15a43739bd4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8126,4 +8126,14 @@ Disabled for user %s\n + + + Autofill app + + auto, fill, autofill + + + Make %1$s your autofill app? %1$s will be able to read your screen and fill fields in other apps. + + diff --git a/res/xml/app_default_settings.xml b/res/xml/app_default_settings.xml index 9b585c1edd9..27200e7dba7 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"/> + + + android:order="-18"> @@ -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"/> + android:order="-16"/> + android:order="-15"/> + android:order="-14"/> + android:order="-13"/> - \ No newline at end of file + diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java index 4cf4996972e..85854548cb2 100644 --- a/src/com/android/settings/AppListPreference.java +++ b/src/com/android/settings/AppListPreference.java @@ -61,6 +61,8 @@ public class AppListPreference extends CustomListPreference { 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 @@ public class AppListPreference extends CustomListPreference { : UserHandle.myUserId(); } + public void setSavesState(boolean savesState) { + mSavesState = savesState; + } + public void setShowItemNone(boolean showItemNone) { mShowItemNone = showItemNone; } @@ -261,12 +267,16 @@ public class AppListPreference extends CustomListPreference { @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 00000000000..9ed2e19ef16 --- /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 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 getInfos() { + PackageManager pm = getContext().getPackageManager(); + List resolveInfos = pm.queryIntentServices( + new Intent(AutoFillService.SERVICE_INTERFACE), + PackageManager.GET_META_DATA); + List 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; + } +}