summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/PackageManagerService.java
diff options
context:
space:
mode:
authorSuchi Amalapurapu <asuchitra@google.com>2010-04-08 14:37:05 -0700
committerSuchi Amalapurapu <asuchitra@google.com>2010-04-13 11:20:57 -0700
commit3d24425165aabfd2a8d5e5f973f085c6e6446341 (patch)
treec8f3c3a3f4448aa285bf6833aef9f361a181b830 /services/java/com/android/server/PackageManagerService.java
parentbcac496076ef6f439147e7a2be71e8a2b76ddede (diff)
downloadframeworks_base-3d24425165aabfd2a8d5e5f973f085c6e6446341.zip
frameworks_base-3d24425165aabfd2a8d5e5f973f085c6e6446341.tar.gz
frameworks_base-3d24425165aabfd2a8d5e5f973f085c6e6446341.tar.bz2
Fix crashes related to unmounting when app on sdcard has an active notification
in status bar. When unmounting sdcard, all the secure containers have to be unmounted first before invoking the MountService call back. We send a broadcast about disabled packages. Force a gc to clean up any stale asset references and then unmount the containers before invoking the MountService call back. Change-Id: I831da1ae54aeec89de3601b94a4a2fae5dc7e495
Diffstat (limited to 'services/java/com/android/server/PackageManagerService.java')
-rw-r--r--services/java/com/android/server/PackageManagerService.java165
1 files changed, 101 insertions, 64 deletions
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 3908389..78f7b33 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -615,10 +615,27 @@ class PackageManagerService extends IPackageManager.Stub {
}
} break;
case UPDATED_MEDIA_STATUS: {
- try {
- PackageHelper.getMountService().finishMediaUpdate();
- } catch (RemoteException e) {
- Log.e(TAG, "MountService not running?");
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
+ boolean reportStatus = msg.arg1 == 1;
+ boolean doGc = msg.arg2 == 1;
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
+ if (doGc) {
+ // Force a gc to clear up stale containers.
+ Runtime.getRuntime().gc();
+ }
+ if (msg.obj != null) {
+ Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
+ // Unload containers
+ unloadAllContainers(args);
+ }
+ if (reportStatus) {
+ try {
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
+ PackageHelper.getMountService().finishMediaUpdate();
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService not running?");
+ }
}
} break;
case WRITE_SETTINGS: {
@@ -9429,9 +9446,9 @@ class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
mediaStatus+", mMediaMounted=" + mMediaMounted);
if (mediaStatus == mMediaMounted) {
- if (reportStatus) {
- mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
- }
+ Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
+ reportStatus ? 1 : 0, -1);
+ mHandler.sendMessage(msg);
return;
}
mMediaMounted = mediaStatus;
@@ -9440,38 +9457,42 @@ class PackageManagerService extends IPackageManager.Stub {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- try {
- updateExternalMediaStatusInner(mediaStatus);
- } finally {
- if (reportStatus) {
- mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
- }
- }
+ updateExternalMediaStatusInner(mediaStatus, reportStatus);
}
});
}
- private void updateExternalMediaStatusInner(boolean mediaStatus) {
- // If we are up here that means there are packages to be
- // enabled or disabled.
+ /*
+ * Collect information of applications on external media, map them
+ * against existing containers and update information based on current
+ * mount status. Please note that we always have to report status
+ * if reportStatus has been set to true especially when unloading packages.
+ */
+ private void updateExternalMediaStatusInner(boolean mediaStatus,
+ boolean reportStatus) {
+ // Collection of uids
+ int uidArr[] = null;
+ // Collection of stale containers
+ HashSet<String> removeCids = new HashSet<String>();
+ // Collection of packages on external media with valid containers.
+ HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
+ // Get list of secure containers.
final String list[] = PackageHelper.getSecureContainerList();
if (list == null || list.length == 0) {
Log.i(TAG, "No secure containers on sdcard");
- return;
- }
-
- int uidList[] = new int[list.length];
- int num = 0;
- HashSet<String> removeCids = new HashSet<String>();
- HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
- synchronized (mPackages) {
- for (String cid : list) {
- SdInstallArgs args = new SdInstallArgs(cid);
- if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
- boolean failed = true;
- try {
+ } else {
+ // Process list of secure containers and categorize them
+ // as active or stale based on their package internal state.
+ int uidList[] = new int[list.length];
+ int num = 0;
+ synchronized (mPackages) {
+ for (String cid : list) {
+ SdInstallArgs args = new SdInstallArgs(cid);
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
String pkgName = args.getPackageName();
if (pkgName == null) {
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
+ removeCids.add(cid);
continue;
}
if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
@@ -9483,33 +9504,29 @@ class PackageManagerService extends IPackageManager.Stub {
" at code path: " + ps.codePathString);
// We do have a valid package installed on sdcard
processCids.put(args, ps.codePathString);
- failed = false;
int uid = ps.userId;
if (uid != -1) {
uidList[num++] = uid;
}
- }
- } finally {
- if (failed) {
+ } else {
// Stale container on sdcard. Just delete
if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
removeCids.add(cid);
}
}
}
- }
- // Organize uids
- int uidArr[] = null;
- if (num > 0) {
- // Sort uid list
- Arrays.sort(uidList, 0, num);
- // Throw away duplicates
- uidArr = new int[num];
- uidArr[0] = uidList[0];
- int di = 0;
- for (int i = 1; i < num; i++) {
- if (uidList[i-1] != uidList[i]) {
- uidArr[di++] = uidList[i];
+
+ if (num > 0) {
+ // Sort uid list
+ Arrays.sort(uidList, 0, num);
+ // Throw away duplicates
+ uidArr = new int[num];
+ uidArr[0] = uidList[0];
+ int di = 0;
+ for (int i = 1; i < num; i++) {
+ if (uidList[i-1] != uidList[i]) {
+ uidArr[di++] = uidList[i];
+ }
}
}
}
@@ -9520,7 +9537,7 @@ class PackageManagerService extends IPackageManager.Stub {
startCleaningPackages();
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
- unloadMediaPackages(processCids, uidArr);
+ unloadMediaPackages(processCids, uidArr, reportStatus);
}
}
@@ -9545,10 +9562,7 @@ class PackageManagerService extends IPackageManager.Stub {
* Look at potentially valid container ids from processCids
* If package information doesn't match the one on record
* or package scanning fails, the cid is added to list of
- * removeCids and cleaned up. Since cleaning up containers
- * involves destroying them, we do not want any parse
- * references to such stale containers. So force gc's
- * to avoid unnecessary crashes.
+ * removeCids. We currently don't delete stale containers.
*/
private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
int uidArr[], HashSet<String> removeCids) {
@@ -9626,6 +9640,7 @@ class PackageManagerService extends IPackageManager.Stub {
if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
}
+ // Force gc to avoid any stale parser references that we might have.
if (doGc) {
Runtime.getRuntime().gc();
}
@@ -9637,12 +9652,33 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ /*
+ * Utility method to unload a list of specified containers
+ */
+ private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
+ // Just unmount all valid containers.
+ for (SdInstallArgs arg : cidArgs) {
+ synchronized (mInstallLock) {
+ arg.doPostDeleteLI(false);
+ }
+ }
+ }
+
+ /*
+ * Unload packages mounted on external media. This involves deleting
+ * package data from internal structures, sending broadcasts about
+ * diabled packages, gc'ing to free up references, unmounting all
+ * secure containers corresponding to packages on external media, and
+ * posting a UPDATED_MEDIA_STATUS message if status has been requested.
+ * Please note that we always have to post this message if status has
+ * been requested no matter what.
+ */
private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
- int uidArr[]) {
+ int uidArr[], final boolean reportStatus) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
ArrayList<String> pkgList = new ArrayList<String>();
ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
- Set<SdInstallArgs> keys = processCids.keySet();
+ final Set<SdInstallArgs> keys = processCids.keySet();
for (SdInstallArgs args : keys) {
String cid = args.cid;
String pkgName = args.getPackageName();
@@ -9660,22 +9696,23 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
}
- // Send broadcasts
+ // We have to absolutely send UPDATED_MEDIA_STATUS only
+ // after confirming that all the receivers processed the ordered
+ // broadcast when packages get disabled, force a gc to clean things up.
+ // and unload all the containers.
if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException {
- // Force gc now that everyone is done cleaning up, to release
- // references on assets.
- Runtime.getRuntime().gc();
+ Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
+ reportStatus ? 1 : 0, 1, keys);
+ mHandler.sendMessage(msg);
}
});
- }
- // Just unmount all valid containers.
- for (SdInstallArgs args : keys) {
- synchronized (mInstallLock) {
- args.doPostDeleteLI(false);
- }
+ } else {
+ Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
+ reportStatus ? 1 : 0, -1, keys);
+ mHandler.sendMessage(msg);
}
}