Merge change 8728 into donut

* changes:
  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.
This commit is contained in:
Android (Google) Code Review
2009-07-28 10:18:47 -07:00
4 changed files with 139 additions and 32 deletions

View File

@ -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;
}

View File

@ -267,6 +267,8 @@ public interface IActivityManager extends IInterface {
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;
}

View File

@ -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;
if (outInfo != null) {
outInfo.removedPackage = packageName;
}
removePackageLI(p, true);
// Retrieve object to delete permissions for shared user later on
PackageSetting deletedPs;
@ -4178,9 +4199,11 @@ class PackageManagerService extends IPackageManager.Stub {
dataDir.delete();
}
synchronized (mPackages) {
if (outInfo != null) {
outInfo.removedUid = mSettings.removePackageLP(packageName);
}
}
}
synchronized (mPackages) {
if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
// remove permissions associated with package
@ -4283,7 +4306,9 @@ class PackageManagerService extends IPackageManager.Stub {
Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
return false;
}
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) {
// 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;
}

View File

@ -4737,6 +4737,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
/*
* 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,