summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2010-08-27 16:45:45 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-08-27 16:45:45 -0700
commit8328578152fbfd23952a6cda4b2e60853d78eb74 (patch)
tree9467164d24c5dba533a2d1f4b1f9e9b89a6536c7
parent63b5b8701092de71e48b36cce8eb36f51f9d4d5e (diff)
parent7046bd924f77c54585b9e0e0c95e5edd2ceb55a3 (diff)
downloadframeworks_base-8328578152fbfd23952a6cda4b2e60853d78eb74.zip
frameworks_base-8328578152fbfd23952a6cda4b2e60853d78eb74.tar.gz
frameworks_base-8328578152fbfd23952a6cda4b2e60853d78eb74.tar.bz2
am 7046bd92: Merge "Allow native shared libraries in ASEC containers" into gingerbread
Merge commit '7046bd924f77c54585b9e0e0c95e5edd2ceb55a3' into gingerbread-plus-aosp * commit '7046bd924f77c54585b9e0e0c95e5edd2ceb55a3': Allow native shared libraries in ASEC containers
-rw-r--r--core/java/android/app/ActivityThread.java1
-rw-r--r--core/java/android/app/ApplicationLoaders.java10
-rw-r--r--core/java/android/app/LoadedApk.java8
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java20
-rw-r--r--core/java/android/content/pm/InstrumentationInfo.java12
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java296
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java16
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java3
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java81
-rw-r--r--services/java/com/android/server/PackageManagerService.java564
10 files changed, 613 insertions, 398 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 084f637..ca6fc8a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3181,6 +3181,7 @@ public final class ActivityThread {
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.dataDir = ii.dataDir;
+ instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp,
appContext.getClassLoader(), false, true);
ContextImpl instrContext = new ContextImpl();
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 2e301c9..9e3cd7e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -19,6 +19,7 @@ package android.app;
import dalvik.system.PathClassLoader;
import java.util.HashMap;
+import java.util.Map;
class ApplicationLoaders
{
@@ -27,8 +28,7 @@ class ApplicationLoaders
return gApplicationLoaders;
}
- public ClassLoader getClassLoader(String zip, String appDataDir,
- ClassLoader parent)
+ public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
{
/*
* This is the parent we use if they pass "null" in. In theory
@@ -49,13 +49,13 @@ class ApplicationLoaders
* new ClassLoader for the zip archive.
*/
if (parent == baseParent) {
- ClassLoader loader = (ClassLoader)mLoaders.get(zip);
+ ClassLoader loader = mLoaders.get(zip);
if (loader != null) {
return loader;
}
PathClassLoader pathClassloader =
- new PathClassLoader(zip, appDataDir + "/lib", parent);
+ new PathClassLoader(zip, libPath, parent);
mLoaders.put(zip, pathClassloader);
return pathClassloader;
@@ -65,7 +65,7 @@ class ApplicationLoaders
}
}
- private final HashMap mLoaders = new HashMap();
+ private final Map<String, ClassLoader> mLoaders = new HashMap<String, ClassLoader>();
private static final ApplicationLoaders gApplicationLoaders
= new ApplicationLoaders();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0f98152..0644f96 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -72,6 +72,7 @@ final class LoadedApk {
private final String mResDir;
private final String[] mSharedLibraries;
private final String mDataDir;
+ private final String mLibDir;
private final File mDataDirFile;
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
@@ -108,6 +109,7 @@ final class LoadedApk {
mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
+ mLibDir = aInfo.nativeLibraryDir;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
@@ -140,6 +142,7 @@ final class LoadedApk {
mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
+ mLibDir = null;
mBaseClassLoader = null;
mSecurityViolation = false;
mIncludeCode = true;
@@ -279,11 +282,12 @@ final class LoadedApk {
* create the class loader.
*/
- if (ActivityThread.localLOGV) Slog.v(ActivityThread.TAG, "Class path: " + zip);
+ if (ActivityThread.localLOGV)
+ Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + mLibDir);
mClassLoader =
ApplicationLoaders.getDefault().getClassLoader(
- zip, mDataDir, mBaseClassLoader);
+ zip, mLibDir, mBaseClassLoader);
initializeJavaContextClassLoader();
} else {
if (mBaseClassLoader == null) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index c812f36..ae6a311 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -291,14 +291,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_FORWARD_LOCK = 1<<29;
/**
- * Value for {@link #flags}: Set to true if the application is
- * native-debuggable, i.e. embeds a gdbserver binary in its .apk
- *
- * {@hide}
- */
- public static final int FLAG_NATIVE_DEBUGGABLE = 1<<28;
-
- /**
* Value for {@link #flags}: set to <code>true</code> if the application
* has reported that it is heavy-weight, and thus can not participate in
* the normal application lifecycle.
@@ -359,7 +351,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* data.
*/
public String dataDir;
-
+
+ /**
+ * Full path to the directory where native JNI libraries are stored.
+ *
+ * {@hide}
+ */
+ public String nativeLibraryDir;
+
/**
* The kernel user-ID that has been assigned to this application;
* currently this is not a unique ID (multiple applications can have
@@ -452,6 +451,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
flags = orig.flags;
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
+ nativeLibraryDir = orig.nativeLibraryDir;
resourceDirs = orig.resourceDirs;
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
@@ -483,6 +483,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(flags);
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
+ dest.writeString(nativeLibraryDir);
dest.writeStringArray(resourceDirs);
dest.writeStringArray(sharedLibraryFiles);
dest.writeString(dataDir);
@@ -514,6 +515,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
flags = source.readInt();
sourceDir = source.readString();
publicSourceDir = source.readString();
+ nativeLibraryDir = source.readString();
resourceDirs = source.readStringArray();
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index 3e868a7..ea47e8e 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -50,7 +50,14 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
* data.
*/
public String dataDir;
-
+
+ /**
+ * Full path to the directory where the native JNI libraries are stored.
+ *
+ * {@hide}
+ */
+ public String nativeLibraryDir;
+
/**
* Specifies whether or not this instrumentation will handle profiling.
*/
@@ -68,6 +75,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
dataDir = orig.dataDir;
+ nativeLibraryDir = orig.nativeLibraryDir;
handleProfiling = orig.handleProfiling;
functionalTest = orig.functionalTest;
}
@@ -88,6 +96,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
dest.writeString(dataDir);
+ dest.writeString(nativeLibraryDir);
dest.writeInt((handleProfiling == false) ? 0 : 1);
dest.writeInt((functionalTest == false) ? 0 : 1);
}
@@ -108,6 +117,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
sourceDir = source.readString();
publicSourceDir = source.readString();
dataDir = source.readString();
+ nativeLibraryDir = source.readString();
handleProfiling = source.readInt() != 0;
functionalTest = source.readInt() != 0;
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
new file mode 100644
index 0000000..8b618c7
--- /dev/null
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -0,0 +1,296 @@
+package com.android.internal.content;
+
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.FileUtils;
+import android.os.SystemProperties;
+import android.util.Config;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+/**
+ * Native libraries helper.
+ *
+ * @hide
+ */
+public class NativeLibraryHelper {
+ private static final String TAG = "NativeHelper";
+
+ private static final boolean DEBUG_NATIVE = false;
+
+ /*
+ * The following constants are returned by listPackageSharedLibsForAbiLI
+ * to indicate if native shared libraries were found in the package.
+ * Values are:
+ * PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
+ * PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
+ * PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
+ * in package (and not installed)
+ *
+ */
+ private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
+ private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
+ private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
+
+ // Directory in the APK that holds all the native shared libraries.
+ private static final String APK_LIB = "lib/";
+ private static final int APK_LIB_LENGTH = APK_LIB.length();
+
+ // Prefix that native shared libraries must have.
+ private static final String LIB_PREFIX = "lib";
+ private static final int LIB_PREFIX_LENGTH = LIB_PREFIX.length();
+
+ // Suffix that the native shared libraries must have.
+ private static final String LIB_SUFFIX = ".so";
+ private static final int LIB_SUFFIX_LENGTH = LIB_SUFFIX.length();
+
+ // Name of the GDB binary.
+ private static final String GDBSERVER = "gdbserver";
+
+ // the minimum length of a valid native shared library of the form
+ // lib/<something>/lib<name>.so.
+ private static final int MIN_ENTRY_LENGTH = APK_LIB_LENGTH + 2 + LIB_PREFIX_LENGTH + 1
+ + LIB_SUFFIX_LENGTH;
+
+ /*
+ * Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
+ * and add them to a list to be installed later.
+ *
+ * NOTE: this method may throw an IOException if the library cannot
+ * be copied to its final destination, e.g. if there isn't enough
+ * room left on the data partition, or a ZipException if the package
+ * file is malformed.
+ */
+ private static int listPackageSharedLibsForAbiLI(ZipFile zipFile,
+ String cpuAbi, List<Pair<ZipEntry, String>> libEntries) throws IOException,
+ ZipException {
+ final int cpuAbiLen = cpuAbi.length();
+ boolean hasNativeLibraries = false;
+ boolean installedNativeLibraries = false;
+
+ if (DEBUG_NATIVE) {
+ Slog.d(TAG, "Checking " + zipFile.getName() + " for shared libraries of CPU ABI type "
+ + cpuAbi);
+ }
+
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+
+ // skip directories
+ if (entry.isDirectory()) {
+ continue;
+ }
+ String entryName = entry.getName();
+
+ /*
+ * Check that the entry looks like lib/<something>/lib<name>.so
+ * here, but don't check the ABI just yet.
+ *
+ * - must be sufficiently long
+ * - must end with LIB_SUFFIX, i.e. ".so"
+ * - must start with APK_LIB, i.e. "lib/"
+ */
+ if (entryName.length() < MIN_ENTRY_LENGTH || !entryName.endsWith(LIB_SUFFIX)
+ || !entryName.startsWith(APK_LIB)) {
+ continue;
+ }
+
+ // file name must start with LIB_PREFIX, i.e. "lib"
+ int lastSlash = entryName.lastIndexOf('/');
+
+ if (lastSlash < 0
+ || !entryName.regionMatches(lastSlash + 1, LIB_PREFIX, 0, LIB_PREFIX_LENGTH)) {
+ continue;
+ }
+
+ hasNativeLibraries = true;
+
+ // check the cpuAbi now, between lib/ and /lib<name>.so
+ if (lastSlash != APK_LIB_LENGTH + cpuAbiLen
+ || !entryName.regionMatches(APK_LIB_LENGTH, cpuAbi, 0, cpuAbiLen))
+ continue;
+
+ /*
+ * Extract the library file name, ensure it doesn't contain
+ * weird characters. we're guaranteed here that it doesn't contain
+ * a directory separator though.
+ */
+ String libFileName = entryName.substring(lastSlash+1);
+ if (!FileUtils.isFilenameSafe(new File(libFileName))) {
+ continue;
+ }
+
+ installedNativeLibraries = true;
+
+ if (DEBUG_NATIVE) {
+ Log.d(TAG, "Caching shared lib " + entry.getName());
+ }
+
+ libEntries.add(Pair.create(entry, libFileName));
+ }
+ if (!hasNativeLibraries)
+ return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
+
+ if (!installedNativeLibraries)
+ return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
+
+ return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
+ }
+
+ /*
+ * Find the gdbserver executable program in a package at
+ * lib/<cpuAbi>/gdbserver and add it to the list of binaries
+ * to be copied out later.
+ *
+ * Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
+ * or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
+ */
+ private static int listPackageGdbServerLI(ZipFile zipFile, String cpuAbi,
+ List<Pair<ZipEntry, String>> nativeFiles) throws IOException, ZipException {
+ final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
+
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ // skip directories
+ if (entry.isDirectory()) {
+ continue;
+ }
+ String entryName = entry.getName();
+
+ if (!entryName.equals(apkGdbServerPath)) {
+ continue;
+ }
+
+ if (Config.LOGD) {
+ Log.d(TAG, "Found gdbserver: " + entry.getName());
+ }
+
+ final String installGdbServerPath = APK_LIB + GDBSERVER;
+ nativeFiles.add(Pair.create(entry, installGdbServerPath));
+
+ return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
+ }
+ return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
+ }
+
+ /*
+ * Examine shared libraries stored in the APK as
+ * lib/<cpuAbi>/lib<name>.so and add them to a list to be copied
+ * later.
+ *
+ * This function will first try the main CPU ABI defined by Build.CPU_ABI
+ * (which corresponds to ro.product.cpu.abi), and also try an alternate
+ * one if ro.product.cpu.abi2 is defined.
+ */
+ public static int listPackageNativeBinariesLI(ZipFile zipFile,
+ List<Pair<ZipEntry, String>> nativeFiles) throws ZipException, IOException {
+ String cpuAbi = Build.CPU_ABI;
+
+ int result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi, nativeFiles);
+
+ /*
+ * Some architectures are capable of supporting several CPU ABIs
+ * for example, 'armeabi-v7a' also supports 'armeabi' native code
+ * this is indicated by the definition of the ro.product.cpu.abi2
+ * system property.
+ *
+ * only scan the package twice in case of ABI mismatch
+ */
+ if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
+ final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2", null);
+ if (cpuAbi2 != null) {
+ result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi2, nativeFiles);
+ }
+
+ if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
+ Slog.w(TAG, "Native ABI mismatch from package file");
+ return PackageManager.INSTALL_FAILED_INVALID_APK;
+ }
+
+ if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
+ cpuAbi = cpuAbi2;
+ }
+ }
+
+ /*
+ * Debuggable packages may have gdbserver embedded, so add it to
+ * the list to the list of items to be extracted (as lib/gdbserver)
+ * into the application's native library directory later.
+ */
+ if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
+ listPackageGdbServerLI(zipFile, cpuAbi, nativeFiles);
+ }
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
+ public static int copyNativeBinariesLI(File scanFile, File sharedLibraryDir) {
+ /*
+ * Check all the native files that need to be copied and add
+ * that to the container size.
+ */
+ ZipFile zipFile;
+ try {
+ zipFile = new ZipFile(scanFile);
+
+ List<Pair<ZipEntry, String>> nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
+
+ NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
+
+ final int N = nativeFiles.size();
+
+ for (int i = 0; i < N; i++) {
+ final Pair<ZipEntry, String> entry = nativeFiles.get(i);
+
+ File destFile = new File(sharedLibraryDir, entry.second);
+ copyNativeBinaryLI(zipFile, entry.first, sharedLibraryDir, destFile);
+ }
+ } catch (ZipException e) {
+ Slog.w(TAG, "Failed to extract data from package file", e);
+ return PackageManager.INSTALL_FAILED_INVALID_APK;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to cache package shared libs", e);
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
+ private static void copyNativeBinaryLI(ZipFile zipFile, ZipEntry entry,
+ File binaryDir, File binaryFile) throws IOException {
+ InputStream inputStream = zipFile.getInputStream(entry);
+ try {
+ File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
+ String tempFilePath = tempFile.getPath();
+ // XXX package manager can't change owner, so the executable files for
+ // now need to be left as world readable and owned by the system.
+ if (!FileUtils.copyToFile(inputStream, tempFile)
+ || !tempFile.setLastModified(entry.getTime())
+ || FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR | FileUtils.S_IWUSR
+ | FileUtils.S_IRGRP | FileUtils.S_IXUSR | FileUtils.S_IXGRP
+ | FileUtils.S_IXOTH | FileUtils.S_IROTH, -1, -1) != 0
+ || !tempFile.renameTo(binaryFile)) {
+ // Failed to properly write file.
+ tempFile.delete();
+ throw new IOException("Couldn't create cached binary " + binaryFile + " in "
+ + binaryDir);
+ }
+ } finally {
+ inputStream.close();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 4d0a9e0..d6c43f9 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -56,22 +56,22 @@ public class PackageHelper {
return null;
}
- public static String createSdDir(File tmpPackageFile, String cid,
+ public static String createSdDir(long sizeBytes, String cid,
String sdEncKey, int uid) {
// Create mount point via MountService
IMountService mountService = getMountService();
- long len = tmpPackageFile.length();
- int mbLen = (int) (len >> 20);
- if ((len - (mbLen * 1024 * 1024)) > 0) {
- mbLen++;
+ int sizeMb = (int) (sizeBytes >> 20);
+ if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) {
+ sizeMb++;
}
// Add buffer size
- mbLen++;
- if (localLOGV) Log.i(TAG, "Size of container " + mbLen + " MB " + len + " bytes");
+ sizeMb++;
+ if (localLOGV)
+ Log.i(TAG, "Size of container " + sizeMb + " MB " + sizeBytes + " bytes");
try {
int rc = mountService.createSecureContainer(
- cid, mbLen, "fat", sdEncKey, uid);
+ cid, sizeMb, "fat", sdEncKey, uid);
if (rc != StorageResultCode.OperationSucceeded) {
Log.e(TAG, "Failed to create secure container " + cid);
return null;
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index cbf8c87..de3d153 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -358,6 +358,7 @@ public class PackageManagerTests extends AndroidTestCase {
assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
assertEquals(srcPath, drmInstallPath);
assertEquals(publicSrcPath, appInstallPath);
+ assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
} else {
assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
@@ -365,10 +366,12 @@ public class PackageManagerTests extends AndroidTestCase {
assertEquals(srcPath, appInstallPath);
assertEquals(publicSrcPath, appInstallPath);
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+ assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
} else if (rLoc == INSTALL_LOC_SD){
assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
} else {
// TODO handle error. Install should have failed.
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index c6e0a24..f08bd3c 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -17,7 +17,9 @@
package com.android.defcontainer;
import com.android.internal.app.IMediaContainerService;
+import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
@@ -37,6 +39,7 @@ import android.os.StatFs;
import android.app.IntentService;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import java.io.File;
import java.io.FileInputStream;
@@ -44,6 +47,11 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
import android.os.FileUtils;
import android.provider.Settings;
@@ -59,6 +67,8 @@ public class DefaultContainerService extends IntentService {
private static final String TAG = "DefContainer";
private static final boolean localLOGV = true;
+ private static final String LIB_DIR_NAME = "lib";
+
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
/*
* Creates a new container and copies resource there.
@@ -194,18 +204,51 @@ public class DefaultContainerService extends IntentService {
Log.w(TAG, "Make sure sdcard is mounted.");
return null;
}
- // Create new container at newCachePath
+
+ // The .apk file
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
- String newCachePath = null;
+
+ // Calculate size of container needed to hold base APK.
+ long sizeBytes = codeFile.length();
+
+ // Check all the native files that need to be copied and add that to the container size.
+ ZipFile zipFile;
+ List<Pair<ZipEntry, String>> nativeFiles;
+ try {
+ zipFile = new ZipFile(codeFile);
+
+ nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
+
+ NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
+
+ final int N = nativeFiles.size();
+ for (int i = 0; i < N; i++) {
+ final Pair<ZipEntry, String> entry = nativeFiles.get(i);
+
+ /*
+ * Note that PackageHelper.createSdDir adds a 1MB padding on
+ * our claimed size, so we don't have to worry about block
+ * alignment here.
+ */
+ sizeBytes += entry.first.getSize();
+ }
+ } catch (ZipException e) {
+ Log.w(TAG, "Failed to extract data from package file", e);
+ return null;
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to cache package shared libs", e);
+ return null;
+ }
+
// Create new container
- if ((newCachePath = PackageHelper.createSdDir(codeFile,
- newCid, key, Process.myUid())) == null) {
+ String newCachePath = null;
+ if ((newCachePath = PackageHelper.createSdDir(sizeBytes, newCid, key, Process.myUid())) == null) {
Log.e(TAG, "Failed to create container " + newCid);
return null;
}
- if (localLOGV) Log.i(TAG, "Created container for " + newCid
- + " at path : " + newCachePath);
+ if (localLOGV)
+ Log.i(TAG, "Created container for " + newCid + " at path : " + newCachePath);
File resFile = new File(newCachePath, resFileName);
if (!FileUtils.copyFile(new File(codePath), resFile)) {
Log.e(TAG, "Failed to copy " + codePath + " to " + resFile);
@@ -213,6 +256,32 @@ public class DefaultContainerService extends IntentService {
PackageHelper.destroySdDir(newCid);
return null;
}
+
+ try {
+ File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
+ sharedLibraryDir.mkdir();
+
+ final int N = nativeFiles.size();
+ for (int i = 0; i < N; i++) {
+ final Pair<ZipEntry, String> entry = nativeFiles.get(i);
+
+ InputStream is = zipFile.getInputStream(entry.first);
+ try {
+ File destFile = new File(sharedLibraryDir, entry.second);
+ if (!FileUtils.copyToFile(is, destFile)) {
+ throw new IOException("Couldn't copy native binary "
+ + entry.first.getName() + " to " + entry.second);
+ }
+ } finally {
+ is.close();
+ }
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't copy native file to container", e);
+ PackageHelper.destroySdDir(newCid);
+ return null;
+ }
+
if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
if (!PackageHelper.finalizeSdDir(newCid)) {
Log.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 0ff33d1..a2d3298 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -18,6 +18,7 @@ package com.android.server;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
@@ -112,6 +113,7 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -188,6 +190,8 @@ class PackageManagerService extends IPackageManager.Stub {
"com.android.defcontainer",
"com.android.defcontainer.DefaultContainerService");
+ private static final String LIB_DIR_NAME = "lib";
+
static final String mTempContainerPrefix = "smdl2tmp";
final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
@@ -678,13 +682,6 @@ class PackageManagerService extends IPackageManager.Stub {
return false;
}
- static boolean isFwdLocked(int flags) {
- if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
- return true;
- }
- return false;
- }
-
public static final IPackageManager main(Context context, boolean factoryTest) {
PackageManagerService m = new PackageManagerService(context, factoryTest);
ServiceManager.addService("package", m);
@@ -1497,6 +1494,7 @@ class PackageManagerService extends IPackageManager.Stub {
ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
ps.pkg.applicationInfo.sourceDir = ps.codePathString;
ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
+ ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
ps.pkg.mSetEnabled = ps.enabled;
}
return generatePackageInfo(ps.pkg, flags);
@@ -2376,8 +2374,7 @@ class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package p = i.next();
if (p.applicationInfo != null
&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
- && (!mSafeMode || (p.applicationInfo.flags
- &ApplicationInfo.FLAG_SYSTEM) != 0)) {
+ && (!mSafeMode || isSystemApp(p))) {
finalList.add(PackageParser.generateApplicationInfo(p, flags));
}
}
@@ -2621,9 +2618,9 @@ class PackageManagerService extends IPackageManager.Stub {
+ "reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
- InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
+ InstallArgs args = new FileInstallArgs(ps.codePathString,
+ ps.resourcePathString, ps.nativeLibraryPathString);
args.cleanUpResourcesLI();
- removeNativeBinariesLI(pkg);
mSettings.enableSystemPackageLP(ps.name);
}
}
@@ -2663,8 +2660,8 @@ class PackageManagerService extends IPackageManager.Stub {
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
}
- private static void setApplicationInfoPaths(PackageParser.Package pkg,
- String destCodePath, String destResPath) {
+ private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
+ String destResPath) {
pkg.mPath = pkg.mScanPath = destCodePath;
pkg.applicationInfo.sourceDir = destCodePath;
pkg.applicationInfo.publicSourceDir = destResPath;
@@ -3146,10 +3143,10 @@ class PackageManagerService extends IPackageManager.Stub {
if (dataPath.exists()) {
mOutPermissions[1] = 0;
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
- if (mOutPermissions[1] == pkg.applicationInfo.uid
- || !Process.supportsProcesses()) {
- pkg.applicationInfo.dataDir = dataPath.getPath();
- } else {
+
+ // If we have mismatched owners for the data path, we have a
+ // problem (unless we're running in the simulator.)
+ if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
boolean recovered = false;
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// If this is a system app, we can at least delete its
@@ -3186,6 +3183,7 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
+ pkg.applicationInfo.uid + "/fs_"
+ mOutPermissions[1];
+ pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
String msg = "Package " + pkg.packageName
+ " has mismatched uid: "
+ mOutPermissions[1] + " on disk, "
@@ -3229,32 +3227,38 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.dataDir = null;
}
}
-
+
+ /*
+ * Set the data dir to the default "/data/data/<package name>/lib"
+ * if we got here without anyone telling us different (e.g., apps
+ * stored on SD card have their native libraries stored in the ASEC
+ * container with the APK).
+ */
+ if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
+ pkg.applicationInfo.nativeLibraryDir = new File(dataPath, LIB_DIR_NAME).getPath();
+ }
+
pkgSetting.uidError = uidError;
}
- // Perform shared library installation and dex validation and
- // optimization, if this is not a system app.
+ // If we're running in the simulator, we don't need to unpack anything.
if (mInstaller != null) {
String path = scanFile.getPath();
- if (scanFileNewer) {
- // 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;
- }
- }
+ /* 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).
+ * Also, don't unpack libs for apps on the external card
+ * since they should have their libraries in the ASEC
+ * container already.
+ *
+ * In other words, we're going to unpack the binaries
+ * only for non-system apps and system app upgrades.
+ */
+ if ((!isSystemApp(pkg) || isUpdatedSystemApp(pkg)) && !isExternal(pkg)) {
+ Log.i(TAG, path + " changed; unpacking");
+ File sharedLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+ sharedLibraryDir.mkdir();
+ NativeLibraryHelper.copyNativeBinariesLI(scanFile, sharedLibraryDir);
}
pkg.mScanPath = path;
@@ -3517,6 +3521,7 @@ class PackageManagerService extends IPackageManager.Stub {
a.info.sourceDir = pkg.applicationInfo.sourceDir;
a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
a.info.dataDir = pkg.applicationInfo.dataDir;
+ a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
mInstrumentation.put(a.getComponentName(), a);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
@@ -3557,266 +3562,30 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
- // The following constants are returned by cachePackageSharedLibsForAbiLI
- // to indicate if native shared libraries were found in the package.
- // Values are:
- // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
- // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
- // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
- // in package (and not installed)
- //
- private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
- 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.
- //
- // NOTE: this method may throw an IOException if the library cannot
- // be copied to its final destination, e.g. if there isn't enough
- // room left on the data partition, or a ZipException if the package
- // file is malformed.
- //
- private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
- 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();
- final String libPrefix = "lib";
- final int libPrefixLen = libPrefix.length();
- final String libSuffix = ".so";
- final int libSuffixLen = libSuffix.length();
- boolean hasNativeLibraries = false;
- boolean installedNativeLibraries = false;
-
- // the minimum length of a valid native shared library of the form
- // lib/<something>/lib<name>.so.
- final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
-
- ZipFile zipFile = new ZipFile(scanFile);
- Enumeration<ZipEntry> entries =
- (Enumeration<ZipEntry>) zipFile.entries();
-
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
- // skip directories
- if (entry.isDirectory()) {
- continue;
- }
- String entryName = entry.getName();
-
- // check that the entry looks like lib/<something>/lib<name>.so
- // here, but don't check the ABI just yet.
- //
- // - must be sufficiently long
- // - must end with libSuffix, i.e. ".so"
- // - must start with apkLib, i.e. "lib/"
- if (entryName.length() < minEntryLen ||
- !entryName.endsWith(libSuffix) ||
- !entryName.startsWith(apkLib) ) {
- continue;
- }
-
- // file name must start with libPrefix, i.e. "lib"
- int lastSlash = entryName.lastIndexOf('/');
-
- if (lastSlash < 0 ||
- !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
- continue;
- }
-
- hasNativeLibraries = true;
-
- // check the cpuAbi now, between lib/ and /lib<name>.so
- //
- if (lastSlash != apkLibLen + cpuAbiLen ||
- !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
- continue;
-
- // extract the library file name, ensure it doesn't contain
- // weird characters. we're guaranteed here that it doesn't contain
- // a directory separator though.
- String libFileName = entryName.substring(lastSlash+1);
- if (!FileUtils.isFilenameSafe(new File(libFileName))) {
- continue;
- }
-
- installedNativeLibraries = true;
-
- // Always extract the shared library
- String sharedLibraryFilePath = sharedLibraryDir.getPath() +
- File.separator + libFileName;
- File sharedLibraryFile = new File(sharedLibraryFilePath);
-
- if (Config.LOGD) {
- Log.d(TAG, "Caching shared lib " + entry.getName());
- }
- if (mInstaller == null) {
- sharedLibraryDir.mkdir();
- }
- cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
- sharedLibraryFile);
- }
- if (!hasNativeLibraries)
- return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
-
- if (!installedNativeLibraries)
- return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
-
- return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
- }
-
- // Find the gdbserver executable program in a package at
- // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
- //
- // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
- // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
- //
- private int cachePackageGdbServerLI(PackageParser.Package pkg,
- File scanFile, String cpuAbi) throws IOException, ZipException {
- File installGdbServerDir = getNativeBinaryDirForPackage(pkg);
- final String GDBSERVER = "gdbserver";
- final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
-
- ZipFile zipFile = new ZipFile(scanFile);
- Enumeration<ZipEntry> entries =
- (Enumeration<ZipEntry>) zipFile.entries();
-
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
- // skip directories
- if (entry.isDirectory()) {
- continue;
- }
- String entryName = entry.getName();
-
- if (!entryName.equals(apkGdbServerPath)) {
- continue;
- }
-
- String installGdbServerPath = installGdbServerDir.getPath() +
- "/" + GDBSERVER;
- File installGdbServerFile = new File(installGdbServerPath);
-
- if (Config.LOGD) {
- Log.d(TAG, "Caching gdbserver " + entry.getName());
- }
- if (mInstaller == null) {
- installGdbServerDir.mkdir();
- }
- cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
- installGdbServerFile);
-
- return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
- }
- return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
- }
-
- // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
- // and copy them to /data/data/<appname>/lib.
- //
- // This function will first try the main CPU ABI defined by Build.CPU_ABI
- // (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 scanFile) {
- // Remove all native binaries from a directory. This is used when upgrading
- // a package: in case the new .apk doesn't contain a native binary that was
- // in the old one (and thus installed), we need to remove it from
- // /data/data/<appname>/lib
- //
- // The simplest way to do that is to remove all files in this directory,
- // since it is owned by "system", applications are not supposed to write
- // anything there.
- removeNativeBinariesLI(pkg);
-
- String cpuAbi = Build.CPU_ABI;
- try {
- int result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi);
-
- // some architectures are capable of supporting several CPU ABIs
- // for example, 'armeabi-v7a' also supports 'armeabi' native code
- // this is indicated by the definition of the ro.product.cpu.abi2
- // system property.
- //
- // only scan the package twice in case of ABI mismatch
- if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
- final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
- if (cpuAbi2 != null) {
- result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi2);
- }
-
- if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
- Slog.w(TAG,"Native ABI mismatch from package file");
- return PackageManager.INSTALL_FAILED_INVALID_APK;
- }
-
- if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
- cpuAbi = cpuAbi2;
- }
- }
-
- // for debuggable packages, also extract gdbserver from lib/<abi>
- // into /data/data/<appname>/lib too.
- if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
- (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- int result2 = cachePackageGdbServerLI(pkg, scanFile, cpuAbi);
- if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
- pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
- }
- }
- } catch (ZipException e) {
- Slog.w(TAG, "Failed to extract data from package file", e);
- return PackageManager.INSTALL_FAILED_INVALID_APK;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to cache package shared libs", e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ private File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
+ final String nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
+ if (nativeLibraryDir != null) {
+ return new File(nativeLibraryDir);
+ } else {
+ // Fall back for old packages
+ return new File(pkg.applicationInfo.dataDir, LIB_DIR_NAME);
}
- return PackageManager.INSTALL_SUCCEEDED;
}
- private void cacheNativeBinaryLI(PackageParser.Package pkg,
- ZipFile zipFile, ZipEntry entry,
- File binaryDir,
- File binaryFile) throws IOException {
- InputStream inputStream = zipFile.getInputStream(entry);
- try {
- File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
- String tempFilePath = tempFile.getPath();
- // XXX package manager can't change owner, so the executable files for
- // now need to be left as world readable and owned by the system.
- if (! FileUtils.copyToFile(inputStream, tempFile) ||
- ! tempFile.setLastModified(entry.getTime()) ||
- FileUtils.setPermissions(tempFilePath,
- FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
- |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
- |FileUtils.S_IROTH, -1, -1) != 0 ||
- ! tempFile.renameTo(binaryFile)) {
- // Failed to properly write file.
- tempFile.delete();
- throw new IOException("Couldn't create cached binary "
- + binaryFile + " in " + binaryDir);
- }
- } finally {
- inputStream.close();
- }
+ // Convenience call for removeNativeBinariesLI(File)
+ private void removeNativeBinariesLI(PackageParser.Package pkg) {
+ File nativeLibraryDir = getNativeBinaryDirForPackage(pkg);
+ removeNativeBinariesLI(nativeLibraryDir);
}
// 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);
-
+ public void removeNativeBinariesLI(File binaryDir) {
if (DEBUG_NATIVE) {
- Slog.w(TAG,"Deleting native binaries from: " + binaryDir.getPath());
+ Slog.w(TAG, "Deleting native binaries from: " + binaryDir.getPath());
}
// Just remove any file in the directory. Since the directory
@@ -3824,15 +3593,14 @@ class PackageManagerService extends IPackageManager.Stub {
// to have written anything there.
//
if (binaryDir.exists()) {
- File[] binaries = binaryDir.listFiles();
+ File[] binaries = binaryDir.listFiles();
if (binaries != null) {
- for (int nn=0; nn < binaries.length; nn++) {
+ for (int nn = 0; nn < binaries.length; nn++) {
if (DEBUG_NATIVE) {
- Slog.d(TAG," Deleting " + binaries[nn].getName());
+ Slog.d(TAG, " Deleting " + binaries[nn].getName());
}
if (!binaries[nn].delete()) {
- Slog.w(TAG,"Could not delete native binary: " +
- binaries[nn].getPath());
+ Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath());
}
}
}
@@ -4144,11 +3912,10 @@ class PackageManagerService extends IPackageManager.Stub {
|| (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
== PackageManager.SIGNATURE_MATCH);
if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
- if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if (isSystemApp(pkg)) {
// For updated system applications, the signatureOrSystem permission
// is granted only if it had been defined by the original application.
- if ((pkg.applicationInfo.flags
- & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ if (isUpdatedSystemApp(pkg)) {
PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
if(sysPs.grantedPermissions.contains(perm)) {
allowed = true;
@@ -4936,7 +4703,7 @@ class PackageManagerService extends IPackageManager.Stub {
// App explictly prefers external. Let policy decide
} else {
// Prefer previous location
- if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+ if (isExternal(pkg)) {
return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
}
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
@@ -5048,16 +4815,16 @@ class PackageManagerService extends IPackageManager.Stub {
final InstallArgs srcArgs;
final InstallArgs targetArgs;
int mRet;
- MoveParams(InstallArgs srcArgs,
- IPackageMoveObserver observer,
- int flags, String packageName) {
+
+ MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
+ String packageName, String dataDir) {
this.srcArgs = srcArgs;
this.observer = observer;
this.flags = flags;
this.packageName = packageName;
if (srcArgs != null) {
Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
- targetArgs = createInstallArgs(packageUri, flags, packageName);
+ targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
} else {
targetArgs = null;
}
@@ -5113,21 +4880,22 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
- private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
+ private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
+ String nativeLibraryPath) {
if (installOnSd(flags)) {
- return new SdInstallArgs(fullCodePath, fullResourcePath);
+ return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
} else {
- return new FileInstallArgs(fullCodePath, fullResourcePath);
+ return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
}
}
- private InstallArgs createInstallArgs(Uri packageURI, int flags,
- String pkgName) {
+ // Used by package mover
+ private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
if (installOnSd(flags)) {
String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
return new SdInstallArgs(packageURI, cid);
} else {
- return new FileInstallArgs(packageURI, pkgName);
+ return new FileInstallArgs(packageURI, pkgName, dataDir);
}
}
@@ -5154,6 +4922,7 @@ class PackageManagerService extends IPackageManager.Stub {
abstract int doPostInstall(int status);
abstract String getCodePath();
abstract String getResourcePath();
+ abstract String getNativeLibraryPath();
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
abstract boolean doPostDeleteLI(boolean delete);
@@ -5164,6 +4933,7 @@ class PackageManagerService extends IPackageManager.Stub {
File installDir;
String codeFileName;
String resourceFileName;
+ String libraryPath;
boolean created = false;
FileInstallArgs(InstallParams params) {
@@ -5171,21 +4941,22 @@ class PackageManagerService extends IPackageManager.Stub {
params.flags, params.installerPackageName);
}
- FileInstallArgs(String fullCodePath, String fullResourcePath) {
+ FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
super(null, null, 0, null);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
resourceFileName = fullResourcePath;
+ libraryPath = nativeLibraryPath;
}
- FileInstallArgs(Uri packageURI, String pkgName) {
+ FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
super(packageURI, null, 0, null);
- boolean fwdLocked = isFwdLocked(flags);
- installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
+ installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
resourceFileName = getResourcePathFromCodePath();
+ libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -5197,8 +4968,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
void createCopyFile() {
- boolean fwdLocked = isFwdLocked(flags);
- installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
+ installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
codeFileName = createTempPackageFile(installDir).getPath();
resourceFileName = getResourcePathFromCodePath();
created = true;
@@ -5226,8 +4996,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
ParcelFileDescriptor out = null;
try {
- out = ParcelFileDescriptor.open(codeFile,
- ParcelFileDescriptor.MODE_READ_WRITE);
+ out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
} catch (FileNotFoundException e) {
Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -5241,6 +5010,11 @@ class PackageManagerService extends IPackageManager.Stub {
} finally {
try { if (out != null) out.close(); } catch (IOException e) {}
}
+
+ if (!temp) {
+ NativeLibraryHelper.copyNativeBinariesLI(codeFile, new File(libraryPath));
+ }
+
return ret;
}
@@ -5296,6 +5070,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
+ String getNativeLibraryPath() {
+ return libraryPath;
+ }
+
private boolean cleanUp() {
boolean ret = true;
String sourceDir = getCodePath();
@@ -5332,11 +5111,14 @@ class PackageManagerService extends IPackageManager.Stub {
// we don't consider this to be a failure of the core package deletion
}
}
+ if (libraryPath != null) {
+ removeNativeBinariesLI(new File(libraryPath));
+ }
}
private boolean setPermissions() {
// TODO Do this in a more elegant way later on. for now just a hack
- if (!isFwdLocked(flags)) {
+ if (!isFwdLocked()) {
final int filePermissions =
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
|FileUtils.S_IROTH;
@@ -5354,35 +5136,42 @@ class PackageManagerService extends IPackageManager.Stub {
}
boolean doPostDeleteLI(boolean delete) {
+ // XXX err, shouldn't we respect the delete flag?
cleanUpResourcesLI();
return true;
}
+
+ private boolean isFwdLocked() {
+ return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+ }
}
class SdInstallArgs extends InstallArgs {
- String cid;
- String cachePath;
static final String RES_FILE_NAME = "pkg.apk";
+ String cid;
+ String packagePath;
+ String libraryPath;
+
SdInstallArgs(InstallParams params) {
super(params.packageURI, params.observer,
params.flags, params.installerPackageName);
}
- SdInstallArgs(String fullCodePath, String fullResourcePath) {
+ SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
int sidx = subStr1.lastIndexOf("/");
cid = subStr1.substring(sidx+1, eidx);
- cachePath = subStr1;
+ setCachePath(subStr1);
}
SdInstallArgs(String cid) {
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
this.cid = cid;
- cachePath = PackageHelper.getSdDir(cid);
+ setCachePath(PackageHelper.getSdDir(cid));
}
SdInstallArgs(Uri packageURI, String cid) {
@@ -5402,21 +5191,30 @@ class PackageManagerService extends IPackageManager.Stub {
if (temp) {
createCopyFile();
}
- cachePath = imcs.copyResourceToContainer(
+ String newCachePath = imcs.copyResourceToContainer(
packageURI, cid,
getEncryptKey(), RES_FILE_NAME);
- return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
- PackageManager.INSTALL_SUCCEEDED;
+ if (newCachePath != null) {
+ setCachePath(newCachePath);
+ return PackageManager.INSTALL_SUCCEEDED;
+ } else {
+ return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+ }
}
@Override
String getCodePath() {
- return cachePath + "/" + RES_FILE_NAME;
+ return packagePath;
}
@Override
String getResourcePath() {
- return cachePath + "/" + RES_FILE_NAME;
+ return packagePath;
+ }
+
+ @Override
+ String getNativeLibraryPath() {
+ return libraryPath;
}
int doPreInstall(int status) {
@@ -5426,8 +5224,11 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
boolean mounted = PackageHelper.isContainerMounted(cid);
if (!mounted) {
- cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
- if (cachePath == null) {
+ String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
+ Process.SYSTEM_UID);
+ if (newCachePath != null) {
+ setCachePath(newCachePath);
+ } else {
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
}
}
@@ -5473,13 +5274,19 @@ class PackageManagerService extends IPackageManager.Stub {
return false;
}
Log.i(TAG, "Succesfully renamed " + cid +
- " at path: " + cachePath + " to " + newCacheId +
+ " to " + newCacheId +
" at new path: " + newCachePath);
cid = newCacheId;
- cachePath = newCachePath;
+ setCachePath(newCachePath);
return true;
}
+ private void setCachePath(String newCachePath) {
+ File cachePath = new File(newCachePath);
+ libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
+ packagePath = new File(cachePath, RES_FILE_NAME).getPath();
+ }
+
int doPostInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
@@ -5695,7 +5502,7 @@ class PackageManagerService extends IPackageManager.Stub {
return;
}
}
- boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
} else {
@@ -5855,7 +5662,7 @@ class PackageManagerService extends IPackageManager.Stub {
!ps.codePathString.equals(oldPkgSetting.codePathString)) {
int installFlags = 0;
res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
- oldPkgSetting.resourcePathString);
+ oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
}
}
}
@@ -6006,6 +5813,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
// Set application objects path explicitly after the rename
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
+ pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
if (replace) {
replacePackageLI(pkg, parseFlags, scanMode,
installerPackageName, res);
@@ -6020,8 +5828,7 @@ class PackageManagerService extends IPackageManager.Stub {
int retCode = 0;
// TODO Gross hack but fix later. Ideally move this to be a post installation
// check after alloting uid.
- if ((newPackage.applicationInfo.flags
- & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
+ if (isForwardLocked(newPackage)) {
File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
try {
extractPublicFiles(newPackage, destResourceFile);
@@ -6056,12 +5863,20 @@ class PackageManagerService extends IPackageManager.Stub {
return PackageManager.INSTALL_SUCCEEDED;
}
- private boolean isForwardLocked(PackageParser.Package pkg) {
- return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+ private static boolean isForwardLocked(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
+ }
+
+ private static boolean isExternal(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
+ }
+
+ private static boolean isSystemApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
- private boolean isExternal(PackageParser.Package pkg) {
- return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+ private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
private void extractPublicFiles(PackageParser.Package newPackage,
@@ -6291,7 +6106,7 @@ class PackageManagerService extends IPackageManager.Stub {
// we don't consider this to be a failure of the core package deletion
}
} else {
- //for emulator
+ // for simulator
PackageParser.Package pkg = mPackages.get(packageName);
File dataDir = new File(pkg.applicationInfo.dataDir);
dataDir.delete();
@@ -6374,7 +6189,7 @@ class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
// Reinstate the old system package
mSettings.enableSystemPackageLP(p.packageName);
- // Remove any native libraries.
+ // Remove any native libraries. XXX needed?
removeNativeBinariesLI(p);
}
// Install the system package
@@ -6410,12 +6225,10 @@ class PackageManagerService extends IPackageManager.Stub {
// Delete application code and resources
if (deleteCodeAndResources) {
// TODO can pick up from PackageSettings as well
- int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ?
- PackageManager.INSTALL_EXTERNAL : 0;
- installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
- PackageManager.INSTALL_FORWARD_LOCK : 0;
- outInfo.args = createInstallArgs(installFlags,
- applicationInfo.sourceDir, applicationInfo.publicSourceDir);
+ int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
+ installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
+ outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
+ applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
}
return true;
}
@@ -6460,7 +6273,7 @@ class PackageManagerService extends IPackageManager.Stub {
return false;
}
boolean ret = false;
- if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if (isSystemApp(p)) {
Log.i(TAG, "Removing system package:"+p.packageName);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
@@ -7160,10 +6973,14 @@ class PackageManagerService extends IPackageManager.Stub {
pw.print(" pkg="); pw.println(ps.pkg);
pw.print(" codePath="); pw.println(ps.codePathString);
pw.print(" resourcePath="); pw.println(ps.resourcePathString);
+ pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
pw.print(" obbPath="); pw.println(ps.obbPathString);
if (ps.pkg != null) {
pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
+ if (ps.pkg.mOperationPending) {
+ pw.println(" mOperationPending=true");
+ }
pw.print(" supportsScreens=[");
boolean first = true;
if ((ps.pkg.applicationInfo.flags &
@@ -7211,9 +7028,6 @@ class PackageManagerService extends IPackageManager.Stub {
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
pw.print(" installStatus="); pw.print(ps.installStatus);
pw.print(" enabled="); pw.println(ps.enabled);
- if (ps.pkg.mOperationPending) {
- pw.println(" mOperationPending=true");
- }
if (ps.disabledComponents.size() > 0) {
pw.println(" disabledComponents:");
for (String s : ps.disabledComponents) {
@@ -7730,6 +7544,7 @@ class PackageManagerService extends IPackageManager.Stub {
String codePathString;
File resourcePath;
String resourcePathString;
+ String nativeLibraryPathString;
String obbPathString;
private long timeStamp;
private String timeStampString = "0";
@@ -7769,7 +7584,7 @@ class PackageManagerService extends IPackageManager.Stub {
this.resourcePathString = resourcePath.toString();
this.versionCode = pVersionCode;
}
-
+
public void setInstallerPackageName(String packageName) {
installerPackageName = packageName;
}
@@ -8282,8 +8097,8 @@ class PackageManagerService extends IPackageManager.Stub {
private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
pkg.mSetEnabled = p.enabled;
- String codePath = pkg.applicationInfo.sourceDir;
- String resourcePath = pkg.applicationInfo.publicSourceDir;
+ final String codePath = pkg.applicationInfo.sourceDir;
+ final String resourcePath = pkg.applicationInfo.publicSourceDir;
// Update code path if needed
if (!codePath.equalsIgnoreCase(p.codePathString)) {
Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
@@ -8298,6 +8113,12 @@ class PackageManagerService extends IPackageManager.Stub {
p.resourcePath = new File(resourcePath);
p.resourcePathString = resourcePath;
}
+ // Update the native library path if needed
+ final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
+ if (nativeLibraryPath != null
+ && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
+ p.nativeLibraryPathString = nativeLibraryPath;
+ }
// Update version code if needed
if (pkg.mVersionCode != p.versionCode) {
p.versionCode = pkg.mVersionCode;
@@ -8595,7 +8416,7 @@ class PackageManagerService extends IPackageManager.Stub {
StringBuilder sb = new StringBuilder();
for (PackageSetting pkg : mPackages.values()) {
ApplicationInfo ai = pkg.pkg.applicationInfo;
- String dataPath = ai.dataDir;
+ String dataPath = ai.dataDir;
boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
// Avoid any application that has a space in its path
@@ -8668,6 +8489,9 @@ class PackageManagerService extends IPackageManager.Stub {
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
+ if (pkg.nativeLibraryPathString != null) {
+ serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
+ }
if (pkg.sharedUser == null) {
serializer.attribute(null, "userId",
Integer.toString(pkg.userId));
@@ -8707,6 +8531,9 @@ class PackageManagerService extends IPackageManager.Stub {
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
+ if (pkg.nativeLibraryPathString != null) {
+ serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
+ }
serializer.attribute(null, "flags",
Integer.toString(pkg.pkgFlags));
serializer.attribute(null, "ts", pkg.getTimeStampStr());
@@ -9111,6 +8938,7 @@ class PackageManagerService extends IPackageManager.Stub {
String sharedIdStr = null;
String codePathStr = null;
String resourcePathStr = null;
+ String nativeLibraryPathStr = null;
String obbPathStr = null;
String systemStr = null;
String installerPackageName = null;
@@ -9129,6 +8957,7 @@ class PackageManagerService extends IPackageManager.Stub {
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
+ nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
obbPathStr = parser.getAttributeValue(null, "obbPath");
version = parser.getAttributeValue(null, "version");
if (version != null) {
@@ -9227,6 +9056,7 @@ class PackageManagerService extends IPackageManager.Stub {
if (packageSetting != null) {
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
+ packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
packageSetting.obbPathString = obbPathStr;
final String enabledStr = parser.getAttributeValue(null, "enabled");
if (enabledStr != null) {
@@ -9893,12 +9723,10 @@ class PackageManagerService extends IPackageManager.Stub {
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
} else {
// Disable moving fwd locked apps and system packages
- if (pkg.applicationInfo != null &&
- (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if (pkg.applicationInfo != null && isSystemApp(pkg)) {
Slog.w(TAG, "Cannot move system application");
returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
- } else if (pkg.applicationInfo != null &&
- (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
+ } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
Slog.w(TAG, "Cannot move forward locked app.");
returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
} else if (pkg.mOperationPending) {
@@ -9913,8 +9741,8 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
- currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
- PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
+ currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
+ : PackageManager.INSTALL_INTERNAL;
if (newFlags == currFlags) {
Slog.w(TAG, "No move required. Trying to move to same location");
returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
@@ -9926,13 +9754,13 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- processPendingMove(new MoveParams(null, observer, 0, packageName), returnCode);
+ processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
- pkg.applicationInfo.publicSourceDir);
- MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
- packageName);
+ pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
+ MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
+ pkg.applicationInfo.dataDir);
msg.obj = mp;
mHandler.sendMessage(msg);
}
@@ -9950,7 +9778,7 @@ class PackageManagerService extends IPackageManager.Stub {
ArrayList<String> pkgList = null;
synchronized (mPackages) {
PackageParser.Package pkg = mPackages.get(mp.packageName);
- if (pkg == null ) {
+ if (pkg == null) {
Slog.w(TAG, " Package " + mp.packageName +
" doesn't exist. Aborting move");
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
@@ -9983,9 +9811,10 @@ class PackageManagerService extends IPackageManager.Stub {
" Aborting move and returning error");
returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
} else {
- String oldCodePath = pkg.mPath;
- String newCodePath = mp.targetArgs.getCodePath();
- String newResPath = mp.targetArgs.getResourcePath();
+ final String oldCodePath = pkg.mPath;
+ final String newCodePath = mp.targetArgs.getCodePath();
+ final String newResPath = mp.targetArgs.getResourcePath();
+ final String newNativePath = mp.targetArgs.getNativeLibraryPath();
pkg.mPath = newCodePath;
// Move dex files around
if (moveDexFilesLI(pkg)
@@ -9998,6 +9827,7 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.mScanPath = newCodePath;
pkg.applicationInfo.sourceDir = newCodePath;
pkg.applicationInfo.publicSourceDir = newResPath;
+ pkg.applicationInfo.nativeLibraryDir = newNativePath;
PackageSetting ps = (PackageSetting) pkg.mExtras;
ps.codePath = new File(pkg.applicationInfo.sourceDir);
ps.codePathString = ps.codePath.getPath();