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:
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user