blob: 387857f0c99715f7e2e0278fb6b88cf129479d97 [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
25/**
26 * Creates class loaders.
27 *
28 * @hide
29 */
30public class ClassLoaderFactory {
31 // Unconstructable
32 private ClassLoaderFactory() {}
33
34 private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
Calin Juravlef8c14e92017-07-24 17:56:51 -070035 private static final String DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName();
Narayan Kamathf9419f02017-06-15 11:35:38 +010036 private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
37 DelegateLastClassLoader.class.getName();
38
39 /**
40 * Returns true if {@code name} is a supported classloader. {@code name} must be a
41 * binary name of a class, as defined by {@code Class.getName}.
42 */
43 public static boolean isValidClassLoaderName(String name) {
Calin Juravle19da1cf2017-07-12 18:52:49 -070044 // This method is used to parse package data and does not accept null names.
45 return name != null && (isPathClassLoaderName(name) || isDelegateLastClassLoaderName(name));
46 }
47
48 /**
Calin Juravlef8c14e92017-07-24 17:56:51 -070049 * Returns true if {@code name} is the encoding for either PathClassLoader or DexClassLoader.
50 * The two class loaders are grouped together because they have the same behaviour.
Calin Juravle19da1cf2017-07-12 18:52:49 -070051 */
52 public static boolean isPathClassLoaderName(String name) {
53 // For null values we default to PathClassLoader. This cover the case when packages
54 // don't specify any value for their class loaders.
Calin Juravlef8c14e92017-07-24 17:56:51 -070055 return name == null || PATH_CLASS_LOADER_NAME.equals(name) ||
56 DEX_CLASS_LOADER_NAME.equals(name);
Calin Juravle19da1cf2017-07-12 18:52:49 -070057 }
58
59 /**
60 * Returns true if {@code name} is the encoding for the DelegateLastClassLoader.
61 */
62 public static boolean isDelegateLastClassLoaderName(String name) {
63 return DELEGATE_LAST_CLASS_LOADER_NAME.equals(name);
Narayan Kamathf9419f02017-06-15 11:35:38 +010064 }
65
66 /**
67 * Same as {@code createClassLoader} below, except that no associated namespace
68 * is created.
69 */
70 public static ClassLoader createClassLoader(String dexPath,
71 String librarySearchPath, ClassLoader parent, String classloaderName) {
Calin Juravle19da1cf2017-07-12 18:52:49 -070072 if (isPathClassLoaderName(classloaderName)) {
Narayan Kamathf9419f02017-06-15 11:35:38 +010073 return new PathClassLoader(dexPath, librarySearchPath, parent);
Narayan Kamath590b90f2017-08-10 12:09:13 +010074 } else if (isDelegateLastClassLoaderName(classloaderName)) {
Narayan Kamathf9419f02017-06-15 11:35:38 +010075 return new DelegateLastClassLoader(dexPath, librarySearchPath, parent);
76 }
77
78 throw new AssertionError("Invalid classLoaderName: " + classloaderName);
79 }
80
81 /**
82 * Create a ClassLoader and initialize a linker-namespace for it.
83 */
84 public static ClassLoader createClassLoader(String dexPath,
85 String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
86 int targetSdkVersion, boolean isNamespaceShared, String classloaderName) {
87
88 final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
89 classloaderName);
90
Jiyong Parkfcad6962017-08-22 10:24:28 +090091 boolean isForVendor = false;
92 for (String path : dexPath.split(":")) {
93 if (path.startsWith("/vendor/")) {
94 isForVendor = true;
95 break;
96 }
97 }
Narayan Kamathf9419f02017-06-15 11:35:38 +010098 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
99 String errorMessage = createClassloaderNamespace(classLoader,
100 targetSdkVersion,
101 librarySearchPath,
102 libraryPermittedPath,
Jiyong Parkfcad6962017-08-22 10:24:28 +0900103 isNamespaceShared,
104 isForVendor);
Narayan Kamathf9419f02017-06-15 11:35:38 +0100105 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
106
107 if (errorMessage != null) {
108 throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
109 classLoader + ": " + errorMessage);
110 }
111
112 return classLoader;
113 }
114
115 private static native String createClassloaderNamespace(ClassLoader classLoader,
116 int targetSdkVersion,
117 String librarySearchPath,
118 String libraryPermittedPath,
Jiyong Parkfcad6962017-08-22 10:24:28 +0900119 boolean isNamespaceShared,
120 boolean isForVendor);
Narayan Kamathf9419f02017-06-15 11:35:38 +0100121}