diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java index 76729abecb1..8a99e032181 100644 --- a/src/com/android/settings/applications/AppInfoBase.java +++ b/src/com/android/settings/applications/AppInfoBase.java @@ -136,7 +136,8 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment mPackageInfo = mPm.getPackageInfo(mAppEntry.info.packageName, PackageManager.GET_DISABLED_COMPONENTS | PackageManager.GET_UNINSTALLED_PACKAGES | - PackageManager.GET_SIGNATURES); + PackageManager.GET_SIGNATURES | + PackageManager.GET_PERMISSIONS); } catch (NameNotFoundException e) { Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e); } diff --git a/src/com/android/settings/applications/AppStateBaseBridge.java b/src/com/android/settings/applications/AppStateBaseBridge.java index 1e04e13cc21..d0b8431e337 100644 --- a/src/com/android/settings/applications/AppStateBaseBridge.java +++ b/src/com/android/settings/applications/AppStateBaseBridge.java @@ -43,7 +43,8 @@ public abstract class AppStateBaseBridge implements ApplicationsState.Callbacks // Running on the same background thread as the ApplicationsState lets // us run in the background and make sure they aren't doing updates at // the same time as us as well. - mHandler = new BackgroundHandler(mAppState.getBackgroundLooper()); + mHandler = new BackgroundHandler(mAppState != null ? mAppState.getBackgroundLooper() + : Looper.getMainLooper()); mMainHandler = new MainHandler(); } diff --git a/src/com/android/settings/applications/DefaultBrowserPreference.java b/src/com/android/settings/applications/DefaultBrowserPreference.java index a3ce6f24ad9..d25e2242344 100644 --- a/src/com/android/settings/applications/DefaultBrowserPreference.java +++ b/src/com/android/settings/applications/DefaultBrowserPreference.java @@ -22,6 +22,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Handler; +import android.os.UserHandle; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -172,4 +173,21 @@ public class DefaultBrowserPreference extends AppListPreference { mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_BROWSER_MILLIS); } }; + + public static boolean hasBrowserPreference(String pkg, Context context) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + intent.setData(Uri.parse("http:")); + intent.setPackage(pkg); + final List resolveInfos = + context.getPackageManager().queryIntentActivities(intent, 0); + return resolveInfos != null && resolveInfos.size() != 0; + } + + public static boolean isBrowserDefault(String pkg, Context context) { + String defaultPackage = context.getPackageManager() + .getDefaultBrowserPackageNameAsUser(UserHandle.myUserId()); + return defaultPackage != null && defaultPackage.equals(pkg); + } } diff --git a/src/com/android/settings/applications/DefaultEmergencyPreference.java b/src/com/android/settings/applications/DefaultEmergencyPreference.java index 4b448224cda..2a376337fa9 100644 --- a/src/com/android/settings/applications/DefaultEmergencyPreference.java +++ b/src/com/android/settings/applications/DefaultEmergencyPreference.java @@ -16,6 +16,7 @@ package com.android.settings.applications; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -29,6 +30,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; import android.util.AttributeSet; +import com.android.internal.telephony.SmsApplication; import com.android.settings.AppListPreference; import com.android.settings.SelfAvailablePreference; @@ -146,4 +148,18 @@ public class DefaultEmergencyPreference extends AppListPreference return isCapable(context) && context.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null; } + + public static boolean hasEmergencyPreference(String pkg, Context context) { + Intent i = new Intent(QUERY_INTENT); + i.setPackage(pkg); + final List resolveInfos = + context.getPackageManager().queryIntentActivities(i, 0); + return resolveInfos != null && resolveInfos.size() != 0; + } + + public static boolean isEmergencyDefault(String pkg, Context context) { + String defaultPackage = Settings.Secure.getString(context.getContentResolver(), + Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION); + return defaultPackage != null && defaultPackage.equals(pkg); + } } diff --git a/src/com/android/settings/applications/DefaultHomePreference.java b/src/com/android/settings/applications/DefaultHomePreference.java index 987d7c4733b..9f4a9130779 100644 --- a/src/com/android/settings/applications/DefaultHomePreference.java +++ b/src/com/android/settings/applications/DefaultHomePreference.java @@ -114,4 +114,24 @@ public class DefaultHomePreference extends AppListPreference { } return false; } + + public static boolean hasHomePreference(String pkg, Context context) { + ArrayList homeActivities = new ArrayList(); + PackageManager pm = context.getPackageManager(); + pm.getHomeActivities(homeActivities); + for (int i = 0; i < homeActivities.size(); i++) { + if (homeActivities.get(i).activityInfo.packageName.equals(pkg)) { + return true; + } + } + return false; + } + + public static boolean isHomeDefault(String pkg, Context context) { + ArrayList homeActivities = new ArrayList(); + PackageManager pm = context.getPackageManager(); + ComponentName def = pm.getHomeActivities(homeActivities); + + return def != null && def.getPackageName().equals(pkg); + } } diff --git a/src/com/android/settings/applications/DefaultPhonePreference.java b/src/com/android/settings/applications/DefaultPhonePreference.java index 3b614241f81..23f392939f4 100644 --- a/src/com/android/settings/applications/DefaultPhonePreference.java +++ b/src/com/android/settings/applications/DefaultPhonePreference.java @@ -17,6 +17,7 @@ package com.android.settings.applications; import android.content.Context; +import android.os.UserHandle; import android.os.UserManager; import android.telecom.DefaultDialerManager; import android.telephony.TelephonyManager; @@ -74,4 +75,16 @@ public class DefaultPhonePreference extends AppListPreference implements SelfAva (UserManager) context.getSystemService(Context.USER_SERVICE); return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS); } + + public static boolean hasPhonePreference(String pkg, Context context) { + List dialerPackages = + DefaultDialerManager.getInstalledDialerApplications(context, UserHandle.myUserId()); + return dialerPackages.contains(pkg); + } + + public static boolean isPhoneDefault(String pkg, Context context) { + String def = DefaultDialerManager.getDefaultDialerApplication(context, + UserHandle.myUserId()); + return def != null && def.equals(pkg); + } } diff --git a/src/com/android/settings/applications/DefaultSmsPreference.java b/src/com/android/settings/applications/DefaultSmsPreference.java index dd85b891b5a..9315102015e 100644 --- a/src/com/android/settings/applications/DefaultSmsPreference.java +++ b/src/com/android/settings/applications/DefaultSmsPreference.java @@ -77,4 +77,20 @@ public class DefaultSmsPreference extends AppListPreference implements SelfAvail (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return !isRestrictedUser && tm.isSmsCapable(); } + + public static boolean hasSmsPreference(String pkg, Context context) { + Collection smsApplications = + SmsApplication.getApplicationCollection(context); + for (SmsApplicationData data : smsApplications) { + if (data.mPackageName.equals(pkg)) { + return true; + } + } + return false; + } + + public static boolean isSmsDefault(String pkg, Context context) { + ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true); + return appName != null && appName.getPackageName().equals(pkg); + } } diff --git a/src/com/android/settings/applications/DrawOverlayDetails.java b/src/com/android/settings/applications/DrawOverlayDetails.java index 92ff4807929..7e87d8e94cd 100644 --- a/src/com/android/settings/applications/DrawOverlayDetails.java +++ b/src/com/android/settings/applications/DrawOverlayDetails.java @@ -156,13 +156,17 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc } public static CharSequence getSummary(Context context, AppEntry entry) { - if (entry.extraInfo != null) { - return getSummary(context, new OverlayState((PermissionState)entry.extraInfo)); + OverlayState state; + if (entry.extraInfo instanceof OverlayState) { + state = (OverlayState) entry.extraInfo; + } else if (entry.extraInfo instanceof PermissionState) { + state = new OverlayState((PermissionState) entry.extraInfo); + } else { + state = new AppStateOverlayBridge(context, null, null).getOverlayInfo( + entry.info.packageName, entry.info.uid); } - // fallback if for whatever reason entry.extrainfo is null - the result - // may be less accurate - return getSummary(context, entry.info.packageName); + return getSummary(context, state); } public static CharSequence getSummary(Context context, OverlayState overlayState) { diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 7ba6c7ff35e..197da7c0d98 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -16,6 +16,7 @@ package com.android.settings.applications; +import android.Manifest.permission; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; @@ -51,6 +52,8 @@ import android.os.UserHandle; import android.os.UserManager; import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceClickListener; +import android.support.v7.preference.PreferenceCategory; +import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.Formatter; @@ -285,6 +288,7 @@ public class InstalledAppDetails extends AppInfoBase setHasOptionsMenu(true); addPreferencesFromResource(R.xml.installed_app_details); + addDynamicPrefs(); if (Utils.isBandwidthControlEnabled()) { INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( @@ -321,6 +325,7 @@ public class InstalledAppDetails extends AppInfoBase } new BatteryUpdater().execute(); new MemoryUpdater().execute(); + updateDynamicPrefs(); } @Override @@ -806,6 +811,119 @@ public class InstalledAppDetails extends AppInfoBase return true; } + private void addDynamicPrefs() { + if (Utils.isManagedProfile(UserManager.get(getContext()))) { + return; + } + final PreferenceScreen screen = getPreferenceScreen(); + if (DefaultHomePreference.hasHomePreference(mPackageName, getContext())) { + screen.addPreference(new ShortcutPreference(getPrefContext(), + AdvancedAppSettings.class, "default_home", R.string.home_app, + R.string.configure_apps)); + } + if (DefaultBrowserPreference.hasBrowserPreference(mPackageName, getContext())) { + screen.addPreference(new ShortcutPreference(getPrefContext(), + AdvancedAppSettings.class, "default_browser", R.string.default_browser_title, + R.string.configure_apps)); + } + if (DefaultPhonePreference.hasPhonePreference(mPackageName, getContext())) { + screen.addPreference(new ShortcutPreference(getPrefContext(), + AdvancedAppSettings.class, "default_phone_app", R.string.default_phone_title, + R.string.configure_apps)); + } + if (DefaultEmergencyPreference.hasEmergencyPreference(mPackageName, getContext())) { + screen.addPreference(new ShortcutPreference(getPrefContext(), + AdvancedAppSettings.class, "default_emergency_app", + R.string.default_emergency_app, R.string.configure_apps)); + } + if (DefaultSmsPreference.hasSmsPreference(mPackageName, getContext())) { + screen.addPreference(new ShortcutPreference(getPrefContext(), + AdvancedAppSettings.class, "default_sms_app", R.string.sms_application_title, + R.string.configure_apps)); + } + boolean hasDrawOverOtherApps = hasPermission(permission.SYSTEM_ALERT_WINDOW); + boolean hasWriteSettings = hasPermission(permission.WRITE_SETTINGS); + if (hasDrawOverOtherApps || hasWriteSettings) { + PreferenceCategory category = new PreferenceCategory(getPrefContext()); + category.setTitle(R.string.advanced_apps); + screen.addPreference(category); + + if (hasDrawOverOtherApps) { + Preference pref = new Preference(getPrefContext()); + pref.setTitle(R.string.draw_overlay); + pref.setKey("system_alert_window"); + pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + startAppInfoFragment(DrawOverlayDetails.class, + getString(R.string.draw_overlay)); + return true; + } + }); + category.addPreference(pref); + } + if (hasWriteSettings) { + Preference pref = new Preference(getPrefContext()); + pref.setTitle(R.string.write_settings); + pref.setKey("write_settings_apps"); + pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + startAppInfoFragment(WriteSettingsDetails.class, + getString(R.string.write_settings)); + return true; + } + }); + category.addPreference(pref); + } + } + } + + private boolean hasPermission(String permission) { + for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) { + if (mPackageInfo.requestedPermissions[i].equals(permission)) { + return true; + } + } + return false; + } + + private void updateDynamicPrefs() { + Preference pref = findPreference("default_home"); + if (pref != null) { + pref.setSummary(DefaultHomePreference.isHomeDefault(mPackageName, getContext()) + ? R.string.yes : R.string.no); + } + pref = findPreference("default_browser"); + if (pref != null) { + pref.setSummary(DefaultBrowserPreference.isBrowserDefault(mPackageName, getContext()) + ? R.string.yes : R.string.no); + } + pref = findPreference("default_phone_app"); + if (pref != null) { + pref.setSummary(DefaultPhonePreference.isPhoneDefault(mPackageName, getContext()) + ? R.string.yes : R.string.no); + } + pref = findPreference("default_emergency_app"); + if (pref != null) { + pref.setSummary(DefaultEmergencyPreference.isEmergencyDefault(mPackageName, + getContext()) ? R.string.yes : R.string.no); + } + pref = findPreference("default_sms_app"); + if (pref != null) { + pref.setSummary(DefaultSmsPreference.isSmsDefault(mPackageName, getContext()) + ? R.string.yes : R.string.no); + } + pref = findPreference("system_alert_window"); + if (pref != null) { + pref.setSummary(DrawOverlayDetails.getSummary(getContext(), mAppEntry)); + } + pref = findPreference("write_settings_apps"); + if (pref != null) { + pref.setSummary(WriteSettingsDetails.getSummary(getContext(), mAppEntry)); + } + } + public static void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon, CharSequence versionName) { LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views, diff --git a/src/com/android/settings/applications/ShortcutPreference.java b/src/com/android/settings/applications/ShortcutPreference.java new file mode 100644 index 00000000000..e3db57a9444 --- /dev/null +++ b/src/com/android/settings/applications/ShortcutPreference.java @@ -0,0 +1,47 @@ +/* + * 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.content.Context; +import android.os.Bundle; +import android.support.v7.preference.Preference; +import com.android.settings.SettingsActivity; +import com.android.settings.Utils; + +public class ShortcutPreference extends Preference { + + private final Class mTarget; + private final String mPrefKey; + private final int mTitle; + + public ShortcutPreference(Context context, Class target, String prefKey, int prefTitle, + int title) { + super(context); + mTarget = target; + mPrefKey = prefKey; + mTitle = title; + setTitle(prefTitle); + setKey(mPrefKey); + } + + @Override + public void performClick() { + super.performClick(); + Bundle bundle = new Bundle(); + bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, mPrefKey); + Utils.startWithFragment(getContext(), mTarget.getName(), bundle, null, 0, + mTitle, null); + } +} diff --git a/src/com/android/settings/applications/WriteSettingsDetails.java b/src/com/android/settings/applications/WriteSettingsDetails.java index a4200d71634..d310d2b5220 100644 --- a/src/com/android/settings/applications/WriteSettingsDetails.java +++ b/src/com/android/settings/applications/WriteSettingsDetails.java @@ -158,13 +158,17 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere } public static CharSequence getSummary(Context context, AppEntry entry) { - if (entry.extraInfo != null) { - return getSummary(context, new WriteSettingsState((PermissionState)entry - .extraInfo)); + WriteSettingsState state; + if (entry.extraInfo instanceof WriteSettingsState) { + state = (WriteSettingsState) entry.extraInfo; + } else if (entry.extraInfo instanceof PermissionState) { + state = new WriteSettingsState((PermissionState) entry.extraInfo); + } else { + state = new AppStateWriteSettingsBridge(context, null, null).getWriteSettingsInfo( + entry.info.packageName, entry.info.uid); } - // fallback if entry.extrainfo is null - although this should not happen - return getSummary(context, entry.info.packageName); + return getSummary(context, state); } public static CharSequence getSummary(Context context, WriteSettingsState writeSettingsState) {