diff options
| author | 2018-05-03 16:38:54 +0000 | |
|---|---|---|
| committer | 2018-05-03 16:38:54 +0000 | |
| commit | f4e0438a46e7d9194338933ca5689dc769e43a57 (patch) | |
| tree | 53cc8500efb792cec1b02cf82c7e04dd8d26a93a | |
| parent | 2b9d205fbbb2e966a62d2c6746ca33b4a75ea7f2 (diff) | |
| parent | 1bea237aa296a35c263f0c4965ba0f5a140cd848 (diff) | |
Merge "In place split install native support" into pi-dev
5 files changed, 98 insertions, 7 deletions
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index 8c0738a91f6c..4a5312aeffe2 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -3709,6 +3709,7 @@ Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File; Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V +Ldalvik/system/DexPathList;->addNativePath(Ljava/util/Collection;)V Ldalvik/system/DexPathList;->definingContext:Ljava/lang/ClassLoader; Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element; Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile; diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index 725704422290..0ed50f2bea97 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -25,6 +25,8 @@ import com.android.internal.os.ClassLoaderFactory; import dalvik.system.PathClassLoader; +import java.util.Collection; + /** @hide */ public class ApplicationLoaders { public static ApplicationLoaders getDefault() { @@ -121,6 +123,17 @@ public class ApplicationLoaders { baseDexClassLoader.addDexPath(dexPath); } + /** + * @hide + */ + void addNative(ClassLoader classLoader, Collection<String> libPaths) { + if (!(classLoader instanceof PathClassLoader)) { + throw new IllegalStateException("class loader is not a PathClassLoader"); + } + final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader; + baseDexClassLoader.addNativePath(libPaths); + } + private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>(); private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders(); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index fc7d9a553e31..8c0cd23e5fbd 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -90,6 +90,7 @@ final class ServiceConnectionLeaked extends AndroidRuntimeException { public final class LoadedApk { static final String TAG = "LoadedApk"; static final boolean DEBUG = false; + private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths"; private final ActivityThread mActivityThread; final String mPackageName; @@ -723,6 +724,10 @@ public final class LoadedApk { needToSetupJitProfiles = true; } + if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) { + ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths); + } + if (addedPaths != null && addedPaths.size() > 0) { final String add = TextUtils.join(File.pathSeparator, addedPaths); ApplicationLoaders.getDefault().addPath(mClassLoader, add); diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index a1e6fd8e22f9..c3881485d4f9 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -282,7 +282,10 @@ public class NativeLibraryHelper { } } - private static void createNativeLibrarySubdir(File path) throws IOException { + /** + * @hide + */ + public static void createNativeLibrarySubdir(File path) throws IOException { if (!path.isDirectory()) { path.delete(); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index f7a02156c15a..fa934fe23fff 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -17,7 +17,6 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED; -import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA; import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; @@ -74,6 +73,7 @@ import android.os.ParcelableException; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; import android.system.ErrnoException; @@ -111,9 +111,9 @@ import java.io.FileDescriptor; import java.io.FileFilter; import java.io.FileOutputStream; import java.io.IOException; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -154,6 +154,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String ATTR_NAME = "name"; private static final String ATTR_INSTALL_REASON = "installRason"; + private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill"; + // TODO: enforce INSTALL_ALLOW_TEST // TODO: enforce INSTALL_ALLOW_DOWNGRADE @@ -255,6 +257,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private final List<String> mResolvedInstructionSets = new ArrayList<>(); @GuardedBy("mLock") + private final List<String> mResolvedNativeLibPaths = new ArrayList<>(); + @GuardedBy("mLock") private File mInheritedFilesBase; private static final FileFilter sAddedFilter = new FileFilter() { @@ -971,6 +975,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final File oatDir = new File(toDir, "oat"); createOatDirs(mResolvedInstructionSets, oatDir); } + // pre-create lib dirs for linking if necessary + if (!mResolvedNativeLibPaths.isEmpty()) { + for (String libPath : mResolvedNativeLibPaths) { + // "/lib/arm64" -> ["lib", "arm64"] + final int splitIndex = libPath.lastIndexOf('/'); + if (splitIndex < 0 || splitIndex >= libPath.length() - 1) { + Slog.e(TAG, "Skipping native library creation for linking due to " + + "invalid path: " + libPath); + continue; + } + final String libDirPath = libPath.substring(1, splitIndex); + final File libDir = new File(toDir, libDirPath); + if (!libDir.exists()) { + NativeLibraryHelper.createNativeLibrarySubdir(libDir); + } + final String archDirPath = libPath.substring(splitIndex + 1); + NativeLibraryHelper.createNativeLibrarySubdir( + new File(libDir, archDirPath)); + } + } linkFiles(fromFiles, toDir, mInheritedFilesBase); } else { // TODO: this should delegate to DCS so the system process @@ -988,7 +1012,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { computeProgressLocked(true); // Unpack native libraries - extractNativeLibraries(mResolvedStageDir, params.abiOverride); + extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs()); // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. @@ -1028,6 +1052,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } /** + * Returns true if the session should attempt to inherit any existing native libraries already + * extracted at the current install location. This is necessary to prevent double loading of + * native libraries already loaded by the running app. + */ + private boolean mayInheritNativeLibs() { + return SystemProperties.getBoolean(PROPERTY_NAME_INHERIT_NATIVE, true) && + params.mode == SessionParams.MODE_INHERIT_EXISTING && + (params.installFlags & PackageManager.DONT_KILL_APP) != 0; + } + + /** * Validate install by confirming that all application packages are have * consistent package name, version code, and signing certificates. * <p> @@ -1249,6 +1284,38 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } } + + // Inherit native libraries for DONT_KILL sessions. + if (mayInheritNativeLibs() && removeSplitList.isEmpty()) { + File[] libDirs = new File[]{ + new File(packageInstallDir, NativeLibraryHelper.LIB_DIR_NAME), + new File(packageInstallDir, NativeLibraryHelper.LIB64_DIR_NAME)}; + for (File libDir : libDirs) { + if (!libDir.exists() || !libDir.isDirectory()) { + continue; + } + final List<File> libDirsToInherit = new LinkedList<>(); + for (File archSubDir : libDir.listFiles()) { + if (!archSubDir.isDirectory()) { + continue; + } + String relLibPath; + try { + relLibPath = getRelativePath(archSubDir, packageInstallDir); + } catch (IOException e) { + Slog.e(TAG, "Skipping linking of native library directory!", e); + // shouldn't be possible, but let's avoid inheriting these to be safe + libDirsToInherit.clear(); + break; + } + if (!mResolvedNativeLibPaths.contains(relLibPath)) { + mResolvedNativeLibPaths.add(relLibPath); + } + libDirsToInherit.addAll(Arrays.asList(archSubDir.listFiles())); + } + mResolvedInheritedFiles.addAll(libDirsToInherit); + } + } } } @@ -1374,11 +1441,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir); } - private static void extractNativeLibraries(File packageDir, String abiOverride) + private static void extractNativeLibraries(File packageDir, String abiOverride, boolean inherit) throws PackageManagerException { - // Always start from a clean slate final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME); - NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true); + if (!inherit) { + // Start from a clean slate + NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true); + } NativeLibraryHelper.Handle handle = null; try { |