diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 6b6e7043c5e..5c77a9793e2 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -564,7 +564,9 @@ public class Settings extends PreferenceActivity int headerIndex = i + 1; i = insertAccountsHeaders(target, headerIndex); } else if (id == R.id.home_settings) { - updateHomeSettingHeaders(header); + if (!updateHomeSettingHeaders(header)) { + target.remove(i); + } } else if (id == R.id.user_settings) { if (!UserHandle.MU_ENABLED || !UserManager.supportsMultipleUsers() @@ -669,11 +671,16 @@ public class Settings extends PreferenceActivity return ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0); } - private void updateHomeSettingHeaders(Header header) { + private boolean updateHomeSettingHeaders(Header header) { final PackageManager pm = getPackageManager(); final ArrayList homeApps = new ArrayList(); try { ComponentName currentHome = pm.getHomeActivities(homeApps); + if (homeApps.size() < 2) { + // When there's only one available home app, omit this settings + // category entirely at the top level UI. + return false; + } ResolveInfo iconSource = null; if (currentHome == null) { // no current default, so find the system home app and use that @@ -708,6 +715,7 @@ public class Settings extends PreferenceActivity // Can't look up the home activity; bail on configuring the icon Log.w(LOG_TAG, "Problem looking up home activity!", e); } + return true; } private void getMetaData() { diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 37c33db6796..1b3938c2d74 100644 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -66,6 +66,7 @@ import android.util.Log; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import android.view.LayoutInflater; import android.view.Menu; @@ -143,6 +144,8 @@ public class InstalledAppDetails extends Fragment private PackageMoveObserver mPackageMoveObserver; + private final HashSet mHomePackages = new HashSet(); + private boolean mDisableAfterUninstall; private boolean mHaveSizes = false; @@ -320,29 +323,20 @@ public class InstalledAppDetails extends Fragment private boolean handleDisableable(Button button) { boolean disableable = false; - try { - // Try to prevent the user from bricking their phone - // by not allowing disabling of apps signed with the - // system cert and any launcher app in the system. - PackageInfo sys = mPm.getPackageInfo("android", - PackageManager.GET_SIGNATURES); - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(Intent.CATEGORY_HOME); - intent.setPackage(mAppEntry.info.packageName); - List homes = mPm.queryIntentActivities(intent, 0); - if ((homes != null && homes.size() > 0) || isThisASystemPackage()) { - // Disable button for core system applications. - button.setText(R.string.disable_text); - } else if (mAppEntry.info.enabled) { - button.setText(R.string.disable_text); - disableable = true; - } else { - button.setText(R.string.enable_text); - disableable = true; - } - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Unable to get package info", e); + // Try to prevent the user from bricking their phone + // by not allowing disabling of apps signed with the + // system cert and any launcher app in the system. + if (mHomePackages.contains(mAppEntry.info.packageName) || isThisASystemPackage()) { + // Disable button for core system applications. + button.setText(R.string.disable_text); + } else if (mAppEntry.info.enabled) { + button.setText(R.string.disable_text); + disableable = true; + } else { + button.setText(R.string.enable_text); + disableable = true; } + return disableable; } @@ -638,6 +632,21 @@ public class InstalledAppDetails extends Fragment return packageName; } + private boolean signaturesMatch(String pkg1, String pkg2) { + if (pkg1 != null && pkg2 != null) { + try { + final int match = mPm.checkSignatures(pkg1, pkg2); + if (match >= PackageManager.SIGNATURE_MATCH) { + return true; + } + } catch (Exception e) { + // e.g. named alternate package not found during lookup; + // this is an expected case sometimes + } + } + return false; + } + private boolean refreshUi() { if (mMoveInProgress) { return true; @@ -652,6 +661,25 @@ public class InstalledAppDetails extends Fragment return false; // onCreate must have failed, make sure to exit } + // Get list of "home" apps and trace through any meta-data references + List homeActivities = new ArrayList(); + mPm.getHomeActivities(homeActivities); + mHomePackages.clear(); + for (int i = 0; i< homeActivities.size(); i++) { + ResolveInfo ri = homeActivities.get(i); + final String activityPkg = ri.activityInfo.packageName; + mHomePackages.add(activityPkg); + + // Also make sure to include anything proxying for the home app + final Bundle metadata = ri.activityInfo.metaData; + if (metadata != null) { + final String metaPkg = metadata.getString(ActivityManager.META_HOME_ALTERNATE); + if (signaturesMatch(metaPkg, activityPkg)) { + mHomePackages.add(metaPkg); + } + } + } + // Get list of preferred activities List prefActList = new ArrayList(); @@ -1237,8 +1265,8 @@ public class InstalledAppDetails extends Fragment intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mAppEntry.info.packageName }); intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid)); - getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null, - Activity.RESULT_CANCELED, null, null); + getActivity().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, + mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null); } }