Merge "Create AppComponentFactory.instantiateClassLoader API"
This commit is contained in:
@@ -4200,8 +4200,10 @@ package android.app {
|
|||||||
|
|
||||||
public class AppComponentFactory {
|
public class AppComponentFactory {
|
||||||
ctor public 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.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 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.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.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;
|
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;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used to control the instantiation of manifest elements.
|
* Interface used to control the instantiation of manifest elements.
|
||||||
@@ -32,6 +33,17 @@ import android.content.Intent;
|
|||||||
*/
|
*/
|
||||||
public class AppComponentFactory {
|
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
|
* 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
|
* 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();
|
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
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ public final class LoadedApk {
|
|||||||
private File mCredentialProtectedDataDirFile;
|
private File mCredentialProtectedDataDirFile;
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private final ClassLoader mBaseClassLoader;
|
private final ClassLoader mBaseClassLoader;
|
||||||
|
private ClassLoader mDefaultClassLoader;
|
||||||
private final boolean mSecurityViolation;
|
private final boolean mSecurityViolation;
|
||||||
private final boolean mIncludeCode;
|
private final boolean mIncludeCode;
|
||||||
private final boolean mRegisterPackage;
|
private final boolean mRegisterPackage;
|
||||||
@@ -224,9 +225,10 @@ public final class LoadedApk {
|
|||||||
mSecurityViolation = false;
|
mSecurityViolation = false;
|
||||||
mIncludeCode = true;
|
mIncludeCode = true;
|
||||||
mRegisterPackage = false;
|
mRegisterPackage = false;
|
||||||
mClassLoader = ClassLoader.getSystemClassLoader();
|
|
||||||
mResources = Resources.getSystem();
|
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) {
|
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
|
||||||
assert info.packageName.equals("android");
|
assert info.packageName.equals("android");
|
||||||
mApplicationInfo = info;
|
mApplicationInfo = info;
|
||||||
mClassLoader = classLoader;
|
mDefaultClassLoader = classLoader;
|
||||||
mAppComponentFactory = createAppFactory(info, classLoader);
|
mAppComponentFactory = createAppFactory(info, mDefaultClassLoader);
|
||||||
|
mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
|
private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
|
||||||
if (appInfo.appComponentFactory != null && cl != null) {
|
if (appInfo.appComponentFactory != null && cl != null) {
|
||||||
try {
|
try {
|
||||||
return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
|
AppComponentFactory factory = (AppComponentFactory) cl.loadClass(
|
||||||
.newInstance();
|
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) {
|
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
|
||||||
Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
|
Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
|
||||||
}
|
}
|
||||||
@@ -357,7 +365,7 @@ public final class LoadedApk {
|
|||||||
getClassLoader());
|
getClassLoader());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mAppComponentFactory = createAppFactory(aInfo, mClassLoader);
|
mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setApplicationInfo(ApplicationInfo aInfo) {
|
private void setApplicationInfo(ApplicationInfo aInfo) {
|
||||||
@@ -633,11 +641,12 @@ public final class LoadedApk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mBaseClassLoader != null) {
|
if (mBaseClassLoader != null) {
|
||||||
mClassLoader = mBaseClassLoader;
|
mDefaultClassLoader = mBaseClassLoader;
|
||||||
} else {
|
} else {
|
||||||
mClassLoader = ClassLoader.getSystemClassLoader();
|
mDefaultClassLoader = ClassLoader.getSystemClassLoader();
|
||||||
}
|
}
|
||||||
mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
|
mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
|
||||||
|
mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -715,9 +724,9 @@ public final class LoadedApk {
|
|||||||
// call System.loadLibrary() on a classloader from a LoadedApk with
|
// call System.loadLibrary() on a classloader from a LoadedApk with
|
||||||
// mIncludeCode == false).
|
// mIncludeCode == false).
|
||||||
if (!mIncludeCode) {
|
if (!mIncludeCode) {
|
||||||
if (mClassLoader == null) {
|
if (mDefaultClassLoader == null) {
|
||||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
||||||
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
|
mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(
|
||||||
"" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
|
"" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
|
||||||
librarySearchPath, libraryPermittedPath, mBaseClassLoader,
|
librarySearchPath, libraryPermittedPath, mBaseClassLoader,
|
||||||
null /* classLoaderName */);
|
null /* classLoaderName */);
|
||||||
@@ -725,6 +734,10 @@ public final class LoadedApk {
|
|||||||
mAppComponentFactory = AppComponentFactory.DEFAULT;
|
mAppComponentFactory = AppComponentFactory.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mClassLoader == null) {
|
||||||
|
mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,16 +754,16 @@ public final class LoadedApk {
|
|||||||
", JNI path: " + librarySearchPath);
|
", JNI path: " + librarySearchPath);
|
||||||
|
|
||||||
boolean needToSetupJitProfiles = false;
|
boolean needToSetupJitProfiles = false;
|
||||||
if (mClassLoader == null) {
|
if (mDefaultClassLoader == null) {
|
||||||
// Temporarily disable logging of disk reads on the Looper thread
|
// Temporarily disable logging of disk reads on the Looper thread
|
||||||
// as this is early and necessary.
|
// as this is early and necessary.
|
||||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
|
mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
|
||||||
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
|
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
|
||||||
libraryPermittedPath, mBaseClassLoader,
|
libraryPermittedPath, mBaseClassLoader,
|
||||||
mApplicationInfo.classLoaderName);
|
mApplicationInfo.classLoaderName);
|
||||||
mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
|
mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
|
||||||
|
|
||||||
StrictMode.setThreadPolicy(oldPolicy);
|
StrictMode.setThreadPolicy(oldPolicy);
|
||||||
// Setup the class loader paths for profiling.
|
// 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
|
// Temporarily disable logging of disk reads on the Looper thread as this is necessary
|
||||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
||||||
try {
|
try {
|
||||||
ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths);
|
ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths);
|
||||||
} finally {
|
} finally {
|
||||||
StrictMode.setThreadPolicy(oldPolicy);
|
StrictMode.setThreadPolicy(oldPolicy);
|
||||||
}
|
}
|
||||||
@@ -799,7 +812,7 @@ public final class LoadedApk {
|
|||||||
if (!extraLibPaths.isEmpty()) {
|
if (!extraLibPaths.isEmpty()) {
|
||||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
||||||
try {
|
try {
|
||||||
ApplicationLoaders.getDefault().addNative(mClassLoader, extraLibPaths);
|
ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, extraLibPaths);
|
||||||
} finally {
|
} finally {
|
||||||
StrictMode.setThreadPolicy(oldPolicy);
|
StrictMode.setThreadPolicy(oldPolicy);
|
||||||
}
|
}
|
||||||
@@ -807,7 +820,7 @@ public final class LoadedApk {
|
|||||||
|
|
||||||
if (addedPaths != null && addedPaths.size() > 0) {
|
if (addedPaths != null && addedPaths.size() > 0) {
|
||||||
final String add = TextUtils.join(File.pathSeparator, addedPaths);
|
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.
|
// Setup the new code paths for profiling.
|
||||||
needToSetupJitProfiles = true;
|
needToSetupJitProfiles = true;
|
||||||
}
|
}
|
||||||
@@ -824,6 +837,13 @@ public final class LoadedApk {
|
|||||||
if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
|
if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
|
||||||
setupJitProfileSupport();
|
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
|
@UnsupportedAppUsage
|
||||||
|
|||||||
Reference in New Issue
Block a user