diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 61b62cbee7f..32ec381883f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2768,7 +2768,7 @@ - @@ -2780,7 +2780,7 @@ + android:value="com.android.settings.applications.AdvancedAppSettings" /> + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 3b9e71269ae..98d78c0d134 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6511,7 +6511,10 @@ Not recognized - Default Apps + Default + + + Default for work Assist & voice input @@ -7246,4 +7249,8 @@ default none + + + Special access + diff --git a/res/xml/advanced_apps.xml b/res/xml/advanced_apps.xml index 70b68568c26..99e81a60dbe 100644 --- a/res/xml/advanced_apps.xml +++ b/res/xml/advanced_apps.xml @@ -24,52 +24,80 @@ android:title="@string/app_permissions" settings:keywords="@string/keywords_app_permissions" /> - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + android:title="@string/advanced_apps"> - - - - - - - - - - - - - + + diff --git a/res/xml/default_apps.xml b/res/xml/default_apps.xml deleted file mode 100644 index 76d0e8ca5b6..00000000000 --- a/res/xml/default_apps.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml new file mode 100644 index 00000000000..9b404dfd692 --- /dev/null +++ b/res/xml/special_access.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java index 1c1ccd7447a..8dee7b8f530 100644 --- a/src/com/android/settings/AppListPreference.java +++ b/src/com/android/settings/AppListPreference.java @@ -23,9 +23,12 @@ import android.content.DialogInterface; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; +import android.os.UserHandle; +import android.os.UserManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -47,6 +50,9 @@ public class AppListPreference extends CustomListPreference { public static final String ITEM_NONE_VALUE = ""; + protected final boolean mForWork; + protected final int mUserId; + private Drawable[] mEntryDrawables; private boolean mShowItemNone = false; private CharSequence[] mSummaries; @@ -91,13 +97,24 @@ public class AppListPreference extends CustomListPreference { } } - public AppListPreference(Context context, AttributeSet attrs, - int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); + public AppListPreference(Context context, AttributeSet attrs, int defStyle, int defAttrs) { + super(context, attrs, defStyle, defAttrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WorkPreference, 0, 0); + mForWork = a.getBoolean(R.styleable.WorkPreference_forWork, false); + final UserHandle managedProfile = Utils.getManagedProfile(UserManager.get(context)); + mUserId = mForWork && managedProfile != null ? managedProfile.getIdentifier() + : UserHandle.myUserId(); } public AppListPreference(Context context, AttributeSet attrs) { super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WorkPreference, 0, 0); + mForWork = a.getBoolean(R.styleable.WorkPreference_forWork, false); + final UserHandle managedProfile = Utils.getManagedProfile(UserManager.get(context)); + mUserId = mForWork && managedProfile != null ? managedProfile.getIdentifier() + : UserHandle.myUserId(); } public void setShowItemNone(boolean showItemNone) { @@ -114,7 +131,8 @@ public class AppListPreference extends CustomListPreference { int selectedIndex = -1; for (int i = 0; i < packageNames.length; i++) { try { - ApplicationInfo appInfo = pm.getApplicationInfo(packageNames[i].toString(), 0); + ApplicationInfo appInfo = pm.getApplicationInfoAsUser(packageNames[i].toString(), 0, + mUserId); applicationNames.add(appInfo.loadLabel(pm)); validatedPackageNames.add(appInfo.packageName); entryDrawables.add(appInfo.loadIcon(pm)); @@ -162,8 +180,8 @@ public class AppListPreference extends CustomListPreference { int selectedIndex = -1; for (int i = 0; i < componentNames.length; i++) { try { - ApplicationInfo appInfo = pm.getApplicationInfo( - componentNames[i].getPackageName().toString(), 0); + ApplicationInfo appInfo = pm.getApplicationInfoAsUser( + componentNames[i].getPackageName().toString(), 0, mUserId); applicationNames.add(appInfo.loadLabel(pm)); validatedComponentNames.add(componentNames[i].flattenToString()); entryDrawables.add(appInfo.loadIcon(pm)); diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java index b5f99b5ce32..9c0c9bef87e 100644 --- a/src/com/android/settings/InstrumentedFragment.java +++ b/src/com/android/settings/InstrumentedFragment.java @@ -47,6 +47,7 @@ public abstract class InstrumentedFragment extends PreferenceFragment { // Used for generic logging of Settings Preference Persistence, should not be used // outside SharedPreferencesLogger. public static final int ACTION_GENERIC_PACKAGE = UNDECLARED + 16; + public static final int SPECIAL_ACCESS = UNDECLARED + 17; /** * Declare the view of this category. diff --git a/src/com/android/settings/PreferenceAvailabilityProvider.java b/src/com/android/settings/SelfAvailablePreference.java similarity index 95% rename from src/com/android/settings/PreferenceAvailabilityProvider.java rename to src/com/android/settings/SelfAvailablePreference.java index bb33aee9c41..8e4e56df721 100644 --- a/src/com/android/settings/PreferenceAvailabilityProvider.java +++ b/src/com/android/settings/SelfAvailablePreference.java @@ -21,7 +21,7 @@ import android.content.Context; /** * Interface for classes whose instances can provide the availability of the preference. */ -public interface PreferenceAvailabilityProvider { +public interface SelfAvailablePreference { /** * @return the availability of the preference. Please make sure the availability in managed * profile is taken into account. diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 494fd3ba165..95aa70097b5 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -124,7 +124,7 @@ public class Settings extends SettingsActivity { public static class WriteSettingsActivity extends SettingsActivity { /* empty */ } public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ } public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ } - public static class ManageDefaultAppsActivity extends SettingsActivity { /* empty */ } + public static class AdvancedAppsActivity extends SettingsActivity { /* empty */ } public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ } public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index b8758238906..3f69a36f370 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -56,11 +56,11 @@ import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard; import com.android.settings.accessibility.CaptionPropertiesFragment; import com.android.settings.accounts.AccountSettings; import com.android.settings.accounts.AccountSyncSettings; +import com.android.settings.applications.AdvancedAppSettings; import com.android.settings.applications.DrawOverlayDetails; import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.ManageApplications; import com.android.settings.applications.ManageAssist; -import com.android.settings.applications.ManageDefaultApps; import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.applications.ProcessStatsUi; import com.android.settings.applications.UsageAccessDetails; @@ -315,7 +315,7 @@ public class SettingsActivity extends SettingsDrawerActivity ProcessStatsSummary.class.getName(), DrawOverlayDetails.class.getName(), WriteSettingsDetails.class.getName(), - ManageDefaultApps.class.getName(), + AdvancedAppSettings.class.getName(), WallpaperTypeSettings.class.getName(), }; diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java index e871c82b0b3..6144f72d7e7 100644 --- a/src/com/android/settings/SettingsPreferenceFragment.java +++ b/src/com/android/settings/SettingsPreferenceFragment.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.os.Bundle; +import android.support.annotation.XmlRes; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceGroupAdapter; @@ -132,6 +133,25 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { } + @Override + public void addPreferencesFromResource(@XmlRes int preferencesResId) { + super.addPreferencesFromResource(preferencesResId); + checkAvailablePrefs(getPreferenceScreen()); + } + + private void checkAvailablePrefs(PreferenceGroup preferenceGroup) { + if (preferenceGroup == null) return; + for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) { + Preference pref = preferenceGroup.getPreference(i); + if (pref instanceof SelfAvailablePreference + && !((SelfAvailablePreference) pref).isAvailable(getContext())) { + preferenceGroup.removePreference(pref); + } else if (pref instanceof PreferenceGroup) { + checkAvailablePrefs((PreferenceGroup) pref); + } + } + } + public FloatingActionButton getFloatingActionButton() { return mFloatingActionButton; } diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index b54c414d78d..c6af8fb6296 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -64,6 +64,8 @@ import android.provider.ContactsContract.RawContacts; import android.service.persistentdata.PersistentDataBlockManager; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; +import android.support.v7.preference.PreferenceManager; +import android.support.v7.preference.PreferenceScreen; import android.telephony.TelephonyManager; import android.text.Spannable; import android.text.SpannableString; @@ -83,7 +85,6 @@ import android.view.animation.AnimationUtils; import android.widget.ListView; import android.widget.TabWidget; import com.android.internal.util.UserIcons; -import com.android.settings.datausage.DataUsageList; import java.io.IOException; import java.io.InputStream; @@ -1025,5 +1026,41 @@ public final class Utils extends com.android.settingslib.Utils { .toString(); } } + + public static List getNonIndexable(int xml, Context context) { + List ret = new ArrayList<>(); + PreferenceManager manager = new PreferenceManager(context); + PreferenceScreen screen = manager.inflateFromResource(context, xml, null); + checkPrefs(screen, ret); + + return ret; + } + + private static void checkPrefs(PreferenceGroup group, List ret) { + if (group == null) return; + for (int i = 0; i < group.getPreferenceCount(); i++) { + Preference pref = group.getPreference(i); + if (pref instanceof SelfAvailablePreference + && !((SelfAvailablePreference) pref).isAvailable(group.getContext())) { + ret.add(pref.getKey()); + if (pref instanceof PreferenceGroup) { + addAll((PreferenceGroup) pref, ret); + } + } else if (pref instanceof PreferenceGroup) { + checkPrefs((PreferenceGroup) pref, ret); + } + } + } + + private static void addAll(PreferenceGroup group, List ret) { + if (group == null) return; + for (int i = 0; i < group.getPreferenceCount(); i++) { + Preference pref = group.getPreference(i); + ret.add(pref.getKey()); + if (pref instanceof PreferenceGroup) { + addAll((PreferenceGroup) pref, ret); + } + } + } } diff --git a/src/com/android/settings/WorkOnlyCategory.java b/src/com/android/settings/WorkOnlyCategory.java new file mode 100644 index 00000000000..ca4c82d7e98 --- /dev/null +++ b/src/com/android/settings/WorkOnlyCategory.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 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; + +import android.content.Context; +import android.os.UserManager; +import android.support.v7.preference.PreferenceCategory; +import android.util.AttributeSet; + +/** + * A PreferenceCategory that is only visible when the device has a work profile. + */ +public class WorkOnlyCategory extends PreferenceCategory implements SelfAvailablePreference { + + public WorkOnlyCategory(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean isAvailable(Context context) { + return Utils.getManagedProfile(UserManager.get(context)) != null; + } +} diff --git a/src/com/android/settings/applications/AdvancedAppSettings.java b/src/com/android/settings/applications/AdvancedAppSettings.java index 50f9a5bb6e6..6edbf60d933 100644 --- a/src/com/android/settings/applications/AdvancedAppSettings.java +++ b/src/com/android/settings/applications/AdvancedAppSettings.java @@ -16,23 +16,29 @@ package com.android.settings.applications; import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; +import android.provider.SearchIndexableResource; import android.support.v7.preference.Preference; - import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.Session; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class AdvancedAppSettings extends SettingsPreferenceFragment implements - ApplicationsState.Callbacks { + ApplicationsState.Callbacks, Indexable { static final String TAG = "AdvancedAppSettings"; @@ -176,4 +182,20 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements } } } + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.advanced_apps; + return Arrays.asList(sir); + } + + @Override + public List getNonIndexableKeys(Context context) { + return Utils.getNonIndexable(R.xml.advanced_apps, context); + } + }; } diff --git a/src/com/android/settings/applications/DefaultBrowserPreference.java b/src/com/android/settings/applications/DefaultBrowserPreference.java index a9a4e2a5c2d..a3ce6f24ad9 100644 --- a/src/com/android/settings/applications/DefaultBrowserPreference.java +++ b/src/com/android/settings/applications/DefaultBrowserPreference.java @@ -21,17 +21,25 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; -import android.os.UserHandle; +import android.os.Handler; +import android.text.TextUtils; import android.util.AttributeSet; - +import android.util.Log; +import com.android.internal.content.PackageMonitor; import com.android.settings.AppListPreference; -import com.android.settings.PreferenceAvailabilityProvider; +import com.android.settings.R; import java.util.ArrayList; import java.util.List; public class DefaultBrowserPreference extends AppListPreference { + private static final String TAG = "DefaultBrowserPref"; + + private static final long DELAY_UPDATE_BROWSER_MILLIS = 500; + + private final Handler mHandler = new Handler(); + final private PackageManager mPm; public DefaultBrowserPreference(Context context, AttributeSet attrs) { @@ -41,12 +49,70 @@ public class DefaultBrowserPreference extends AppListPreference { refreshBrowserApps(); } + @Override + public void onAttached() { + super.onAttached(); + updateDefaultBrowserPreference(); + mPackageMonitor.register(getContext(), getContext().getMainLooper(), false); + } + + @Override + public void onDetached() { + mPackageMonitor.unregister(); + super.onDetached(); + } + + @Override + protected boolean persistString(String newValue) { + + if (newValue == null) { + return false; + } + final CharSequence packageName = (CharSequence) newValue; + if (TextUtils.isEmpty(packageName)) { + return false; + } + boolean result = mPm.setDefaultBrowserPackageNameAsUser( + packageName.toString(), mUserId); + if (result) { + setSummary("%s"); + } + return result && super.persistString(newValue); + } + public void refreshBrowserApps() { List browsers = resolveBrowserApps(); setPackageNames(browsers.toArray(new String[browsers.size()]), null); } + private void updateDefaultBrowserPreference() { + refreshBrowserApps(); + + final PackageManager pm = getContext().getPackageManager(); + + String packageName = pm.getDefaultBrowserPackageNameAsUser(mUserId); + if (!TextUtils.isEmpty(packageName)) { + // Check if the default Browser package is still there + Intent intent = new Intent(); + intent.setPackage(packageName); + intent.setAction(Intent.ACTION_VIEW); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + intent.setData(Uri.parse("http:")); + + ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, mUserId); + if (info != null) { + setValue(packageName); + setSummary("%s"); + } else { + setSummary(R.string.default_browser_title_none); + } + } else { + setSummary(R.string.default_browser_title_none); + Log.d(TAG, "Cannot set empty default Browser value!"); + } + } + private List resolveBrowserApps() { List result = new ArrayList<>(); @@ -58,7 +124,7 @@ public class DefaultBrowserPreference extends AppListPreference { // Resolve that intent and check that the handleAllWebDataURI boolean is set List list = mPm.queryIntentActivitiesAsUser(intent, PackageManager.MATCH_ALL, - UserHandle.myUserId()); + mUserId); final int count = list.size(); for (int i=0; i dialerPackages = - DefaultDialerManager.getInstalledDialerApplications(getContext()); + DefaultDialerManager.getInstalledDialerApplications(getContext(), mUserId); final String[] dialers = new String[dialerPackages.size()]; for (int i = 0; i < dialerPackages.size(); i++) { @@ -62,22 +59,19 @@ public class DefaultPhonePreference extends AppListPreference { } private String getDefaultPackage() { - return DefaultDialerManager.getDefaultDialerApplication(getContext()); + return DefaultDialerManager.getDefaultDialerApplication(getContext(), mUserId); } - public static class AvailabilityProvider implements PreferenceAvailabilityProvider { - @Override - public boolean isAvailable(Context context) { - - final TelephonyManager tm = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - if (!tm.isVoiceCapable()) { - return false; - } - - final UserManager um = - (UserManager) context.getSystemService(Context.USER_SERVICE); - return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS); + @Override + public boolean isAvailable(Context context) { + final TelephonyManager tm = + (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (!tm.isVoiceCapable()) { + return false; } + + final UserManager um = + (UserManager) context.getSystemService(Context.USER_SERVICE); + return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS); } } diff --git a/src/com/android/settings/applications/DefaultSmsPreference.java b/src/com/android/settings/applications/DefaultSmsPreference.java index 73404bbc905..dd85b891b5a 100644 --- a/src/com/android/settings/applications/DefaultSmsPreference.java +++ b/src/com/android/settings/applications/DefaultSmsPreference.java @@ -22,17 +22,15 @@ import android.os.UserManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.AttributeSet; - import com.android.internal.telephony.SmsApplication; import com.android.internal.telephony.SmsApplication.SmsApplicationData; import com.android.settings.AppListPreference; -import com.android.settings.PreferenceAvailabilityProvider; -import com.android.settings.Utils; +import com.android.settings.SelfAvailablePreference; import java.util.Collection; import java.util.Objects; -public class DefaultSmsPreference extends AppListPreference { +public class DefaultSmsPreference extends AppListPreference implements SelfAvailablePreference { public DefaultSmsPreference(Context context, AttributeSet attrs) { super(context, attrs); @@ -70,18 +68,13 @@ public class DefaultSmsPreference extends AppListPreference { return true; } - public static class AvailabilityProvider implements PreferenceAvailabilityProvider { - @Override - public boolean isAvailable(Context context) { - boolean isRestrictedUser = - UserManager.get(context) - .getUserInfo(UserHandle.myUserId()).isRestricted(); - TelephonyManager tm = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - return !isRestrictedUser - && tm.isSmsCapable() - && !Utils.isManagedProfile(UserManager.get(context)); - } + @Override + public boolean isAvailable(Context context) { + boolean isRestrictedUser = + UserManager.get(context) + .getUserInfo(UserHandle.myUserId()).isRestricted(); + TelephonyManager tm = + (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + return !isRestrictedUser && tm.isSmsCapable(); } - } diff --git a/src/com/android/settings/applications/ManageAssist.java b/src/com/android/settings/applications/ManageAssist.java index 5a17a315744..7af967cddb6 100644 --- a/src/com/android/settings/applications/ManageAssist.java +++ b/src/com/android/settings/applications/ManageAssist.java @@ -18,20 +18,15 @@ package com.android.settings.applications; import android.app.AlertDialog; import android.content.ComponentName; -import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; -import android.os.UserManager; import android.provider.Settings; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; - import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.settings.PreferenceAvailabilityProvider; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.Utils; import com.android.settings.voice.VoiceInputListPreference; /** @@ -179,11 +174,4 @@ public class ManageAssist extends SettingsPreferenceFragment mDefaultAssitPref.setValue(assistPackage); updateUi(); } - - public static class AvailabilityProvider implements PreferenceAvailabilityProvider { - @Override - public boolean isAvailable(Context context) { - return !Utils.isManagedProfile(UserManager.get(context)); - } - } } diff --git a/src/com/android/settings/applications/ManageDefaultApps.java b/src/com/android/settings/applications/ManageDefaultApps.java deleted file mode 100644 index 327c98b1d19..00000000000 --- a/src/com/android/settings/applications/ManageDefaultApps.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2015 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.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.SearchIndexableResource; -import android.provider.Settings; -import android.support.v4.util.ArrayMap; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceScreen; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.content.PackageMonitor; -import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.settings.PreferenceAvailabilityProvider; -import com.android.settings.R; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.Index; -import com.android.settings.search.Indexable; -import com.android.settings.utils.ProfileSettingsPreferenceFragment; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ManageDefaultApps extends ProfileSettingsPreferenceFragment - implements Preference.OnPreferenceClickListener, Indexable { - - private static final String TAG = ManageDefaultApps.class.getSimpleName(); - - private static final String KEY_DEFAULT_HOME = "default_home"; - private static final String KEY_ASSIST_AND_VOICE_INPUT = "assist_and_voice_input"; - private static final String KEY_DEFAULT_BROWSER = "default_browser"; - private static final String KEY_DEFAULT_PHONE_APP = "default_phone_app"; - private static final String KEY_DEFAULT_EMERGENCY_APP = "default_emergency_app"; - private static final String KEY_SMS_APPLICATION = "default_sms_app"; - private static final String KEY_DEFAULT_NOTIFICATION_ASST = "default_notification_asst_app"; - private static final String[] PREFERENCE_KEYS = new String[] { - KEY_DEFAULT_HOME, KEY_ASSIST_AND_VOICE_INPUT, KEY_DEFAULT_BROWSER, - KEY_DEFAULT_PHONE_APP, KEY_DEFAULT_EMERGENCY_APP, KEY_SMS_APPLICATION, - KEY_DEFAULT_NOTIFICATION_ASST - }; - - private DefaultBrowserPreference mDefaultBrowserPreference; - private PackageManager mPm; - private int myUserId; - - private static final long DELAY_UPDATE_BROWSER_MILLIS = 500; - - private final Handler mHandler = new Handler(); - - private final Runnable mUpdateRunnable = new Runnable() { - @Override - public void run() { - updateDefaultBrowserPreference(); - } - }; - - private final PackageMonitor mPackageMonitor = new PackageMonitor() { - @Override - public void onPackageAdded(String packageName, int uid) { - sendUpdate(); - } - - @Override - public void onPackageAppeared(String packageName, int reason) { - sendUpdate(); - } - - @Override - public void onPackageDisappeared(String packageName, int reason) { - sendUpdate(); - } - - @Override - public void onPackageRemoved(String packageName, int uid) { - sendUpdate(); - } - - private void sendUpdate() { - mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_BROWSER_MILLIS); - } - }; - - private void updateDefaultBrowserPreference() { - mDefaultBrowserPreference.refreshBrowserApps(); - - final PackageManager pm = getPackageManager(); - - String packageName = pm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId()); - if (!TextUtils.isEmpty(packageName)) { - // Check if the default Browser package is still there - Intent intent = new Intent(); - intent.setPackage(packageName); - intent.setAction(Intent.ACTION_VIEW); - intent.addCategory(Intent.CATEGORY_BROWSABLE); - intent.setData(Uri.parse("http:")); - - ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, myUserId); - if (info != null) { - mDefaultBrowserPreference.setValue(packageName); - CharSequence label = info.loadLabel(pm); - mDefaultBrowserPreference.setSummary(label); - } else { - mDefaultBrowserPreference.setSummary(R.string.default_browser_title_none); - } - } else { - mDefaultBrowserPreference.setSummary(R.string.default_browser_title_none); - Log.d(TAG, "Cannot set empty default Browser value!"); - } - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - addPreferencesFromResource(R.xml.default_apps); - - mPm = getPackageManager(); - myUserId = UserHandle.myUserId(); - - - mDefaultBrowserPreference = (DefaultBrowserPreference) findPreference(KEY_DEFAULT_BROWSER); - mDefaultBrowserPreference.setOnPreferenceChangeListener( - new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - - if (newValue == null) { - return false; - } - final CharSequence packageName = (CharSequence) newValue; - if (TextUtils.isEmpty(packageName)) { - return false; - } - boolean result = mPm.setDefaultBrowserPackageNameAsUser( - packageName.toString(), myUserId); - if (result) { - mDefaultBrowserPreference.setValue(packageName.toString()); - final CharSequence appName = mDefaultBrowserPreference.getEntry(); - mDefaultBrowserPreference.setSummary(appName); - } - return result; - } - }); - - updatePreferenceVisibility(); - // Update the index. - Index.getInstance(getActivity()).updateFromClassNameResource( - ManageDefaultApps.class.getName(), true, true); - } - - /** - * Iterate all preferences and hide it if it is unavailable. - */ - private void updatePreferenceVisibility() { - PreferenceScreen preferenceScreen = getPreferenceScreen(); - int count = preferenceScreen.getPreferenceCount(); - List preferenceKeys = new ArrayList<>(); - for (int i = 0; i < count; i++) { - String preferenceKey = preferenceScreen.getPreference(i).getKey(); - if (!TextUtils.isEmpty(preferenceKey)) { - preferenceKeys.add(preferenceKey); - } - } - for (String preferenceKey : preferenceKeys) { - boolean isAvailable = getPreferenceAvailability(getContext(), preferenceKey); - if (!isAvailable) { - Preference preference = preferenceScreen.findPreference(preferenceKey); - preferenceScreen.removePreference(preference); - } - } - } - - /** - * Get availability of preference from {@link PreferenceAvailabilityProvider}. - */ - private static boolean getPreferenceAvailability(Context context, - String preferenceKey) { - // Consider the preference is unavailable if no corresponding provider is found. - PreferenceAvailabilityProvider provider = getPreferenceAvailabilityProvider(preferenceKey); - return (provider == null) ? false : provider.isAvailable(context); - } - - private static PreferenceAvailabilityProvider getPreferenceAvailabilityProvider( - String preferenceKey) { - switch (preferenceKey) { - case KEY_ASSIST_AND_VOICE_INPUT: - return new ManageAssist.AvailabilityProvider(); - case KEY_DEFAULT_BROWSER: - return new DefaultBrowserPreference.AvailabilityProvider(); - case KEY_DEFAULT_EMERGENCY_APP: - return new DefaultEmergencyPreference.AvailabilityProvider(); - case KEY_DEFAULT_HOME: - return new DefaultHomePreference.AvailabilityProvider(); - case KEY_DEFAULT_NOTIFICATION_ASST: - return new DefaultNotificationAssistantPreference.AvailabilityProvider(); - case KEY_DEFAULT_PHONE_APP: - return new DefaultPhonePreference.AvailabilityProvider(); - case KEY_SMS_APPLICATION: - return new DefaultSmsPreference.AvailabilityProvider(); - } - Log.w(TAG, "getPreferenceAvailabilityProvider: Cannot find provider for " + preferenceKey); - return null; - } - - @Override - public void onResume() { - super.onResume(); - updateDefaultBrowserPreference(); - mPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false); - } - - @Override - public void onPause() { - super.onPause(); - - mPackageMonitor.unregister(); - } - - @Override - protected int getMetricsCategory() { - return MetricsEvent.APPLICATIONS_DEFAULT_APPS; - } - - @Override - public boolean onPreferenceClick(Preference preference) { - return false; - } - - public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider() { - @Override - public List getXmlResourcesToIndex( - Context context, boolean enabled) { - SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = R.xml.default_apps; - return Arrays.asList(sir); - } - - @Override - public List getNonIndexableKeys(Context context) { - // Iterate all preferences to see which is not available. - final ArrayList result = new ArrayList<>(); - for (String key : PREFERENCE_KEYS) { - boolean isAvailable = getPreferenceAvailability(context, key); - if (!isAvailable) { - result.add(key); - } - } - return result; - } - }; - - protected String getIntentActionString() { - return Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS; - } - -} diff --git a/src/com/android/settings/applications/SpecialAccessSettings.java b/src/com/android/settings/applications/SpecialAccessSettings.java new file mode 100644 index 00000000000..8320b29dd72 --- /dev/null +++ b/src/com/android/settings/applications/SpecialAccessSettings.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 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.os.Bundle; +import com.android.settings.InstrumentedFragment; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +public class SpecialAccessSettings extends SettingsPreferenceFragment { + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.special_access); + } + + @Override + protected int getMetricsCategory() { + return InstrumentedFragment.SPECIAL_ACCESS; + } +} diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java index 59f83ec9380..e961474513d 100644 --- a/src/com/android/settings/search/Ranking.java +++ b/src/com/android/settings/search/Ranking.java @@ -32,7 +32,7 @@ import com.android.settings.WirelessSettings; import com.android.settings.accessibility.AccessibilitySettings; import com.android.settings.accounts.AccountSettings; import com.android.settings.applications.AdvancedAppSettings; -import com.android.settings.applications.ManageDefaultApps; +import com.android.settings.applications.SpecialAccessSettings; import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.datausage.DataUsageMeteredSettings; import com.android.settings.datausage.DataUsageSummary; @@ -148,7 +148,7 @@ public final class Ranking { // Advanced app settings sRankMap.put(AdvancedAppSettings.class.getName(), RANK_APPS); - sRankMap.put(ManageDefaultApps.class.getName(), RANK_APPS); + sRankMap.put(SpecialAccessSettings.class.getName(), RANK_APPS); // Users sRankMap.put(UserSettings.class.getName(), RANK_USERS); diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 1d55b5534fc..6aeb2a6bae3 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -16,6 +16,7 @@ package com.android.settings.search; +import android.provider.SearchIndexableResource; import com.android.settings.DateTimeSettings; import com.android.settings.DevelopmentSettings; import com.android.settings.DeviceInfoSettings; @@ -32,7 +33,7 @@ import com.android.settings.WirelessSettings; import com.android.settings.accessibility.AccessibilitySettings; import com.android.settings.accounts.AccountSettings; import com.android.settings.applications.AdvancedAppSettings; -import com.android.settings.applications.ManageDefaultApps; +import com.android.settings.applications.SpecialAccessSettings; import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.datausage.DataUsageMeteredSettings; import com.android.settings.datausage.DataUsageSummary; @@ -56,8 +57,6 @@ import com.android.settings.wifi.AdvancedWifiSettings; import com.android.settings.wifi.SavedAccessPointsWifiSettings; import com.android.settings.wifi.WifiSettings; -import android.provider.SearchIndexableResource; - import java.util.Collection; import java.util.HashMap; @@ -212,15 +211,15 @@ public final class SearchIndexableResources { sResMap.put(AdvancedAppSettings.class.getName(), new SearchIndexableResource( Ranking.getRankForClassName(AdvancedAppSettings.class.getName()), - R.xml.advanced_apps, + NO_DATA_RES_ID, AdvancedAppSettings.class.getName(), R.drawable.ic_settings_applications)); - sResMap.put(ManageDefaultApps.class.getName(), + sResMap.put(SpecialAccessSettings.class.getName(), new SearchIndexableResource( - Ranking.getRankForClassName(ManageDefaultApps.class.getName()), - NO_DATA_RES_ID, - ManageDefaultApps.class.getName(), + Ranking.getRankForClassName(SpecialAccessSettings.class.getName()), + R.xml.special_access, + SpecialAccessSettings.class.getName(), R.drawable.ic_settings_applications)); sResMap.put(UserSettings.class.getName(),