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

Commit 4879460f authored by Nicolas Geoffray's avatar Nicolas Geoffray Committed by android-build-merger
Browse files

Merge "Start using shared libraries class loader."

am: e7753e08

Change-Id: I927599cc923e61d73d03c3ec9b469529f42f3225
parents fd5131bb e7753e08
Loading
Loading
Loading
Loading
+16 −5
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.internal.os.ClassLoaderFactory;
import dalvik.system.PathClassLoader;
import dalvik.system.PathClassLoader;


import java.util.Collection;
import java.util.Collection;
import java.util.List;


/** @hide */
/** @hide */
public class ApplicationLoaders {
public class ApplicationLoaders {
@@ -38,15 +39,25 @@ public class ApplicationLoaders {
    ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
    ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                               String librarySearchPath, String libraryPermittedPath,
                               String librarySearchPath, String libraryPermittedPath,
                               ClassLoader parent, String classLoaderName) {
                               ClassLoader parent, String classLoaderName) {
        return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
                              librarySearchPath, libraryPermittedPath, parent, classLoaderName,
                              null);
    }

    ClassLoader getClassLoaderWithSharedLibraries(
            String zip, int targetSdkVersion, boolean isBundled,
            String librarySearchPath, String libraryPermittedPath,
            ClassLoader parent, String classLoaderName,
            List<ClassLoader> sharedLibraries) {
        // For normal usage the cache key used is the same as the zip path.
        // For normal usage the cache key used is the same as the zip path.
        return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
        return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
                              libraryPermittedPath, parent, zip, classLoaderName);
                              libraryPermittedPath, parent, zip, 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,
                                       String classLoaderName) {
                                       String classLoaderName, List<ClassLoader> sharedLibraries) {
        /*
        /*
         * This is the parent we use if they pass "null" in.  In theory
         * This is the parent we use if they pass "null" in.  In theory
         * this should be the "system" class loader; in practice we
         * this should be the "system" class loader; in practice we
@@ -75,7 +86,7 @@ public class ApplicationLoaders {


                ClassLoader classloader = ClassLoaderFactory.createClassLoader(
                ClassLoader classloader = ClassLoaderFactory.createClassLoader(
                        zip,  librarySearchPath, libraryPermittedPath, parent,
                        zip,  librarySearchPath, libraryPermittedPath, parent,
                        targetSdkVersion, isBundled, classLoaderName);
                        targetSdkVersion, isBundled, classLoaderName, sharedLibraries);


                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);


@@ -90,7 +101,7 @@ public class ApplicationLoaders {


            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
            ClassLoader loader = ClassLoaderFactory.createClassLoader(
            ClassLoader loader = ClassLoaderFactory.createClassLoader(
                    zip, null, parent, classLoaderName);
                    zip, null, parent, classLoaderName, sharedLibraries);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            return loader;
            return loader;
        }
        }
@@ -110,7 +121,7 @@ public class ApplicationLoaders {
        // The cache key is passed separately to enable the stub WebView to be cached under the
        // The cache key is passed separately to enable the stub WebView to be cached under the
        // stub's APK path, when the actual package path is the donor APK.
        // stub's APK path, when the actual package path is the donor APK.
        return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
        return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
                              cacheKey, null /* classLoaderName */);
                              cacheKey, null /* classLoaderName */, null /* sharedLibraries */);
    }
    }


    /**
    /**
+77 −8
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.dex.ArtManager;
import android.content.pm.dex.ArtManager;
import android.content.pm.split.SplitDependencyLoader;
import android.content.pm.split.SplitDependencyLoader;
import android.content.res.AssetManager;
import android.content.res.AssetManager;
@@ -70,8 +71,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;


final class IntentReceiverLeaked extends AndroidRuntimeException {
final class IntentReceiverLeaked extends AndroidRuntimeException {
    @UnsupportedAppUsage
    @UnsupportedAppUsage
@@ -397,6 +400,24 @@ public final class LoadedApk {
        makePaths(activityThread, false, aInfo, outZipPaths, null);
        makePaths(activityThread, false, aInfo, outZipPaths, null);
    }
    }


    private static void appendSharedLibrariesLibPathsIfNeeded(
            List<SharedLibraryInfo> sharedLibraries, ApplicationInfo aInfo,
            Set<String> outSeenPaths,
            List<String> outLibPaths) {
        if (sharedLibraries == null) {
            return;
        }
        for (SharedLibraryInfo lib : sharedLibraries) {
            List<String> paths = lib.getAllCodePaths();
            outSeenPaths.addAll(paths);
            for (String path : paths) {
                appendApkLibPathIfNeeded(path, aInfo, outLibPaths);
            }
            appendSharedLibrariesLibPathsIfNeeded(
                    lib.getDependencies(), aInfo, outSeenPaths, outLibPaths);
        }
    }

    public static void makePaths(ActivityThread activityThread,
    public static void makePaths(ActivityThread activityThread,
                                 boolean isBundledApp,
                                 boolean isBundledApp,
                                 ApplicationInfo aInfo,
                                 ApplicationInfo aInfo,
@@ -404,7 +425,6 @@ public final class LoadedApk {
                                 List<String> outLibPaths) {
                                 List<String> outLibPaths) {
        final String appDir = aInfo.sourceDir;
        final String appDir = aInfo.sourceDir;
        final String libDir = aInfo.nativeLibraryDir;
        final String libDir = aInfo.nativeLibraryDir;
        final String[] sharedLibraries = aInfo.sharedLibraryFiles;


        outZipPaths.clear();
        outZipPaths.clear();
        outZipPaths.add(appDir);
        outZipPaths.add(appDir);
@@ -499,11 +519,19 @@ public final class LoadedApk {
            }
            }
        }
        }


        // Prepend the shared libraries, maintaining their original order where possible.
        // Add the shared libraries native paths. The dex files in shared libraries will
        if (sharedLibraries != null) {
        // be resolved through shared library loaders, which are setup later.
        Set<String> outSeenPaths = new LinkedHashSet<>();
        appendSharedLibrariesLibPathsIfNeeded(
                aInfo.sharedLibraryInfos, aInfo, outSeenPaths, outLibPaths);

        // ApplicationInfo.sharedLibraryFiles is a public API, so anyone can change it.
        // We prepend shared libraries that the package manager hasn't seen, maintaining their
        // original order where possible.
        if (aInfo.sharedLibraryFiles != null) {
            int index = 0;
            int index = 0;
            for (String lib : sharedLibraries) {
            for (String lib : aInfo.sharedLibraryFiles) {
                if (!outZipPaths.contains(lib)) {
                if (!outSeenPaths.contains(lib) && !outZipPaths.contains(lib)) {
                    outZipPaths.add(index, lib);
                    outZipPaths.add(index, lib);
                    index++;
                    index++;
                    appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
                    appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
@@ -631,6 +659,43 @@ public final class LoadedApk {
        return mSplitLoader.getSplitPathsForSplit(splitName);
        return mSplitLoader.getSplitPathsForSplit(splitName);
    }
    }


    /**
     * Create a class loader for the {@code sharedLibrary}. Shared libraries are canonicalized,
     * so if we already created a class loader with that shared library, we return it.
     *
     * Implementation notes: the canonicalization of shared libraries is something dex2oat
     * also does.
     */
    ClassLoader createSharedLibraryLoader(SharedLibraryInfo sharedLibrary,
            boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
        List<String> paths = sharedLibrary.getAllCodePaths();
        List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
                sharedLibrary.getDependencies(), isBundledApp, librarySearchPath,
                libraryPermittedPath);
        final String jars = (paths.size() == 1) ? paths.get(0) :
                TextUtils.join(File.pathSeparator, paths);

        // 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.
        return ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(jars,
                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                    libraryPermittedPath, /* parent */ null,
                    /* classLoaderName */ null, sharedLibraries);
    }

    private List<ClassLoader> createSharedLibrariesLoaders(List<SharedLibraryInfo> sharedLibraries,
            boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
        if (sharedLibraries == null) {
            return null;
        }
        List<ClassLoader> loaders = new ArrayList<>();
        for (SharedLibraryInfo info : sharedLibraries) {
            loaders.add(createSharedLibraryLoader(
                    info, isBundledApp, librarySearchPath, libraryPermittedPath));
        }
        return loaders;
    }

    private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
    private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
        if (mPackageName.equals("android")) {
        if (mPackageName.equals("android")) {
            // Note: This branch is taken for system server and we don't need to setup
            // Note: This branch is taken for system server and we don't need to setup
@@ -759,10 +824,14 @@ public final class LoadedApk {
            // as this is early and necessary.
            // as this is early and necessary.
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();


            mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
            List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                    mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
                    libraryPermittedPath);

            mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
                    zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                    libraryPermittedPath, mBaseClassLoader,
                    libraryPermittedPath, mBaseClassLoader,
                    mApplicationInfo.classLoaderName);
                    mApplicationInfo.classLoaderName, sharedLibraries);
            mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
            mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);


            StrictMode.setThreadPolicy(oldPolicy);
            StrictMode.setThreadPolicy(oldPolicy);
