1f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov/*
2f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
3f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov *
4f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
5f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * you may not use this file except in compliance with the License.
6f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * You may obtain a copy of the License at
7f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov *
8f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
9f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov *
10f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
11f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
12f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * See the License for the specific language governing permissions and
14f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov * limitations under the License.
15f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov */
16f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov
17f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikovpackage com.android.contacts;
18f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov
19f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikovimport android.app.Application;
207c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onukiimport android.app.FragmentManager;
217c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onukiimport android.app.LoaderManager;
2243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikovimport android.content.ContentResolver;
23fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onukiimport android.content.ContentUris;
243b7dedd2cea8000200fd28f8aa6f9664c9044cefDmitri Plotnikovimport android.content.Context;
25072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikovimport android.content.SharedPreferences;
26fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onukiimport android.os.AsyncTask;
27f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikovimport android.os.StrictMode;
283b7dedd2cea8000200fd28f8aa6f9664c9044cefDmitri Plotnikovimport android.preference.PreferenceManager;
29fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onukiimport android.provider.ContactsContract.Contacts;
3049627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onukiimport android.util.Log;
313b7dedd2cea8000200fd28f8aa6f9664c9044cefDmitri Plotnikov
3279a6b5d3a885bc508b4b98c92a946fe12643c444Chiao Chengimport com.android.contacts.common.ContactPhotoManager;
330d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.list.ContactListFilterController;
340d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager;
357039633999b3a46a87c851fa06d9168897ccc54bYorke Leeimport com.android.contacts.common.testing.InjectedServices;
36d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Chengimport com.android.contacts.common.util.Constants;
37e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.annotations.VisibleForTesting;
38e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
39f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikovpublic final class ContactsApplication extends Application {
407c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki    private static final boolean ENABLE_LOADER_LOG = false; // Don't submit with true
417c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki    private static final boolean ENABLE_FRAGMENT_LOG = false; // Don't submit with true
427c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki
4343fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    private static InjectedServices sInjectedServices;
44d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng    /**
45d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     * Log tag for enabling/disabling StrictMode violation log.
46d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     * To enable: adb shell setprop log.tag.ContactsStrictMode DEBUG
47d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     */
48d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng    public static final String STRICT_MODE_TAG = "ContactsStrictMode";
4934b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov    private ContactPhotoManager mContactPhotoManager;
50a012aec6f22dd6a37c518c895db45b173e186ef4Daisuke Miyakawa    private ContactListFilterController mContactListFilterController;
5143fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
5243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    /**
5343fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov     * Overrides the system services with mocks for testing.
5443fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov     */
5537a2684d1e47f6d78d757c437a187548f242ee13Flavio Lerda    @VisibleForTesting
566f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    public static void injectServices(InjectedServices services) {
5743fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        sInjectedServices = services;
5843fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    }
5943fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
601173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov    public static InjectedServices getInjectedServices() {
611173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov        return sInjectedServices;
621173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov    }
631173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov
6443fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    @Override
6543fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    public ContentResolver getContentResolver() {
6643fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        if (sInjectedServices != null) {
6743fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            ContentResolver resolver = sInjectedServices.getContentResolver();
6843fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            if (resolver != null) {
6943fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov                return resolver;
7043fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            }
7143fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        }
7243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        return super.getContentResolver();
73072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    }
74072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov
75072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    @Override
76072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    public SharedPreferences getSharedPreferences(String name, int mode) {
77072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        if (sInjectedServices != null) {
78072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            SharedPreferences prefs = sInjectedServices.getSharedPreferences();
79072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            if (prefs != null) {
80072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov                return prefs;
81072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            }
82072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        }
83072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov
84072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        return super.getSharedPreferences(name, mode);
8543fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    }
8643fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
87f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    @Override
886f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    public Object getSystemService(String name) {
896f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        if (sInjectedServices != null) {
906f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            Object service = sInjectedServices.getSystemService(name);
916f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            if (service != null) {
926f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov                return service;
936f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            }
946f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        }
956f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov
9634b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov        if (ContactPhotoManager.CONTACT_PHOTO_SERVICE.equals(name)) {
9734b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov            if (mContactPhotoManager == null) {
9834b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov                mContactPhotoManager = ContactPhotoManager.createContactPhotoManager(this);
998f8bd6dd334155c4fb953ca2735328d5a5b0c737Makoto Onuki                registerComponentCallbacks(mContactPhotoManager);
1007edf238cb6e051bb53d327d9b435bbf5b4aa11c4Dmitri Plotnikov                mContactPhotoManager.preloadPhotosInBackground();
10134b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov            }
10234b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov            return mContactPhotoManager;
10334b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov        }
10434b24ef363e2bcca072c34371144a845186d625eDmitri Plotnikov
1056f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        return super.getSystemService(name);
1066f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    }
1076f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov
1086f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    @Override
109f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    public void onCreate() {
110f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov        super.onCreate();
111f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov
11249627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
11349627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki            Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate start");
11449627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        }
11549627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki
1167c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki        if (ENABLE_FRAGMENT_LOG) FragmentManager.enableDebugLogging(true);
1177c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki        if (ENABLE_LOADER_LOG) LoaderManager.enableDebugLogging(true);
1183b7dedd2cea8000200fd28f8aa6f9664c9044cefDmitri Plotnikov
119d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng        if (Log.isLoggable(STRICT_MODE_TAG, Log.DEBUG)) {
120b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa            StrictMode.setThreadPolicy(
121b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa                    new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
122b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa        }
12349627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki
124fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        // Perform the initialization that doesn't have to finish immediately.
125fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        // We use an async task here just to avoid creating a new thread.
126fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        (new DelayedInitializer()).execute();
127fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
12849627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
12949627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki            Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate finish");
13049627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        }
131f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    }
132fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
133fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki    private class DelayedInitializer extends AsyncTask<Void, Void, Void> {
134fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        @Override
135fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        protected Void doInBackground(Void... params) {
136fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            final Context context = ContactsApplication.this;
137fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
138fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            // Warm up the preferences, the account type manager and the contacts provider.
139fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            PreferenceManager.getDefaultSharedPreferences(context);
140fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            AccountTypeManager.getInstance(context);
141fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            getContentResolver().getType(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1));
142fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            return null;
143fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        }
144fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
145fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        public void execute() {
146fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
147fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki                    (Void[]) null);
148fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        }
149fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki    }
150f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov}
151