blob: d32349834dd8e46f36343c6d0835d97f45cae59f [file] [log] [blame]
/*
* 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.annotation.UnsupportedAppUsage;
import android.os.Trace;
import dalvik.system.DelegateLastClassLoader;
import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;
import java.util.List;
/**
* 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 DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName();
private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
DelegateLastClassLoader.class.getName();
/**
* Returns the name of the class for PathClassLoader.
*/
public static String getPathClassLoaderName() {
return PATH_CLASS_LOADER_NAME;
}
/**
* 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) {
// This method is used to parse package data and does not accept null names.
return name != null && (isPathClassLoaderName(name) || isDelegateLastClassLoaderName(name));
}
/**
* Returns true if {@code name} is the encoding for either PathClassLoader or DexClassLoader.
* The two class loaders are grouped together because they have the same behaviour.
*/
public static boolean isPathClassLoaderName(String name) {
// For null values we default to PathClassLoader. This cover the case when packages
// don't specify any value for their class loaders.
return name == null || PATH_CLASS_LOADER_NAME.equals(name) ||
DEX_CLASS_LOADER_NAME.equals(name);
}
/**
* Returns true if {@code name} is the encoding for the DelegateLastClassLoader.
*/
public static boolean isDelegateLastClassLoaderName(String name) {
return 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,
List<ClassLoader> sharedLibraries) {
ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
? null
: sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
if (isPathClassLoaderName(classloaderName)) {
return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries);
} else if (isDelegateLastClassLoaderName(classloaderName)) {
return new DelegateLastClassLoader(dexPath, librarySearchPath, parent,
arrayOfSharedLibraries);
}
throw new AssertionError("Invalid classLoaderName: " + classloaderName);
}
/**
* Same as {@code createClassLoader} below, but passes a null list of shared
* libraries.
*/
public static ClassLoader createClassLoader(String dexPath,
String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
parent, targetSdkVersion, isNamespaceShared, classLoaderName, null);
}
/**
* 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,
List<ClassLoader> sharedLibraries) {
final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
classLoaderName, sharedLibraries);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
String errorMessage = createClassloaderNamespace(classLoader,
targetSdkVersion,
librarySearchPath,
libraryPermittedPath,
isNamespaceShared,
dexPath);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (errorMessage != null) {
throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
classLoader + ": " + errorMessage);
}
return classLoader;
}
@UnsupportedAppUsage
private static native String createClassloaderNamespace(ClassLoader classLoader,
int targetSdkVersion,
String librarySearchPath,
String libraryPermittedPath,
boolean isNamespaceShared,
String dexPath);
}