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