public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
if (vol.state == VolumeInfo.STATE_MOUNTED) {
+ // TODO: ensure that private directories exist for all active users
+ // TODO: remove user data whose serial number doesn't match
loadPrivatePackages(vol);
} else if (vol.state == VolumeInfo.STATE_EJECTING) {
unloadPrivatePackages(vol);
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; wiping its data");
- removeDataDirsLI(ps.name);
+ removeDataDirsLI(null, ps.name);
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; wiping its data";
- removeDataDirsLI(deletedAppName);
+ removeDataDirsLI(null, deletedAppName);
} else {
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint);
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
- for (String pkgName : mSettings.mPackages.keySet()) {
- deleteCodeCacheDirsLI(pkgName);
+ for (int i = 0; i < mSettings.mPackages.size(); i++) {
+ final PackageSetting ps = mSettings.mPackages.valueAt(i);
+ deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
}
mSettings.mFingerprint = Build.FINGERPRINT;
}
void cleanupInstallFailedPackage(PackageSetting ps) {
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + ps.name);
- removeDataDirsLI(ps.name);
+ removeDataDirsLI(ps.volumeUuid, ps.name);
if (ps.codePath != null) {
if (ps.codePath.isDirectory()) {
mInstaller.rmPackageDir(ps.codePath.getAbsolutePath());
return null;
}
-
@Override
- public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
+ public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
+ final IPackageDataObserver observer) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_CACHE, null);
// Queue up an async operation since clearing cache may take a little while.
mHandler.removeCallbacks(this);
int retCode = -1;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(freeStorageSize);
+ retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
if (retCode < 0) {
Slog.w(TAG, "Couldn't clear application caches");
}
}
@Override
- public void freeStorage(final long freeStorageSize, final IntentSender pi) {
+ public void freeStorage(final String volumeUuid, final long freeStorageSize,
+ final IntentSender pi) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_CACHE, null);
// Queue up an async operation since clearing cache may take a little while.
mHandler.removeCallbacks(this);
int retCode = -1;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(freeStorageSize);
+ retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
if (retCode < 0) {
Slog.w(TAG, "Couldn't clear application caches");
}
});
}
- void freeStorage(long freeStorageSize) throws IOException {
+ void freeStorage(String volumeUuid, long freeStorageSize) throws IOException {
synchronized (mInstallLock) {
- if (mInstaller.freeCache(freeStorageSize) < 0) {
+ if (mInstaller.freeCache(volumeUuid, freeStorageSize) < 0) {
throw new IOException("Failed to free enough space");
}
}
return true;
}
- private int createDataDirsLI(String packageName, int uid, String seinfo) {
+ private int createDataDirsLI(String volumeUuid, String packageName, int uid, String seinfo) {
int[] users = sUserManager.getUserIds();
- int res = mInstaller.install(packageName, uid, uid, seinfo);
+ int res = mInstaller.install(volumeUuid, packageName, uid, uid, seinfo);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
- res = mInstaller.createUserData(packageName,
+ res = mInstaller.createUserData(volumeUuid, packageName,
UserHandle.getUid(user, uid), user, seinfo);
if (res < 0) {
return res;
return res;
}
- private int removeDataDirsLI(String packageName) {
+ private int removeDataDirsLI(String volumeUuid, String packageName) {
int[] users = sUserManager.getUserIds();
int res = 0;
for (int user : users) {
- int resInner = mInstaller.remove(packageName, user);
+ int resInner = mInstaller.remove(volumeUuid, packageName, user);
if (resInner < 0) {
res = resInner;
}
return res;
}
- private int deleteCodeCacheDirsLI(String packageName) {
+ private int deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
int[] users = sUserManager.getUserIds();
int res = 0;
for (int user : users) {
- int resInner = mInstaller.deleteCodeCacheFiles(packageName, user);
+ int resInner = mInstaller.deleteCodeCacheFiles(volumeUuid, packageName, user);
if (resInner < 0) {
res = resInner;
}
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
- removeDataDirsLI(pkg.packageName);
+ removeDataDirsLI(pkg.volumeUuid, pkg.packageName);
}
}
}
// This is probably because the system was stopped while
// installd was in the middle of messing with its libs
// directory. Ask installd to fix that.
- int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.uid);
+ int ret = mInstaller.fixUid(pkg.volumeUuid, pkgName,
+ pkg.applicationInfo.uid, pkg.applicationInfo.uid);
if (ret >= 0) {
recovered = true;
String msg = "Package " + pkg.packageName
|| (scanFlags&SCAN_BOOTING) != 0)) {
// If this is a system app, we can at least delete its
// current data so the application will still work.
- int ret = removeDataDirsLI(pkgName);
+ int ret = removeDataDirsLI(pkg.volumeUuid, pkgName);
if (ret >= 0) {
// TODO: Kill the processes first
// Old data gone!
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.seinfo);
+ ret = createDataDirsLI(pkg.volumeUuid, pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
pkg.applicationInfo.dataDir = dataPath.getPath();
if (mShouldRestoreconData) {
Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
- mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
- pkg.applicationInfo.uid);
+ mInstaller.restoreconData(pkg.volumeUuid, pkg.packageName,
+ pkg.applicationInfo.seinfo, pkg.applicationInfo.uid);
}
} else {
if (DEBUG_PACKAGE_SCANNING) {
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.seinfo);
+ int ret = createDataDirsLI(pkg.volumeUuid, pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
final long sizeBytes = mContainerService.calculateInstalledSize(
origin.resolvedPath, isForwardLocked(), packageAbiOverride);
- if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) {
+ if (mInstaller.freeCache(null, sizeBytes + lowThreshold) >= 0) {
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
installFlags, packageAbiOverride);
}
sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
}
- deleteCodeCacheDirsLI(pkgName);
+ deleteCodeCacheDirsLI(pkg.volumeUuid, pkgName);
try {
final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
}
// Successfully disabled the old package. Now proceed with re-installation
- deleteCodeCacheDirsLI(packageName);
+ deleteCodeCacheDirsLI(pkg.volumeUuid, packageName);
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
}
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
- removeDataDirsLI(packageName);
+ removeDataDirsLI(ps.volumeUuid, packageName);
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
// writer
outInfo.removedAppId = appId;
outInfo.removedUsers = new int[] {removeUser};
}
- mInstaller.clearUserData(packageName, removeUser);
+ mInstaller.clearUserData(ps.volumeUuid, packageName, removeUser);
removeKeystoreDataIfNeeded(removeUser, appId);
schedulePackageCleaning(packageName, removeUser, false);
synchronized (mPackages) {
// Always delete data directories for package, even if we found no other
// record of app. This helps users recover from UID mismatches without
// resorting to a full data wipe.
- int retCode = mInstaller.clearUserData(packageName, userId);
+ int retCode = mInstaller.clearUserData(pkg.volumeUuid, packageName, userId);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: " + packageName);
return false;
if (pkg != null && pkg.applicationInfo.primaryCpuAbi != null &&
!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
- if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < 0) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
+ nativeLibPath, userId) < 0) {
Slog.w(TAG, "Failed linking native library dir");
return false;
}
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
- int retCode = mInstaller.deleteCacheFiles(packageName, userId);
+ int retCode = mInstaller.deleteCacheFiles(p.volumeUuid, packageName, userId);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: "
+ packageName + " u" + userId);
// TODO(multiArch): Extend getSizeInfo to look at *all* instruction sets, not
// just the primary.
String[] dexCodeInstructionSets = getDexCodeInstructionSets(getAppDexInstructionSets(ps));
- int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirRoot,
- publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
+ int res = mInstaller.getSizeInfo(p.volumeUuid, packageName, userHandle, p.baseCodePath,
+ libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
if (res < 0) {
return false;
}
// Technically, we shouldn't be doing this with the package lock
// held. However, this is very rare, and there is already so much
// other disk I/O going on, that we'll let it slide for now.
- mInstaller.removeUserDataDirs(userHandle);
+ final StorageManager storage = StorageManager.from(mContext);
+ final List<VolumeInfo> vols = storage.getVolumes();
+ for (VolumeInfo vol : vols) {
+ if (vol.getType() == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
+ final String volumeUuid = vol.getFsUuid();
+ Slog.d(TAG, "Removing user data on volume " + volumeUuid);
+ mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ }
+ }
}
mUserNeedsBadging.delete(userHandle);
removeUnusedPackagesLILPw(userManager, userHandle);