Remove native binaries when an updated system application is upgraded through OTA.
The point of this patch is to deal with the following case: - A system application exists in the system partition. As such its native code lies under /system/lib - An upgrade for it is installed through Market and overrides the version on the system partition. This places its native libraries under /data/data/<pkgname>/lib/ - Finally, the system is upgraded through an OTA, with an even more recent of the system application. We thus must remove the Market package as well as the native libraries that are in <dataDir>/lib since the new versions in /system/lib will be more recent. The patch itself removes the files in <dataDir>/lib when such a situation is detected. Note that this directory is created by the PackageManager service and owned by the 'system' userID. The application cannot create files there so simply erasing the content of the directory is enough (and avoids reparsing the market package file to list the installed binaries). The patch also fixes a different issue which can be reproduced with: - have system app installed on /system partition - install an update (e.g. adb install -r Term.apk) - uninstall the update (e.g. adb uninstall com.android.term) the logcat shows that the PackageManager will unpack the native libraries from the original /system/app/Term.apk into <dataDir>/lib, while they already are in /system/lib. The patch fixes that too. Change-Id: I5dfe27b91b6b31972e9cd4c196d15c3692732127
This commit is contained in:
@ -137,6 +137,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
private static final boolean DEBUG_PREFERRED = false;
|
||||
private static final boolean DEBUG_UPGRADE = false;
|
||||
private static final boolean DEBUG_INSTALL = false;
|
||||
private static final boolean DEBUG_NATIVE = false;
|
||||
|
||||
private static final boolean MULTIPLE_APPLICATION_UIDS = true;
|
||||
private static final int RADIO_UID = Process.PHONE_UID;
|
||||
@ -2607,6 +2608,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
+ " better than installed " + ps.versionCode);
|
||||
InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
|
||||
args.cleanUpResourcesLI();
|
||||
removeNativeBinariesLI(pkg);
|
||||
mSettings.enableSystemPackageLP(ps.name);
|
||||
}
|
||||
}
|
||||
@ -3208,11 +3210,22 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
if (mInstaller != null) {
|
||||
String path = scanFile.getPath();
|
||||
if (scanFileNewer) {
|
||||
Log.i(TAG, path + " changed; unpacking");
|
||||
int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
|
||||
if (err != PackageManager.INSTALL_SUCCEEDED) {
|
||||
mLastScanError = err;
|
||||
return null;
|
||||
// Note: We don't want to unpack the native binaries for
|
||||
// system applications, unless they have been updated
|
||||
// (the binaries are already under /system/lib).
|
||||
//
|
||||
// In other words, we're going to unpack the binaries
|
||||
// only for non-system apps and system app upgrades.
|
||||
//
|
||||
int flags = pkg.applicationInfo.flags;
|
||||
if ((flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
|
||||
(flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
|
||||
Log.i(TAG, path + " changed; unpacking");
|
||||
int err = cachePackageSharedLibsLI(pkg, scanFile);
|
||||
if (err != PackageManager.INSTALL_SUCCEEDED) {
|
||||
mLastScanError = err;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
pkg.mScanPath = path;
|
||||
@ -3528,6 +3541,13 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
|
||||
private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
|
||||
|
||||
// Return the path of the directory that will contain the native binaries
|
||||
// of a given installed package. This is relative to the data path.
|
||||
//
|
||||
private static File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
|
||||
return new File(pkg.applicationInfo.dataDir + "/lib");
|
||||
}
|
||||
|
||||
// Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
|
||||
// and automatically copy them to /data/data/<appname>/lib if present.
|
||||
//
|
||||
@ -3537,8 +3557,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// file is malformed.
|
||||
//
|
||||
private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
|
||||
File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
|
||||
File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
|
||||
File scanFile, String cpuAbi) throws IOException, ZipException {
|
||||
File sharedLibraryDir = getNativeBinaryDirForPackage(pkg);
|
||||
final String apkLib = "lib/";
|
||||
final int apkLibLen = apkLib.length();
|
||||
final int cpuAbiLen = cpuAbi.length();
|
||||
@ -3635,8 +3655,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
|
||||
//
|
||||
private int cachePackageGdbServerLI(PackageParser.Package pkg,
|
||||
File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
|
||||
File installGdbServerDir = new File(dataPath.getPath() + "/lib");
|
||||
File scanFile, String cpuAbi) throws IOException, ZipException {
|
||||
File installGdbServerDir = getNativeBinaryDirForPackage(pkg);
|
||||
final String GDBSERVER = "gdbserver";
|
||||
final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
|
||||
|
||||
@ -3683,11 +3703,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// (which corresponds to ro.product.cpu.abi), and also try an alternate
|
||||
// one if ro.product.cpu.abi2 is defined.
|
||||
//
|
||||
private int cachePackageSharedLibsLI(PackageParser.Package pkg,
|
||||
File dataPath, File scanFile) {
|
||||
private int cachePackageSharedLibsLI(PackageParser.Package pkg, File scanFile) {
|
||||
String cpuAbi = Build.CPU_ABI;
|
||||
try {
|
||||
int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
|
||||
int result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi);
|
||||
|
||||
// some architectures are capable of supporting several CPU ABIs
|
||||
// for example, 'armeabi-v7a' also supports 'armeabi' native code
|
||||
@ -3698,7 +3717,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
||||
final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
|
||||
if (cpuAbi2 != null) {
|
||||
result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
|
||||
result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi2);
|
||||
}
|
||||
|
||||
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
||||
@ -3715,7 +3734,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// into /data/data/<appname>/lib too.
|
||||
if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
|
||||
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
|
||||
int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
|
||||
int result2 = cachePackageGdbServerLI(pkg, scanFile, cpuAbi);
|
||||
if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
|
||||
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
|
||||
}
|
||||
@ -3757,6 +3776,37 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the native binaries of a given package. This simply
|
||||
// gets rid of the files in the 'lib' sub-directory.
|
||||
private void removeNativeBinariesLI(PackageParser.Package pkg) {
|
||||
File binaryDir = getNativeBinaryDirForPackage(pkg);
|
||||
|
||||
if (DEBUG_NATIVE) {
|
||||
Slog.w(TAG,"Deleting native binaries from: " + binaryDir.getPath());
|
||||
}
|
||||
|
||||
// Just remove any file in the directory. Since the directory
|
||||
// is owned by the 'system' UID, the application is not supposed
|
||||
// to have written anything there.
|
||||
//
|
||||
if (binaryDir.exists()) {
|
||||
File[] binaries = binaryDir.listFiles();
|
||||
if (binaries != null) {
|
||||
for (int nn=0; nn < binaries.length; nn++) {
|
||||
if (DEBUG_NATIVE) {
|
||||
Slog.d(TAG," Deleting " + binaries[nn].getName());
|
||||
}
|
||||
if (!binaries[nn].delete()) {
|
||||
Slog.w(TAG,"Could not delete native binary: " +
|
||||
binaries[nn].getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do not delete 'lib' directory itself, or this will prevent
|
||||
// installation of future updates.
|
||||
}
|
||||
}
|
||||
|
||||
void removePackageLI(PackageParser.Package pkg, boolean chatty) {
|
||||
if (chatty && Config.LOGD) Log.d(
|
||||
TAG, "Removing package " + pkg.applicationInfo.packageName );
|
||||
@ -6236,6 +6286,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
synchronized (mPackages) {
|
||||
// Reinstate the old system package
|
||||
mSettings.enableSystemPackageLP(p.packageName);
|
||||
// Remove any native libraries.
|
||||
removeNativeBinariesLI(p);
|
||||
}
|
||||
// Install the system package
|
||||
PackageParser.Package newPkg = scanPackageLI(ps.codePath,
|
||||
|
Reference in New Issue
Block a user