diff options
4 files changed, 139 insertions, 32 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index ba6cc32808d4..3aeac538f044 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1085,6 +1085,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeInt(result); return true; } + case KILL_APPLICATION_WITH_UID_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String pkg = data.readString(); + int uid = data.readInt(); + killApplicationWithUid(pkg, uid); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -2368,6 +2376,17 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return result; } + public void killApplicationWithUid(String pkg, int uid) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(pkg); + data.writeInt(uid); + mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } private IBinder mRemote; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 95b376cce673..b1b52824bfae 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -266,6 +266,8 @@ public interface IActivityManager extends IInterface { Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded) throws RemoteException; + + public void killApplicationWithUid(String pkg, int uid) throws RemoteException; /* * Private non-Binder interfaces @@ -421,4 +423,5 @@ public interface IActivityManager extends IInterface { int REGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92; int UNREGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93; int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94; + int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95; } diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 4afa03e7f954..b39f2f666571 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 81a715d972e2..5ea59ca20ffa 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, |