diff options
Diffstat (limited to 'services/java/com/android/server/PackageManagerService.java')
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 393 |
1 files changed, 284 insertions, 109 deletions
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 387f139..10bf851 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -20,6 +20,7 @@ import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; import com.android.common.FastXmlSerializer; import com.android.common.XmlUtils; +import com.android.server.JournaledFile; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -74,7 +75,7 @@ import android.os.Environment; import android.os.FileObserver; import android.os.FileUtils; import android.os.Handler; -import android.os.MountServiceResultCode; +import android.os.storage.StorageResultCode; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.ServiceManager; @@ -148,6 +149,10 @@ class PackageManagerService extends IPackageManager.Stub { static final int SCAN_NEW_INSTALL = 1<<4; static final int SCAN_NO_PATHS = 1<<5; + static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( + "com.android.defcontainer", + "com.android.defcontainer.DefaultContainerService"); + final HandlerThread mHandlerThread = new HandlerThread("PackageManager", Process.THREAD_PRIORITY_BACKGROUND); final PackageHandler mHandler; @@ -298,6 +303,7 @@ class PackageManagerService extends IPackageManager.Stub { static final int END_COPY = 4; static final int INIT_COPY = 5; static final int MCS_UNBIND = 6; + static final int START_CLEANING_PACKAGE = 7; // Delay time in millisecs static final int BROADCAST_DELAY = 10 * 1000; private ServiceConnection mDefContainerConn = new ServiceConnection() { @@ -328,9 +334,7 @@ class PackageManagerService extends IPackageManager.Stub { case INIT_COPY: { InstallArgs args = (InstallArgs) msg.obj; args.createCopyFile(); - Intent service = new Intent().setComponent(new ComponentName( - "com.android.defcontainer", - "com.android.defcontainer.DefaultContainerService")); + Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); if (mContainerService != null) { // No need to add to pending list. Use remote stub directly handleStartCopy(args); @@ -405,6 +409,15 @@ class PackageManagerService extends IPackageManager.Stub { } break; } + case START_CLEANING_PACKAGE: { + String packageName = (String)msg.obj; + synchronized (mPackages) { + if (!mSettings.mPackagesToBeCleaned.contains(packageName)) { + mSettings.mPackagesToBeCleaned.add(packageName); + } + } + startCleaningPackages(); + } break; } } @@ -2111,6 +2124,12 @@ class PackageManagerService extends IPackageManager.Stub { File file = new File(dir, files[i]); PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode); + // Don't mess around with apps in system partition. + if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0) { + // Delete the apk + Log.w(TAG, "Cleaning up failed install of " + file); + file.delete(); + } } } @@ -2353,6 +2372,13 @@ class PackageManagerService extends IPackageManager.Stub { private PackageParser.Package scanPackageLI( PackageParser.Package pkg, int parseFlags, int scanMode) { File scanFile = new File(pkg.mScanPath); + if (scanFile == null || pkg.applicationInfo.sourceDir == null || + pkg.applicationInfo.publicSourceDir == null) { + // Bail out. The resource and code paths haven't been set. + Log.w(TAG, " Code and resource paths haven't been set correctly"); + mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK; + return null; + } mScanningPath = scanFile; if (pkg == null) { mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; @@ -2810,6 +2836,9 @@ class PackageManagerService extends IPackageManager.Stub { mSettings.insertPackageSettingLP(pkgSetting, pkg); // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); + // Make sure we don't accidentally delete its data. + mSettings.mPackagesToBeCleaned.remove(pkgName); + int N = pkg.providers.size(); StringBuilder r = null; int i; @@ -4005,7 +4034,47 @@ class PackageManagerService extends IPackageManager.Stub { } } } + + public String nextPackageToClean(String lastPackage) { + synchronized (mPackages) { + if (!mMediaMounted) { + // If the external storage is no longer mounted at this point, + // the caller may not have been able to delete all of this + // packages files and can not delete any more. Bail. + return null; + } + if (lastPackage != null) { + mSettings.mPackagesToBeCleaned.remove(lastPackage); + } + return mSettings.mPackagesToBeCleaned.size() > 0 + ? mSettings.mPackagesToBeCleaned.get(0) : null; + } + } + void schedulePackageCleaning(String packageName) { + mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName)); + } + + void startCleaningPackages() { + synchronized (mPackages) { + if (!mMediaMounted) { + return; + } + if (mSettings.mPackagesToBeCleaned.size() <= 0) { + return; + } + } + Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE); + intent.setComponent(DEFAULT_CONTAINER_COMPONENT); + IActivityManager am = ActivityManagerNative.getDefault(); + if (am != null) { + try { + am.startService(null, intent, null); + } catch (RemoteException e) { + } + } + } + private final class AppDirObserver extends FileObserver { public AppDirObserver(String path, int mask, boolean isrom) { super(path, mask); @@ -4959,69 +5028,82 @@ class PackageManagerService extends IPackageManager.Stub { File tmpPackageFile = new File(args.getCodePath()); boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0); - boolean replacingExistingPackage = false; + boolean replace = false; int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE | (newInstall ? SCAN_NEW_INSTALL : 0); // Result object to be returned res.returnCode = PackageManager.INSTALL_SUCCEEDED; - main_flow: try { - // Retrieve PackageSettings and parse package - int parseFlags = PackageParser.PARSE_CHATTY | - (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | - (onSd ? PackageParser.PARSE_ON_SDCARD : 0); - parseFlags |= mDefParseFlags; - PackageParser pp = new PackageParser(tmpPackageFile.getPath()); - pp.setSeparateProcesses(mSeparateProcesses); - final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, - null, mMetrics, parseFlags); - if (pkg == null) { - res.returnCode = pp.getParseError(); - break main_flow; - } - String pkgName = res.name = pkg.packageName; - if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { - if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) { - res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY; - break main_flow; - } + // Retrieve PackageSettings and parse package + int parseFlags = PackageParser.PARSE_CHATTY | + (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | + (onSd ? PackageParser.PARSE_ON_SDCARD : 0); + parseFlags |= mDefParseFlags; + PackageParser pp = new PackageParser(tmpPackageFile.getPath()); + pp.setSeparateProcesses(mSeparateProcesses); + final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, + null, mMetrics, parseFlags); + if (pkg == null) { + res.returnCode = pp.getParseError(); + return; + } + String pkgName = res.name = pkg.packageName; + if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { + if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) { + res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY; + return; } - if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) { - res.returnCode = pp.getParseError(); - break main_flow; + } + if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) { + res.returnCode = pp.getParseError(); + return; + } + // Some preinstall checks + if (forwardLocked && onSd) { + // Make sure forward locked apps can only be installed + // on internal storage + Log.w(TAG, "Cannot install protected apps on sdcard"); + res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; + return; + } + // Get rid of all references to package scan path via parser. + pp = null; + String oldCodePath = null; + boolean systemApp = false; + synchronized (mPackages) { + // Check if installing already existing package + if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0 + && mPackages.containsKey(pkgName)) { + replace = true; } - - // Get rid of all references to package scan path via parser. - pp = null; - String oldCodePath = null; - synchronized (mPackages) { - //check if installing already existing package - 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; + PackageSetting ps = mSettings.mPackages.get(pkgName); + if (ps != null) { + oldCodePath = mSettings.mPackages.get(pkgName).codePathString; + if (ps.pkg != null && ps.pkg.applicationInfo != null) { + systemApp = (ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SYSTEM) != 0; } } + } - if (!args.doRename(res.returnCode, pkgName, oldCodePath)) { - res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; - break main_flow; - } - // Set application objects path explicitly after the rename - setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath()); - if(replacingExistingPackage) { - replacePackageLI(pkg, parseFlags, scanMode, - installerPackageName, res); - } else { - installNewPackageLI(pkg, parseFlags, scanMode, - installerPackageName,res); - } - } finally { - if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { - } + if (systemApp && onSd) { + // Disable updates to system apps on sdcard + Log.w(TAG, "Cannot install updates to system apps on sdcard"); + res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; + return; + } + if (!args.doRename(res.returnCode, pkgName, oldCodePath)) { + res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; + return; + } + // Set application objects path explicitly after the rename + setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath()); + if(replace) { + replacePackageLI(pkg, parseFlags, scanMode, + installerPackageName, res); + } else { + installNewPackageLI(pkg, parseFlags, scanMode, + installerPackageName,res); } } @@ -5198,7 +5280,6 @@ class PackageManagerService extends IPackageManager.Stub { * persisting settings for later use * sending a broadcast if necessary */ - private boolean deletePackageX(String packageName, boolean sendBroadCast, boolean deleteCodeAndResources, int flags) { PackageRemovedInfo info = new PackageRemovedInfo(); @@ -5290,6 +5371,7 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = new File(pkg.applicationInfo.dataDir); dataDir.delete(); } + schedulePackageCleaning(packageName); synchronized (mPackages) { if (outInfo != null) { outInfo.removedUid = mSettings.removePackageLP(packageName); @@ -5302,7 +5384,7 @@ class PackageManagerService extends IPackageManager.Stub { mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids); } // Save settings now - mSettings.writeLP (); + mSettings.writeLP(); } } @@ -6745,6 +6827,7 @@ class PackageManagerService extends IPackageManager.Stub { private static final class Settings { private final File mSettingsFilename; private final File mBackupSettingsFilename; + private final File mPackageListFilename; private final HashMap<String, PackageSetting> mPackages = new HashMap<String, PackageSetting>(); // List of replaced system applications @@ -6791,6 +6874,10 @@ class PackageManagerService extends IPackageManager.Stub { final HashMap<String, BasePermission> mPermissionTrees = new HashMap<String, BasePermission>(); + // Packages that have been uninstalled and still need their external + // storage data deleted. + final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>(); + private final StringBuilder mReadMessages = new StringBuilder(); private static final class PendingPackage extends PackageSettingBase { @@ -6822,6 +6909,7 @@ class PackageManagerService extends IPackageManager.Stub { -1, -1); mSettingsFilename = new File(systemDir, "packages.xml"); mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); + mPackageListFilename = new File(systemDir, "packages.list"); } PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage, @@ -7354,6 +7442,14 @@ class PackageManagerService extends IPackageManager.Stub { serializer.endTag(null, "shared-user"); } + if (mPackagesToBeCleaned.size() > 0) { + for (int i=0; i<mPackagesToBeCleaned.size(); i++) { + serializer.startTag(null, "cleaning-package"); + serializer.attribute(null, "name", mPackagesToBeCleaned.get(i)); + serializer.endTag(null, "cleaning-package"); + } + } + serializer.endTag(null, "packages"); serializer.endDocument(); @@ -7369,6 +7465,61 @@ class PackageManagerService extends IPackageManager.Stub { |FileUtils.S_IRGRP|FileUtils.S_IWGRP |FileUtils.S_IROTH, -1, -1); + + // Write package list file now, use a JournaledFile. + // + File tempFile = new File(mPackageListFilename.toString() + ".tmp"); + JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile); + + str = new FileOutputStream(journal.chooseForWrite()); + try { + StringBuilder sb = new StringBuilder(); + for (PackageSetting pkg : mPackages.values()) { + ApplicationInfo ai = pkg.pkg.applicationInfo; + String dataPath = ai.dataDir; + boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + + // Avoid any application that has a space in its path + // or that is handled by the system. + if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID) + continue; + + // we store on each line the following information for now: + // + // pkgName - package name + // userId - application-specific user id + // debugFlag - 0 or 1 if the package is debuggable. + // dataPath - path to package's data path + // + // NOTE: We prefer not to expose all ApplicationInfo flags for now. + // + // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS + // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: + // system/core/run-as/run-as.c + // + sb.setLength(0); + sb.append(ai.packageName); + sb.append(" "); + sb.append((int)ai.uid); + sb.append(isDebug ? " 1 " : " 0 "); + sb.append(dataPath); + sb.append("\n"); + str.write(sb.toString().getBytes()); + } + str.flush(); + str.close(); + journal.commit(); + } + catch (Exception e) { + journal.rollback(); + } + + FileUtils.setPermissions(mPackageListFilename.toString(), + FileUtils.S_IRUSR|FileUtils.S_IWUSR + |FileUtils.S_IRGRP|FileUtils.S_IWGRP + |FileUtils.S_IROTH, + -1, -1); + return; } catch(XmlPullParserException e) { @@ -7376,7 +7527,7 @@ class PackageManagerService extends IPackageManager.Stub { } catch(java.io.IOException e) { Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e); } - // Clean up partially written file + // Clean up partially written files if (mSettingsFilename.exists()) { if (!mSettingsFilename.delete()) { Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename); @@ -7386,7 +7537,7 @@ class PackageManagerService extends IPackageManager.Stub { } void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg) - throws java.io.IOException { + throws java.io.IOException { serializer.startTag(null, "updated-package"); serializer.attribute(null, "name", pkg.name); serializer.attribute(null, "codePath", pkg.codePathString); @@ -7424,7 +7575,7 @@ class PackageManagerService extends IPackageManager.Stub { } void writePackage(XmlSerializer serializer, final PackageSetting pkg) - throws java.io.IOException { + throws java.io.IOException { serializer.startTag(null, "package"); serializer.attribute(null, "name", pkg.name); serializer.attribute(null, "codePath", pkg.codePathString); @@ -7614,6 +7765,11 @@ class PackageManagerService extends IPackageManager.Stub { readPreferredActivitiesLP(parser); } else if(tagName.equals("updated-package")) { readDisabledSysPackageLP(parser); + } else if (tagName.equals("cleaning-package")) { + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + mPackagesToBeCleaned.add(name); + } } else { Log.w(TAG, "Unknown element under <packages>: " + parser.getName()); @@ -7739,7 +7895,7 @@ class PackageManagerService extends IPackageManager.Stub { } private void readDisabledSysPackageLP(XmlPullParser parser) - throws XmlPullParserException, IOException { + throws XmlPullParserException, IOException { String name = parser.getAttributeValue(null, "name"); String codePathStr = parser.getAttributeValue(null, "codePath"); String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); @@ -8269,17 +8425,17 @@ class PackageManagerService extends IPackageManager.Stub { int rc = mountService.createSecureContainer( pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, String.format("Failed to create container (%d)", rc)); rc = mountService.destroySecureContainer(pkgName); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, String.format("Failed to cleanup container (%d)", rc)); return null; } rc = mountService.createSecureContainer( pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, String.format("Failed to create container (2nd try) (%d)", rc)); return null; } @@ -8299,7 +8455,7 @@ class PackageManagerService extends IPackageManager.Stub { int rc = getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " rc : " + rc); return null; } @@ -8310,7 +8466,7 @@ class PackageManagerService extends IPackageManager.Stub { private boolean unMountSdDir(String pkgName) { // STOPSHIP unmount directory int rc = getMountService().unmountSecureContainer(pkgName); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to unmount : " + pkgName + " with rc " + rc); return false; } @@ -8334,7 +8490,7 @@ class PackageManagerService extends IPackageManager.Stub { private boolean finalizeSdDir(String pkgName) { int rc = getMountService().finalizeSecureContainer(pkgName); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to finalize container for pkg : " + pkgName); return false; } @@ -8343,7 +8499,7 @@ class PackageManagerService extends IPackageManager.Stub { private boolean destroySdDir(String pkgName) { int rc = getMountService().destroySecureContainer(pkgName); - if (rc != MountServiceResultCode.OperationSucceeded) { + if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to destroy container for pkg : " + pkgName); return false; } @@ -8409,19 +8565,21 @@ class PackageManagerService extends IPackageManager.Stub { } public void updateExternalMediaStatus(final boolean mediaStatus) { - final boolean DEBUG = true; - if (DEBUG) Log.i(TAG, "updateExterMediaStatus::"); - if (mediaStatus == mMediaMounted) { - return; - } - mMediaMounted = mediaStatus; - // Queue up an async operation since the package installation may take a little while. - mHandler.post(new Runnable() { - public void run() { - mHandler.removeCallbacks(this); - updateExternalMediaStatusInner(mediaStatus); + synchronized (mPackages) { + if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + + mediaStatus+", mMediaMounted=" + mMediaMounted); + if (mediaStatus == mMediaMounted) { + return; } - }); + mMediaMounted = mediaStatus; + // Queue up an async operation since the package installation may take a little while. + mHandler.post(new Runnable() { + public void run() { + mHandler.removeCallbacks(this); + updateExternalMediaStatusInner(mediaStatus); + } + }); + } } void updateExternalMediaStatusInner(boolean mediaStatus) { @@ -8432,9 +8590,6 @@ class PackageManagerService extends IPackageManager.Stub { 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) { @@ -8456,24 +8611,35 @@ class PackageManagerService extends IPackageManager.Stub { 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++; - } + uidList[num++] = uid; } } } - int uidArr[] = uidList; - if ((num > 0) && (num < uidList.length)) { + int uidArr[] = null; + if (num > 0) { + // Sort uid list + Arrays.sort(uidList, 0, num); + // Throw away duplicates uidArr = new int[num]; - for (int i = 0; i < num; i++) { - uidArr[i] = uidList[i]; + 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 (true) { + for (int j = 0; j < num; j++) { + Log.i(TAG, "uidArr[" + j + "]=" + uidArr[j]); + } } } if (mediaStatus) { + if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); loadMediaPackages(processCids, uidArr); + startCleaningPackages(); } else { + if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); unloadMediaPackages(processCids, uidArr); } } @@ -8486,9 +8652,11 @@ class PackageManagerService extends IPackageManager.Stub { 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; + if (uidArr != null) { + extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); + } + String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE + : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; sendPackageBroadcast(action, null, extras); } } @@ -8497,10 +8665,11 @@ class PackageManagerService extends IPackageManager.Stub { 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 (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install pkg : " + + args.cid + " from " + args.cachePath); if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) { - Log.i(TAG, "Failed to install package: " + codePath + " from sdcard"); + Log.e(TAG, "Failed to install package: " + codePath + " from sdcard"); continue; } // Parse package @@ -8511,7 +8680,8 @@ class PackageManagerService extends IPackageManager.Stub { 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"); + Log.e(TAG, "Trying to install pkg : " + + args.cid + " from " + args.cachePath); continue; } setApplicationInfoPaths(pkg, codePath, codePath); @@ -8532,22 +8702,24 @@ class PackageManagerService extends IPackageManager.Stub { } } 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? + if (pkgList.size() > 0) { + 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[]) { + 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(); for (SdInstallArgs args : keys) { String cid = args.cid; String pkgName = args.getPackageName(); - // STOPSHIP Send broadcast to apps to remove references - // STOPSHIP Unmount package + if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName); // Delete package internally PackageRemovedInfo outInfo = new PackageRemovedInfo(); synchronized (mInstallLock) { @@ -8557,14 +8729,17 @@ class PackageManagerService extends IPackageManager.Stub { pkgList.add(pkgName); } else { Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName); + failedList.add(args); } } } // Send broadcasts - sendResourcesChangedBroadcast(false, pkgList, uidArr); - Runtime.getRuntime().gc(); + if (pkgList.size() > 0) { + sendResourcesChangedBroadcast(false, pkgList, uidArr); + Runtime.getRuntime().gc(); + } // Do clean up. Just unmount - for (SdInstallArgs args : keys) { + for (SdInstallArgs args : failedList) { synchronized (mInstallLock) { args.doPostDeleteLI(false); } |