1 /* 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 17 package com.android.internal.os; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.os.Trace; 21 22 import dalvik.system.DelegateLastClassLoader; 23 import dalvik.system.DexClassLoader; 24 import dalvik.system.PathClassLoader; 25 26 import java.util.List; 27 28 /** 29 * Creates class loaders. 30 * 31 * @hide 32 */ 33 public class ClassLoaderFactory { 34 // Unconstructable ClassLoaderFactory()35 private ClassLoaderFactory() {} 36 37 private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName(); 38 private static final String DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName(); 39 private static final String DELEGATE_LAST_CLASS_LOADER_NAME = 40 DelegateLastClassLoader.class.getName(); 41 42 /** 43 * Returns the name of the class for PathClassLoader. 44 */ getPathClassLoaderName()45 public static String getPathClassLoaderName() { 46 return PATH_CLASS_LOADER_NAME; 47 } 48 49 /** 50 * Returns true if {@code name} is a supported classloader. {@code name} must be a 51 * binary name of a class, as defined by {@code Class.getName}. 52 */ isValidClassLoaderName(String name)53 public static boolean isValidClassLoaderName(String name) { 54 // This method is used to parse package data and does not accept null names. 55 return name != null && (isPathClassLoaderName(name) || isDelegateLastClassLoaderName(name)); 56 } 57 58 /** 59 * Returns true if {@code name} is the encoding for either PathClassLoader or DexClassLoader. 60 * The two class loaders are grouped together because they have the same behaviour. 61 */ isPathClassLoaderName(String name)62 public static boolean isPathClassLoaderName(String name) { 63 // For null values we default to PathClassLoader. This cover the case when packages 64 // don't specify any value for their class loaders. 65 return name == null || PATH_CLASS_LOADER_NAME.equals(name) || 66 DEX_CLASS_LOADER_NAME.equals(name); 67 } 68 69 /** 70 * Returns true if {@code name} is the encoding for the DelegateLastClassLoader. 71 */ isDelegateLastClassLoaderName(String name)72 public static boolean isDelegateLastClassLoaderName(String name) { 73 return DELEGATE_LAST_CLASS_LOADER_NAME.equals(name); 74 } 75 76 /** 77 * Same as {@code createClassLoader} below, except that no associated namespace 78 * is created. 79 */ createClassLoader(String dexPath, String librarySearchPath, ClassLoader parent, String classloaderName, List<ClassLoader> sharedLibraries)80 public static ClassLoader createClassLoader(String dexPath, 81 String librarySearchPath, ClassLoader parent, String classloaderName, 82 List<ClassLoader> sharedLibraries) { 83 ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null) 84 ? null 85 : sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]); 86 if (isPathClassLoaderName(classloaderName)) { 87 return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries); 88 } else if (isDelegateLastClassLoaderName(classloaderName)) { 89 return new DelegateLastClassLoader(dexPath, librarySearchPath, parent, 90 arrayOfSharedLibraries); 91 } 92 93 throw new AssertionError("Invalid classLoaderName: " + classloaderName); 94 } 95 96 /** 97 * Same as {@code createClassLoader} below, but passes a null list of shared 98 * libraries. 99 */ createClassLoader(String dexPath, String librarySearchPath, String libraryPermittedPath, ClassLoader parent, int targetSdkVersion, boolean isNamespaceShared, String classLoaderName)100 public static ClassLoader createClassLoader(String dexPath, 101 String librarySearchPath, String libraryPermittedPath, ClassLoader parent, 102 int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) { 103 return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath, 104 parent, targetSdkVersion, isNamespaceShared, classLoaderName, null); 105 } 106 107 108 /** 109 * Create a ClassLoader and initialize a linker-namespace for it. 110 */ createClassLoader(String dexPath, String librarySearchPath, String libraryPermittedPath, ClassLoader parent, int targetSdkVersion, boolean isNamespaceShared, String classLoaderName, List<ClassLoader> sharedLibraries)111 public static ClassLoader createClassLoader(String dexPath, 112 String librarySearchPath, String libraryPermittedPath, ClassLoader parent, 113 int targetSdkVersion, boolean isNamespaceShared, String classLoaderName, 114 List<ClassLoader> sharedLibraries) { 115 116 final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent, 117 classLoaderName, sharedLibraries); 118 119 // TODO(b/142191088) merge 6a5b8b1f6db172b5aaadcec0c3868e54e214b675 120 String sonameList = "ALL"; 121 122 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace"); 123 String errorMessage = createClassloaderNamespace(classLoader, 124 targetSdkVersion, 125 librarySearchPath, 126 libraryPermittedPath, 127 isNamespaceShared, 128 dexPath, 129 sonameList); 130 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 131 132 if (errorMessage != null) { 133 throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " + 134 classLoader + ": " + errorMessage); 135 } 136 137 return classLoader; 138 } 139 140 @UnsupportedAppUsage createClassloaderNamespace(ClassLoader classLoader, int targetSdkVersion, String librarySearchPath, String libraryPermittedPath, boolean isNamespaceShared, String dexPath, String sonameList)141 private static native String createClassloaderNamespace(ClassLoader classLoader, 142 int targetSdkVersion, 143 String librarySearchPath, 144 String libraryPermittedPath, 145 boolean isNamespaceShared, 146 String dexPath, 147 String sonameList); 148 } 149