am a55987df: am 812b24fd: Merge "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

Merge commit 'a55987df919240b045de977217bd55723c37dfcb' into kraken

* commit 'a55987df919240b045de977217bd55723c37dfcb':
  Fix crashes related to unmounting when app on sdcard has an active notification
This commit is contained in:
Suchi Amalapurapu
2010-04-13 15:36:10 -07:00
committed by Android Git Automerger

View File

@@ -621,10 +621,27 @@ class PackageManagerService extends IPackageManager.Stub {
} }
} break; } break;
case UPDATED_MEDIA_STATUS: { case UPDATED_MEDIA_STATUS: {
try { if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
PackageHelper.getMountService().finishMediaUpdate(); boolean reportStatus = msg.arg1 == 1;
} catch (RemoteException e) { boolean doGc = msg.arg2 == 1;
Log.e(TAG, "MountService not running?"); 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; } break;
case WRITE_SETTINGS: { case WRITE_SETTINGS: {
@@ -9465,9 +9482,9 @@ class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
mediaStatus+", mMediaMounted=" + mMediaMounted); mediaStatus+", mMediaMounted=" + mMediaMounted);
if (mediaStatus == mMediaMounted) { if (mediaStatus == mMediaMounted) {
if (reportStatus) { Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS); reportStatus ? 1 : 0, -1);
} mHandler.sendMessage(msg);
return; return;
} }
mMediaMounted = mediaStatus; mMediaMounted = mediaStatus;
@@ -9476,38 +9493,42 @@ class PackageManagerService extends IPackageManager.Stub {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {
mHandler.removeCallbacks(this); mHandler.removeCallbacks(this);
try { updateExternalMediaStatusInner(mediaStatus, reportStatus);
updateExternalMediaStatusInner(mediaStatus);
} finally {
if (reportStatus) {
mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
}
}
} }
}); });
} }
private void updateExternalMediaStatusInner(boolean mediaStatus) { /*
// If we are up here that means there are packages to be * Collect information of applications on external media, map them
// enabled or disabled. * 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(); final String list[] = PackageHelper.getSecureContainerList();
if (list == null || list.length == 0) { if (list == null || list.length == 0) {
Log.i(TAG, "No secure containers on sdcard"); Log.i(TAG, "No secure containers on sdcard");
return; } 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 uidList[] = new int[list.length];
int num = 0; int num = 0;
HashSet<String> removeCids = new HashSet<String>(); synchronized (mPackages) {
HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>(); for (String cid : list) {
synchronized (mPackages) { SdInstallArgs args = new SdInstallArgs(cid);
for (String cid : list) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
SdInstallArgs args = new SdInstallArgs(cid);
if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
boolean failed = true;
try {
String pkgName = args.getPackageName(); String pkgName = args.getPackageName();
if (pkgName == null) { if (pkgName == null) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
removeCids.add(cid);
continue; continue;
} }
if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName); if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
@@ -9519,33 +9540,29 @@ class PackageManagerService extends IPackageManager.Stub {
" at code path: " + ps.codePathString); " at code path: " + ps.codePathString);
// We do have a valid package installed on sdcard // We do have a valid package installed on sdcard
processCids.put(args, ps.codePathString); processCids.put(args, ps.codePathString);
failed = false;
int uid = ps.userId; int uid = ps.userId;
if (uid != -1) { if (uid != -1) {
uidList[num++] = uid; uidList[num++] = uid;
} }
} } else {
} finally {
if (failed) {
// Stale container on sdcard. Just delete // Stale container on sdcard. Just delete
if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale"); if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
removeCids.add(cid); removeCids.add(cid);
} }
} }
} }
}
// Organize uids if (num > 0) {
int uidArr[] = null; // Sort uid list
if (num > 0) { Arrays.sort(uidList, 0, num);
// Sort uid list // Throw away duplicates
Arrays.sort(uidList, 0, num); uidArr = new int[num];
// Throw away duplicates uidArr[0] = uidList[0];
uidArr = new int[num]; int di = 0;
uidArr[0] = uidList[0]; for (int i = 1; i < num; i++) {
int di = 0; if (uidList[i-1] != uidList[i]) {
for (int i = 1; i < num; i++) { uidArr[di++] = uidList[i];
if (uidList[i-1] != uidList[i]) { }
uidArr[di++] = uidList[i];
} }
} }
} }
@@ -9556,7 +9573,7 @@ class PackageManagerService extends IPackageManager.Stub {
startCleaningPackages(); startCleaningPackages();
} else { } else {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
unloadMediaPackages(processCids, uidArr); unloadMediaPackages(processCids, uidArr, reportStatus);
} }
} }
@@ -9581,10 +9598,7 @@ class PackageManagerService extends IPackageManager.Stub {
* Look at potentially valid container ids from processCids * Look at potentially valid container ids from processCids
* If package information doesn't match the one on record * If package information doesn't match the one on record
* or package scanning fails, the cid is added to list of * or package scanning fails, the cid is added to list of
* removeCids and cleaned up. Since cleaning up containers * removeCids. We currently don't delete stale containers.
* involves destroying them, we do not want any parse
* references to such stale containers. So force gc's
* to avoid unnecessary crashes.
*/ */
private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
int uidArr[], HashSet<String> removeCids) { int uidArr[], HashSet<String> removeCids) {
@@ -9662,6 +9676,7 @@ class PackageManagerService extends IPackageManager.Stub {
if (pkgList.size() > 0) { if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(true, pkgList, uidArr, null); sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
} }
// Force gc to avoid any stale parser references that we might have.
if (doGc) { if (doGc) {
Runtime.getRuntime().gc(); Runtime.getRuntime().gc();
} }
@@ -9673,12 +9688,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, private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
int uidArr[]) { int uidArr[], final boolean reportStatus) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages"); if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
ArrayList<String> pkgList = new ArrayList<String>(); ArrayList<String> pkgList = new ArrayList<String>();
ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>(); ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Set<SdInstallArgs> keys = processCids.keySet(); final Set<SdInstallArgs> keys = processCids.keySet();
for (SdInstallArgs args : keys) { for (SdInstallArgs args : keys) {
String cid = args.cid; String cid = args.cid;
String pkgName = args.getPackageName(); String pkgName = args.getPackageName();
@@ -9696,22 +9732,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) { if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException { boolean ordered, boolean sticky) throws RemoteException {
// Force gc now that everyone is done cleaning up, to release Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
// references on assets. reportStatus ? 1 : 0, 1, keys);
Runtime.getRuntime().gc(); mHandler.sendMessage(msg);
} }
}); });
} } else {
// Just unmount all valid containers. Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
for (SdInstallArgs args : keys) { reportStatus ? 1 : 0, -1, keys);
synchronized (mInstallLock) { mHandler.sendMessage(msg);
args.doPostDeleteLI(false);
}
} }
} }