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
17package android.app;
18
19import java.util.ArrayList;
20
21import android.content.ComponentCallbacks;
22import android.content.ComponentCallbacks2;
23import android.content.Context;
24import android.content.ContextWrapper;
25import android.content.Intent;
26import android.content.res.Configuration;
27import android.os.Bundle;
28
29/**
30 * Base class for those who need to maintain global application state. You can
31 * provide your own implementation by specifying its name in your
32 * AndroidManifest.xml's <application> tag, which will cause that class
33 * to be instantiated for you when the process for your application/package is
34 * created.
35 *
36 * <p class="note">There is normally no need to subclass Application.  In
37 * most situation, static singletons can provide the same functionality in a
38 * more modular way.  If your singleton needs a global context (for example
39 * to register broadcast receivers), the function to retrieve it can be
40 * given a {@link android.content.Context} which internally uses
41 * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
42 * when first constructing the singleton.</p>
43 */
44public class Application extends ContextWrapper implements ComponentCallbacks2 {
45    private ArrayList<ComponentCallbacks> mComponentCallbacks =
46            new ArrayList<ComponentCallbacks>();
47    private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
48            new ArrayList<ActivityLifecycleCallbacks>();
49    private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
50
51    /** @hide */
52    public LoadedApk mLoadedApk;
53
54    public interface ActivityLifecycleCallbacks {
55        void onActivityCreated(Activity activity, Bundle savedInstanceState);
56        void onActivityStarted(Activity activity);
57        void onActivityResumed(Activity activity);
58        void onActivityPaused(Activity activity);
59        void onActivityStopped(Activity activity);
60        void onActivitySaveInstanceState(Activity activity, Bundle outState);
61        void onActivityDestroyed(Activity activity);
62    }
63
64    /**
65     * Callback interface for use with {@link Application#registerOnProvideAssistDataListener}
66     * and {@link Application#unregisterOnProvideAssistDataListener}.
67     */
68    public interface OnProvideAssistDataListener {
69        /**
70         * This is called when the user is requesting an assist, to build a full
71         * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
72         * application.  You can override this method to place into the bundle anything
73         * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
74         * of the assist Intent.
75         */
76        public void onProvideAssistData(Activity activity, Bundle data);
77    }
78
79    public Application() {
80        super(null);
81    }
82
83    /**
84     * Called when the application is starting, before any activity, service,
85     * or receiver objects (excluding content providers) have been created.
86     * Implementations should be as quick as possible (for example using
87     * lazy initialization of state) since the time spent in this function
88     * directly impacts the performance of starting the first activity,
89     * service, or receiver in a process.
90     * If you override this method, be sure to call super.onCreate().
91     */
92    public void onCreate() {
93    }
94
95    /**
96     * This method is for use in emulated process environments.  It will
97     * never be called on a production Android device, where processes are
98     * removed by simply killing them; no user code (including this callback)
99     * is executed when doing so.
100     */
101    public void onTerminate() {
102    }
103
104    public void onConfigurationChanged(Configuration newConfig) {
105        Object[] callbacks = collectComponentCallbacks();
106        if (callbacks != null) {
107            for (int i=0; i<callbacks.length; i++) {
108                ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
109            }
110        }
111    }
112
113    public void onLowMemory() {
114        Object[] callbacks = collectComponentCallbacks();
115        if (callbacks != null) {
116            for (int i=0; i<callbacks.length; i++) {
117                ((ComponentCallbacks)callbacks[i]).onLowMemory();
118            }
119        }
120    }
121
122    public void onTrimMemory(int level) {
123        Object[] callbacks = collectComponentCallbacks();
124        if (callbacks != null) {
125            for (int i=0; i<callbacks.length; i++) {
126                Object c = callbacks[i];
127                if (c instanceof ComponentCallbacks2) {
128                    ((ComponentCallbacks2)c).onTrimMemory(level);
129                }
130            }
131        }
132    }
133
134    public void registerComponentCallbacks(ComponentCallbacks callback) {
135        synchronized (mComponentCallbacks) {
136            mComponentCallbacks.add(callback);
137        }
138    }
139
140    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
141        synchronized (mComponentCallbacks) {
142            mComponentCallbacks.remove(callback);
143        }
144    }
145
146    public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
147        synchronized (mActivityLifecycleCallbacks) {
148            mActivityLifecycleCallbacks.add(callback);
149        }
150    }
151
152    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
153        synchronized (mActivityLifecycleCallbacks) {
154            mActivityLifecycleCallbacks.remove(callback);
155        }
156    }
157
158    public void registerOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
159        synchronized (this) {
160            if (mAssistCallbacks == null) {
161                mAssistCallbacks = new ArrayList<OnProvideAssistDataListener>();
162            }
163            mAssistCallbacks.add(callback);
164        }
165    }
166
167    public void unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
168        synchronized (this) {
169            if (mAssistCallbacks != null) {
170                mAssistCallbacks.remove(callback);
171            }
172        }
173    }
174
175    // ------------------ Internal API ------------------
176
177    /**
178     * @hide
179     */
180    /* package */ final void attach(Context context) {
181        attachBaseContext(context);
182        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
183    }
184
185    /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
186        Object[] callbacks = collectActivityLifecycleCallbacks();
187        if (callbacks != null) {
188            for (int i=0; i<callbacks.length; i++) {
189                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
190                        savedInstanceState);
191            }
192        }
193    }
194
195    /* package */ void dispatchActivityStarted(Activity activity) {
196        Object[] callbacks = collectActivityLifecycleCallbacks();
197        if (callbacks != null) {
198            for (int i=0; i<callbacks.length; i++) {
199                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
200            }
201        }
202    }
203
204    /* package */ void dispatchActivityResumed(Activity activity) {
205        Object[] callbacks = collectActivityLifecycleCallbacks();
206        if (callbacks != null) {
207            for (int i=0; i<callbacks.length; i++) {
208                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
209            }
210        }
211    }
212
213    /* package */ void dispatchActivityPaused(Activity activity) {
214        Object[] callbacks = collectActivityLifecycleCallbacks();
215        if (callbacks != null) {
216            for (int i=0; i<callbacks.length; i++) {
217                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
218            }
219        }
220    }
221
222    /* package */ void dispatchActivityStopped(Activity activity) {
223        Object[] callbacks = collectActivityLifecycleCallbacks();
224        if (callbacks != null) {
225            for (int i=0; i<callbacks.length; i++) {
226                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
227            }
228        }
229    }
230
231    /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
232        Object[] callbacks = collectActivityLifecycleCallbacks();
233        if (callbacks != null) {
234            for (int i=0; i<callbacks.length; i++) {
235                ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
236                        outState);
237            }
238        }
239    }
240
241    /* package */ void dispatchActivityDestroyed(Activity activity) {
242        Object[] callbacks = collectActivityLifecycleCallbacks();
243        if (callbacks != null) {
244            for (int i=0; i<callbacks.length; i++) {
245                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
246            }
247        }
248    }
249
250    private Object[] collectComponentCallbacks() {
251        Object[] callbacks = null;
252        synchronized (mComponentCallbacks) {
253            if (mComponentCallbacks.size() > 0) {
254                callbacks = mComponentCallbacks.toArray();
255            }
256        }
257        return callbacks;
258    }
259
260    private Object[] collectActivityLifecycleCallbacks() {
261        Object[] callbacks = null;
262        synchronized (mActivityLifecycleCallbacks) {
263            if (mActivityLifecycleCallbacks.size() > 0) {
264                callbacks = mActivityLifecycleCallbacks.toArray();
265            }
266        }
267        return callbacks;
268    }
269
270    /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
271        Object[] callbacks;
272        synchronized (this) {
273            if (mAssistCallbacks == null) {
274                return;
275            }
276            callbacks = mAssistCallbacks.toArray();
277        }
278        if (callbacks != null) {
279            for (int i=0; i<callbacks.length; i++) {
280                ((OnProvideAssistDataListener)callbacks[i]).onProvideAssistData(activity, data);
281            }
282        }
283    }
284}
285