Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
+ if (appContext.getApplicationContext() instanceof Application) {
+ activity = ((Application) appContext.getApplicationContext())
+ .instantiateActivity(cl, component.getClassName(), r.intent);
+ }
+ if (activity == null) {
+ activity = mInstrumentation.newActivity(
+ cl, component.getClassName(), r.intent);
+ }
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
- receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
+ receiver = instantiate(cl, component, data.intent, app,
+ Application::instantiateReceiver);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
} else {
try {
if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- agent = (BackupAgent) cl.loadClass(classname).newInstance();
+ agent = instantiate(cl, classname, context,
+ Application::instantiateBackupAgent);
// set up the agent's context
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(agent);
agent.attach(context);
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
+ Application app = null;
try {
+ app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- service = (Service) cl.loadClass(data.info.name).newInstance();
+ service = instantiate(cl, data.info.name, data.intent, app,
+ Application::instantiateService);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
- Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
try {
final ClassLoader cl = instrContext.getClassLoader();
- mInstrumentation = (Instrumentation)
- cl.loadClass(data.instrumentationName.getClassName()).newInstance();
+ mInstrumentation = instantiate(cl, data.instrumentationName.getClassName(),
+ instrContext, Application::instantiateInstrumentation);
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
try {
final java.lang.ClassLoader cl = c.getClassLoader();
- localProvider = (ContentProvider)cl.
- loadClass(info.name).newInstance();
+ localProvider = instantiate(cl, info.name, context,
+ Application::instantiateProvider);
provider = localProvider.getIContentProvider();
if (provider == null) {
Slog.e(TAG, "Failed to instantiate class " +
}
}
+ private <T> T instantiate(ClassLoader cl, String className, Context c,
+ Instantiator<T> instantiator)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ if (c.getApplicationContext() instanceof Application) {
+ T a = instantiator.instantiate((Application) c.getApplicationContext(),
+ cl, className);
+ if (a != null) return a;
+ }
+ return (T) cl.loadClass(className).newInstance();
+ }
+
+ private <T> T instantiate(ClassLoader cl, String className, Intent intent, Context c,
+ IntentInstantiator<T> instantiator)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ if (c.getApplicationContext() instanceof Application) {
+ T a = instantiator.instantiate((Application) c.getApplicationContext(),
+ cl, className, intent);
+ if (a != null) return a;
+ }
+ return (T) cl.loadClass(className).newInstance();
+ }
+
+ private interface Instantiator<T> {
+ T instantiate(Application app, ClassLoader cl, String className)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException;
+ }
+
+ private interface IntentInstantiator<T> {
+ T instantiate(Application app, ClassLoader cl, String className, Intent intent)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException;
+ }
+
private static class EventLoggingReporter implements EventLogger.Reporter {
@Override
public void report (int code, Object... list) {
package android.app;
-import java.util.ArrayList;
-
import android.annotation.CallSuper;
+import android.app.backup.BackupAgent;
+import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
+import java.util.ArrayList;
+
/**
* Base class for maintaining global application state. You can provide your own
* implementation by creating a subclass and specifying the fully-qualified name
}
}
}
+
+ /**
+ * Allows application to override the creation of activities. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of receivers. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of services. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public Service instantiateService(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of providers. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public ContentProvider instantiateProvider(ClassLoader cl, String className) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of backup agents. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public BackupAgent instantiateBackupAgent(ClassLoader cl, String className) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of instrumentation. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public Instrumentation instantiateInstrumentation(ClassLoader cl, String className) {
+ return null;
+ }
}
\ No newline at end of file