From d15967489003a96919a697292d34ce018f72c506 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 4 Oct 2013 13:57:22 -0700 Subject: [PATCH] Notify that ASEC containers are being unmounted during upgrades When an apk is installed on ordinary unmountable media, a broadcast is sent when the OS wants to unmount it so that interested parties can cleanly close any files they have open to read that apk's resources or similar. We now send that broadcast when we are about to unmount the ASEC fs container that holds a forward-locked apk as well, so that e.g. Home knows to release the resources that it was using for widget hosting or similar. Bug 7703848 Change-Id: I71aefdb4086c7b73a128f89c15d192a2b92d09a8 --- .../server/pm/PackageManagerService.java | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index f093f2bd2690d..d239be7574bea 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -850,6 +850,19 @@ public class PackageManagerService extends IPackageManager.Stub { sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, res.pkg.applicationInfo.packageName, null, updateUsers); + + // treat asec-hosted packages like removable media on upgrade + if (isForwardLocked(res.pkg) || isExternal(res.pkg)) { + if (DEBUG_INSTALL) { + Slog.i(TAG, "upgrading pkg " + res.pkg + + " is ASEC-hosted -> AVAILABLE"); + } + int[] uidArray = new int[] { res.pkg.applicationInfo.uid }; + ArrayList pkgList = new ArrayList(1); + pkgList.add(res.pkg.applicationInfo.packageName); + sendResourcesChangedBroadcast(true, false, + pkgList,uidArray, null); + } } if (res.removedInfo.args != null) { // Remove the replaced package's older resources safely now @@ -4643,6 +4656,20 @@ public class PackageManagerService extends IPackageManager.Stub { // so that we do not end up in a confused state while the user is still using the older // version of the application while the new one gets installed. if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { + // If the package lives in an asec, tell everyone that the container is going + // away so they can clean up any references to its resources (which would prevent + // vold from being able to unmount the asec) + if (isForwardLocked(pkg) || isExternal(pkg)) { + if (DEBUG_INSTALL) { + Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE"); + } + final int[] uidArray = new int[] { pkg.applicationInfo.uid }; + final ArrayList pkgList = new ArrayList(1); + pkgList.add(pkg.applicationInfo.packageName); + sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null); + } + + // Post the request that it be killed now that the going-away broadcast is en route killApplication(pkg.applicationInfo.packageName, pkg.applicationInfo.uid, "update pkg"); } @@ -10731,8 +10758,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList pkgList, - int uidArr[], IIntentReceiver finishedReceiver) { + private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing, + ArrayList pkgList, int uidArr[], IIntentReceiver finishedReceiver) { int size = pkgList.size(); if (size > 0) { // Send broadcasts here @@ -10742,6 +10769,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (uidArr != null) { extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); } + if (replacing && !mediaStatus) { + extras.putBoolean(Intent.EXTRA_REPLACING, replacing); + } String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; sendPackageBroadcast(action, null, extras, null, finishedReceiver, null); @@ -10844,7 +10874,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Send a broadcast to let everyone know we are done processing if (pkgList.size() > 0) { - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null); } // Force gc to avoid any stale parser references that we might have. if (doGc) { @@ -10921,7 +10951,8 @@ public class PackageManagerService extends IPackageManager.Stub { // 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() { + sendResourcesChangedBroadcast(false, false, pkgList, uidArr, + new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { @@ -11041,7 +11072,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (returnCode == PackageManager.MOVE_SUCCEEDED) { // Send resources unavailable broadcast - sendResourcesChangedBroadcast(false, pkgList, uidArr, null); + sendResourcesChangedBroadcast(false, true, pkgList, uidArr, null); // Update package code and resource paths synchronized (mInstallLock) { synchronized (mPackages) { @@ -11119,7 +11150,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } // Send resources available broadcast - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null); } } if (returnCode != PackageManager.MOVE_SUCCEEDED) {