Merge "In place split install native support" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f4e0438a46
@@ -3709,6 +3709,7 @@ Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
|
|||||||
Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
|
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;-><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;->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;->definingContext:Ljava/lang/ClassLoader;
|
||||||
Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
|
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;
|
Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import com.android.internal.os.ClassLoaderFactory;
|
|||||||
|
|
||||||
import dalvik.system.PathClassLoader;
|
import dalvik.system.PathClassLoader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class ApplicationLoaders {
|
public class ApplicationLoaders {
|
||||||
public static ApplicationLoaders getDefault() {
|
public static ApplicationLoaders getDefault() {
|
||||||
@@ -121,6 +123,17 @@ public class ApplicationLoaders {
|
|||||||
baseDexClassLoader.addDexPath(dexPath);
|
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 final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();
|
||||||
|
|
||||||
private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
|
private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ final class ServiceConnectionLeaked extends AndroidRuntimeException {
|
|||||||
public final class LoadedApk {
|
public final class LoadedApk {
|
||||||
static final String TAG = "LoadedApk";
|
static final String TAG = "LoadedApk";
|
||||||
static final boolean DEBUG = false;
|
static final boolean DEBUG = false;
|
||||||
|
private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths";
|
||||||
|
|
||||||
private final ActivityThread mActivityThread;
|
private final ActivityThread mActivityThread;
|
||||||
final String mPackageName;
|
final String mPackageName;
|
||||||
@@ -723,6 +724,10 @@ public final class LoadedApk {
|
|||||||
needToSetupJitProfiles = true;
|
needToSetupJitProfiles = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) {
|
||||||
|
ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths);
|
||||||
|
}
|
||||||
|
|
||||||
if (addedPaths != null && addedPaths.size() > 0) {
|
if (addedPaths != null && addedPaths.size() > 0) {
|
||||||
final String add = TextUtils.join(File.pathSeparator, addedPaths);
|
final String add = TextUtils.join(File.pathSeparator, addedPaths);
|
||||||
ApplicationLoaders.getDefault().addPath(mClassLoader, add);
|
ApplicationLoaders.getDefault().addPath(mClassLoader, add);
|
||||||
|
|||||||
@@ -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()) {
|
if (!path.isDirectory()) {
|
||||||
path.delete();
|
path.delete();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.server.pm;
|
package com.android.server.pm;
|
||||||
|
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
|
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_CONTAINER_ERROR;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
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.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.RevocableFileDescriptor;
|
import android.os.RevocableFileDescriptor;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
@@ -111,9 +111,9 @@ import java.io.FileDescriptor;
|
|||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
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_NAME = "name";
|
||||||
private static final String ATTR_INSTALL_REASON = "installRason";
|
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_TEST
|
||||||
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
|
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
|
||||||
|
|
||||||
@@ -255,6 +257,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private final List<String> mResolvedInstructionSets = new ArrayList<>();
|
private final List<String> mResolvedInstructionSets = new ArrayList<>();
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
|
private final List<String> mResolvedNativeLibPaths = new ArrayList<>();
|
||||||
|
@GuardedBy("mLock")
|
||||||
private File mInheritedFilesBase;
|
private File mInheritedFilesBase;
|
||||||
|
|
||||||
private static final FileFilter sAddedFilter = new FileFilter() {
|
private static final FileFilter sAddedFilter = new FileFilter() {
|
||||||
@@ -971,6 +975,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
final File oatDir = new File(toDir, "oat");
|
final File oatDir = new File(toDir, "oat");
|
||||||
createOatDirs(mResolvedInstructionSets, oatDir);
|
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);
|
linkFiles(fromFiles, toDir, mInheritedFilesBase);
|
||||||
} else {
|
} else {
|
||||||
// TODO: this should delegate to DCS so the system process
|
// TODO: this should delegate to DCS so the system process
|
||||||
@@ -988,7 +1012,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
computeProgressLocked(true);
|
computeProgressLocked(true);
|
||||||
|
|
||||||
// Unpack native libraries
|
// 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.
|
// We've reached point of no return; call into PMS to install the stage.
|
||||||
// Regardless of success or failure we always destroy session.
|
// Regardless of success or failure we always destroy session.
|
||||||
@@ -1027,6 +1051,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
|
* Validate install by confirming that all application packages are have
|
||||||
* consistent package name, version code, and signing certificates.
|
* consistent package name, version code, and signing certificates.
|
||||||
@@ -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);
|
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 {
|
throws PackageManagerException {
|
||||||
// Always start from a clean slate
|
|
||||||
final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
|
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;
|
NativeLibraryHelper.Handle handle = null;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user