Merge "Maintain restrictions when downgrading system apps" into jb-mr2-dev

This commit is contained in:
Christopher Tate
2013-05-15 00:14:06 +00:00
committed by Android (Google) Code Review

View File

@ -3502,7 +3502,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures) if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) { != PackageManager.SIGNATURE_MATCH) {
if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!"); if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
deletePackageLI(pkg.packageName, null, true, 0, null, false); deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
ps = null; ps = null;
} else { } else {
/* /*
@ -8079,6 +8079,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else { } else {
updateSettingsLI(newPackage, updateSettingsLI(newPackage,
installerPackageName, installerPackageName,
null, null,
res); res);
// delete the partially installed application. the data directory will have to be // delete the partially installed application. the data directory will have to be
// restored if it was already existing // restored if it was already existing
@ -8087,7 +8088,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// delete the package data and cache directories that it created in // delete the package data and cache directories that it created in
// scanPackageLocked, unless those directories existed before we even tried to // scanPackageLocked, unless those directories existed before we even tried to
// install. // install.
deletePackageLI(pkgName, UserHandle.ALL, false, deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0, dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
res.removedInfo, true); res.removedInfo, true);
} }
@ -8100,6 +8101,9 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package oldPackage; PackageParser.Package oldPackage;
String pkgName = pkg.packageName; String pkgName = pkg.packageName;
int[] allUsers;
boolean[] perUserInstalled;
// First find the old package info and check signatures // First find the old package info and check signatures
synchronized(mPackages) { synchronized(mPackages) {
oldPackage = mPackages.get(pkgName); oldPackage = mPackages.get(pkgName);
@ -8110,19 +8114,28 @@ public class PackageManagerService extends IPackageManager.Stub {
res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
return; return;
} }
// In case of rollback, remember per-user/profile install state
PackageSetting ps = mSettings.mPackages.get(pkgName);
allUsers = sUserManager.getUserIds();
perUserInstalled = new boolean[allUsers.length];
for (int i = 0; i < allUsers.length; i++) {
perUserInstalled[i] = ps.getInstalled(allUsers[i]);
}
} }
boolean sysPkg = (isSystemApp(oldPackage)); boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) { if (sysPkg) {
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
user, installerPackageName, res); user, allUsers, perUserInstalled, installerPackageName, res);
} else { } else {
replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
user, installerPackageName, res); user, allUsers, perUserInstalled, installerPackageName, res);
} }
} }
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage, private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
int[] allUsers, boolean[] perUserInstalled,
String installerPackageName, PackageInstalledInfo res) { String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package newPackage = null; PackageParser.Package newPackage = null;
String pkgName = deletedPackage.packageName; String pkgName = deletedPackage.packageName;
@ -8139,7 +8152,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
// First delete the existing package while retaining the data directory // First delete the existing package while retaining the data directory
if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA, if (!deletePackageLI(pkgName, null, true, null, null, PackageManager.DELETE_KEEP_DATA,
res.removedInfo, true)) { res.removedInfo, true)) {
// If the existing package wasn't successfully deleted // If the existing package wasn't successfully deleted
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE; res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@ -8157,6 +8170,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else { } else {
updateSettingsLI(newPackage, updateSettingsLI(newPackage,
installerPackageName, installerPackageName,
allUsers, perUserInstalled,
res); res);
updatedSettings = true; updatedSettings = true;
} }
@ -8170,7 +8184,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if(updatedSettings) { if(updatedSettings) {
if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName); if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
deletePackageLI( deletePackageLI(
pkgName, null, true, pkgName, null, true, allUsers, perUserInstalled,
PackageManager.DELETE_KEEP_DATA, PackageManager.DELETE_KEEP_DATA,
res.removedInfo, true); res.removedInfo, true);
} }
@ -8206,6 +8220,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private void replaceSystemPackageLI(PackageParser.Package deletedPackage, private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
int[] allUsers, boolean[] perUserInstalled,
String installerPackageName, PackageInstalledInfo res) { String installerPackageName, PackageInstalledInfo res) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ ", old=" + deletedPackage); + ", old=" + deletedPackage);
@ -8268,7 +8283,7 @@ public class PackageManagerService extends IPackageManager.Stub {
newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime; newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
newPkgSetting.lastUpdateTime = System.currentTimeMillis(); newPkgSetting.lastUpdateTime = System.currentTimeMillis();
} }
updateSettingsLI(newPackage, installerPackageName, res); updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
updatedSettings = true; updatedSettings = true;
} }
@ -8314,8 +8329,9 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.INSTALL_SUCCEEDED; return PackageManager.INSTALL_SUCCEEDED;
} }
private void updateSettingsLI(PackageParser.Package newPackage, private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
String installerPackageName, PackageInstalledInfo res) { int[] allUsers, boolean[] perUserInstalled,
PackageInstalledInfo res) {
String pkgName = newPackage.packageName; String pkgName = newPackage.packageName;
synchronized (mPackages) { synchronized (mPackages) {
//write settings. the installStatus will be incomplete at this stage. //write settings. the installStatus will be incomplete at this stage.
@ -8353,6 +8369,18 @@ public class PackageManagerService extends IPackageManager.Stub {
userHandle, installerPackageName); userHandle, installerPackageName);
} }
} }
// Also convey the prior install/uninstall state
if (allUsers != null && perUserInstalled != null) {
for (int i = 0; i < allUsers.length; i++) {
if (DEBUG_INSTALL) {
Slog.d(TAG, " user " + allUsers[i]
+ " => " + perUserInstalled[i]);
}
ps.setInstalled(perUserInstalled[i], allUsers[i]);
}
// these install state changes will be persisted in the
// upcoming call to mSettings.writeLPr().
}
} }
} }
res.name = pkgName; res.name = pkgName;
@ -8651,12 +8679,27 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean removedForAllUsers = false; boolean removedForAllUsers = false;
boolean systemUpdate = false; boolean systemUpdate = false;
// for the uninstall-updates case and restricted profiles, remember the per-
// userhandle installed state
int[] allUsers;
boolean[] perUserInstalled;
synchronized (mPackages) {
PackageSetting ps = mSettings.mPackages.get(packageName);
allUsers = sUserManager.getUserIds();
perUserInstalled = new boolean[allUsers.length];
for (int i = 0; i < allUsers.length; i++) {
perUserInstalled[i] = ps.getInstalled(allUsers[i]);
}
}
synchronized (mInstallLock) { synchronized (mInstallLock) {
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId); if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
res = deletePackageLI(packageName, res = deletePackageLI(packageName,
(flags & PackageManager.DELETE_ALL_USERS) != 0 (flags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.ALL : new UserHandle(userId), ? UserHandle.ALL : new UserHandle(userId),
true, flags | REMOVE_CHATTY, info, true); true, allUsers, perUserInstalled,
flags | REMOVE_CHATTY, info, true);
systemUpdate = info.isRemovedPackageSystemUpdate; systemUpdate = info.isRemovedPackageSystemUpdate;
if (res && !systemUpdate && mPackages.get(packageName) == null) { if (res && !systemUpdate && mPackages.get(packageName) == null) {
removedForAllUsers = true; removedForAllUsers = true;
@ -8735,8 +8778,9 @@ public class PackageManagerService extends IPackageManager.Stub {
* make sure this flag is set for partially installed apps. If not its meaningless to * make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application. * delete a partially installed application.
*/ */
private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo, private void removePackageDataLI(PackageSetting ps,
int flags, boolean writeSettings) { int[] allUserHandles, boolean[] perUserInstalled,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = ps.name; String packageName = ps.name;
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps); if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
removePackageLI(ps, (flags&REMOVE_CHATTY) != 0); removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
@ -8772,6 +8816,20 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL); clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
} }
// make sure to preserve per-user disabled state if this removal was just
// a downgrade of a system app to the factory package
if (allUserHandles != null && perUserInstalled != null) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
for (int i = 0; i < allUserHandles.length; i++) {
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + allUserHandles[i]
+ " => " + perUserInstalled[i]);
}
ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
}
}
} }
// can downgrade to reader // can downgrade to reader
if (writeSettings) { if (writeSettings) {
@ -8790,7 +8848,10 @@ public class PackageManagerService extends IPackageManager.Stub {
* Tries to delete system package. * Tries to delete system package.
*/ */
private boolean deleteSystemPackageLI(PackageSetting newPs, private boolean deleteSystemPackageLI(PackageSetting newPs,
int[] allUserHandles, boolean[] perUserInstalled,
int flags, PackageRemovedInfo outInfo, boolean writeSettings) { int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
final boolean applyUserRestrictions
= (allUserHandles != null) && (perUserInstalled != null);
PackageSetting disabledPs = null; PackageSetting disabledPs = null;
// Confirm if the system package has been updated // Confirm if the system package has been updated
// An updated system app can be deleted. This will also have to restore // An updated system app can be deleted. This will also have to restore
@ -8807,6 +8868,14 @@ public class PackageManagerService extends IPackageManager.Stub {
} else if (DEBUG_REMOVE) { } else if (DEBUG_REMOVE) {
Slog.d(TAG, "Deleting system pkg from data partition"); Slog.d(TAG, "Deleting system pkg from data partition");
} }
if (DEBUG_REMOVE) {
if (applyUserRestrictions) {
Slog.d(TAG, "Remembering install states:");
for (int i = 0; i < allUserHandles.length; i++) {
Slog.d(TAG, " u=" + allUserHandles[i] + " inst=" + perUserInstalled[i]);
}
}
}
// Delete the updated package // Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true; outInfo.isRemovedPackageSystemUpdate = true;
if (disabledPs.versionCode < newPs.versionCode) { if (disabledPs.versionCode < newPs.versionCode) {
@ -8816,8 +8885,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Preserve data by setting flag // Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA; flags |= PackageManager.DELETE_KEEP_DATA;
} }
boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo, boolean ret = deleteInstalledPackageLI(newPs, true, flags,
writeSettings); allUserHandles, perUserInstalled, outInfo, writeSettings);
if (!ret) { if (!ret) {
return false; return false;
} }
@ -8843,6 +8912,22 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) { synchronized (mPackages) {
updatePermissionsLPw(newPkg.packageName, newPkg, updatePermissionsLPw(newPkg.packageName, newPkg,
UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
if (applyUserRestrictions) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across reinstall");
}
PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
for (int i = 0; i < allUserHandles.length; i++) {
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + allUserHandles[i]
+ " => " + perUserInstalled[i]);
}
ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
}
// Regardless of writeSettings we need to ensure that this restriction
// state propagation is persisted
mSettings.writeAllUsersPackageRestrictionsLPr();
}
// can downgrade to reader here // can downgrade to reader here
if (writeSettings) { if (writeSettings) {
mSettings.writeLPr(); mSettings.writeLPr();
@ -8852,14 +8937,15 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
private boolean deleteInstalledPackageLI(PackageSetting ps, private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo, boolean deleteCodeAndResources, int flags,
boolean writeSettings) { int[] allUserHandles, boolean[] perUserInstalled,
PackageRemovedInfo outInfo, boolean writeSettings) {
if (outInfo != null) { if (outInfo != null) {
outInfo.uid = ps.appId; outInfo.uid = ps.appId;
} }
// Delete package data from internal structures and also remove data if flag is set // Delete package data from internal structures and also remove data if flag is set
removePackageDataLI(ps, outInfo, flags, writeSettings); removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);
// Delete application code and resources // Delete application code and resources
if (deleteCodeAndResources && (outInfo != null)) { if (deleteCodeAndResources && (outInfo != null)) {
@ -8873,7 +8959,8 @@ public class PackageManagerService extends IPackageManager.Stub {
* This method handles package deletion in general * This method handles package deletion in general
*/ */
private boolean deletePackageLI(String packageName, UserHandle user, private boolean deletePackageLI(String packageName, UserHandle user,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo, boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
int flags, PackageRemovedInfo outInfo,
boolean writeSettings) { boolean writeSettings) {
if (packageName == null) { if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName."); Slog.w(TAG, "Attempt to delete null packageName.");
@ -8950,7 +9037,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (dataOnly) { if (dataOnly) {
// Delete application data first // Delete application data first
if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only"); if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
removePackageDataLI(ps, outInfo, flags, writeSettings); removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
return true; return true;
} }
boolean ret = false; boolean ret = false;
@ -8958,13 +9045,15 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name); if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
// When an updated system application is deleted we delete the existing resources as well and // When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition // fall back to existing code in system partition
ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings); ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
flags, outInfo, writeSettings);
} else { } else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name); if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
// Kill application pre-emptively especially for apps on sd. // Kill application pre-emptively especially for apps on sd.
killApplication(packageName, ps.appId); killApplication(packageName, ps.appId);
ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo, ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,
writeSettings); allUserHandles, perUserInstalled,
outInfo, writeSettings);
} }
return ret; return ret;
} }
@ -10493,7 +10582,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Delete package internally // Delete package internally
PackageRemovedInfo outInfo = new PackageRemovedInfo(); PackageRemovedInfo outInfo = new PackageRemovedInfo();
synchronized (mInstallLock) { synchronized (mInstallLock) {
boolean res = deletePackageLI(pkgName, null, false, boolean res = deletePackageLI(pkgName, null, false, null, null,
PackageManager.DELETE_KEEP_DATA, outInfo, false); PackageManager.DELETE_KEEP_DATA, outInfo, false);
if (res) { if (res) {
pkgList.add(pkgName); pkgList.add(pkgName);