1 /*
2  * Copyright (C) 2010 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 com.android.contacts;
18 
19 import android.app.Application;
20 import android.app.FragmentManager;
21 import android.app.LoaderManager;
22 import android.content.ContentResolver;
23 import android.content.ContentUris;
24 import android.content.Context;
25 import android.content.SharedPreferences;
26 import android.os.AsyncTask;
27 import android.os.StrictMode;
28 import android.preference.PreferenceManager;
29 import android.provider.ContactsContract.Contacts;
30 import android.util.Log;
31 
32 import com.android.contacts.common.ContactPhotoManager;
33 import com.android.contacts.common.list.ContactListFilterController;
34 import com.android.contacts.common.model.AccountTypeManager;
35 import com.android.contacts.common.testing.InjectedServices;
36 import com.android.contacts.common.util.Constants;
37 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
38 
39 import com.google.common.annotations.VisibleForTesting;
40 
41 public final class ContactsApplication extends Application {
42     private static final boolean ENABLE_LOADER_LOG = false; // Don't submit with true
43     private static final boolean ENABLE_FRAGMENT_LOG = false; // Don't submit with true
44 
45     private static InjectedServices sInjectedServices;
46     /**
47      * Log tag for enabling/disabling StrictMode violation log.
48      * To enable: adb shell setprop log.tag.ContactsStrictMode DEBUG
49      */
50     public static final String STRICT_MODE_TAG = "ContactsStrictMode";
51     private ContactPhotoManager mContactPhotoManager;
52     private ContactListFilterController mContactListFilterController;
53 
54     /**
55      * Overrides the system services with mocks for testing.
56      */
57     @VisibleForTesting
injectServices(InjectedServices services)58     public static void injectServices(InjectedServices services) {
59         sInjectedServices = services;
60     }
61 
getInjectedServices()62     public static InjectedServices getInjectedServices() {
63         return sInjectedServices;
64     }
65 
66     @Override
getContentResolver()67     public ContentResolver getContentResolver() {
68         if (sInjectedServices != null) {
69             ContentResolver resolver = sInjectedServices.getContentResolver();
70             if (resolver != null) {
71                 return resolver;
72             }
73         }
74         return super.getContentResolver();
75     }
76 
77     @Override
getSharedPreferences(String name, int mode)78     public SharedPreferences getSharedPreferences(String name, int mode) {
79         if (sInjectedServices != null) {
80             SharedPreferences prefs = sInjectedServices.getSharedPreferences();
81             if (prefs != null) {
82                 return prefs;
83             }
84         }
85 
86         return super.getSharedPreferences(name, mode);
87     }
88 
89     @Override
getSystemService(String name)90     public Object getSystemService(String name) {
91         if (sInjectedServices != null) {
92             Object service = sInjectedServices.getSystemService(name);
93             if (service != null) {
94                 return service;
95             }
96         }
97 
98         if (ContactPhotoManager.CONTACT_PHOTO_SERVICE.equals(name)) {
99             if (mContactPhotoManager == null) {
100                 mContactPhotoManager = ContactPhotoManager.createContactPhotoManager(this);
101                 registerComponentCallbacks(mContactPhotoManager);
102                 mContactPhotoManager.preloadPhotosInBackground();
103             }
104             return mContactPhotoManager;
105         }
106 
107         return super.getSystemService(name);
108     }
109 
110     @Override
onCreate()111     public void onCreate() {
112         super.onCreate();
113 
114         if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
115             Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate start");
116         }
117 
118         if (ENABLE_FRAGMENT_LOG) FragmentManager.enableDebugLogging(true);
119         if (ENABLE_LOADER_LOG) LoaderManager.enableDebugLogging(true);
120 
121         if (Log.isLoggable(STRICT_MODE_TAG, Log.DEBUG)) {
122             StrictMode.setThreadPolicy(
123                     new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
124         }
125 
126         // Perform the initialization that doesn't have to finish immediately.
127         // We use an async task here just to avoid creating a new thread.
128         (new DelayedInitializer()).execute();
129 
130         if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
131             Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate finish");
132         }
133 
134         AnalyticsUtil.initialize(this);
135     }
136 
137     private class DelayedInitializer extends AsyncTask<Void, Void, Void> {
138         @Override
doInBackground(Void... params)139         protected Void doInBackground(Void... params) {
140             final Context context = ContactsApplication.this;
141 
142             // Warm up the preferences, the account type manager and the contacts provider.
143             PreferenceManager.getDefaultSharedPreferences(context);
144             AccountTypeManager.getInstance(context);
145             getContentResolver().getType(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1));
146             return null;
147         }
148 
execute()149         public void execute() {
150             executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
151                     (Void[]) null);
152         }
153     }
154 }
155