blob: c5bc45afee95b56c2384007cabb04e50827854cc [file] [log] [blame]
Narayan Kamathf9419f02017-06-15 11:35:38 +01001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.os;
18
19import android.os.Trace;
20
21import dalvik.system.DelegateLastClassLoader;
Calin Juravlef8c14e92017-07-24 17:56:51 -070022import dalvik.system.DexClassLoader;
Narayan Kamathf9419f02017-06-15 11:35:38 +010023import dalvik.system.PathClassLoader;
24
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000025import java.util.List;
26
Narayan Kamathf9419f02017-06-15 11:35:38 +010027/**
28 * Creates class loaders.
29 *
30 * @hide
31 */
32public class ClassLoaderFactory {
33 // Unconstructable
34 private ClassLoaderFactory() {}
35
36 private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
Calin Juravlef8c14e92017-07-24 17:56:51 -070037 private static final String DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName();
Narayan Kamathf9419f02017-06-15 11:35:38 +010038 private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
39 DelegateLastClassLoader.class.getName();
40
41 /**
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000042 * Returns the name of the class for PathClassLoader.
43 */
44 public static String getPathClassLoaderName() {
45 return PATH_CLASS_LOADER_NAME;
46 }
47
48 /**
Narayan Kamathf9419f02017-06-15 11:35:38 +010049 * Returns true if {@code name} is a supported classloader. {@code name} must be a
50 * binary name of a class, as defined by {@code Class.getName}.
51 */
52 public static boolean isValidClassLoaderName(String name) {
Calin Juravle19da1cf2017-07-12 18:52:49 -070053 // This method is used to parse package data and does not accept null names.
54 return name != null && (isPathClassLoaderName(name) || isDelegateLastClassLoaderName(name));
55 }
56
57 /**
Calin Juravlef8c14e92017-07-24 17:56:51 -070058 * Returns true if {@code name} is the encoding for either PathClassLoader or DexClassLoader.
59 * The two class loaders are grouped together because they have the same behaviour.
Calin Juravle19da1cf2017-07-12 18:52:49 -070060 */
61 public static boolean isPathClassLoaderName(String name) {
62 // For null values we default to PathClassLoader. This cover the case when packages
63 // don't specify any value for their class loaders.
Calin Juravlef8c14e92017-07-24 17:56:51 -070064 return name == null || PATH_CLASS_LOADER_NAME.equals(name) ||
65 DEX_CLASS_LOADER_NAME.equals(name);
Calin Juravle19da1cf2017-07-12 18:52:49 -070066 }
67
68 /**
69 * Returns true if {@code name} is the encoding for the DelegateLastClassLoader.
70 */
71 public static boolean isDelegateLastClassLoaderName(String name) {
72 return DELEGATE_LAST_CLASS_LOADER_NAME.equals(name);
Narayan Kamathf9419f02017-06-15 11:35:38 +010073 }
74
75 /**
76 * Same as {@code createClassLoader} below, except that no associated namespace
77 * is created.
78 */
79 public static ClassLoader createClassLoader(String dexPath,
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000080 String librarySearchPath, ClassLoader parent, String classloaderName,
81 List<ClassLoader> sharedLibraries) {
82 ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
83 ? null
84 : sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
Calin Juravle19da1cf2017-07-12 18:52:49 -070085 if (isPathClassLoaderName(classloaderName)) {
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000086 return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries);
Narayan Kamath590b90f2017-08-10 12:09:13 +010087 } else if (isDelegateLastClassLoaderName(classloaderName)) {
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000088 return new DelegateLastClassLoader(dexPath, librarySearchPath, parent,
89 arrayOfSharedLibraries);
Narayan Kamathf9419f02017-06-15 11:35:38 +010090 }
91
92 throw new AssertionError("Invalid classLoaderName: " + classloaderName);
93 }
94
95 /**
Nicolas Geoffray972b39e2018-11-15 12:59:52 +000096 * Same as {@code createClassLoader} below, but passes a null list of shared
97 * libraries.
98 */
99 public static ClassLoader createClassLoader(String dexPath,
100 String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
101 int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
102 return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
103 parent, targetSdkVersion, isNamespaceShared, classLoaderName, null);
104 }
105
106
107 /**
Narayan Kamathf9419f02017-06-15 11:35:38 +0100108 * Create a ClassLoader and initialize a linker-namespace for it.
109 */
110 public static ClassLoader createClassLoader(String dexPath,
111 String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
Nicolas Geoffray972b39e2018-11-15 12:59:52 +0000112 int targetSdkVersion, boolean isNamespaceShared, String classLoaderName,
113 List<ClassLoader> sharedLibraries) {
Narayan Kamathf9419f02017-06-15 11:35:38 +0100114
115 final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
Nicolas Geoffray972b39e2018-11-15 12:59:52 +0000116 classLoaderName, sharedLibraries);
Narayan Kamathf9419f02017-06-15 11:35:38 +0100117
Jiyong Parkfcad6962017-08-22 10:24:28 +0900118 boolean isForVendor = false;
119 for (String path : dexPath.split(":")) {
120 if (path.startsWith("/vendor/")) {
121 isForVendor = true;
122 break;
123 }
124 }
Narayan Kamathf9419f02017-06-15 11:35:38 +0100125 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
126 String errorMessage = createClassloaderNamespace(classLoader,
127 targetSdkVersion,
128 librarySearchPath,
129 libraryPermittedPath,
Jiyong Parkfcad6962017-08-22 10:24:28 +0900130 isNamespaceShared,
131 isForVendor);
Narayan Kamathf9419f02017-06-15 11:35:38 +0100132 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
133
134 if (errorMessage != null) {
135 throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
136 classLoader + ": " + errorMessage);
137 }
138
139 return classLoader;
140 }
141
142 private static native String createClassloaderNamespace(ClassLoader classLoader,
143 int targetSdkVersion,
144 String librarySearchPath,
145 String libraryPermittedPath,
Jiyong Parkfcad6962017-08-22 10:24:28 +0900146 boolean isNamespaceShared,
147 boolean isForVendor);
Narayan Kamathf9419f02017-06-15 11:35:38 +0100148}