1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.app;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.content.BroadcastReceiver;
21 import android.content.ContentProvider;
22 import android.content.Intent;
23 import android.content.pm.ApplicationInfo;
24 
25 /**
26  * Interface used to control the instantiation of manifest elements.
27  *
28  * @see #instantiateApplication
29  * @see #instantiateActivity
30  * @see #instantiateClassLoader
31  * @see #instantiateService
32  * @see #instantiateReceiver
33  * @see #instantiateProvider
34  */
35 public class AppComponentFactory {
36 
37     /**
38      * Selects the class loader which will be used by the platform to instantiate app components.
39      * <p>
40      * The default implementation of this method returns the {@code cl} parameter unchanged.
41      * Applications can override this method to set up a custom class loader or a custom class
42      * loader hierarchy and return it to the platform.
43      * <p>
44      * The method is a hook invoked before any application components are instantiated or the
45      * application Context is initialized. It is intended to allow the application's classes to
46      * be loaded from a different source than the base/split APK(s).
47      * <p>
48      * The default class loader {@code cl} is created by the platform and used to load the
49      * application's base or split APK(s). Its parent is typically the boot class loader, unless
50      * running under instrumentation. Its classname is configurable using the
51      * {@link android.R.attr#classLoader} manifest attribute.
52      *
53      * @param cl        The default class loader created by the platform.
54      * @param aInfo     Information about the application being loaded.
55      */
instantiateClassLoader(@onNull ClassLoader cl, @NonNull ApplicationInfo aInfo)56     public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl,
57             @NonNull ApplicationInfo aInfo) {
58         return cl;
59     }
60 
61     /**
62      * Allows application to override the creation of the application object. This can be used to
63      * perform things such as dependency injection or class loader changes to these
64      * classes.
65      * <p>
66      * This method is only intended to provide a hook for instantiation. It does not provide
67      * earlier access to the Application object. The returned object will not be initialized
68      * as a Context yet and should not be used to interact with other android APIs.
69      *
70      * @param cl        The default classloader to use for instantiation.
71      * @param className The class to be instantiated.
72      */
instantiateApplication(@onNull ClassLoader cl, @NonNull String className)73     public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
74             @NonNull String className)
75             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
76         return (Application) cl.loadClass(className).newInstance();
77     }
78 
79     /**
80      * Allows application to override the creation of activities. This can be used to
81      * perform things such as dependency injection or class loader changes to these
82      * classes.
83      * <p>
84      * This method is only intended to provide a hook for instantiation. It does not provide
85      * earlier access to the Activity object. The returned object will not be initialized
86      * as a Context yet and should not be used to interact with other android APIs.
87      *
88      * @param cl        The default classloader to use for instantiation.
89      * @param className The class to be instantiated.
90      * @param intent    Intent creating the class.
91      */
instantiateActivity(@onNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)92     public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
93             @Nullable Intent intent)
94             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
95         return (Activity) cl.loadClass(className).newInstance();
96     }
97 
98     /**
99      * Allows application to override the creation of receivers. This can be used to
100      * perform things such as dependency injection or class loader changes to these
101      * classes.
102      *
103      * @param cl        The default classloader to use for instantiation.
104      * @param className The class to be instantiated.
105      * @param intent    Intent creating the class.
106      */
instantiateReceiver(@onNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)107     public @NonNull BroadcastReceiver instantiateReceiver(@NonNull ClassLoader cl,
108             @NonNull String className, @Nullable Intent intent)
109             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
110         return (BroadcastReceiver) cl.loadClass(className).newInstance();
111     }
112 
113     /**
114      * Allows application to override the creation of services. This can be used to
115      * perform things such as dependency injection or class loader changes to these
116      * classes.
117      * <p>
118      * This method is only intended to provide a hook for instantiation. It does not provide
119      * earlier access to the Service object. The returned object will not be initialized
120      * as a Context yet and should not be used to interact with other android APIs.
121      *
122      * @param cl        The default classloader to use for instantiation.
123      * @param className The class to be instantiated.
124      * @param intent    Intent creating the class.
125      */
instantiateService(@onNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)126     public @NonNull Service instantiateService(@NonNull ClassLoader cl,
127             @NonNull String className, @Nullable Intent intent)
128             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
129         return (Service) cl.loadClass(className).newInstance();
130     }
131 
132     /**
133      * Allows application to override the creation of providers. This can be used to
134      * perform things such as dependency injection or class loader changes to these
135      * classes.
136      * <p>
137      * This method is only intended to provide a hook for instantiation. It does not provide
138      * earlier access to the ContentProvider object. The returned object will not be initialized
139      * with a Context yet and should not be used to interact with other android APIs.
140      *
141      * @param cl        The default classloader to use for instantiation.
142      * @param className The class to be instantiated.
143      */
instantiateProvider(@onNull ClassLoader cl, @NonNull String className)144     public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl,
145             @NonNull String className)
146             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
147         return (ContentProvider) cl.loadClass(className).newInstance();
148     }
149 
150     /**
151      * @hide
152      */
153     public static final AppComponentFactory DEFAULT = new AppComponentFactory();
154 }
155