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
3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.testing.InjectedServices;
3369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.util.Constants;
34e837ae3e14c3e5a3f22a1bc69fe462caa278d7d8Walter Jangimport com.android.contactsbind.analytics.AnalyticsUtil;
35a3e498a1d189010791f98183c1267d869f0d941bBrian Attwell
36e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.annotations.VisibleForTesting;
37e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
38457f865b7080218c7253337b667d64d7e51ec11cWalter Jangpublic class ContactsApplication extends Application {
397c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki    private static final boolean ENABLE_LOADER_LOG = false; // Don't submit with true
407c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki    private static final boolean ENABLE_FRAGMENT_LOG = false; // Don't submit with true
417c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki
4243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    private static InjectedServices sInjectedServices;
43d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng    /**
44d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     * Log tag for enabling/disabling StrictMode violation log.
45d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     * To enable: adb shell setprop log.tag.ContactsStrictMode DEBUG
46d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng     */
47d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng    public static final String STRICT_MODE_TAG = "ContactsStrictMode";
4843fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
4943fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    /**
5043fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov     * Overrides the system services with mocks for testing.
5143fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov     */
5237a2684d1e47f6d78d757c437a187548f242ee13Flavio Lerda    @VisibleForTesting
536f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    public static void injectServices(InjectedServices services) {
5443fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        sInjectedServices = services;
5543fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    }
5643fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
571173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov    public static InjectedServices getInjectedServices() {
581173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov        return sInjectedServices;
591173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov    }
601173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov
6143fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    @Override
6243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    public ContentResolver getContentResolver() {
6343fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        if (sInjectedServices != null) {
6443fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            ContentResolver resolver = sInjectedServices.getContentResolver();
6543fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            if (resolver != null) {
6643fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov                return resolver;
6743fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov            }
6843fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        }
6943fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov        return super.getContentResolver();
70072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    }
71072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov
72072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    @Override
73072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov    public SharedPreferences getSharedPreferences(String name, int mode) {
74072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        if (sInjectedServices != null) {
75072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            SharedPreferences prefs = sInjectedServices.getSharedPreferences();
76072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            if (prefs != null) {
77072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov                return prefs;
78072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov            }
79072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        }
80072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov
81072d91171c749f43b64900118e6f4dcbdd7b1097Dmitri Plotnikov        return super.getSharedPreferences(name, mode);
8243fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov    }
8343fd1e84de5e28639062c20d35ba7bfec8a07001Dmitri Plotnikov
84f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    @Override
856f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    public Object getSystemService(String name) {
866f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        if (sInjectedServices != null) {
876f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            Object service = sInjectedServices.getSystemService(name);
886f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            if (service != null) {
896f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov                return service;
906f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov            }
916f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        }
926f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov
936f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov        return super.getSystemService(name);
946f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    }
956f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov
966f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikov    @Override
97f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    public void onCreate() {
98f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov        super.onCreate();
99f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov
10049627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
10149627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki            Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate start");
10249627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        }
10349627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki
1047c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki        if (ENABLE_FRAGMENT_LOG) FragmentManager.enableDebugLogging(true);
1057c91de1e983b35d9c5aef7386ea62c1daa2bf967Makoto Onuki        if (ENABLE_LOADER_LOG) LoaderManager.enableDebugLogging(true);
1063b7dedd2cea8000200fd28f8aa6f9664c9044cefDmitri Plotnikov
107d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Cheng        if (Log.isLoggable(STRICT_MODE_TAG, Log.DEBUG)) {
108b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa            StrictMode.setThreadPolicy(
109b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa                    new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
110b5c9f63a8e32e0eab77daf98661d318f6248eb7dDaisuke Miyakawa        }
11149627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki
112fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        // Perform the initialization that doesn't have to finish immediately.
113fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        // We use an async task here just to avoid creating a new thread.
114fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        (new DelayedInitializer()).execute();
115fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
11649627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
11749627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki            Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate finish");
11849627cc3f606085d001397ebba93dcb52bf67a5cMakoto Onuki        }
119a3e498a1d189010791f98183c1267d869f0d941bBrian Attwell
120a3e498a1d189010791f98183c1267d869f0d941bBrian Attwell        AnalyticsUtil.initialize(this);
121f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov    }
122fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
123fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki    private class DelayedInitializer extends AsyncTask<Void, Void, Void> {
124fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        @Override
125fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        protected Void doInBackground(Void... params) {
126fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            final Context context = ContactsApplication.this;
127fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
128dccfa943899e16aac8f4436916361bfabed3132fWalter Jang            // Warm up the preferences and the contacts provider.  We delay initialization
129dccfa943899e16aac8f4436916361bfabed3132fWalter Jang            // of the account type manager because we may not have the contacts group permission
130dccfa943899e16aac8f4436916361bfabed3132fWalter Jang            // (and thus not have the get accounts permission).
131fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            PreferenceManager.getDefaultSharedPreferences(context);
132fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            getContentResolver().getType(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1));
133dccfa943899e16aac8f4436916361bfabed3132fWalter Jang
134fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            return null;
135fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        }
136fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki
137fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        public void execute() {
138fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
139fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki                    (Void[]) null);
140fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki        }
141fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki    }
142f049ff0f841b90f5e7973dba51b37b4e1ec3c960Dmitri Plotnikov}
143