From 7574b6491029f4830de2e1db0962d301b41083f4 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Mon, 1 Aug 2016 11:00:04 -0700 Subject: [PATCH] Fix crash when selecting AppInfo for uninstalled app from Recents. When an app is uninstalled, the corresponding app info is not removed fromi the Recents tasks. If user selects that app info entry from the recents tasks, it will failed to retrieve the app detail as the package is already removed. Add the package removed event listener in InstalledAppDetails such that when the package has been unintalled, its app info task will also be removed from Recents. Change-Id: I771507f8f53017f87eda31ddef77a95e30921cbf Fixes: 28671923 Fix app info crashes when package is uninstalled from terminal. Move start listening to the package removed intents to onCreate() and continue listening throughout the whole lifecycle of the activity so that if user unintall the package in the background, it will still be notified. Change-Id: I889b0ea3e1245be83750d73349ed3a0f85a51783 Fixes: 28671923 Fix crash in Storage app info when the corresponding app is uninstalled in the background. 1. Move the handling for package removal from InstalledAppDetails to AppInfoBase so that all app info subclass will now finish correspondingly if the package is uninstalled. 2. In InstalledAppDetails, when handling package removal, will also finish the app info fragment that it starts earlier. Change-Id: Id741e7475414045040dd0797ff3bc63ac214f400 Fixes: 27774473 --- src/com/android/settings/Utils.java | 2 +- .../android/settings/applications/AppInfoBase.java | 38 ++++++++++++++++++++ .../settings/applications/InstalledAppDetails.java | 41 +++++++++++++--------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 0725386af7..a37039f796 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -515,7 +515,7 @@ public final class Utils extends com.android.settingslib.Utils { if (resultTo == null) { context.startActivity(intent); } else { - resultTo.startActivityForResult(intent, resultRequestCode); + resultTo.getActivity().startActivityForResult(intent, resultRequestCode); } } diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java index 8a99e03218..f7992cc8fd 100644 --- a/src/com/android/settings/applications/AppInfoBase.java +++ b/src/com/android/settings/applications/AppInfoBase.java @@ -22,8 +22,10 @@ import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -74,6 +76,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment protected static final int DLG_BASE = 0; protected boolean mFinishing; + protected boolean mListeningToPackageRemove; @Override public void onCreate(Bundle savedInstanceState) { @@ -90,6 +93,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment mUsbManager = IUsbManager.Stub.asInterface(b); retrieveAppEntry(); + startListeningToPackageRemove(); } @Override @@ -114,6 +118,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment @Override public void onDestroy() { + stopListeningToPackageRemove(); mSession.release(); super.onDestroy(); } @@ -246,4 +251,37 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment return dialogFragment; } } + + protected void startListeningToPackageRemove() { + if (mListeningToPackageRemove) { + return; + } + mListeningToPackageRemove = true; + final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + getContext().registerReceiver(mPackageRemovedReceiver, filter); + } + + protected void stopListeningToPackageRemove() { + if (!mListeningToPackageRemove) { + return; + } + mListeningToPackageRemove = false; + getContext().unregisterReceiver(mPackageRemovedReceiver); + } + + protected void onPackageRemoved() { + getActivity().finishAndRemoveTask(); + } + + protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String packageName = intent.getData().getSchemeSpecificPart(); + if (!mFinishing && mAppEntry.info.packageName.equals(packageName)) { + onPackageRemoved(); + } + } + }; + } diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index f3d5f516fa..977f0b01bb 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -483,21 +483,22 @@ public class InstalledAppDetails extends AppInfoBase @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_UNINSTALL) { - if (mDisableAfterUninstall) { - mDisableAfterUninstall = false; - new DisableChanger(this, mAppEntry.info, - PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) - .execute((Object)null); - } - if (!refreshUi()) { - setIntentAndFinish(true, true); - } - } - if (requestCode == REQUEST_REMOVE_DEVICE_ADMIN) { - if (!refreshUi()) { - setIntentAndFinish(true, true); - } + switch (requestCode) { + case REQUEST_UNINSTALL: + if (mDisableAfterUninstall) { + mDisableAfterUninstall = false; + new DisableChanger(this, mAppEntry.info, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) + .execute((Object)null); + } + // continue with following operations + case REQUEST_REMOVE_DEVICE_ADMIN: + if (!refreshUi()) { + setIntentAndFinish(true, true); + } else { + startListeningToPackageRemove(); + } + break; } } @@ -675,6 +676,7 @@ public class InstalledAppDetails extends AppInfoBase } private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) { + stopListeningToPackageRemove(); // Create new intent to launch Uninstaller activity Uri packageURI = Uri.parse("package:"+packageName); Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI); @@ -730,7 +732,7 @@ public class InstalledAppDetails extends AppInfoBase intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName); intent.putExtra(AppHeader.EXTRA_HIDE_INFO_BUTTON, true); try { - startActivity(intent); + getActivity().startActivityForResult(intent, SUB_INFO_FRAGMENT); } catch (ActivityNotFoundException e) { Log.w(LOG_TAG, "No app can handle android.intent.action.MANAGE_APP_PERMISSIONS"); } @@ -764,6 +766,7 @@ public class InstalledAppDetails extends AppInfoBase String packageName = mAppEntry.info.packageName; if (v == mUninstallButton) { if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { + stopListeningToPackageRemove(); Activity activity = getActivity(); Intent uninstallDAIntent = new Intent(activity, DeviceAdminAdd.class); uninstallDAIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME, @@ -1077,6 +1080,12 @@ public class InstalledAppDetails extends AppInfoBase return summary.toString(); } + @Override + protected void onPackageRemoved() { + getActivity().finishActivity(SUB_INFO_FRAGMENT); + super.onPackageRemoved(); + } + private class MemoryUpdater extends AsyncTask { @Override -- 2.11.0