Add default app prefs to app info

This makes them easier to discover and to know the state of them.

Bug: 27276982
Change-Id: I24a9d34d7e189b19df39cc0b9028b6412f76aa05
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 76729ab..8a99e03 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -136,7 +136,8 @@
                 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 1e04e13..d0b8431 100644
--- a/src/com/android/settings/applications/AppStateBaseBridge.java
+++ b/src/com/android/settings/applications/AppStateBaseBridge.java
@@ -43,7 +43,8 @@
         // 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 a3ce6f2..d25e224 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.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 @@
             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<ResolveInfo> 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 4b44822..2a37633 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.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 @@
         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<ResolveInfo> 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 987d7c4..9f4a913 100644
--- a/src/com/android/settings/applications/DefaultHomePreference.java
+++ b/src/com/android/settings/applications/DefaultHomePreference.java
@@ -114,4 +114,24 @@
         }
         return false;
     }
+
+    public static boolean hasHomePreference(String pkg, Context context) {
+        ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
+        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<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
+        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 3b61424..23f3929 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 @@
                 (UserManager) context.getSystemService(Context.USER_SERVICE);
         return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
     }
+
+    public static boolean hasPhonePreference(String pkg, Context context) {
+        List<String> 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 dd85b89..9315102 100644
--- a/src/com/android/settings/applications/DefaultSmsPreference.java
+++ b/src/com/android/settings/applications/DefaultSmsPreference.java
@@ -77,4 +77,20 @@
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         return !isRestrictedUser && tm.isSmsCapable();
     }
+
+    public static boolean hasSmsPreference(String pkg, Context context) {
+        Collection<SmsApplicationData> 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 92ff480..7e87d8e 100644
--- a/src/com/android/settings/applications/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/DrawOverlayDetails.java
@@ -156,13 +156,17 @@
     }
 
     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 7ba6c7f..197da7c 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.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 @@
 
         setHasOptionsMenu(true);
         addPreferencesFromResource(R.xml.installed_app_details);
+        addDynamicPrefs();
 
         if (Utils.isBandwidthControlEnabled()) {
             INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
@@ -321,6 +325,7 @@
         }
         new BatteryUpdater().execute();
         new MemoryUpdater().execute();
+        updateDynamicPrefs();
     }
 
     @Override
@@ -806,6 +811,119 @@
         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 0000000..e3db57a
--- /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 a4200d7..d310d2b 100644
--- a/src/com/android/settings/applications/WriteSettingsDetails.java
+++ b/src/com/android/settings/applications/WriteSettingsDetails.java
@@ -158,13 +158,17 @@
     }
 
     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) {