Merge "[DO NOT MERGE] Support native shared libs" into oc-dev
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0708b0b..393909b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -452,6 +452,7 @@
for (String lib : sharedLibraries) {
if (!outZipPaths.contains(lib)) {
outZipPaths.add(0, lib);
+ appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
}
}
}
@@ -460,11 +461,33 @@
for (String lib : instrumentationLibs) {
if (!outZipPaths.contains(lib)) {
outZipPaths.add(0, lib);
+ appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
}
}
}
}
+ /**
+ * This method appends a path to the appropriate native library folder of a
+ * library if this library is hosted in an APK. This allows support for native
+ * shared libraries. The library API is determined based on the application
+ * ABI.
+ *
+ * @param path Path to the library.
+ * @param applicationInfo The application depending on the library.
+ * @param outLibPaths List to which to add the native lib path if needed.
+ */
+ private static void appendApkLibPathIfNeeded(@NonNull String path,
+ @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) {
+ // Looking at the suffix is a little hacky but a safe and simple solution.
+ // We will be revisiting code in the next release and clean this up.
+ if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) {
+ if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
+ outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi);
+ }
+ }
+ }
+
/*
* All indices received by the super class should be shifted by 1 when accessing mSplitNames,
* etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index fdb0f2ba..c67376c 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -5989,6 +5989,10 @@
}
}
+ public boolean isLibrary() {
+ return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
+ }
+
public List<String> getAllCodePaths() {
ArrayList<String> paths = new ArrayList<>();
paths.add(baseCodePath);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6c59505..51f4e2e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -57,6 +57,7 @@
import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
import static android.content.pm.PackageManager.INSTALL_INTERNAL;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -10432,8 +10433,9 @@
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
- derivePackageAbi(
- pkg, scanFile, cpuAbiOverride, true /*extractLibs*/, mAppLib32InstallDir);
+ final boolean extractNativeLibs = !pkg.isLibrary();
+ derivePackageAbi(pkg, scanFile, cpuAbiOverride, extractNativeLibs,
+ mAppLib32InstallDir);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Some system apps still use directory structure for native libraries
@@ -11461,6 +11463,12 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
+ // Shared library native code should be in the APK zip aligned
+ if (abi32 >= 0 && pkg.isLibrary() && extractLibs) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library native lib extraction not supported");
+ }
+
maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 32 bit native libs for multiarch app.", abi32);
@@ -11481,6 +11489,11 @@
"Error unpackaging 64 bit native libs for multiarch app.", abi64);
if (abi64 >= 0) {
+ // Shared library native libs should be in the APK zip aligned
+ if (extractLibs && pkg.isLibrary()) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library native lib extraction not supported");
+ }
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
}
@@ -11497,7 +11510,6 @@
pkg.applicationInfo.primaryCpuAbi = abi;
}
}
-
} else {
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
@@ -11530,6 +11542,11 @@
}
if (copyRet >= 0) {
+ // Shared libraries that have native libs must be multi-architecture
+ if (pkg.isLibrary()) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library with native libs must be multiarch");
+ }
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
} else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
@@ -18084,8 +18101,9 @@
try {
String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
args.abiOverride : pkg.cpuAbiOverride);
+ final boolean extractNativeLibs = !pkg.isLibrary();
derivePackageAbi(pkg, new File(pkg.codePath), abiOverride,
- true /*extractLibs*/, mAppLib32InstallDir);
+ extractNativeLibs, mAppLib32InstallDir);
} catch (PackageManagerException pme) {
Slog.e(TAG, "Error deriving application ABI", pme);
res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");