summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java2
-rw-r--r--core/java/android/app/ApplicationLoaders.java35
-rw-r--r--core/java/android/app/LoadedApk.java19
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java19
-rw-r--r--core/java/android/content/pm/PackageParser.java49
-rw-r--r--core/java/com/android/internal/os/ClassLoaderFactory.java92
-rw-r--r--core/java/com/android/internal/os/PathClassLoaderFactory.java66
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java16
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/jni/AndroidRuntime.cpp4
-rw-r--r--core/jni/com_android_internal_os_ClassLoaderFactory.cpp (renamed from core/jni/com_android_internal_os_PathClassLoaderFactory.cpp)6
-rw-r--r--core/res/res/values/attrs_manifest.xml19
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java2
18 files changed, 205 insertions, 132 deletions
diff --git a/api/current.txt b/api/current.txt
index 38bb68be55a9..cfec8d27258c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -388,6 +388,7 @@ package android {
field public static final int childIndicatorRight = 16843024; // 0x1010110
field public static final int childIndicatorStart = 16843731; // 0x10103d3
field public static final int choiceMode = 16843051; // 0x101012b
+ field public static final int classLoader = 16844139; // 0x101056b
field public static final int clearTaskOnLaunch = 16842773; // 0x1010015
field public static final int clickable = 16842981; // 0x10100e5
field public static final int clipChildren = 16842986; // 0x10100ea
diff --git a/api/system-current.txt b/api/system-current.txt
index d98319cc9c79..de632fda8b23 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -511,6 +511,7 @@ package android {
field public static final int childIndicatorRight = 16843024; // 0x1010110
field public static final int childIndicatorStart = 16843731; // 0x10103d3
field public static final int choiceMode = 16843051; // 0x101012b
+ field public static final int classLoader = 16844139; // 0x101056b
field public static final int clearTaskOnLaunch = 16842773; // 0x1010015
field public static final int clickable = 16842981; // 0x10100e5
field public static final int clipChildren = 16842986; // 0x10100ea
diff --git a/api/test-current.txt b/api/test-current.txt
index 94bfe84c88d0..4616c0bd859a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -388,6 +388,7 @@ package android {
field public static final int childIndicatorRight = 16843024; // 0x1010110
field public static final int childIndicatorStart = 16843731; // 0x10103d3
field public static final int choiceMode = 16843051; // 0x101012b
+ field public static final int classLoader = 16844139; // 0x101056b
field public static final int clearTaskOnLaunch = 16842773; // 0x1010015
field public static final int clickable = 16842981; // 0x10100e5
field public static final int clipChildren = 16842986; // 0x10100ea
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ad989dee7b55..f0189c240a85 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -414,7 +414,7 @@ public final class Pm {
try {
ApkLite baseApk = PackageParser.parseApkLite(file, 0);
PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
- null, null);
+ null, null, null);
params.sessionParams.setSize(
PackageHelper.calculateInstalledSize(pkgLite, false,
params.sessionParams.abiOverride));
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 2062930929a2..b7c1f4e082e2 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -18,9 +18,8 @@ package android.app;
import android.os.Build;
import android.os.Trace;
-import android.text.TextUtils;
import android.util.ArrayMap;
-import com.android.internal.os.PathClassLoaderFactory;
+import com.android.internal.os.ClassLoaderFactory;
import dalvik.system.PathClassLoader;
/** @hide */
@@ -31,15 +30,16 @@ public class ApplicationLoaders {
ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
- ClassLoader parent) {
+ ClassLoader parent, String classLoaderName) {
// For normal usage the cache key used is the same as the zip path.
return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
- libraryPermittedPath, parent, zip);
+ libraryPermittedPath, parent, zip, classLoaderName);
}
private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
- ClassLoader parent, String cacheKey) {
+ ClassLoader parent, String cacheKey,
+ String classLoaderName) {
/*
* This is the parent we use if they pass "null" in. In theory
* this should be the "system" class loader; in practice we
@@ -66,28 +66,25 @@ public class ApplicationLoaders {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
- PathClassLoader pathClassloader = PathClassLoaderFactory.createClassLoader(
- zip,
- librarySearchPath,
- libraryPermittedPath,
- parent,
- targetSdkVersion,
- isBundled);
+ ClassLoader classloader = ClassLoaderFactory.createClassLoader(
+ zip, librarySearchPath, libraryPermittedPath, parent,
+ targetSdkVersion, isBundled, classLoaderName);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupVulkanLayerPath");
- setupVulkanLayerPath(pathClassloader, librarySearchPath);
+ setupVulkanLayerPath(classloader, librarySearchPath);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- mLoaders.put(cacheKey, pathClassloader);
- return pathClassloader;
+ mLoaders.put(cacheKey, classloader);
+ return classloader;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
- PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
+ ClassLoader loader = ClassLoaderFactory.createClassLoader(
+ zip, null, parent, classLoaderName);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- return pathClassloader;
+ return loader;
}
}
@@ -105,7 +102,7 @@ public class ApplicationLoaders {
// The cache key is passed separately to enable the stub WebView to be cached under the
// stub's APK path, when the actual package path is the donor APK.
return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
- cacheKey);
+ cacheKey, null /* classLoaderName */);
}
private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath);
@@ -122,7 +119,7 @@ public class ApplicationLoaders {
baseDexClassLoader.addDexPath(dexPath);
}
- private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<String, ClassLoader>();
+ 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 79e5407a17d3..b38be6626e50 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -97,7 +97,6 @@ public final class LoadedApk {
private String mAppDir;
private String mResDir;
private String[] mOverlayDirs;
- private String[] mSharedLibraries;
private String mDataDir;
private String mLibDir;
private File mDataDirFile;
@@ -116,6 +115,7 @@ public final class LoadedApk {
private String[] mSplitNames;
private String[] mSplitAppDirs;
private String[] mSplitResDirs;
+ private String[] mSplitClassLoaderNames;
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<>();
@@ -126,8 +126,6 @@ public final class LoadedApk {
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
= new ArrayMap<>();
- int mClientCount = 0;
-
Application getApplication() {
return mApplication;
}
@@ -192,8 +190,8 @@ public final class LoadedApk {
mResDir = null;
mSplitAppDirs = null;
mSplitResDirs = null;
+ mSplitClassLoaderNames = null;
mOverlayDirs = null;
- mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
mDeviceProtectedDataDirFile = null;
@@ -324,7 +322,6 @@ public final class LoadedApk {
mAppDir = aInfo.sourceDir;
mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
mOverlayDirs = aInfo.resourceDirs;
- mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
mLibDir = aInfo.nativeLibraryDir;
mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
@@ -334,6 +331,7 @@ public final class LoadedApk {
mSplitNames = aInfo.splitNames;
mSplitAppDirs = aInfo.splitSourceDirs;
mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
+ mSplitClassLoaderNames = aInfo.splitClassLoaderNames;
if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
@@ -530,7 +528,8 @@ public final class LoadedApk {
// Since we handled the special base case above, parentSplitIdx is always valid.
final ClassLoader parent = mCachedClassLoaders[parentSplitIdx];
mCachedClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader(
- mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, null, parent);
+ mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, null, parent,
+ mSplitClassLoaderNames[splitIdx - 1]);
Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]);
splitPaths.add(mSplitResDirs[splitIdx - 1]);
@@ -650,8 +649,9 @@ public final class LoadedApk {
if (mClassLoader == null) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
- "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
- librarySearchPath, libraryPermittedPath, mBaseClassLoader);
+ "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
+ librarySearchPath, libraryPermittedPath, mBaseClassLoader,
+ null /* classLoaderName */);
StrictMode.setThreadPolicy(oldPolicy);
}
@@ -678,7 +678,8 @@ public final class LoadedApk {
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
- libraryPermittedPath, mBaseClassLoader);
+ libraryPermittedPath, mBaseClassLoader,
+ mApplicationInfo.classLoaderName);
StrictMode.setThreadPolicy(oldPolicy);
// Setup the class loader paths for profiling.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 06f7916be4b6..0bfe56797d22 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1005,6 +1005,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
}
}
+ /** @hide */
+ public String classLoaderName;
+
+ /** @hide */
+ public String[] splitClassLoaderNames;
+
public void dump(Printer pw, String prefix) {
dump(pw, prefix, DUMP_FLAG_ALL);
}
@@ -1056,6 +1062,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
}
}
+ if (classLoaderName != null) {
+ pw.println(prefix + "classLoaderName=" + classLoaderName);
+ }
+ if (!ArrayUtils.isEmpty(splitClassLoaderNames)) {
+ pw.println(prefix + "splitClassLoaderNames=" + Arrays.toString(splitClassLoaderNames));
+ }
+
pw.println(prefix + "enabled=" + enabled
+ " minSdkVersion=" + minSdkVersion
+ " targetSdkVersion=" + targetSdkVersion
@@ -1178,6 +1191,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
networkSecurityConfigRes = orig.networkSecurityConfigRes;
category = orig.category;
targetSandboxVersion = orig.targetSandboxVersion;
+ classLoaderName = orig.classLoaderName;
+ splitClassLoaderNames = orig.splitClassLoaderNames;
}
public String toString() {
@@ -1246,6 +1261,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(networkSecurityConfigRes);
dest.writeInt(category);
dest.writeInt(targetSandboxVersion);
+ dest.writeString(classLoaderName);
+ dest.writeStringArray(splitClassLoaderNames);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1311,6 +1328,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
networkSecurityConfigRes = source.readInt();
category = source.readInt();
targetSandboxVersion = source.readInt();
+ classLoaderName = source.readString();
+ splitClassLoaderNames = source.readStringArray();
}
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e4f2fc1c5035..eb6e0d8bd4de 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -88,6 +88,7 @@ import android.view.Gravity;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
@@ -415,9 +416,12 @@ public class PackageParser {
public final boolean extractNativeLibs;
public final boolean isolatedSplits;
+ public final String classLoaderName;
+ public final String[] splitClassLoaderNames;
+
public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
- String[] splitCodePaths, int[] splitRevisionCodes) {
+ String[] splitCodePaths, int[] splitRevisionCodes, String[] splitClassLoaderNames) {
this.packageName = baseApk.packageName;
this.versionCode = baseApk.versionCode;
this.installLocation = baseApk.installLocation;
@@ -437,6 +441,9 @@ public class PackageParser {
this.use32bitAbi = baseApk.use32bitAbi;
this.extractNativeLibs = baseApk.extractNativeLibs;
this.isolatedSplits = baseApk.isolatedSplits;
+
+ this.classLoaderName = baseApk.classLoaderName;
+ this.splitClassLoaderNames = splitClassLoaderNames;
}
public List<String> getAllCodePaths() {
@@ -471,13 +478,14 @@ public class PackageParser {
public final boolean use32bitAbi;
public final boolean extractNativeLibs;
public final boolean isolatedSplits;
+ public final String classLoaderName;
public ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit,
String configForSplit, String usesSplitName, int versionCode, int revisionCode,
int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
Certificate[][] certificates, boolean coreApp, boolean debuggable,
boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs,
- boolean isolatedSplits) {
+ boolean isolatedSplits, String classLoaderName) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -496,6 +504,7 @@ public class PackageParser {
this.use32bitAbi = use32bitAbi;
this.extractNativeLibs = extractNativeLibs;
this.isolatedSplits = isolatedSplits;
+ this.classLoaderName = classLoaderName;
}
}
@@ -863,7 +872,7 @@ public class PackageParser {
final ApkLite baseApk = parseApkLite(packageFile, flags);
final String packagePath = packageFile.getAbsolutePath();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
+ return new PackageLite(packagePath, baseApk, null, null, null, null, null, null, null);
}
static PackageLite parseClusterPackageLite(File packageDir, int flags)
@@ -926,6 +935,7 @@ public class PackageParser {
String[] configForSplits = null;
String[] splitCodePaths = null;
int[] splitRevisionCodes = null;
+ String[] splitClassLoaderNames = null;
if (size > 0) {
splitNames = new String[size];
isFeatureSplits = new boolean[size];
@@ -933,6 +943,7 @@ public class PackageParser {
configForSplits = new String[size];
splitCodePaths = new String[size];
splitRevisionCodes = new int[size];
+ splitClassLoaderNames = new String[size];
splitNames = apks.keySet().toArray(splitNames);
Arrays.sort(splitNames, sSplitNameComparator);
@@ -944,12 +955,13 @@ public class PackageParser {
configForSplits[i] = apk.configForSplit;
splitCodePaths[i] = apk.codePath;
splitRevisionCodes[i] = apk.revisionCode;
+ splitClassLoaderNames[i] = apk.classLoaderName;
}
}
final String codePath = packageDir.getAbsolutePath();
return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
- configForSplits, splitCodePaths, splitRevisionCodes);
+ configForSplits, splitCodePaths, splitRevisionCodes, splitClassLoaderNames);
}
/**
@@ -1187,6 +1199,8 @@ public class PackageParser {
pkg.splitPrivateFlags = new int[num];
pkg.applicationInfo.splitNames = pkg.splitNames;
pkg.applicationInfo.splitDependencies = splitDependencies;
+ pkg.applicationInfo.classLoaderName = lite.classLoaderName;
+ pkg.applicationInfo.splitClassLoaderNames = lite.splitClassLoaderNames;
for (int i = 0; i < num; i++) {
final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
@@ -1697,7 +1711,7 @@ public class PackageParser {
}
final AttributeSet attrs = parser;
- return parseApkLite(apkPath, parser, attrs, flags, signatures, certificates);
+ return parseApkLite(apkPath, parser, attrs, signatures, certificates);
} catch (XmlPullParserException | IOException | RuntimeException e) {
Slog.w(TAG, "Failed to parse " + apkPath, e);
@@ -1784,7 +1798,7 @@ public class PackageParser {
}
private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
- int flags, Signature[] signatures, Certificate[][] certificates)
+ Signature[] signatures, Certificate[][] certificates)
throws IOException, XmlPullParserException, PackageParserException {
final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
@@ -1800,6 +1814,7 @@ public class PackageParser {
boolean isFeatureSplit = false;
String configForSplit = null;
String usesSplitName = null;
+ String classLoaderName = null;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String attr = attrs.getAttributeName(i);
@@ -1856,6 +1871,14 @@ public class PackageParser {
if ("extractNativeLibs".equals(attr)) {
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
}
+ if ("classLoader".equals(attr)) {
+ classLoaderName = attrs.getAttributeValue(i);
+ if (!ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
+ throw new PackageParserException(
+ PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "Invalid class loader name: " + classLoaderName);
+ }
+ }
}
} else if (TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
@@ -1875,19 +1898,7 @@ public class PackageParser {
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, versionCode, revisionCode, installLocation,
verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi,
- extractNativeLibs, isolatedSplits);
- }
-
- /**
- * Temporary.
- */
- static public Signature stringToSignature(String str) {
- final int N = str.length();
- byte[] sig = new byte[N];
- for (int i=0; i<N; i++) {
- sig[i] = (byte)str.charAt(i);
- }
- return new Signature(sig);
+ extractNativeLibs, isolatedSplits, classLoaderName);
}
/**
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
new file mode 100644
index 000000000000..0c041f24b28d
--- /dev/null
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Trace;
+
+import dalvik.system.DelegateLastClassLoader;
+import dalvik.system.PathClassLoader;
+
+/**
+ * Creates class loaders.
+ *
+ * @hide
+ */
+public class ClassLoaderFactory {
+ // Unconstructable
+ private ClassLoaderFactory() {}
+
+ private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
+ private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
+ DelegateLastClassLoader.class.getName();
+
+ /**
+ * Returns true if {@code name} is a supported classloader. {@code name} must be a
+ * binary name of a class, as defined by {@code Class.getName}.
+ */
+ public static boolean isValidClassLoaderName(String name) {
+ return PATH_CLASS_LOADER_NAME.equals(name) ||
+ DELEGATE_LAST_CLASS_LOADER_NAME.equals(name);
+ }
+
+ /**
+ * Same as {@code createClassLoader} below, except that no associated namespace
+ * is created.
+ */
+ public static ClassLoader createClassLoader(String dexPath,
+ String librarySearchPath, ClassLoader parent, String classloaderName) {
+ if (classloaderName == null || PATH_CLASS_LOADER_NAME.equals(classloaderName)) {
+ return new PathClassLoader(dexPath, librarySearchPath, parent);
+ } else if (DELEGATE_LAST_CLASS_LOADER_NAME.equals(classloaderName)) {
+ return new DelegateLastClassLoader(dexPath, librarySearchPath, parent);
+ }
+
+ throw new AssertionError("Invalid classLoaderName: " + classloaderName);
+ }
+
+ /**
+ * Create a ClassLoader and initialize a linker-namespace for it.
+ */
+ public static ClassLoader createClassLoader(String dexPath,
+ String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
+ int targetSdkVersion, boolean isNamespaceShared, String classloaderName) {
+
+ final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
+ classloaderName);
+
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
+ String errorMessage = createClassloaderNamespace(classLoader,
+ targetSdkVersion,
+ librarySearchPath,
+ libraryPermittedPath,
+ isNamespaceShared);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ if (errorMessage != null) {
+ throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
+ classLoader + ": " + errorMessage);
+ }
+
+ return classLoader;
+ }
+
+ private static native String createClassloaderNamespace(ClassLoader classLoader,
+ int targetSdkVersion,
+ String librarySearchPath,
+ String libraryPermittedPath,
+ boolean isNamespaceShared);
+}
diff --git a/core/java/com/android/internal/os/PathClassLoaderFactory.java b/core/java/com/android/internal/os/PathClassLoaderFactory.java
deleted file mode 100644
index 06a93b254bf5..000000000000
--- a/core/java/com/android/internal/os/PathClassLoaderFactory.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.os.Trace;
-
-import dalvik.system.PathClassLoader;
-
-/**
- * Creates path class loaders.
- *
- * @hide
- */
-public class PathClassLoaderFactory {
- // Unconstructable
- private PathClassLoaderFactory() {}
-
- /**
- * Create a PathClassLoader and initialize a linker-namespace for it.
- *
- * @hide
- */
- public static PathClassLoader createClassLoader(String dexPath,
- String librarySearchPath,
- String libraryPermittedPath,
- ClassLoader parent,
- int targetSdkVersion,
- boolean isNamespaceShared) {
- PathClassLoader pathClassloader = new PathClassLoader(dexPath, librarySearchPath, parent);
-
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
- String errorMessage = createClassloaderNamespace(pathClassloader,
- targetSdkVersion,
- librarySearchPath,
- libraryPermittedPath,
- isNamespaceShared);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- if (errorMessage != null) {
- throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
- pathClassloader + ": " + errorMessage);
- }
-
- return pathClassloader;
- }
-
- private static native String createClassloaderNamespace(ClassLoader classLoader,
- int targetSdkVersion,
- String librarySearchPath,
- String libraryPermittedPath,
- boolean isNamespaceShared);
-}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 385976c187ed..77cd984bb4ef 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -24,7 +24,6 @@ import android.content.res.TypedArray;
import android.icu.impl.CacheValue;
import android.icu.text.DecimalFormatSymbols;
import android.icu.util.ULocale;
-import android.net.LocalServerSocket;
import android.opengl.EGL14;
import android.os.Build;
import android.os.IInstalld;
@@ -517,15 +516,12 @@ public class ZygoteInit {
* namespace, i.e., this classloader can access platform-private native libraries. The
* classloader will use java.library.path as the native library path.
*/
- static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
- String libraryPath = System.getProperty("java.library.path");
-
- return PathClassLoaderFactory.createClassLoader(classPath,
- libraryPath,
- libraryPath,
- ClassLoader.getSystemClassLoader(),
- targetSdkVersion,
- true /* isNamespaceShared */);
+ static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
+ String libraryPath = System.getProperty("java.library.path");
+
+ return ClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath,
+ ClassLoader.getSystemClassLoader(), targetSdkVersion, true /* isNamespaceShared */,
+ null /* classLoaderName */);
}
/**
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index c4533c36d0f2..44dfb33effce 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -185,8 +185,8 @@ cc_library_shared {
"android_content_res_Configuration.cpp",
"android_animation_PropertyValuesHolder.cpp",
"com_android_internal_net_NetworkStatsFactory.cpp",
+ "com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
- "com_android_internal_os_PathClassLoaderFactory.cpp",
"com_android_internal_os_Zygote.cpp",
"com_android_internal_util_VirtualRefBasePtr.cpp",
"com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 89e137b7c399..30d4e0276bf0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -203,8 +203,8 @@ extern int register_android_content_res_Configuration(JNIEnv* env);
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
-extern int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
@@ -1402,7 +1402,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_android_os_SharedMemory),
- REG_JNI(register_com_android_internal_os_PathClassLoaderFactory),
+ REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
REG_JNI(register_android_hardware_Camera),
diff --git a/core/jni/com_android_internal_os_PathClassLoaderFactory.cpp b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
index a7a912cd0e05..7052e5f3ce4b 100644
--- a/core/jni/com_android_internal_os_PathClassLoaderFactory.cpp
+++ b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
@@ -39,13 +39,13 @@ static const JNINativeMethod g_methods[] = {
reinterpret_cast<void*>(createClassloaderNamespace_native) },
};
-static const char* const kPathClassLoaderFactoryPathName = "com/android/internal/os/PathClassLoaderFactory";
+static const char* const kClassLoaderFactoryPathName = "com/android/internal/os/ClassLoaderFactory";
namespace android
{
-int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env) {
- return RegisterMethodsOrDie(env, kPathClassLoaderFactoryPathName, g_methods, NELEM(g_methods));
+int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, kClassLoaderFactoryPathName, g_methods, NELEM(g_methods));
}
} // namespace android
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 01b8e1558fb3..33f69b47af36 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1051,6 +1051,22 @@
<p>The default value of this attribute is <code>false</code>. -->
<attr name="isolatedSplits" format="boolean" />
+ <!-- The classname of the classloader used to load the application's classes
+ from its APK. The APK in question can either be the 'base' APK or any
+ of the application's 'split' APKs if it's using a feature split.
+
+ <p>
+ The supported values for this attribute are
+ <code>dalvik.system.PathClassLoader</code> and
+ <code>dalvik.system.DelegateLastClassLoader</code>. If unspecified,
+ the default value of this attribute is <code>dalvik.system.PathClassLoader</code>.
+
+ If an unknown classloader is provided, a PackageParserException with cause
+ <code>PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED</code> will be
+ thrown and the app will not be installed.
+ -->
+ <attr name="classLoader" format="string" />
+
<!-- If set to <code>true</code>, indicates to the platform that this APK is
a 'feature' split and that it implicitly depends on the base APK. This distinguishes
this split APK from a 'configuration' split, which provides resource overrides
@@ -1485,6 +1501,9 @@
<enum name="productivity" value="7" />
</attr>
+ <!-- Declares the kind of classloader this application's classes must be loaded with -->
+ <attr name="classLoader" />
+
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2a4881d6b167..634d79a92a4b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2845,6 +2845,7 @@
<public-group type="attr" first-id="0x01010569">
<public name="showWhenLocked"/>
<public name="turnScreenOn"/>
+ <public name="classLoader" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5c54ba803a05..58237713d793 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -927,7 +927,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// This is kind of hacky; we're creating a half-parsed package that is
// straddled between the inherited and staged APKs.
final PackageLite pkg = new PackageLite(null, baseApk, null, null, null, null,
- splitPaths.toArray(new String[splitPaths.size()]), null);
+ splitPaths.toArray(new String[splitPaths.size()]), null, null);
final boolean isForwardLocked =
(params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 20d7b28c55e1..9765113b7957 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -175,7 +175,7 @@ class PackageManagerShellCommand extends ShellCommand {
try {
ApkLite baseApk = PackageParser.parseApkLite(file, 0);
PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
- null, null);
+ null, null, null);
params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
pkgLite, false, params.sessionParams.abiOverride));
} catch (PackageParserException | IOException e) {