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