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

Commit 67c6ab38 authored by David Brazdil's avatar David Brazdil Committed by Gerrit Code Review
Browse files

Merge "Create AppComponentFactory.instantiateClassLoader API"

parents a21de6f3 b319ccfd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4200,8 +4200,10 @@ package android.app {
  public class AppComponentFactory {
    ctor public AppComponentFactory();
    method public android.content.pm.ApplicationInfo getApplicationInfo();
    method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
    method public android.app.Application instantiateApplication(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
    method public java.lang.ClassLoader instantiateClassLoader(java.lang.ClassLoader);
    method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
    method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
    method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+25 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.Intent;
import android.content.pm.ApplicationInfo;

/**
 * Interface used to control the instantiation of manifest elements.
@@ -32,6 +33,17 @@ import android.content.Intent;
 */
public class AppComponentFactory {

    /**
     * Allows application to override the creation of the default class loader.
     * This can be used to perform things such as dependency injection or setting up
     * a custom class loader hierarchy.
     *
     * @param cl        The default classloader instantiated by platform.
     */
    public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl) {
        return cl;
    }

    /**
     * Allows application to override the creation of the application object. This can be used to
     * perform things such as dependency injection or class loader changes to these
@@ -121,6 +133,19 @@ public class AppComponentFactory {
        return (ContentProvider) cl.loadClass(className).newInstance();
    }

    private ApplicationInfo mApplicationInfo = null;

    void setApplicationInfo(ApplicationInfo info) {
        mApplicationInfo = info;
    }

    /**
     * Returns the ApplicationInfo associated with this package.
     */
    public ApplicationInfo getApplicationInfo() {
        return mApplicationInfo;
    }

    /**
     * @hide
     */
+38 −18
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ public final class LoadedApk {
    private File mCredentialProtectedDataDirFile;
    @UnsupportedAppUsage
    private final ClassLoader mBaseClassLoader;
    private ClassLoader mDefaultClassLoader;
    private final boolean mSecurityViolation;
    private final boolean mIncludeCode;
    private final boolean mRegisterPackage;
@@ -224,9 +225,10 @@ public final class LoadedApk {
        mSecurityViolation = false;
        mIncludeCode = true;
        mRegisterPackage = false;
        mClassLoader = ClassLoader.getSystemClassLoader();
        mResources = Resources.getSystem();
        mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
        mDefaultClassLoader = ClassLoader.getSystemClassLoader();
        mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
    }

    /**
@@ -235,15 +237,21 @@ public final class LoadedApk {
    void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        assert info.packageName.equals("android");
        mApplicationInfo = info;
        mClassLoader = classLoader;
        mAppComponentFactory = createAppFactory(info, classLoader);
        mDefaultClassLoader = classLoader;
        mAppComponentFactory = createAppFactory(info, mDefaultClassLoader);
        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
    }

    private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
        if (appInfo.appComponentFactory != null && cl != null) {
            try {
                return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
                        .newInstance();
                AppComponentFactory factory = (AppComponentFactory) cl.loadClass(
                        appInfo.appComponentFactory).newInstance();
                // Pass a copy of ApplicationInfo to the factory. Copying protects the framework
                // from apps which would override the factory and change ApplicationInfo contents.
                // ApplicationInfo is used to set up the default class loader.
                factory.setApplicationInfo(new ApplicationInfo(appInfo));
                return factory;
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
            }
@@ -357,7 +365,7 @@ public final class LoadedApk {
                        getClassLoader());
            }
        }
        mAppComponentFactory = createAppFactory(aInfo, mClassLoader);
        mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader);
    }

    private void setApplicationInfo(ApplicationInfo aInfo) {
@@ -633,11 +641,12 @@ public final class LoadedApk {
            }

            if (mBaseClassLoader != null) {
                mClassLoader = mBaseClassLoader;
                mDefaultClassLoader = mBaseClassLoader;
            } else {
                mClassLoader = ClassLoader.getSystemClassLoader();
                mDefaultClassLoader = ClassLoader.getSystemClassLoader();
            }
            mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
            mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);

            return;
        }
@@ -715,9 +724,9 @@ public final class LoadedApk {
        // call System.loadLibrary() on a classloader from a LoadedApk with
        // mIncludeCode == false).
        if (!mIncludeCode) {
            if (mClassLoader == null) {
            if (mDefaultClassLoader == null) {
                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
                mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(
                        "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
                        librarySearchPath, libraryPermittedPath, mBaseClassLoader,
                        null /* classLoaderName */);
@@ -725,6 +734,10 @@ public final class LoadedApk {
                mAppComponentFactory = AppComponentFactory.DEFAULT;
            }

            if (mClassLoader == null) {
                mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
            }

            return;
        }

@@ -741,16 +754,16 @@ public final class LoadedApk {
                    ", JNI path: " + librarySearchPath);

        boolean needToSetupJitProfiles = false;
        if (mClassLoader == null) {
        if (mDefaultClassLoader == null) {
            // Temporarily disable logging of disk reads on the Looper thread
            // as this is early and necessary.
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();

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

            StrictMode.setThreadPolicy(oldPolicy);
            // Setup the class loader paths for profiling.
@@ -761,7 +774,7 @@ public final class LoadedApk {
            // Temporarily disable logging of disk reads on the Looper thread as this is necessary
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths);
                ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths);
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
@@ -799,7 +812,7 @@ public final class LoadedApk {
        if (!extraLibPaths.isEmpty()) {
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                ApplicationLoaders.getDefault().addNative(mClassLoader, extraLibPaths);
                ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, extraLibPaths);
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
@@ -807,7 +820,7 @@ public final class LoadedApk {

        if (addedPaths != null && addedPaths.size() > 0) {
            final String add = TextUtils.join(File.pathSeparator, addedPaths);
            ApplicationLoaders.getDefault().addPath(mClassLoader, add);
            ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add);
            // Setup the new code paths for profiling.
            needToSetupJitProfiles = true;
        }
@@ -824,6 +837,13 @@ public final class LoadedApk {
        if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
            setupJitProfileSupport();
        }

        // Call AppComponentFactory to select/create the main class loader of this app.
        // Since this may call code in the app, mDefaultClassLoader must be fully set up
        // before invoking the factory.
        if (mClassLoader == null) {
            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
        }
    }

    @UnsupportedAppUsage