1636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden/*
2636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * Copyright (C) 2010 The Android Open Source Project
3636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden *
4636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
5636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * you may not use this file except in compliance with the License.
6636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * You may obtain a copy of the License at
7636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden *
8636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
9636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden *
10636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * Unless required by applicable law or agreed to in writing, software
11636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
12636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * See the License for the specific language governing permissions and
14636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * limitations under the License.
15636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden */
16636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
17636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenpackage com.android.calendar;
18636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
19636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.content.AsyncQueryHandler;
20636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.content.ContentResolver;
21636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.content.ContentValues;
22636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.content.Context;
23636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.content.SharedPreferences;
24636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.database.Cursor;
252dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowskiimport android.os.Looper;
26a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.CalendarCache;
27636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.text.TextUtils;
28636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.text.format.DateUtils;
29636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.text.format.Time;
30636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport android.util.Log;
31636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
32636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport java.util.Formatter;
33636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport java.util.HashSet;
34636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport java.util.Locale;
35636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
36636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden/**
37636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * A class containing utility methods related to Calendar apps.
38636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden *
39636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden * This class is expected to move into the app framework eventually.
40636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden */
41636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenpublic class CalendarUtils {
42636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden    private static final boolean DEBUG = false;
43636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden    private static final String TAG = "CalendarUtils";
44636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
45636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden    /**
46636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden     * This class contains methods specific to reading and writing time zone
47636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden     * values.
48636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden     */
49636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden    public static class TimeZoneUtils {
50fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        private static final String[] TIMEZONE_TYPE_ARGS = { CalendarCache.KEY_TIMEZONE_TYPE };
51636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static final String[] TIMEZONE_INSTANCES_ARGS =
52fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                { CalendarCache.KEY_TIMEZONE_INSTANCES };
53a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        public static final String[] CALENDAR_CACHE_POJECTION = {
54a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                CalendarCache.KEY, CalendarCache.VALUE
55a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        };
56636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
57636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static StringBuilder mSB = new StringBuilder(50);
58636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static Formatter mF = new Formatter(mSB, Locale.getDefault());
59636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private volatile static boolean mFirstTZRequest = true;
60636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private volatile static boolean mTZQueryInProgress = false;
61636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
62636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private volatile static boolean mUseHomeTZ = false;
63636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private volatile static String mHomeTZ = Time.getCurrentTimezone();
64636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
65636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>();
66636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static int mToken = 1;
67636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private static AsyncTZHandler mHandler;
68636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
69636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        // The name of the shared preferences file. This name must be maintained for historical
70636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        // reasons, as it's what PreferenceManager assigned the first time the file was created.
71636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private final String mPrefsName;
72636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
73636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
74636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This is the key used for writing whether or not a home time zone should
75636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * be used in the Calendar app to the Calendar Preferences.
76636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
77636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled";
78636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
79636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This is the key used for writing the time zone that should be used if
80636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * home time zones are enabled for the Calendar app.
81636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
82636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public static final String KEY_HOME_TZ = "preferences_home_tz";
83636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
84636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
85636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This is a helper class for handling the async queries and updates for the
86636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * time zone settings in Calendar.
87636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
88636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        private class AsyncTZHandler extends AsyncQueryHandler {
89636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            public AsyncTZHandler(ContentResolver cr) {
90636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                super(cr);
91636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
92636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
93636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            @Override
94636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
95636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                synchronized (mTZCallbacks) {
96636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    if (cursor == null) {
97636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        mTZQueryInProgress = false;
98636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        mFirstTZRequest = true;
99636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        return;
100636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
101636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
102636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    boolean writePrefs = false;
103636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    // Check the values in the db
104636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    int keyColumn = cursor.getColumnIndexOrThrow(CalendarCache.KEY);
105636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    int valueColumn = cursor.getColumnIndexOrThrow(CalendarCache.VALUE);
106636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    while(cursor.moveToNext()) {
107636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        String key = cursor.getString(keyColumn);
108636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        String value = cursor.getString(valueColumn);
109fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                        if (TextUtils.equals(key, CalendarCache.KEY_TIMEZONE_TYPE)) {
110636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            boolean useHomeTZ = !TextUtils.equals(
111636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                                    value, CalendarCache.TIMEZONE_TYPE_AUTO);
112636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            if (useHomeTZ != mUseHomeTZ) {
113636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                                writePrefs = true;
114636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                                mUseHomeTZ = useHomeTZ;
115636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            }
116636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        } else if (TextUtils.equals(
117fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                                key, CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS)) {
118636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            if (!TextUtils.isEmpty(value) && !TextUtils.equals(mHomeTZ, value)) {
119636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                                writePrefs = true;
120636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                                mHomeTZ = value;
121636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            }
122636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        }
123636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
124636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    cursor.close();
125636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    if (writePrefs) {
126636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        SharedPreferences prefs = getSharedPreferences((Context)cookie, mPrefsName);
127636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        // Write the prefs
128636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ);
129636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ);
130636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
131636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
132636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mTZQueryInProgress = false;
133636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    for (Runnable callback : mTZCallbacks) {
134636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        if (callback != null) {
135636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                            callback.run();
136636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        }
137636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
138636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mTZCallbacks.clear();
139636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
140636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
141636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
142636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
143636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
144636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * The name of the file where the shared prefs for Calendar are stored
145636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * must be provided. All activities within an app should provide the
146636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * same preferences name or behavior may become erratic.
147636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
148636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param prefsName
149636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
150636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public TimeZoneUtils(String prefsName) {
151636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            mPrefsName = prefsName;
152636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
153636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
154636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
155636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * Formats a date or a time range according to the local conventions.
156636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
157636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This formats a date/time range using Calendar's time zone and the
158636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * local conventions for the region of the device.
159636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
160636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * If the {@link DateUtils#FORMAT_UTC} flag is used it will pass in
161636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * the UTC time zone instead.
162636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
163636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context the context is required only if the time is shown
164636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param startMillis the start time in UTC milliseconds
165636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param endMillis the end time in UTC milliseconds
166636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param flags a bit mask of options See
167636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * {@link DateUtils#formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
168636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @return a string containing the formatted date/time range.
169636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
170636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public String formatDateRange(Context context, long startMillis,
171636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                long endMillis, int flags) {
172636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            String date;
173636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            String tz;
174636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            if ((flags & DateUtils.FORMAT_UTC) != 0) {
175636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                tz = Time.TIMEZONE_UTC;
176636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            } else {
177636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                tz = getTimeZone(context, null);
178636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
179636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            synchronized (mSB) {
180636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                mSB.setLength(0);
181636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                date = DateUtils.formatDateRange(context, mF, startMillis, endMillis, flags,
182636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        tz).toString();
183636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
184636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            return date;
185636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
186636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
187636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
188636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * Writes a new home time zone to the db.
189636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
190636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * Updates the home time zone in the db asynchronously and updates
191636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * the local cache. Sending a time zone of
192636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * {@link CalendarCache#TIMEZONE_TYPE_AUTO} will cause it to be set
193636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * to the device's time zone. null or empty tz will be ignored.
194636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
195636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context The calling activity
196636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param timeZone The time zone to set Calendar to, or
197636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * {@link CalendarCache#TIMEZONE_TYPE_AUTO}
198636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
199636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public void setTimeZone(Context context, String timeZone) {
200636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            if (TextUtils.isEmpty(timeZone)) {
201636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (DEBUG) {
202636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    Log.d(TAG, "Empty time zone, nothing to be done.");
203636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
204636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                return;
205636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
206636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            boolean updatePrefs = false;
207636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            synchronized (mTZCallbacks) {
208636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (CalendarCache.TIMEZONE_TYPE_AUTO.equals(timeZone)) {
209636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    if (mUseHomeTZ) {
210636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        updatePrefs = true;
211636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
212636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mUseHomeTZ = false;
213636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                } else {
214636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    if (!mUseHomeTZ || !TextUtils.equals(mHomeTZ, timeZone)) {
215636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        updatePrefs = true;
216636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
217636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mUseHomeTZ = true;
218636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mHomeTZ = timeZone;
219636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
220636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
221636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            if (updatePrefs) {
222636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                // Write the prefs
223636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                SharedPreferences prefs = getSharedPreferences(context, mPrefsName);
224636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ);
225636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ);
226636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
227636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                // Update the db
228636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                ContentValues values = new ContentValues();
229636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (mHandler != null) {
230636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mHandler.cancelOperation(mToken);
231636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
232636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
233636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                mHandler = new AsyncTZHandler(context.getContentResolver());
234636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
235636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                // skip 0 so query can use it
236636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (++mToken == 0) {
237636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mToken = 1;
238636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
239636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
240636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                // Write the use home tz setting
241636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                values.put(CalendarCache.VALUE, mUseHomeTZ ? CalendarCache.TIMEZONE_TYPE_HOME
242636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        : CalendarCache.TIMEZONE_TYPE_AUTO);
243fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                mHandler.startUpdate(mToken, null, CalendarCache.URI, values, "key=?",
244636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                        TIMEZONE_TYPE_ARGS);
245636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
246636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                // If using a home tz write it to the db
247636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (mUseHomeTZ) {
248636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    ContentValues values2 = new ContentValues();
249636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    values2.put(CalendarCache.VALUE, mHomeTZ);
250636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mHandler.startUpdate(mToken, null, CalendarCache.URI, values2,
251fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                            "key=?", TIMEZONE_INSTANCES_ARGS);
252636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
253636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
254636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
255636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
256636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
257636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * Gets the time zone that Calendar should be displayed in
258636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
259636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This is a helper method to get the appropriate time zone for Calendar. If this
260636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * is the first time this method has been called it will initiate an asynchronous
261636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * query to verify that the data in preferences is correct. The callback supplied
262636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * will only be called if this query returns a value other than what is stored in
263636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * preferences and should cause the calling activity to refresh anything that
264636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * depends on calling this method.
265636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
266636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context The calling activity
267636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param callback The runnable that should execute if a query returns new values
268636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @return The string value representing the time zone Calendar should display
269636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
270636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public String getTimeZone(Context context, Runnable callback) {
271636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            synchronized (mTZCallbacks){
272636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (mFirstTZRequest) {
273636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    SharedPreferences prefs = getSharedPreferences(context, mPrefsName);
274636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mUseHomeTZ = prefs.getBoolean(KEY_HOME_TZ_ENABLED, false);
275636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mHomeTZ = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone());
276636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
2772dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                    // Only check content resolver if we have a looper to attach to use
2782dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                    if (Looper.myLooper() != null) {
2792dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        mTZQueryInProgress = true;
2802dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        mFirstTZRequest = false;
2812dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski
2822dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        // When the async query returns it should synchronize on
2832dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the
2842dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        // preferences, set mTZQueryInProgress to false, and call all
2852dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        // the runnables in mTZCallbacks.
2862dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        if (mHandler == null) {
2872dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                            mHandler = new AsyncTZHandler(context.getContentResolver());
2882dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        }
2892dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                        mHandler.startQuery(0, context, CalendarCache.URI, CALENDAR_CACHE_POJECTION,
2902dc5984c3b2c7001c676922b51edc1a799fc7b0cPaul Sliwowski                                null, null, null);
291636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    }
292636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
293636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (mTZQueryInProgress) {
294636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mTZCallbacks.add(callback);
295636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
296636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
297636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone();
298636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
299636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
300636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
301636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * Forces a query of the database to check for changes to the time zone.
302636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * This should be called if another app may have modified the db. If a
303636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * query is already in progress the callback will be added to the list
304636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * of callbacks to be called when it returns.
305636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
306636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context The calling activity
307636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param callback The runnable that should execute if a query returns
308636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *            new values
309636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
310636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public void forceDBRequery(Context context, Runnable callback) {
311636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            synchronized (mTZCallbacks){
312636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                if (mTZQueryInProgress) {
313636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    mTZCallbacks.add(callback);
314636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                    return;
315636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                }
316636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                mFirstTZRequest = true;
317636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden                getTimeZone(context, callback);
318636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            }
319636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
320636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden    }
321636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
322636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
323636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * A helper method for writing a String value to the preferences
324636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * asynchronously.
325636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
326636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context A context with access to the correct preferences
327636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param key The preference to write to
328636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param value The value to write
329636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
330636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public static void setSharedPreference(SharedPreferences prefs, String key, String value) {
331636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden//            SharedPreferences prefs = getSharedPreferences(context);
332636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            SharedPreferences.Editor editor = prefs.edit();
333636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            editor.putString(key, value);
334636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            editor.apply();
335636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
336636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
337636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /**
338636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * A helper method for writing a boolean value to the preferences
339636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * asynchronously.
340636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         *
341636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param context A context with access to the correct preferences
342636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param key The preference to write to
343636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         * @param value The value to write
344636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden         */
345636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public static void setSharedPreference(SharedPreferences prefs, String key, boolean value) {
346636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden//            SharedPreferences prefs = getSharedPreferences(context, prefsName);
347636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            SharedPreferences.Editor editor = prefs.edit();
348636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            editor.putBoolean(key, value);
349636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            editor.apply();
350636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
351636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden
352636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        /** Return a properly configured SharedPreferences instance */
353636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        public static SharedPreferences getSharedPreferences(Context context, String prefsName) {
354636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden            return context.getSharedPreferences(prefsName, Context.MODE_PRIVATE);
355636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden        }
356636269c7220a2b12e090cab43a91eb34922eb61fAndy McFadden}
357