Home | History | Annotate | Download | only in os
      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.os.Trace;
     20 
     21 import dalvik.system.DelegateLastClassLoader;
     22 import dalvik.system.DexClassLoader;
     23 import dalvik.system.PathClassLoader;
     24 
     25 /**
     26  * Creates class loaders.
     27  *
     28  * @hide
     29  */
     30 public class ClassLoaderFactory {
     31     // Unconstructable
     32     private ClassLoaderFactory() {}
     33 
     34     private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
     35     private static final String DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName();
     36     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) {
     44         // 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     /**
     49      * 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.
     51      */
     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.
     55         return name == null || PATH_CLASS_LOADER_NAME.equals(name) ||
     56                 DEX_CLASS_LOADER_NAME.equals(name);
     57     }
     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);
     64     }
     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) {
     72         if (isPathClassLoaderName(classloaderName)) {
     73             return new PathClassLoader(dexPath, librarySearchPath, parent);
     74         } else if (isDelegateLastClassLoaderName(classloaderName)) {
     75             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 
     91         boolean isForVendor = false;
     92         for (String path : dexPath.split(":")) {
     93             if (path.startsWith("/vendor/")) {
     94                 isForVendor = true;
     95                 break;
     96             }
     97         }
     98         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
     99         String errorMessage = createClassloaderNamespace(classLoader,
    100                                                          targetSdkVersion,
    101                                                          librarySearchPath,
    102                                                          libraryPermittedPath,
    103                                                          isNamespaceShared,
    104                                                          isForVendor);
    105         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,
    119                                                             boolean isNamespaceShared,
    120                                                             boolean isForVendor);
    121 }
    122