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