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
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f093f2b..d239be7 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -850,6 +850,19 @@
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<String> pkgList = new ArrayList<String>(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 @@
// 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<String> pkgList = new ArrayList<String>(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 @@
}
}
- private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
- int uidArr[], IIntentReceiver finishedReceiver) {
+ private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
+ ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
int size = pkgList.size();
if (size > 0) {
// Send broadcasts here
@@ -10742,6 +10769,9 @@
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 @@
}
// 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 @@
// 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 @@
}
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 @@
}
}
// Send resources available broadcast
- sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
+ sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
}
}
if (returnCode != PackageManager.MOVE_SUCCEEDED) {