Allow splits to declare a classloader type.

Add an attribute android:classLoader which can be set to the name
of the classloader the base or split wishes to use. For now, this can
only be set to "dalvik.system.PathClassLoader" or
"dalvik.system.DelegateLastClassLoader". The current implementation
only allows the classloader to exist in the boot classpath but that
restriction can be loosened in a future change if necessary.

Test: cts-tradefed run cts-dev -m CtsAppSecurityHostTestCases
Bug: 36044779

Change-Id: I5a51f7aa0c8c4c398d2f46129eb06785cc8e3c3f
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 2062930..b7c1f4e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -18,9 +18,8 @@
 
 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 @@
 
     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 @@
 
                 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 @@
         // 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 @@
         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 79e5407..b38be66 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -97,7 +97,6 @@
     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 @@
     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 @@
     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
         = new ArrayMap<>();
 
-    int mClientCount = 0;
-
     Application getApplication() {
         return mApplication;
     }
@@ -192,8 +190,8 @@
         mResDir = null;
         mSplitAppDirs = null;
         mSplitResDirs = null;
+        mSplitClassLoaderNames = null;
         mOverlayDirs = null;
-        mSharedLibraries = null;
         mDataDir = null;
         mDataDirFile = null;
         mDeviceProtectedDataDirFile = null;
@@ -324,7 +322,6 @@
         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 @@
         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 @@
             // 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 @@
             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 @@
 
             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 06f7916..0bfe567 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1005,6 +1005,12 @@
         }
     }
 
+    /** @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 @@
                 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 @@
         networkSecurityConfigRes = orig.networkSecurityConfigRes;
         category = orig.category;
         targetSandboxVersion = orig.targetSandboxVersion;
+        classLoaderName = orig.classLoaderName;
+        splitClassLoaderNames = orig.splitClassLoaderNames;
     }
 
     public String toString() {
@@ -1246,6 +1261,8 @@
         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 @@
         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 e4f2fc1..eb6e0d8 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -88,6 +88,7 @@
 
 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 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 @@
             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 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 @@
             this.use32bitAbi = use32bitAbi;
             this.extractNativeLibs = extractNativeLibs;
             this.isolatedSplits = isolatedSplits;
+            this.classLoaderName = classLoaderName;
         }
     }
 
@@ -863,7 +872,7 @@
         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 @@
         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 @@
             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 @@
                 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 @@
                 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 @@
             }
 
             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 @@
     }
 
     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 @@
         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 @@
                     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 @@
         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 0000000..0c041f2
--- /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 06a93b2..0000000
--- 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 385976c..77cd984 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.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 @@
      * 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");
+    static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
+        String libraryPath = System.getProperty("java.library.path");
 
-      return PathClassLoaderFactory.createClassLoader(classPath,
-                                                      libraryPath,
-                                                      libraryPath,
-                                                      ClassLoader.getSystemClassLoader(),
-                                                      targetSdkVersion,
-                                                      true /* isNamespaceShared */);
+        return ClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath,
+                ClassLoader.getSystemClassLoader(), targetSdkVersion, true /* isNamespaceShared */,
+                null /* classLoaderName */);
     }
 
     /**