Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ec1b0f9 authored by Steven Moreland's avatar Steven Moreland Committed by android-build-merger
Browse files

Merge "Revert "Revert "Preload non-bootclasspath Java lib ClassLoaders.""" am:...

Merge "Revert "Revert "Preload non-bootclasspath Java lib ClassLoaders.""" am: 4b5ca28d am: 4e709ea3
am: 96724b57

Change-Id: I3de2f4b4fb092d0db5001209d68ea217e150b8da
parents 5a326402 96724b57
Loading
Loading
Loading
Loading
+150 −1
Original line number Original line Diff line number Diff line
@@ -17,20 +17,27 @@
package android.app;
package android.app;


import android.annotation.UnsupportedAppUsage;
import android.annotation.UnsupportedAppUsage;
import android.content.pm.SharedLibraryInfo;
import android.os.Build;
import android.os.Build;
import android.os.GraphicsEnvironment;
import android.os.GraphicsEnvironment;
import android.os.Trace;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.Log;


import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.os.ClassLoaderFactory;


import dalvik.system.PathClassLoader;
import dalvik.system.PathClassLoader;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;


/** @hide */
/** @hide */
public class ApplicationLoaders {
public class ApplicationLoaders {
    private static final String TAG = "ApplicationLoaders";

    @UnsupportedAppUsage
    @UnsupportedAppUsage
    public static ApplicationLoaders getDefault() {
    public static ApplicationLoaders getDefault() {
        return gApplicationLoaders;
        return gApplicationLoaders;
@@ -54,6 +61,26 @@ public class ApplicationLoaders {
                              libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries);
                              libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries);
    }
    }


    /**
     * Gets a class loader for a shared library. Additional dependent shared libraries are allowed
     * to be specified (sharedLibraries).
     *
     * Additionally, as an optimization, this will return a pre-created ClassLoader if one has
     * been cached by createAndCacheNonBootclasspathSystemClassLoaders.
     */
    ClassLoader getSharedLibraryClassLoaderWithSharedLibraries(String zip, int targetSdkVersion,
            boolean isBundled, String librarySearchPath, String libraryPermittedPath,
            ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries) {
        ClassLoader loader = getCachedNonBootclasspathSystemLib(zip, parent, classLoaderName,
                sharedLibraries);
        if (loader != null) {
            return loader;
        }

        return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
              librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries);
    }

    private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
    private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                                       String librarySearchPath, String libraryPermittedPath,
                                       String librarySearchPath, String libraryPermittedPath,
                                       ClassLoader parent, String cacheKey,
                                       ClassLoader parent, String cacheKey,
@@ -95,7 +122,9 @@ public class ApplicationLoaders {
                        classloader, librarySearchPath, libraryPermittedPath);
                        classloader, librarySearchPath, libraryPermittedPath);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);


                if (cacheKey != null) {
                    mLoaders.put(cacheKey, classloader);
                    mLoaders.put(cacheKey, classloader);
                }
                return classloader;
                return classloader;
            }
            }