+15 −1
Original line number Original line Diff line number Diff line
@@ -45,6 +45,7 @@ import java.lang.annotation.RetentionPolicy;
import java.text.Collator;
import java.text.Collator;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.UUID;
import java.util.UUID;


@@ -815,6 +816,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     */
     */
    public String[] sharedLibraryFiles;
    public String[] sharedLibraryFiles;


    /**
     * List of all shared libraries this application is linked against.  This
     * field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
     * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
     * the structure.
     *
     * {@hide}
     */
    public List<SharedLibraryInfo> sharedLibraryInfos;

    /**
    /**
     * Full path to the default directory assigned to the package for its
     * Full path to the default directory assigned to the package for its
     * persistent data.
     * persistent data.
@@ -1458,6 +1469,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        seInfo = orig.seInfo;
        seInfo = orig.seInfo;
        seInfoUser = orig.seInfoUser;
        seInfoUser = orig.seInfoUser;
        sharedLibraryFiles = orig.sharedLibraryFiles;
        sharedLibraryFiles = orig.sharedLibraryFiles;
        sharedLibraryInfos = orig.sharedLibraryInfos;
        dataDir = orig.dataDir;
        dataDir = orig.dataDir;
        deviceProtectedDataDir = orig.deviceProtectedDataDir;
        deviceProtectedDataDir = orig.deviceProtectedDataDir;
        credentialProtectedDataDir = orig.credentialProtectedDataDir;
        credentialProtectedDataDir = orig.credentialProtectedDataDir;
@@ -1533,6 +1545,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        dest.writeString(seInfo);
        dest.writeString(seInfo);
        dest.writeString(seInfoUser);
        dest.writeString(seInfoUser);
        dest.writeStringArray(sharedLibraryFiles);
        dest.writeStringArray(sharedLibraryFiles);
        dest.writeTypedList(sharedLibraryInfos);
        dest.writeString(dataDir);
        dest.writeString(dataDir);
        dest.writeString(deviceProtectedDataDir);
        dest.writeString(deviceProtectedDataDir);
        dest.writeString(credentialProtectedDataDir);
        dest.writeString(credentialProtectedDataDir);
@@ -1605,6 +1618,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        seInfo = source.readString();
        seInfo = source.readString();
        seInfoUser = source.readString();
        seInfoUser = source.readString();
        sharedLibraryFiles = source.readStringArray();
        sharedLibraryFiles = source.readStringArray();
        sharedLibraryInfos = source.createTypedArrayList(SharedLibraryInfo.CREATOR);
        dataDir = source.readString();
        dataDir = source.readString();
        deviceProtectedDataDir = source.readString();
        deviceProtectedDataDir = source.readString();
        credentialProtectedDataDir = source.readString();
        credentialProtectedDataDir = source.readString();
+1 −0
Original line number Original line Diff line number Diff line
@@ -7555,6 +7555,7 @@ public class PackageParser {
        }
        }
        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
            ai.sharedLibraryFiles = p.usesLibraryFiles;
            ai.sharedLibraryFiles = p.usesLibraryFiles;
            ai.sharedLibraryInfos = p.usesLibraryInfos;
        }
        }
        if (state.stopped) {
        if (state.stopped) {
            ai.flags |= ApplicationInfo.FLAG_STOPPED;
            ai.flags |= ApplicationInfo.FLAG_STOPPED;
+28 −2
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ public final class SharedLibraryInfo implements Parcelable {
    private final String mPath;
    private final String mPath;
    private final String mPackageName;
    private final String mPackageName;
    private final String mName;
    private final String mName;
    private final List<String> mCodePaths;


    private final long mVersion;
    private final long mVersion;
    private final @Type int mType;
    private final @Type int mType;
@@ -84,6 +85,8 @@ public final class SharedLibraryInfo implements Parcelable {
    /**
    /**
     * Creates a new instance.
     * Creates a new instance.
     *
     *
     * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
     *                  this shared library. Null for builtin library.
     * @param name The lib name.
     * @param name The lib name.
     * @param version The lib version if not builtin.
     * @param version The lib version if not builtin.
     * @param type The lib type.
     * @param type The lib type.
@@ -92,11 +95,13 @@ public final class SharedLibraryInfo implements Parcelable {
     *
     *
     * @hide
     * @hide
     */
     */
    public SharedLibraryInfo(String path, String packageName, String name, long version, int type,
    public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
            String name, long version, int type,
            VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
            VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
            List<SharedLibraryInfo> dependencies) {
            List<SharedLibraryInfo> dependencies) {
        mPath = path;
        mPath = path;
        mPackageName = packageName;
        mPackageName = packageName;
        mCodePaths = codePaths;
        mName = name;
        mName = name;
        mVersion = version;
        mVersion = version;
        mType = type;
        mType = type;
@@ -106,7 +111,8 @@ public final class SharedLibraryInfo implements Parcelable {
    }
    }


    private SharedLibraryInfo(Parcel parcel) {
    private SharedLibraryInfo(Parcel parcel) {
        this(parcel.readString(), parcel.readString(), parcel.readString(), parcel.readLong(),
        this(parcel.readString(), parcel.readString(), parcel.readArrayList(null),
                parcel.readString(), parcel.readLong(),
                parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null),
                parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null),
                parcel.createTypedArrayList(SharedLibraryInfo.CREATOR));
                parcel.createTypedArrayList(SharedLibraryInfo.CREATOR));
    }
    }
@@ -154,6 +160,25 @@ public final class SharedLibraryInfo implements Parcelable {
        return mPackageName;
        return mPackageName;
    }
    }


    /**
     * Get all code paths for that library.
     *
     * @return All code paths.
     *
     * @hide
     */
    public List<String> getAllCodePaths() {
        if (getPath() != null) {
            // Builtin library.
            ArrayList<String> list = new ArrayList<>();
            list.add(getPath());
            return list;
        } else {
            // Static or dynamic library.
            return mCodePaths;
        }
    }

    /**
    /**
     * Add a library dependency to that library. Note that this
     * Add a library dependency to that library. Note that this
     * should be called under the package manager lock.
     * should be called under the package manager lock.
@@ -273,6 +298,7 @@ public final class SharedLibraryInfo implements Parcelable {
    public void writeToParcel(Parcel parcel, int flags) {
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(mPath);
        parcel.writeString(mPath);
        parcel.writeString(mPackageName);
        parcel.writeString(mPackageName);
        parcel.writeList(mCodePaths);
        parcel.writeString(mName);
        parcel.writeString(mName);
        parcel.writeLong(mVersion);
        parcel.writeLong(mVersion);
        parcel.writeInt(mType);
        parcel.writeInt(mType);
Loading