Merge "Create AppComponentFactory.instantiateClassLoader API"
diff --git a/api/current.txt b/api/current.txt
index b192d7f..56433f3 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -4226,8 +4226,10 @@
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;
diff --git a/core/java/android/app/AppComponentFactory.java b/core/java/android/app/AppComponentFactory.java
index cfaeec9..ae63291 100644
--- a/core/java/android/app/AppComponentFactory.java
+++ b/core/java/android/app/AppComponentFactory.java
@@ -20,6 +20,7 @@
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.
@@ -33,6 +34,17 @@
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
* classes.
@@ -121,6 +133,19 @@
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
*/
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b827d01..da4f77b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -117,6 +117,7 @@
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 @@
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 @@
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 @@
getClassLoader());
}
}
- mAppComponentFactory = createAppFactory(aInfo, mClassLoader);
+ mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader);
}
private void setApplicationInfo(ApplicationInfo aInfo) {
@@ -633,11 +641,12 @@
}
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 @@
// 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 @@
mAppComponentFactory = AppComponentFactory.DEFAULT;
}
+ if (mClassLoader == null) {
+ mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
+ }
+
return;
}
@@ -741,16 +754,16 @@
", 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 @@
// 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 @@
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 @@
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 @@
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