@@ -107,6 +136,112 @@ public class ApplicationLoaders {
        }
        }
    }
    }


    /**
     * Caches system library class loaders which are not on the bootclasspath but are still used
     * by many system apps.
     *
     * All libraries in the closure of libraries to be loaded must be in libs. A library can
     * only depend on libraries that come before it in the list.
     */
    public void createAndCacheNonBootclasspathSystemClassLoaders(SharedLibraryInfo[] libs) {
        if (mSystemLibsCacheMap != null) {
            Log.wtf(TAG, "Already cached.");
            return;
        }

        mSystemLibsCacheMap = new HashMap<String, CachedClassLoader>();

        for (SharedLibraryInfo lib : libs) {
            createAndCacheNonBootclasspathSystemClassLoader(lib);
        }
    }

    /**
     * Caches a single non-bootclasspath class loader.
     *
     * All of this library's dependencies must have previously been cached.
     */
    private void createAndCacheNonBootclasspathSystemClassLoader(SharedLibraryInfo lib) {
        String path = lib.getPath();
        List<SharedLibraryInfo> dependencies = lib.getDependencies();

        // get cached classloaders for dependencies
        ArrayList<ClassLoader> sharedLibraries = null;
        if (dependencies != null) {
            sharedLibraries = new ArrayList<ClassLoader>(dependencies.size());
            for (SharedLibraryInfo dependency : dependencies) {
                String dependencyPath = dependency.getPath();
                CachedClassLoader cached = mSystemLibsCacheMap.get(dependencyPath);

                if (cached == null) {
                    Log.e(TAG, "Failed to find dependency " + dependencyPath
                            + " of cached library " + path);
                    return;
                }

                sharedLibraries.add(cached.loader);
            }
        }

        // assume cached libraries work with current sdk since they are built-in
        ClassLoader classLoader = getClassLoader(path, Build.VERSION.SDK_INT, true /*isBundled*/,
                null /*librarySearchPath*/, null /*libraryPermittedPath*/, null /*parent*/,
                null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/);

        if (classLoader == null) {
            Log.e(TAG, "Failed to cache " + path);
            return;
        }

        CachedClassLoader cached = new CachedClassLoader();
        cached.loader = classLoader;
        cached.sharedLibraries = sharedLibraries;

        Log.d(TAG, "Created zygote-cached class loader: " + path);
        mSystemLibsCacheMap.put(path, cached);
    }

    private static boolean sharedLibrariesEquals(List<ClassLoader> lhs, List<ClassLoader> rhs) {
        if (lhs == null) {
            return rhs == null;
        }

        return lhs.equals(rhs);
    }

    /**
     * Returns lib cached with createAndCacheNonBootclasspathSystemClassLoader. This is called by
     * the zygote during caching.
     *
     * If there is an error or the cache is not available, this returns null.
     */
    private ClassLoader getCachedNonBootclasspathSystemLib(String zip, ClassLoader parent,
            String classLoaderName, List<ClassLoader> sharedLibraries) {
        if (mSystemLibsCacheMap == null) {
            return null;
        }

        // we only cache top-level libs with the default class loader
        if (parent != null || classLoaderName != null) {
            return null;
        }

        CachedClassLoader cached = mSystemLibsCacheMap.get(zip);
        if (cached == null) {
            return null;
        }

        // cached must be built and loaded in the same environment
        if (!sharedLibrariesEquals(sharedLibraries, cached.sharedLibraries)) {
            Log.w(TAG, "Unexpected environment for cached library: (" + sharedLibraries + "|"
                    + cached.sharedLibraries + ")");
            return null;
        }

        Log.d(TAG, "Returning zygote-cached class loader: " + zip);
        return cached.loader;
    }

    /**
    /**
     * Creates a classloader for the WebView APK and places it in the cache of loaders maintained
     * Creates a classloader for the WebView APK and places it in the cache of loaders maintained
     * by this class. This is used in the WebView zygote, where its presence in the cache speeds up
     * by this class. This is used in the WebView zygote, where its presence in the cache speeds up
@@ -151,4 +286,18 @@ public class ApplicationLoaders {
    private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();
    private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();


    private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
    private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();

    private static class CachedClassLoader {
        ClassLoader loader;

        /**
         * The shared libraries used when constructing loader for verification.
         */
        List<ClassLoader> sharedLibraries;
    }

    /**
     * This is a map of zip to associated class loader.
     */
    private Map<String, CachedClassLoader> mSystemLibsCacheMap = null;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -676,7 +676,7 @@ public final class LoadedApk {


        // Shared libraries get a null parent: this has the side effect of having canonicalized
        // Shared libraries get a null parent: this has the side effect of having canonicalized
        // shared libraries using ApplicationLoaders cache, which is the behavior we want.
        // shared libraries using ApplicationLoaders cache, which is the behavior we want.
        return ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(jars,
        return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars,
                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                    libraryPermittedPath, /* parent */ null,
                    libraryPermittedPath, /* parent */ null,
                    /* classLoaderName */ null, sharedLibraries);
                    /* classLoaderName */ null, sharedLibraries);
+31 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.system.OsConstants.S_IRWXO;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.app.ApplicationLoaders;
import android.content.pm.SharedLibraryInfo;
import android.os.Build;
import android.os.Build;
import android.os.Environment;
import android.os.Environment;
import android.os.IInstalld;
import android.os.IInstalld;
@@ -138,6 +140,9 @@ public class ZygoteInit {
        bootTimingsTraceLog.traceBegin("PreloadClasses");
        bootTimingsTraceLog.traceBegin("PreloadClasses");
        preloadClasses();
        preloadClasses();
        bootTimingsTraceLog.traceEnd(); // PreloadClasses
        bootTimingsTraceLog.traceEnd(); // PreloadClasses
        bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
        cacheNonBootClasspathClassLoaders();
        bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
        bootTimingsTraceLog.traceBegin("PreloadResources");
        bootTimingsTraceLog.traceBegin("PreloadResources");
        preloadResources();
        preloadResources();
        bootTimingsTraceLog.traceEnd(); // PreloadResources
        bootTimingsTraceLog.traceEnd(); // PreloadResources
@@ -343,6 +348,32 @@ public class ZygoteInit {
        }
        }
    }
    }


    /**
     * Load in things which are used by many apps but which cannot be put in the boot
     * classpath.
     */
    private static void cacheNonBootClasspathClassLoaders() {
        // These libraries used to be part of the bootclasspath, but had to be removed.
        // Old system applications still get them for backwards compatibility reasons,
        // so they are cached here in order to preserve performance characteristics.
        SharedLibraryInfo hidlBase = new SharedLibraryInfo(
                "/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/,
                null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
                null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/);
        SharedLibraryInfo hidlManager = new SharedLibraryInfo(
                "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/,
                null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
                null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/);
        hidlManager.addDependency(hidlBase);

        ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders(
                new SharedLibraryInfo[]{
                    // ordered dependencies first
                    hidlBase,
                    hidlManager,
                });
    }

    /**
    /**
     * Load in commonly used resources, so they can be shared across processes.
     * Load in commonly used resources, so they can be shared across processes.
     *
     *