1 /*
2  * Copyright (C) 2006 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 
17 package android.app;
18 
19 import android.annotation.CallSuper;
20 import android.content.ComponentCallbacks;
21 import android.content.ComponentCallbacks2;
22 import android.content.Context;
23 import android.content.ContextWrapper;
24 import android.content.Intent;
25 import android.content.res.Configuration;
26 import android.os.Bundle;
27 import android.util.Log;
28 import android.view.autofill.AutofillManager;
29 
30 import java.util.ArrayList;
31 
32 /**
33  * Base class for maintaining global application state. You can provide your own
34  * implementation by creating a subclass and specifying the fully-qualified name
35  * of this subclass as the <code>"android:name"</code> attribute in your
36  * AndroidManifest.xml's <code>&lt;application&gt;</code> tag. The Application
37  * class, or your subclass of the Application class, is instantiated before any
38  * other class when the process for your application/package is created.
39  *
40  * <p class="note"><strong>Note: </strong>There is normally no need to subclass
41  * Application.  In most situations, static singletons can provide the same
42  * functionality in a more modular way.  If your singleton needs a global
43  * context (for example to register broadcast receivers), include
44  * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
45  * as a {@link android.content.Context} argument when invoking your singleton's
46  * <code>getInstance()</code> method.
47  * </p>
48  */
49 public class Application extends ContextWrapper implements ComponentCallbacks2 {
50     private static final String TAG = "Application";
51     private ArrayList<ComponentCallbacks> mComponentCallbacks =
52             new ArrayList<ComponentCallbacks>();
53     private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
54             new ArrayList<ActivityLifecycleCallbacks>();
55     private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
56 
57     /** @hide */
58     public LoadedApk mLoadedApk;
59 
60     public interface ActivityLifecycleCallbacks {
onActivityCreated(Activity activity, Bundle savedInstanceState)61         void onActivityCreated(Activity activity, Bundle savedInstanceState);
onActivityStarted(Activity activity)62         void onActivityStarted(Activity activity);
onActivityResumed(Activity activity)63         void onActivityResumed(Activity activity);
onActivityPaused(Activity activity)64         void onActivityPaused(Activity activity);
onActivityStopped(Activity activity)65         void onActivityStopped(Activity activity);
onActivitySaveInstanceState(Activity activity, Bundle outState)66         void onActivitySaveInstanceState(Activity activity, Bundle outState);
onActivityDestroyed(Activity activity)67         void onActivityDestroyed(Activity activity);
68     }
69 
70     /**
71      * Callback interface for use with {@link Application#registerOnProvideAssistDataListener}
72      * and {@link Application#unregisterOnProvideAssistDataListener}.
73      */
74     public interface OnProvideAssistDataListener {
75         /**
76          * This is called when the user is requesting an assist, to build a full
77          * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
78          * application.  You can override this method to place into the bundle anything
79          * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
80          * of the assist Intent.
81          */
onProvideAssistData(Activity activity, Bundle data)82         public void onProvideAssistData(Activity activity, Bundle data);
83     }
84 
Application()85     public Application() {
86         super(null);
87     }
88 
89     /**
90      * Called when the application is starting, before any activity, service,
91      * or receiver objects (excluding content providers) have been created.
92      *
93      * <p>Implementations should be as quick as possible (for example using
94      * lazy initialization of state) since the time spent in this function
95      * directly impacts the performance of starting the first activity,
96      * service, or receiver in a process.</p>
97      *
98      * <p>If you override this method, be sure to call {@code super.onCreate()}.</p>
99      *
100      * <p class="note">Be aware that direct boot may also affect callback order on
101      * Android {@link android.os.Build.VERSION_CODES#N} and later devices.
102      * Until the user unlocks the device, only direct boot aware components are
103      * allowed to run. You should consider that all direct boot unaware
104      * components, including such {@link android.content.ContentProvider}, are
105      * disabled until user unlock happens, especially when component callback
106      * order matters.</p>
107      */
108     @CallSuper
onCreate()109     public void onCreate() {
110     }
111 
112     /**
113      * This method is for use in emulated process environments.  It will
114      * never be called on a production Android device, where processes are
115      * removed by simply killing them; no user code (including this callback)
116      * is executed when doing so.
117      */
118     @CallSuper
onTerminate()119     public void onTerminate() {
120     }
121 
122     @CallSuper
onConfigurationChanged(Configuration newConfig)123     public void onConfigurationChanged(Configuration newConfig) {
124         Object[] callbacks = collectComponentCallbacks();
125         if (callbacks != null) {
126             for (int i=0; i<callbacks.length; i++) {
127                 ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
128             }
129         }
130     }
131 
132     @CallSuper
onLowMemory()133     public void onLowMemory() {
134         Object[] callbacks = collectComponentCallbacks();
135         if (callbacks != null) {
136             for (int i=0; i<callbacks.length; i++) {
137                 ((ComponentCallbacks)callbacks[i]).onLowMemory();
138             }
139         }
140     }
141 
142     @CallSuper
onTrimMemory(int level)143     public void onTrimMemory(int level) {
144         Object[] callbacks = collectComponentCallbacks();
145         if (callbacks != null) {
146             for (int i=0; i<callbacks.length; i++) {
147                 Object c = callbacks[i];
148                 if (c instanceof ComponentCallbacks2) {
149                     ((ComponentCallbacks2)c).onTrimMemory(level);
150                 }
151             }
152         }
153     }
154 
registerComponentCallbacks(ComponentCallbacks callback)155     public void registerComponentCallbacks(ComponentCallbacks callback) {
156         synchronized (mComponentCallbacks) {
157             mComponentCallbacks.add(callback);
158         }
159     }
160 
unregisterComponentCallbacks(ComponentCallbacks callback)161     public void unregisterComponentCallbacks(ComponentCallbacks callback) {
162         synchronized (mComponentCallbacks) {
163             mComponentCallbacks.remove(callback);
164         }
165     }
166 
registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)167     public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
168         synchronized (mActivityLifecycleCallbacks) {
169             mActivityLifecycleCallbacks.add(callback);
170         }
171     }
172 
unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)173     public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
174         synchronized (mActivityLifecycleCallbacks) {
175             mActivityLifecycleCallbacks.remove(callback);
176         }
177     }
178 
registerOnProvideAssistDataListener(OnProvideAssistDataListener callback)179     public void registerOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
180         synchronized (this) {
181             if (mAssistCallbacks == null) {
182                 mAssistCallbacks = new ArrayList<OnProvideAssistDataListener>();
183             }
184             mAssistCallbacks.add(callback);
185         }
186     }
187 
unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback)188     public void unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
189         synchronized (this) {
190             if (mAssistCallbacks != null) {
191                 mAssistCallbacks.remove(callback);
192             }
193         }
194     }
195 
196     /**
197      * Returns the name of the current process. A package's default process name
198      * is the same as its package name. Non-default processes will look like
199      * "$PACKAGE_NAME:$NAME", where $NAME corresponds to an android:process
200      * attribute within AndroidManifest.xml.
201      */
getProcessName()202     public static String getProcessName() {
203         return ActivityThread.currentProcessName();
204     }
205 
206     // ------------------ Internal API ------------------
207 
208     /**
209      * @hide
210      */
attach(Context context)211     /* package */ final void attach(Context context) {
212         attachBaseContext(context);
213         mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
214     }
215 
dispatchActivityCreated(Activity activity, Bundle savedInstanceState)216     /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
217         Object[] callbacks = collectActivityLifecycleCallbacks();
218         if (callbacks != null) {
219             for (int i=0; i<callbacks.length; i++) {
220                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
221                         savedInstanceState);
222             }
223         }
224     }
225 
dispatchActivityStarted(Activity activity)226     /* package */ void dispatchActivityStarted(Activity activity) {
227         Object[] callbacks = collectActivityLifecycleCallbacks();
228         if (callbacks != null) {
229             for (int i=0; i<callbacks.length; i++) {
230                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
231             }
232         }
233     }
234 
dispatchActivityResumed(Activity activity)235     /* package */ void dispatchActivityResumed(Activity activity) {
236         Object[] callbacks = collectActivityLifecycleCallbacks();
237         if (callbacks != null) {
238             for (int i=0; i<callbacks.length; i++) {
239                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
240             }
241         }
242     }
243 
dispatchActivityPaused(Activity activity)244     /* package */ void dispatchActivityPaused(Activity activity) {
245         Object[] callbacks = collectActivityLifecycleCallbacks();
246         if (callbacks != null) {
247             for (int i=0; i<callbacks.length; i++) {
248                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
249             }
250         }
251     }
252 
dispatchActivityStopped(Activity activity)253     /* package */ void dispatchActivityStopped(Activity activity) {
254         Object[] callbacks = collectActivityLifecycleCallbacks();
255         if (callbacks != null) {
256             for (int i=0; i<callbacks.length; i++) {
257                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
258             }
259         }
260     }
261 
dispatchActivitySaveInstanceState(Activity activity, Bundle outState)262     /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
263         Object[] callbacks = collectActivityLifecycleCallbacks();
264         if (callbacks != null) {
265             for (int i=0; i<callbacks.length; i++) {
266                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
267                         outState);
268             }
269         }
270     }
271 
dispatchActivityDestroyed(Activity activity)272     /* package */ void dispatchActivityDestroyed(Activity activity) {
273         Object[] callbacks = collectActivityLifecycleCallbacks();
274         if (callbacks != null) {
275             for (int i=0; i<callbacks.length; i++) {
276                 ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
277             }
278         }
279     }
280 
collectComponentCallbacks()281     private Object[] collectComponentCallbacks() {
282         Object[] callbacks = null;
283         synchronized (mComponentCallbacks) {
284             if (mComponentCallbacks.size() > 0) {
285                 callbacks = mComponentCallbacks.toArray();
286             }
287         }
288         return callbacks;
289     }
290 
collectActivityLifecycleCallbacks()291     private Object[] collectActivityLifecycleCallbacks() {
292         Object[] callbacks = null;
293         synchronized (mActivityLifecycleCallbacks) {
294             if (mActivityLifecycleCallbacks.size() > 0) {
295                 callbacks = mActivityLifecycleCallbacks.toArray();
296             }
297         }
298         return callbacks;
299     }
300 
dispatchOnProvideAssistData(Activity activity, Bundle data)301     /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
302         Object[] callbacks;
303         synchronized (this) {
304             if (mAssistCallbacks == null) {
305                 return;
306             }
307             callbacks = mAssistCallbacks.toArray();
308         }
309         if (callbacks != null) {
310             for (int i=0; i<callbacks.length; i++) {
311                 ((OnProvideAssistDataListener)callbacks[i]).onProvideAssistData(activity, data);
312             }
313         }
314     }
315 
316     /** @hide */
317     @Override
getAutofillClient()318     public AutofillManager.AutofillClient getAutofillClient() {
319         final AutofillManager.AutofillClient client = super.getAutofillClient();
320         if (client != null) {
321             return client;
322         }
323         if (android.view.autofill.Helper.sVerbose) {
324             Log.v(TAG, "getAutofillClient(): null on super, trying to find activity thread");
325         }
326         // Okay, ppl use the application context when they should not. This breaks
327         // autofill among other things. We pick the focused activity since autofill
328         // interacts only with the currently focused activity and we need the fill
329         // client only if a call comes from the focused activity. Sigh...
330         final ActivityThread activityThread = ActivityThread.currentActivityThread();
331         if (activityThread == null) {
332             return null;
333         }
334         final int activityCount = activityThread.mActivities.size();
335         for (int i = 0; i < activityCount; i++) {
336             final ActivityThread.ActivityClientRecord record =
337                     activityThread.mActivities.valueAt(i);
338             if (record == null) {
339                 continue;
340             }
341             final Activity activity = record.activity;
342             if (activity == null) {
343                 continue;
344             }
345             if (activity.getWindow().getDecorView().hasFocus()) {
346                 if (android.view.autofill.Helper.sVerbose) {
347                     Log.v(TAG, "getAutofillClient(): found activity for " + this + ": " + activity);
348                 }
349                 return activity;
350             }
351         }
352         if (android.view.autofill.Helper.sVerbose) {
353             Log.v(TAG, "getAutofillClient(): none of the " + activityCount + " activities on "
354                     + this + " have focus");
355         }
356         return null;
357     }
358 }
359