summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java61
-rw-r--r--core/java/android/content/pm/PackageInfoLite.java7
-rw-r--r--core/java/android/content/pm/PackageParser.java16
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java55
4 files changed, 107 insertions, 32 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1e93d92..4939fb6 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -491,13 +491,55 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public String nativeLibraryDir;
/**
- * The ABI that this application requires, This is inferred from the ABIs
+ * The path under the apps data directory we store unpacked libraries. For
+ * new installs, we create subdirectories under legacyNativeLibraryDir that are
+ * architecture specific. For legacy installs, the shared libraries are
+ * placed directly under this path.
+ *
+ * For "legacy" installs {@code nativeLibraryDir} will be equal to this path.
+ * For newer installs, it will be derived based on the codePath and the primary
+ * cpu abi.
+ *
+ * @hide.
+ */
+ public String legacyNativeLibraryDir;
+
+ /**
+ * The primary ABI that this application requires, This is inferred from the ABIs
* of the native JNI libraries the application bundles. Will be {@code null}
* if this application does not require any particular ABI.
*
+ * If non-null, the application will always be launched with this ABI.
+ *
+ * {@hide}
+ */
+ public String primaryCpuAbi;
+
+ /**
+ * The secondary ABI for this application. Might be non-null for multi-arch
+ * installs. The application itself never uses this ABI, but other applications that
+ * use its code might.
+ *
+ * {@hide}
+ */
+ public String secondaryCpuAbi;
+
+ /**
+ * The derived APK "root" for the given package. Will be non-null for bundled and
+ * updated system apps. This will be a top level path under which apks and libraries
+ * are installed, for eg. {@code /system}, {@code /oem} or {@code /vendor}. This is
+ * used to calculate the location of native code for a given package, for e.g
+ * {@code /vendor/lib} or {@code /vendor/lib64}.
+ *
+ * For app updates or fresh app installs, this will be {@code null} and we will use
+ * {@code legacyNativeLibraryDir}
+ *
+ * NOTE: This can be removed if we have a unified layout for bundled and installed
+ * apps.
+ *
* {@hide}
*/
- public String cpuAbi;
+ public String apkRoot;
/**
* The kernel user-ID that has been assigned to this application;
@@ -641,7 +683,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
splitSourceDirs = orig.splitSourceDirs;
splitPublicSourceDirs = orig.splitPublicSourceDirs;
nativeLibraryDir = orig.nativeLibraryDir;
- cpuAbi = orig.cpuAbi;
+ legacyNativeLibraryDir = orig.legacyNativeLibraryDir;
+ primaryCpuAbi = orig.primaryCpuAbi;
+ secondaryCpuAbi = orig.secondaryCpuAbi;
+ apkRoot = orig.apkRoot;
resourceDirs = orig.resourceDirs;
seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
@@ -685,7 +730,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeStringArray(splitSourceDirs);
dest.writeStringArray(splitPublicSourceDirs);
dest.writeString(nativeLibraryDir);
- dest.writeString(cpuAbi);
+ dest.writeString(legacyNativeLibraryDir);
+ dest.writeString(primaryCpuAbi);
+ dest.writeString(secondaryCpuAbi);
+ dest.writeString(apkRoot);
dest.writeStringArray(resourceDirs);
dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
@@ -728,7 +776,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
splitSourceDirs = source.readStringArray();
splitPublicSourceDirs = source.readStringArray();
nativeLibraryDir = source.readString();
- cpuAbi = source.readString();
+ legacyNativeLibraryDir = source.readString();
+ primaryCpuAbi = source.readString();
+ secondaryCpuAbi = source.readString();
+ apkRoot = source.readString();
resourceDirs = source.readStringArray();
seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index a1566da..50a0483 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -37,6 +37,13 @@ public class PackageInfoLite implements Parcelable {
public int versionCode;
/**
+ * The android:multiArch flag from the package manifest. If set,
+ * we will extract all native libraries for the given app, not just those
+ * from the preferred ABI.
+ */
+ public boolean multiArch;
+
+ /**
* Specifies the recommended install location. Can be one of
* {@link #PackageHelper.RECOMMEND_INSTALL_INTERNAL} to install on internal storage
* {@link #PackageHelper.RECOMMEND_INSTALL_EXTERNAL} to install on external media
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ab0bf25..6e0ca50 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -249,6 +249,8 @@ public class PackageParser {
/** Paths of any split APKs, ordered by parsed splitName */
public final String[] splitCodePaths;
+ public final boolean multiArch;
+
private PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
String[] splitCodePaths) {
this.packageName = baseApk.packageName;
@@ -259,6 +261,7 @@ public class PackageParser {
this.codePath = codePath;
this.baseCodePath = baseApk.codePath;
this.splitCodePaths = splitCodePaths;
+ this.multiArch = baseApk.multiArch;
}
public List<String> getAllCodePaths() {
@@ -282,9 +285,11 @@ public class PackageParser {
public final int installLocation;
public final VerifierInfo[] verifiers;
public final Signature[] signatures;
+ public final boolean multiArch;
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
- int installLocation, List<VerifierInfo> verifiers, Signature[] signatures) {
+ int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
+ boolean multiArch) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -292,6 +297,7 @@ public class PackageParser {
this.installLocation = installLocation;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
this.signatures = signatures;
+ this.multiArch = multiArch;
}
}
@@ -1114,6 +1120,7 @@ public class PackageParser {
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
int versionCode = 0;
int numFound = 0;
+ boolean multiArch = false;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
@@ -1123,8 +1130,11 @@ public class PackageParser {
} else if (attr.equals("versionCode")) {
versionCode = attrs.getAttributeIntValue(i, 0);
numFound++;
+ } else if (attr.equals("multiArch")) {
+ multiArch = attrs.getAttributeBooleanValue(i, false);
+ numFound++;
}
- if (numFound >= 2) {
+ if (numFound >= 3) {
break;
}
}
@@ -1149,7 +1159,7 @@ public class PackageParser {
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
- installLocation, verifiers, signatures);
+ installLocation, verifiers, signatures, multiArch);
}
/**
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index d66a7bb..d76d0d4 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -131,10 +131,15 @@ public class NativeLibraryHelper {
*
* @return size of all native binary files in bytes
*/
- public static long sumNativeBinariesLI(Handle handle, String abi) {
+ public static long sumNativeBinariesLI(Handle handle, String[] abis) {
long sum = 0;
for (long apkHandle : handle.apkHandles) {
- sum += nativeSumNativeBinaries(apkHandle, abi);
+ // NOTE: For a given APK handle, we parse the central directory precisely
+ // once, but prefix matching of entries requires a CD traversal, which can
+ // take a while (even if it needs no additional I/O).
+ for (String abi : abis) {
+ sum += nativeSumNativeBinaries(apkHandle, abi);
+ }
}
return sum;
}
@@ -196,45 +201,47 @@ public class NativeLibraryHelper {
private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
// Convenience method to call removeNativeBinariesFromDirLI(File)
- public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
- if (nativeLibraryPath == null) return false;
- return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));
+ public static void removeNativeBinariesLI(String nativeLibraryPath) {
+ if (nativeLibraryPath == null) return;
+ removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */);
}
- // Remove the native binaries of a given package. This simply
- // gets rid of the files in the 'lib' sub-directory.
- public static boolean removeNativeBinariesFromDirLI(File nativeLibraryDir) {
+ /**
+ * Remove the native binaries of a given package. This deletes the files
+ */
+ public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, boolean deleteRootDir) {
if (DEBUG_NATIVE) {
- Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryDir.getPath());
+ Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
}
- boolean deletedFiles = false;
-
/*
* 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 (nativeLibraryDir.exists()) {
- final File[] binaries = nativeLibraryDir.listFiles();
- if (binaries != null) {
- for (int nn = 0; nn < binaries.length; nn++) {
+ if (nativeLibraryRoot.exists()) {
+ final File[] files = nativeLibraryRoot.listFiles();
+ if (files != null) {
+ for (int nn = 0; nn < files.length; nn++) {
if (DEBUG_NATIVE) {
- Slog.d(TAG, " Deleting " + binaries[nn].getName());
+ Slog.d(TAG, " Deleting " + files[nn].getName());
}
- if (!binaries[nn].delete()) {
- Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath());
- } else {
- deletedFiles = true;
+ if (files[nn].isDirectory()) {
+ removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */);
+ } else if (!files[nn].delete()) {
+ Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath());
}
}
}
- // Do not delete 'lib' directory itself, or this will prevent
- // installation of future updates.
+ // Do not delete 'lib' directory itself, unless we're specifically
+ // asked to or this will prevent installation of future updates.
+ if (deleteRootDir) {
+ if (!nativeLibraryRoot.delete()) {
+ Slog.w(TAG, "Could not delete native binary directory: " + nativeLibraryRoot.getPath());
+ }
+ }
}
-
- return deletedFiles;
}
// We don't care about the other return values for now.