Apps on sdcard: Add new broadcasts
Add new broadcasts ACTION_MEDIA_RESOURCES_AVAILABLE and
ACTION_MEDIA_RESOURCES_UNAVAILABLE that get broadcast by
PackageManagerService when sdcard gets mounted/unmounted
by MountService so that packages on sdcard get recognized by
various system services as being installed/available or
removed/unavailable by the system.
The broadcasts are sent before the actual package cleanup which includes
mounting/unmounting the packages and we force a gc right after so
that any lingering file references to resources on sdcard get
released.
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index f67a7ae..b56b13b 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -174,6 +174,11 @@
packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
packageFilter.addDataScheme("package");
context.registerReceiver(broadcastReceiver, packageFilter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(broadcastReceiver, sdFilter);
// boot completed
IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 18a5615..f330651 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -772,16 +772,33 @@
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(this, sdFilter);
}
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
- Uri data = intent.getData();
- if (data != null) {
- String pkg = data.getSchemeSpecificPart();
- removeLocked(pkg);
- mBroadcastStats.remove(pkg);
+ String action = intent.getAction();
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
+ Uri data = intent.getData();
+ if (data != null) {
+ String pkg = data.getSchemeSpecificPart();
+ if (pkg != null) {
+ pkgList = new String[]{pkg};
+ }
+ }
+ }
+ if (pkgList != null && (pkgList.length > 0)) {
+ for (String pkg : pkgList) {
+ removeLocked(pkg);
+ mBroadcastStats.remove(pkg);
+ }
}
}
}
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index ec7c60b..684f117 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -145,6 +145,11 @@
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
}
@Override
@@ -1070,36 +1075,55 @@
}
}
} else {
- Uri uri = intent.getData();
- if (uri == null) {
+ boolean added = false;
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ added = true;
+ } if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ added = false;
+ } else {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName == null) {
+ return;
+ }
+ pkgList = new String[] { pkgName };
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ }
+ if (pkgList == null || pkgList.length == 0) {
return;
}
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
- return;
- }
-
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ if (added) {
synchronized (mAppWidgetIds) {
Bundle extras = intent.getExtras();
if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
- // The package was just upgraded
- updateProvidersForPackageLocked(pkgName);
+ for (String pkgName : pkgList) {
+ // The package was just upgraded
+ updateProvidersForPackageLocked(pkgName);
+ }
} else {
// The package was just added
- addProvidersForPackageLocked(pkgName);
+ for (String pkgName : pkgList) {
+ addProvidersForPackageLocked(pkgName);
+ }
}
saveStateLocked();
}
- }
- else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ } else {
Bundle extras = intent.getExtras();
if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
} else {
synchronized (mAppWidgetIds) {
- removeProvidersForPackageLocked(pkgName);
- saveStateLocked();
+ for (String pkgName : pkgList) {
+ removeProvidersForPackageLocked(pkgName);
+ saveStateLocked();
+ }
}
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index ef184d2..0562c55 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -529,6 +529,11 @@
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
}
private void parseLeftoverJournals() {
@@ -665,35 +670,53 @@
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Received broadcast " + intent);
- Uri uri = intent.getData();
- if (uri == null) {
- return;
- }
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
- return;
- }
-
String action = intent.getAction();
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ boolean replacing = false;
+ boolean added = false;
+ Bundle extras = intent.getExtras();
+ String pkgList[] = null;
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName != null) {
+ pkgList = new String[] { pkgName };
+ }
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ } else if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action)) {
+ added = true;
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ added = false;
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ }
+ if (pkgList == null || pkgList.length == 0) {
+ return;
+ }
+ if (added) {
synchronized (mBackupParticipants) {
- Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
- // The package was just upgraded
- updatePackageParticipantsLocked(pkgName);
- } else {
- // The package was just added
- addPackageParticipantsLocked(pkgName);
+ for (String pkgName : pkgList) {
+ if (replacing) {
+ // The package was just upgraded
+ updatePackageParticipantsLocked(pkgName);
+ } else {
+ // The package was just added
+ addPackageParticipantsLocked(pkgName);
+ }
}
}
- }
- else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+ } else {
+ if (replacing) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
} else {
synchronized (mBackupParticipants) {
- removePackageParticipantsLocked(pkgName);
+ for (String pkgName : pkgList) {
+ removePackageParticipantsLocked(pkgName);
+ }
}
}
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 405dc2e..dc942a2 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -335,6 +335,22 @@
class PackageReceiver extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ String pkgList[] = null;
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Uri uri = intent.getData();
+ String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+ if (pkg != null) {
+ pkgList = new String[] { pkg };
+ }
+ } else if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action) ||
+ Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ }
+ if (pkgList == null || pkgList.length == 0) {
+ return;
+ }
synchronized (mMethodMap) {
buildInputMethodListLocked(mMethodList, mMethodMap);
@@ -352,38 +368,45 @@
boolean changed = false;
- Uri uri = intent.getData();
- String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
- if (curIm != null && curIm.getPackageName().equals(pkg)) {
- ServiceInfo si = null;
- try {
- si = mContext.getPackageManager().getServiceInfo(
- curIm.getComponent(), 0);
- } catch (PackageManager.NameNotFoundException ex) {
- }
- if (si == null) {
- // Uh oh, current input method is no longer around!
- // Pick another one...
- Log.i(TAG, "Current input method removed: " + curInputMethodId);
- if (!chooseNewDefaultIME()) {
- changed = true;
- curIm = null;
- curInputMethodId = "";
- Log.i(TAG, "Unsetting current input method");
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD,
- curInputMethodId);
+ if (curIm != null) {
+ boolean foundPkg = false;
+ for (String pkg : pkgList) {
+ if (curIm.getPackageName().equals(pkg)) {
+ foundPkg = true;
+ break;
}
}
+ if (foundPkg) {
+ ServiceInfo si = null;
+ try {
+ si = mContext.getPackageManager().getServiceInfo(
+ curIm.getComponent(), 0);
+ } catch (PackageManager.NameNotFoundException ex) {
+ }
+ if (si == null) {
+ // Uh oh, current input method is no longer around!
+ // Pick another one...
+ Log.i(TAG, "Current input method removed: " + curInputMethodId);
+ if (!chooseNewDefaultIME()) {
+ changed = true;
+ curIm = null;
+ curInputMethodId = "";
+ Log.i(TAG, "Unsetting current input method");
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD,
+ curInputMethodId);
+ }
+ }
- } else if (curIm == null) {
- // We currently don't have a default input method... is
- // one now available?
- changed = chooseNewDefaultIME();
- }
+ } else if (curIm == null) {
+ // We currently don't have a default input method... is
+ // one now available?
+ changed = chooseNewDefaultIME();
+ }
- if (changed) {
- updateFromSettingsLocked();
+ if (changed) {
+ updateFromSettingsLocked();
+ }
}
}
}
@@ -415,13 +438,19 @@
}
});
+ PackageReceiver mBroadcastReceiver = new PackageReceiver();
IntentFilter packageFilt = new IntentFilter();
packageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
packageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
packageFilt.addDataScheme("package");
- mContext.registerReceiver(new PackageReceiver(), packageFilt);
+ mContext.registerReceiver(mBroadcastReceiver, packageFilt);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
IntentFilter screenOnOffFilt = new IntentFilter();
screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 1c82c94..3a42b37 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -484,6 +484,8 @@
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
// listen for settings changes
ContentResolver resolver = mContext.getContentResolver();
@@ -1549,43 +1551,54 @@
String action = intent.getAction();
if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
- || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
+ || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
+ || action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
synchronized (mLock) {
- int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- if (uid >= 0) {
- ArrayList<Receiver> removedRecs = null;
- for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
- for (int j=i.size()-1; j>=0; j--) {
- UpdateRecord ur = i.get(j);
- if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
- if (removedRecs == null) {
- removedRecs = new ArrayList<Receiver>();
- }
- if (!removedRecs.contains(ur.mReceiver)) {
- removedRecs.add(ur.mReceiver);
+ int uidList[] = null;
+ if (action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ } else {
+ uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
+ }
+ if (uidList == null || uidList.length == 0) {
+ return;
+ }
+ for (int uid : uidList) {
+ if (uid >= 0) {
+ ArrayList<Receiver> removedRecs = null;
+ for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
+ for (int j=i.size()-1; j>=0; j--) {
+ UpdateRecord ur = i.get(j);
+ if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
+ if (removedRecs == null) {
+ removedRecs = new ArrayList<Receiver>();
+ }
+ if (!removedRecs.contains(ur.mReceiver)) {
+ removedRecs.add(ur.mReceiver);
+ }
}
}
}
- }
- ArrayList<ProximityAlert> removedAlerts = null;
- for (ProximityAlert i : mProximityAlerts.values()) {
- if (i.mUid == uid) {
- if (removedAlerts == null) {
- removedAlerts = new ArrayList<ProximityAlert>();
- }
- if (!removedAlerts.contains(i)) {
- removedAlerts.add(i);
+ ArrayList<ProximityAlert> removedAlerts = null;
+ for (ProximityAlert i : mProximityAlerts.values()) {
+ if (i.mUid == uid) {
+ if (removedAlerts == null) {
+ removedAlerts = new ArrayList<ProximityAlert>();
+ }
+ if (!removedAlerts.contains(i)) {
+ removedAlerts.add(i);
+ }
}
}
- }
- if (removedRecs != null) {
- for (int i=removedRecs.size()-1; i>=0; i--) {
- removeUpdatesLocked(removedRecs.get(i));
+ if (removedRecs != null) {
+ for (int i=removedRecs.size()-1; i>=0; i--) {
+ removeUpdatesLocked(removedRecs.get(i));
+ }
}
- }
- if (removedAlerts != null) {
- for (int i=removedAlerts.size()-1; i>=0; i--) {
- removeProximityAlertLocked(removedAlerts.get(i).mIntent);
+ if (removedAlerts != null) {
+ for (int i=removedAlerts.size()-1; i>=0; i--) {
+ removeProximityAlertLocked(removedAlerts.get(i).mIntent);
+ }
}
}
}
@@ -1599,7 +1612,7 @@
mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
}
NetworkInfo info =
- (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+ (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
// Notify location providers of current network state
synchronized (mLock) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index fc89ec8..02a0401 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -329,16 +329,27 @@
mUsbConnected = false;
updateAdbNotification();
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
- || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
- Uri uri = intent.getData();
- if (uri == null) {
- return;
+ || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
+ || action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ String pkgList[] = null;
+ if (action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName == null) {
+ return;
+ }
+ pkgList = new String[]{pkgName};
}
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
- return;
+ if (pkgList != null && (pkgList.length > 0)) {
+ for (String pkgName : pkgList) {
+ cancelAllNotificationsInt(pkgName, 0, 0);
+ }
}
- cancelAllNotificationsInt(pkgName, 0, 0);
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
mScreenOn = true;
updateNotificationPulse();
@@ -429,6 +440,8 @@
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(mIntentReceiver, filter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mIntentReceiver, sdFilter);
SettingsObserver observer = new SettingsObserver(mHandler);
observer.observe();
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4801817..238403c 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -63,6 +63,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Debug;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
@@ -2179,21 +2180,32 @@
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
+ String codePath = null;
+ String resPath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
if (ps != null && ps.resourcePathString != null) {
- pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
+ resPath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
- pkg.applicationInfo.publicSourceDir = pkg.mScanPath;
+ resPath = pkg.mScanPath;
}
- pkg.applicationInfo.sourceDir = pkg.mScanPath;
+ codePath = pkg.mScanPath;
+ // Set application objects path explicitly.
+ setApplicationInfoPaths(pkg, codePath, resPath);
// Note that we invoke the following method only if we are about to unpack an application
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
}
+ private static void setApplicationInfoPaths(PackageParser.Package pkg,
+ String destCodePath, String destResPath) {
+ pkg.mPath = pkg.mScanPath = destCodePath;
+ pkg.applicationInfo.sourceDir = destCodePath;
+ pkg.applicationInfo.publicSourceDir = destResPath;
+ }
+
private static String fixProcessName(String defProcessName,
String processName, int uid) {
if (processName == null) {
@@ -4025,7 +4037,7 @@
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
synchronized (mInstallLock) {
- res.removedInfo.args.cleanUpResourcesLI();
+ res.removedInfo.args.doPostDeleteLI(true);
}
}
}
@@ -4051,13 +4063,14 @@
abstract void createCopyFile();
abstract int copyApk(IMediaContainerService imcs);
- abstract void doPreInstall(int status);
+ abstract int doPreInstall(int status);
abstract boolean doRename(int status, String pkgName, String oldCodePath);
- abstract void doPostInstall(int status);
+ abstract int doPostInstall(int status);
abstract String getCodePath();
abstract String getResourcePath();
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
+ abstract boolean doPostDeleteLI(boolean delete);
}
class FileInstallArgs extends InstallArgs {
@@ -4114,10 +4127,11 @@
return ret;
}
- void doPreInstall(int status) {
+ int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
+ return status;
}
boolean doRename(int status, final String pkgName, String oldCodePath) {
@@ -4144,10 +4158,11 @@
}
}
- void doPostInstall(int status) {
+ int doPostInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
+ return status;
}
String getResourcePath() {
@@ -4220,6 +4235,11 @@
}
return true;
}
+
+ boolean doPostDeleteLI(boolean delete) {
+ cleanUpResourcesLI();
+ return true;
+ }
}
class SdInstallArgs extends InstallArgs {
@@ -4234,7 +4254,7 @@
}
SdInstallArgs(String fullCodePath, String fullResourcePath) {
- super(null, null, 0, null);
+ super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -4243,6 +4263,11 @@
cachePath = subStr1;
}
+ SdInstallArgs(String cid) {
+ super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
+ this.cid = cid;
+ }
+
void createCopyFile() {
cid = getTempContainerId();
}
@@ -4254,16 +4279,8 @@
getEncryptKey(), RES_FILE_NAME);
} catch (RemoteException e) {
}
-
- if (cachePath != null) {
- // Mount container once its created with system_uid
- cachePath = mountSdDir(cid, Process.SYSTEM_UID);
- }
- if (cachePath == null) {
- return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
- } else {
- return PackageManager.INSTALL_SUCCEEDED;
- }
+ return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
+ PackageManager.INSTALL_SUCCEEDED;
}
@Override
@@ -4276,25 +4293,81 @@
return cachePath + "/" + RES_FILE_NAME;
}
- void doPreInstall(int status) {
+ int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
// Destroy container
destroySdDir(cid);
+ } else {
+ // STOPSHIP Remove once new api is added in MountService
+ //boolean mounted = isContainerMounted(cid);
+ boolean mounted = false;
+ if (!mounted) {
+ cachePath = mountSdDir(cid, Process.SYSTEM_UID);
+ if (cachePath == null) {
+ return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+ }
+ }
}
+ return status;
}
boolean doRename(int status, final String pkgName,
String oldCodePath) {
String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
+ String newCachePath = null;
+ /*final int RENAME_FAILED = 1;
+ final int MOUNT_FAILED = 2;
+ final int DESTROY_FAILED = 3;
+ final int PASS = 4;
+ int errCode = RENAME_FAILED;
+ if (mounted) {
+ // Unmount the container
+ if (!unMountSdDir(cid)) {
+ Log.i(TAG, "Failed to unmount " + cid + " before renaming");
+ return false;
+ }
+ mounted = false;
+ }
+ if (renameSdDir(cid, newCacheId)) {
+ errCode = MOUNT_FAILED;
+ if ((newCachePath = mountSdDir(newCacheId, Process.SYSTEM_UID)) != null) {
+ errCode = PASS;
+ }
+ }
+ String errMsg = "";
+ switch (errCode) {
+ case RENAME_FAILED:
+ errMsg = "RENAME_FAILED";
+ break;
+ case MOUNT_FAILED:
+ errMsg = "MOUNT_FAILED";
+ break;
+ case DESTROY_FAILED:
+ errMsg = "DESTROY_FAILED";
+ break;
+ default:
+ errMsg = "PASS";
+ break;
+ }
+ Log.i(TAG, "Status: " + errMsg);
+ if (errCode != PASS) {
+ return false;
+ }
+ Log.i(TAG, "Succesfully renamed " + cid + " to " +newCacheId +
+ " at path: " + cachePath + " to new path: " + newCachePath);
+ cid = newCacheId;
+ cachePath = newCachePath;
+ return true;
+ */
// STOPSHIP TEMPORARY HACK FOR RENAME
// Create new container at newCachePath
String codePath = getCodePath();
- String newCachePath = null;
final int CREATE_FAILED = 1;
final int COPY_FAILED = 3;
final int FINALIZE_FAILED = 5;
final int PASS = 7;
int errCode = CREATE_FAILED;
+
if ((newCachePath = createSdDir(new File(codePath), newCacheId)) != null) {
errCode = COPY_FAILED;
// Copy file from codePath
@@ -4335,13 +4408,18 @@
return true;
}
- void doPostInstall(int status) {
+ int doPostInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
} else {
- // Unmount container
- // Rename and remount based on package name and new uid
+ // STOP SHIP Change this once new api is added.
+ //boolean mounted = isContainerMounted(cid);
+ boolean mounted = false;
+ if (!mounted) {
+ mountSdDir(cid, Process.SYSTEM_UID);
+ }
}
+ return status;
}
private void cleanUp() {
@@ -4363,32 +4441,66 @@
}
cleanUp();
}
+
+ boolean matchContainer(String app) {
+ if (cid.startsWith(app)) {
+ return true;
+ }
+ return false;
+ }
+
+ String getPackageName() {
+ int idx = cid.lastIndexOf("-");
+ if (idx == -1) {
+ return cid;
+ }
+ return cid.substring(0, idx);
+ }
+
+ boolean doPostDeleteLI(boolean delete) {
+ boolean ret = false;
+ boolean mounted = isContainerMounted(cid);
+ if (mounted) {
+ // Unmount first
+ ret = unMountSdDir(cid);
+ }
+ if (ret && delete) {
+ cleanUpResourcesLI();
+ }
+ return ret;
+ }
};
// Utility method used to create code paths based on package name and available index.
private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
String idxStr = "";
int idx = 1;
+ // Fall back to default value of idx=1 if prefix is not
+ // part of oldCodePath
if (oldCodePath != null) {
String subStr = oldCodePath;
- if (subStr.startsWith(prefix)) {
- subStr = subStr.substring(prefix.length());
- }
+ // Drop the suffix right away
if (subStr.endsWith(suffix)) {
subStr = subStr.substring(0, subStr.length() - suffix.length());
}
- if (subStr != null) {
- if (subStr.startsWith("-")) {
- subStr = subStr.substring(1);
- }
- try {
- idx = Integer.parseInt(subStr);
- if (idx <= 1) {
- idx++;
- } else {
- idx--;
+ // If oldCodePath already contains prefix find out the
+ // ending index to either increment or decrement.
+ int sidx = subStr.lastIndexOf(prefix);
+ if (sidx != -1) {
+ subStr = subStr.substring(sidx + prefix.length());
+ if (subStr != null) {
+ if (subStr.startsWith("-")) {
+ subStr = subStr.substring(1);
}
- } catch(NumberFormatException e) {
+ try {
+ idx = Integer.parseInt(subStr);
+ if (idx <= 1) {
+ idx++;
+ } else {
+ idx--;
+ }
+ } catch(NumberFormatException e) {
+ }
}
}
}
@@ -4753,6 +4865,9 @@
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
&& mPackages.containsKey(pkgName)) {
replacingExistingPackage = true;
+ }
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (ps != null) {
oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
}
}
@@ -4761,9 +4876,8 @@
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
break main_flow;
}
- // TODO rename pkg.mScanPath In scanPackageLI let it just set values based on mScanPath
- pkg.applicationInfo.sourceDir = pkg.mScanPath= pkg.mPath = args.getCodePath();
- pkg.applicationInfo.publicSourceDir = args.getResourcePath();
+ // Set application objects path explicitly after the rename
+ setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
if(replacingExistingPackage) {
replacePackageLI(pkg, parseFlags, scanMode,
installerPackageName, res);
@@ -4977,9 +5091,9 @@
}
// Delete the resources here after sending the broadcast to let
// other processes clean up before deleting resources.
- synchronized (mInstallLock) {
- if (info.args != null) {
- info.args.cleanUpResourcesLI();
+ if (info.args != null) {
+ synchronized (mInstallLock) {
+ info.args.doPostDeleteLI(deleteCodeAndResources);
}
}
return res;
@@ -6948,6 +7062,17 @@
}
}
+ private Set<String> findPackagesWithFlag(int flag) {
+ Set<String> ret = new HashSet<String>();
+ for (PackageSetting ps : mPackages.values()) {
+ // Has to match atleast all the flag bits set on flag
+ if ((ps.pkgFlags & flag) == flag) {
+ ret.add(ps.name);
+ }
+ }
+ return ret;
+ }
+
private void removeUserIdLP(int uid) {
if (uid >= FIRST_APPLICATION_UID) {
int N = mUserIds.size();
@@ -7992,9 +8117,20 @@
return true;
}
- private String getSdDir(String pkgName) {
- return getMountService().getSecureContainerPath(pkgName);
- }
+ private boolean renameSdDir(String oldId, String newId) {
+ try {
+ getMountService().renameSecureContainer(oldId, newId);
+ return true;
+ } catch (IllegalStateException e) {
+ Log.i(TAG, "Failed ot rename " + oldId + " to " + newId +
+ " with exception : " + e);
+ }
+ return false;
+ }
+
+ private String getSdDir(String pkgName) {
+ return getMountService().getSecureContainerPath(pkgName);
+ }
private boolean finalizeSdDir(String pkgName) {
int rc = getMountService().finalizeSecureContainer(pkgName);
@@ -8019,6 +8155,16 @@
return list.length == 0 ? null : list;
}
+ static boolean isContainerMounted(String cid) {
+ // STOPSHIP
+ // New api from MountService
+ try {
+ return (getMountService().getSecureContainerPath(cid) != null);
+ } catch (IllegalStateException e) {
+ }
+ return false;
+ }
+
static String getTempContainerId() {
String prefix = "smdl1tmp";
int tmpIdx = 1;
@@ -8063,6 +8209,8 @@
}
public void updateExternalMediaStatus(final boolean mediaStatus) {
+ final boolean DEBUG = true;
+ if (DEBUG) Log.i(TAG, "updateExterMediaStatus::");
if (mediaStatus == mMediaMounted) {
return;
}
@@ -8071,54 +8219,155 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- final String list[] = getSecureContainerList();
- if (list == null || list.length == 0) {
- return;
+ updateExternalMediaStatusInner(mediaStatus);
+ }
+ });
+ }
+
+ void updateExternalMediaStatusInner(boolean mediaStatus) {
+ final String list[] = getSecureContainerList();
+ if (list == null || list.length == 0) {
+ return;
+ }
+ HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
+ int uidList[] = new int[list.length];
+ int num = 0;
+ for (int i = 0; i < uidList.length; i++) {
+ uidList[i] = Process.LAST_APPLICATION_UID;
+ }
+ synchronized (mPackages) {
+ Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
+ for (String cid : list) {
+ SdInstallArgs args = new SdInstallArgs(cid);
+ String removeEntry = null;
+ for (String app : appList) {
+ if (args.matchContainer(app)) {
+ removeEntry = app;
+ break;
+ }
}
- for (int i = 0; i < list.length; i++) {
- String mountPkg = list[i];
- // TODO compare with default package
- synchronized (mPackages) {
- PackageSetting ps = mSettings.mPackages.get(mountPkg);
- if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
- if (mediaStatus) {
- String pkgPath = getSdDir(mountPkg);
- if (pkgPath == null) {
- continue;
- }
- pkgPath = ps.codePathString;
- int parseFlags = PackageParser.PARSE_CHATTY |
- PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
- PackageParser pp = new PackageParser(pkgPath);
- pp.setSeparateProcesses(mSeparateProcesses);
- final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
- null, mMetrics, parseFlags);
- if (pkg == null) {
- Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
- continue;
- }
- int scanMode = SCAN_MONITOR;
- // Scan the package
- if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
- // Grant permissions
- grantPermissionsLP(pkg, false);
- // Persist settings
- mSettings.writeLP();
- } else {
- Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
- }
- } else {
- // Delete package
- PackageRemovedInfo outInfo = new PackageRemovedInfo();
- boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
- if (!res) {
- Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
- }
- }
- }
+ if (removeEntry == null) {
+ // No matching app on device. Skip entry or may be cleanup?
+ // Ignore default package
+ continue;
+ }
+ appList.remove(removeEntry);
+ PackageSetting ps = mSettings.mPackages.get(removeEntry);
+ processCids.put(args, ps.codePathString);
+ int uid = ps.userId;
+ if (uid != -1) {
+ int idx = Arrays.binarySearch(uidList, uid);
+ if (idx < 0) {
+ uidList[-idx] = uid;
+ num++;
}
}
}
- });
+ }
+ int uidArr[] = uidList;
+ if ((num > 0) && (num < uidList.length)) {
+ uidArr = new int[num];
+ for (int i = 0; i < num; i++) {
+ uidArr[i] = uidList[i];
+ }
+ }
+ if (mediaStatus) {
+ loadMediaPackages(processCids, uidArr);
+ } else {
+ unloadMediaPackages(processCids, uidArr);
+ }
+ }
+
+ private void sendResourcesChangedBroadcast(boolean mediaStatus,
+ ArrayList<String> pkgList, int uidArr[]) {
+ int size = pkgList.size();
+ if (size > 0) {
+ // Send broadcasts here
+ Bundle extras = new Bundle();
+ extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
+ pkgList.toArray(new String[size]));
+ extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
+ String action = mediaStatus ? Intent.ACTION_MEDIA_RESOURCES_AVAILABLE
+ : Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE;
+ sendPackageBroadcast(action, null, extras);
+ }
+ }
+
+ void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+ ArrayList<String> pkgList = new ArrayList<String>();
+ Set<SdInstallArgs> keys = processCids.keySet();
+ for (SdInstallArgs args : keys) {
+ String cid = args.cid;
+ String codePath = processCids.get(args);
+ if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
+ Log.i(TAG, "Failed to install package: " + codePath + " from sdcard");
+ continue;
+ }
+ // Parse package
+ int parseFlags = PackageParser.PARSE_CHATTY |
+ PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
+ PackageParser pp = new PackageParser(codePath);
+ pp.setSeparateProcesses(mSeparateProcesses);
+ final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
+ codePath, mMetrics, parseFlags);
+ if (pkg == null) {
+ Log.w(TAG, "Failed to install package : " + cid + " from sd card");
+ continue;
+ }
+ setApplicationInfoPaths(pkg, codePath, codePath);
+ int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+ synchronized (mInstallLock) {
+ // Scan the package
+ if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
+ synchronized (mPackages) {
+ // Grant permissions
+ grantPermissionsLP(pkg, false);
+ // Persist settings
+ mSettings.writeLP();
+ retCode = PackageManager.INSTALL_SUCCEEDED;
+ pkgList.add(pkg.packageName);
+ }
+ } else {
+ Log.i(TAG, "Failed to install package: " + pkg.packageName + " from sdcard");
+ }
+ }
+ args.doPostInstall(retCode);
+ pkgList.add(pkg.packageName);
+ }
+ // Send broadcasts first
+ sendResourcesChangedBroadcast(true, pkgList, uidArr);
+ Runtime.getRuntime().gc();
+ // If something failed do we clean up here or next install?
+ }
+
+ void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+ ArrayList<String> pkgList = new ArrayList<String>();
+ Set<SdInstallArgs> keys = processCids.keySet();
+ for (SdInstallArgs args : keys) {
+ String cid = args.cid;
+ String pkgName = args.getPackageName();
+ // STOPSHIP Send broadcast to apps to remove references
+ // STOPSHIP Unmount package
+ // Delete package internally
+ PackageRemovedInfo outInfo = new PackageRemovedInfo();
+ synchronized (mInstallLock) {
+ boolean res = deletePackageLI(pkgName, false,
+ PackageManager.DONT_DELETE_DATA, outInfo);
+ if (res) {
+ pkgList.add(pkgName);
+ } else {
+ Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
+ }
+ }
+ }
+ // Send broadcasts
+ sendResourcesChangedBroadcast(false, pkgList, uidArr);
+ Runtime.getRuntime().gc();
+ // Do clean up. Just unmount
+ for (SdInstallArgs args : keys) {
+ synchronized (mInstallLock) {
+ args.doPostDeleteLI(false);
+ }
+ }
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b723dcd..5e6881c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1196,7 +1196,7 @@
int uid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart);
+ forceStopPackageLocked(pkg, uid, restart, false);
}
} break;
}
@@ -4998,7 +4998,7 @@
}
private void forceStopPackageLocked(final String packageName, int uid) {
- forceStopPackageLocked(packageName, uid, false);
+ forceStopPackageLocked(packageName, uid, false, false);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, uid);
@@ -5037,9 +5037,9 @@
removeProcessLocked(procs.get(i), callerWillRestart);
}
}
-
+
private final void forceStopPackageLocked(String name, int uid,
- boolean callerWillRestart) {
+ boolean callerWillRestart, boolean purgeCache) {
int i, N;
if (uid < 0) {
@@ -5091,6 +5091,12 @@
}
resumeTopActivityLocked(null);
+ if (purgeCache) {
+ AttributeCache ac = AttributeCache.instance();
+ if (ac != null) {
+ ac.removePackage(name);
+ }
+ }
}
private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
@@ -8054,7 +8060,7 @@
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false);
+ forceStopPackageLocked(packageName, -1, false, false);
Binder.restoreCallingIdentity(origId);
}
}
@@ -11935,6 +11941,7 @@
intent.getAction());
if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|| intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+ || Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())
|| uidRemoved) {
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
@@ -11951,15 +11958,22 @@
}
}
} else {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
- if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
- forceStopPackageLocked(ssp,
- intent.getIntExtra(Intent.EXTRA_UID, -1), false);
- AttributeCache ac = AttributeCache.instance();
- if (ac != null) {
- ac.removePackage(ssp);
+ // If resources are unvailble just force stop all
+ // those packages and flush the attribute cache as well.
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())) {
+ String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (list != null && (list.length > 0)) {
+ for (String pkg : list) {
+ forceStopPackageLocked(pkg, -1, false, true);
+ }
+ }
+ } else {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+ forceStopPackageLocked(ssp,
+ intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
}
}
}
@@ -12121,25 +12135,32 @@
// installed. Maybe in the future we want to have a special install
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
- boolean skip = false;
- if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
- skip = true;
- } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
- skip = true;
- } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
- skip = true;
+ String skipPackages[] = null;
+ if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
+ || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
+ || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
+ Uri data = intent.getData();
+ if (data != null) {
+ String pkgName = data.getSchemeSpecificPart();
+ if (pkgName != null) {
+ skipPackages = new String[] { pkgName };
+ }
+ }
+ } else if (intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(intent.getAction())) {
+ skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
- String skipPackage = (skip && intent.getData() != null)
- ? intent.getData().getSchemeSpecificPart()
- : null;
- if (skipPackage != null && receivers != null) {
- int NT = receivers.size();
- for (int it=0; it<NT; it++) {
- ResolveInfo curt = (ResolveInfo)receivers.get(it);
- if (curt.activityInfo.packageName.equals(skipPackage)) {
- receivers.remove(it);
- it--;
- NT--;
+ if (skipPackages != null && (skipPackages.length > 0)) {
+ for (String skipPackage : skipPackages) {
+ if (skipPackage != null) {
+ int NT = receivers.size();
+ for (int it=0; it<NT; it++) {
+ ResolveInfo curt = (ResolveInfo)receivers.get(it);
+ if (curt.activityInfo.packageName.equals(skipPackage)) {
+ receivers.remove(it);
+ it--;
+ NT--;
+ }
+ }
}
}
}
@@ -12923,7 +12944,7 @@
}
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(ii.targetPackage, -1, true);
+ forceStopPackageLocked(ii.targetPackage, -1, true, false);
ProcessRecord app = addAppLocked(ai);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
@@ -12978,7 +12999,7 @@
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
- forceStopPackageLocked(app.processName, -1, false);
+ forceStopPackageLocked(app.processName, -1, false, false);
}
public void finishInstrumentation(IApplicationThread target,
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 2d0f254..7b722a5 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -1807,16 +1807,30 @@
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(this, sdFilter);
}
@Override
public void onReceive(Context context, Intent intent) {
- ArrayList<StatusBarNotification> list = null;
- synchronized (StatusBarService.this) {
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
Uri data = intent.getData();
if (data != null) {
String pkg = data.getSchemeSpecificPart();
- list = mNotificationData.notificationsForPackage(pkg);
+ if (pkg != null) {
+ pkgList = new String[]{pkg};
+ }
+ }
+ }
+ ArrayList<StatusBarNotification> list = null;
+ if (pkgList != null) {
+ synchronized (StatusBarService.this) {
+ for (String pkg : pkgList) {
+ list = mNotificationData.notificationsForPackage(pkg);
+ }
}
}