diff options
author | Suchi Amalapurapu <asuchitra@google.com> | 2009-07-27 15:21:34 -0700 |
---|---|---|
committer | Suchi Amalapurapu <asuchitra@google.com> | 2009-07-28 10:21:38 -0700 |
commit | 261e66acd1963d9c404fd2d3ddc6ef99ccd745cf (patch) | |
tree | 69757958b6319885f0d17283201542184219cfaa /services | |
parent | 95fa929ebe55b3745eb59a1c4b8f21cb9f8e6b1d (diff) | |
download | frameworks_base-261e66acd1963d9c404fd2d3ddc6ef99ccd745cf.zip frameworks_base-261e66acd1963d9c404fd2d3ddc6ef99ccd745cf.tar.gz frameworks_base-261e66acd1963d9c404fd2d3ddc6ef99ccd745cf.tar.bz2 |
Fix resource code and version attributes
Create a new package setting object for updated system apps rather than moving
around the same setting. This updates the resource, code and version correctly.
For updating system packages, disable the package first which removes the entry
from internal structures, create a new package setting, add it to list of user id's
then rest of installation steps, kill the process if needed via ActivityManager
then add this setting if everything was successful. This also fixes issues with
updating values prematurely.
When a new version of system package is available via OTA, just physically remove
entries for pkg. Note that the component and other info will be eventually updated
later on when scanning the package.
Also move certificate verification slightly ahead before scanning packages.
Some null checks
New api's in ActivityManager to kill an application pkg before finishing installation
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 124 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 25 |
2 files changed, 117 insertions, 32 deletions
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 4afa03e..b39f2f6 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -60,7 +60,6 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.Debug; import android.os.HandlerThread; import android.os.Parcel; import android.os.RemoteException; @@ -1826,6 +1825,11 @@ class PackageManagerService extends IPackageManager.Stub { ps = mSettings.peekPackageLP(pkg.packageName); updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName); } + // Verify certificates first + if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) { + Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName); + return null; + } if (updatedPkg != null) { // An updated system app will not have the PARSE_IS_SYSTEM flag set initially parseFlags |= PackageParser.PARSE_IS_SYSTEM; @@ -1843,16 +1847,19 @@ class PackageManagerService extends IPackageManager.Stub { return null; } else { // Delete the older apk pointed to by ps + // At this point, its safely assumed that package installation for + // apps in system partition will go through. If not there won't be a working + // version of the app + synchronized (mPackages) { + // Just remove the loaded entries from package lists. + mPackages.remove(ps.name); + } deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString); mSettings.enableSystemPackageLP(ps.name); } } } } - if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) { - Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName); - return null; - } // The apk is forward locked (not public) if its code and resources // are kept in different files. if (ps != null && !ps.codePath.equals(ps.resourcePath)) { @@ -2132,7 +2139,7 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.packageName, pkg.applicationInfo.processName, pkg.applicationInfo.uid); - pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString; + pkg.applicationInfo.publicSourceDir = destResourceFile.toString(); File dataPath; if (mPlatformPackage == pkg) { @@ -2259,15 +2266,26 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST; } + // We don't expect installation to fail beyond this point, if ((scanMode&SCAN_MONITOR) != 0) { pkg.mPath = destCodeFile.getAbsolutePath(); mAppDirs.put(pkg.mPath, pkg); } + // Request the ActivityManager to kill the process(only for existing packages) + // so that we do not end up in a confused state while the user is still using the older + // version of the application while the new one gets installed. + IActivityManager am = ActivityManagerNative.getDefault(); + if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) { + try { + am.killApplicationWithUid(pkg.applicationInfo.packageName, + pkg.applicationInfo.uid); + } catch (RemoteException e) { + } + } synchronized (mPackages) { - // We don't expect installation to fail beyond this point // Add the new setting to mSettings - mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid); + mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile); // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); int N = pkg.providers.size(); @@ -2955,7 +2973,8 @@ class PackageManagerService extends IPackageManager.Stub { } if ((addedPermission || replace) && !ps.permissionsFixed && - (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { + ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) || + ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){ // This is the first that we have heard about this package, so the // permissions we have now selected are fixed until explicitly // changed. @@ -4156,7 +4175,9 @@ class PackageManagerService extends IPackageManager.Stub { private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo, int flags) { String packageName = p.packageName; - outInfo.removedPackage = packageName; + if (outInfo != null) { + outInfo.removedPackage = packageName; + } removePackageLI(p, true); // Retrieve object to delete permissions for shared user later on PackageSetting deletedPs; @@ -4178,7 +4199,9 @@ class PackageManagerService extends IPackageManager.Stub { dataDir.delete(); } synchronized (mPackages) { - outInfo.removedUid = mSettings.removePackageLP(packageName); + if (outInfo != null) { + outInfo.removedUid = mSettings.removePackageLP(packageName); + } } } synchronized (mPackages) { @@ -4253,7 +4276,7 @@ class PackageManagerService extends IPackageManager.Stub { } return true; } - + private void deletePackageResourcesLI(String packageName, String sourceDir, String publicSourceDir) { File sourceFile = new File(sourceDir); @@ -4283,7 +4306,9 @@ class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Package " + p.packageName + " has no applicationInfo."); return false; } - outInfo.uid = applicationInfo.uid; + if (outInfo != null) { + outInfo.uid = applicationInfo.uid; + } // Delete package data from internal structures and also remove data if flag is set removePackageDataLI(p, outInfo, flags); @@ -5460,7 +5485,7 @@ class PackageManagerService extends IPackageManager.Stub { String resourcePathString; private long timeStamp; private String timeStampString = "0"; - final int versionCode; + int versionCode; PackageSignatures signatures = new PackageSignatures(); @@ -5698,10 +5723,6 @@ class PackageManagerService extends IPackageManager.Stub { final String name = pkg.packageName; PackageSetting p = getPackageLP(name, sharedUser, codePath, resourcePath, pkg.mVersionCode, pkgFlags, create, add); - - if (p != null) { - p.pkg = pkg; - } return p; } @@ -5849,22 +5870,18 @@ class PackageManagerService extends IPackageManager.Stub { if (p != null) { if (!p.codePath.equals(codePath)) { // Check to see if its a disabled system app - PackageSetting ps = mDisabledSysPackages.get(name); - if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) { + if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) { // This is an updated system app with versions in both system // and data partition. Just let the most recent version // take precedence. - return p; + Log.w(TAG, "Trying to update system app code path from " + + p.codePathString + " to " + codePath.toString()); } else { // Let the app continue with previous uid if code path changes. reportSettingsProblem(Log.WARN, "Package " + name + " codePath changed from " + p.codePath + " to " + codePath + "; Retaining data and using new code from " + codePath); - p.codePath = codePath; - p.resourcePath = resourcePath; - p.codePathString = codePath.toString(); - p.resourcePathString = resourcePath.toString(); } } else if (p.sharedUser != sharedUser) { reportSettingsProblem(Log.WARN, @@ -5888,8 +5905,29 @@ class PackageManagerService extends IPackageManager.Stub { if (sharedUser != null) { p.userId = sharedUser.userId; } else if (MULTIPLE_APPLICATION_UIDS) { - // Assign new user id - p.userId = newUserIdLP(p); + // Clone the setting here for disabled system packages + PackageSetting dis = mDisabledSysPackages.get(name); + if (dis != null) { + // For disabled packages a new setting is created + // from the existing user id. This still has to be + // added to list of user id's + // Copy signatures from previous setting + if (dis.signatures.mSignatures != null) { + p.signatures.mSignatures = dis.signatures.mSignatures.clone(); + } + p.userId = dis.userId; + // Clone permissions + p.grantedPermissions = new HashSet<String>(dis.grantedPermissions); + p.loadedPermissions = new HashSet<String>(dis.loadedPermissions); + // Clone component info + p.disabledComponents = new HashSet<String>(dis.disabledComponents); + p.enabledComponents = new HashSet<String>(dis.enabledComponents); + // Add new setting to list of user ids + addUserIdLP(p.userId, p, name); + } else { + // Assign new user id + p.userId = newUserIdLP(p); + } } else { p.userId = FIRST_APPLICATION_UID; } @@ -5901,15 +5939,39 @@ class PackageManagerService extends IPackageManager.Stub { if (add) { // Finish adding new package by adding it and updating shared // user preferences - insertPackageSettingLP(p, name, sharedUser); + addPackageSettingLP(p, name, sharedUser); } } return p; } - + + private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg, + File codePath, File resourcePath) { + p.pkg = pkg; + // Update code path if needed + if (!codePath.toString().equalsIgnoreCase(p.codePathString)) { + Log.w(TAG, "Code path for pkg : " + p.pkg.packageName + + " changing form " + p.codePathString + " to " + codePath); + p.codePath = codePath; + p.codePathString = codePath.toString(); + } + //Update resource path if needed + if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) { + Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName + + " changing form " + p.resourcePathString + " to " + resourcePath); + p.resourcePath = resourcePath; + p.resourcePathString = resourcePath.toString(); + } + // Update version code if needed + if (pkg.mVersionCode != p.versionCode) { + p.versionCode = pkg.mVersionCode; + } + addPackageSettingLP(p, pkg.packageName, p.sharedUser); + } + // Utility method that adds a PackageSetting to mPackages and // completes updating the shared user attributes - private void insertPackageSettingLP(PackageSetting p, String name, + private void addPackageSettingLP(PackageSetting p, String name, SharedUserSetting sharedUser) { mPackages.put(name, p); if (sharedUser != null) { @@ -6002,7 +6064,7 @@ class PackageManagerService extends IPackageManager.Stub { } if (mUserIds.get(index) != null) { reportSettingsProblem(Log.ERROR, - "Adding duplicate shared id: " + uid + "Adding duplicate user id: " + uid + " name=" + name); return false; } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 81a715d..5ea59ca 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4736,7 +4736,30 @@ public final class ActivityManagerService extends ActivityManagerNative implemen Binder.restoreCallingIdentity(callingId); } } - + + /* + * The pkg name and uid have to be specified. + * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int) + */ + public void killApplicationWithUid(String pkg, int uid) { + if (pkg == null) { + return; + } + // Make sure the uid is valid. + if (uid < 0) { + Log.w(TAG, "Invalid uid specified for pkg : " + pkg); + return; + } + int callerUid = Binder.getCallingUid(); + // Only the system server can kill an application + if (callerUid == Process.SYSTEM_UID) { + uninstallPackageLocked(pkg, uid, false); + } else { + throw new SecurityException(callerUid + " cannot kill pkg: " + + pkg); + } + } + private void restartPackageLocked(final String packageName, int uid) { uninstallPackageLocked(packageName, uid, false); Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, |