1cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project/*
2cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project**
3cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** Copyright 2008, The Android Open Source Project
4cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project**
5cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** you may not use this file except in compliance with the License.
7cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** You may obtain a copy of the License at
8cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project**
9cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project**
11cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** See the License for the specific language governing permissions and
14cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project** limitations under the License.
16cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project*/
17cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
18cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectpackage com.android.providers.calendar;
19cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
20cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
21cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectimport android.content.ContentValues;
22cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectimport android.database.Cursor;
23cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
24cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper;
25b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.CalendarMetaData;
26cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
27cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project/**
28cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project * The global meta-data used for expanding the Instances table is stored in one
29cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project * row of the "CalendarMetaData" table.  This class is used for caching those
30cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project * values to avoid repeatedly banging on the database.  It is also used
31cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project * for writing the values back to the database, while maintaining the
32cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project * consistency of the cache.
334caf8d015918f619a67d321a152f150a01022717Andy McFadden * <p>
344caf8d015918f619a67d321a152f150a01022717Andy McFadden * TODO: there must be only one of these active within CalendarProvider.  Enforce this.
35cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project */
36cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Projectpublic class MetaData {
37cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
38cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * These fields are updated atomically with the database.
39cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * If fields are added or removed from the CalendarMetaData table, those
40cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * changes must also be reflected here.
41cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
42cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public class Fields {
43cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        public String timezone;     // local timezone used for Instance expansion
44cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        public long minInstance;    // UTC millis
45cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        public long maxInstance;    // UTC millis
46cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
476db535b458146a279bebd4a51d56c1bdfc204528Erik
48cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
49cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * The cached copy of the meta-data fields from the database.
50cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
51cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private Fields mFields = new Fields();
526db535b458146a279bebd4a51d56c1bdfc204528Erik
53cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private final SQLiteOpenHelper mOpenHelper;
54cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private boolean mInitialized;
55cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
56cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
57cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * The column names in the CalendarMetaData table.  This projection
58cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * must contain all of the columns.
59cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
60cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private static final String[] sCalendarMetaDataProjection = {
61cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        CalendarMetaData.LOCAL_TIMEZONE,
62cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        CalendarMetaData.MIN_INSTANCE,
636db535b458146a279bebd4a51d56c1bdfc204528Erik        CalendarMetaData.MAX_INSTANCE};
646db535b458146a279bebd4a51d56c1bdfc204528Erik
65cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private static final int METADATA_INDEX_LOCAL_TIMEZONE = 0;
66cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private static final int METADATA_INDEX_MIN_INSTANCE = 1;
67cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private static final int METADATA_INDEX_MAX_INSTANCE = 2;
686db535b458146a279bebd4a51d56c1bdfc204528Erik
69cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public MetaData(SQLiteOpenHelper openHelper) {
70cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mOpenHelper = openHelper;
71cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
726db535b458146a279bebd4a51d56c1bdfc204528Erik
73cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
74cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Returns a copy of all the MetaData fields.  This method grabs a
75cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * database lock to read all the fields atomically.
766db535b458146a279bebd4a51d56c1bdfc204528Erik     *
77cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @return a copy of all the MetaData fields.
78cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
79cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public Fields getFields() {
80cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        Fields fields = new Fields();
81cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
82cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        db.beginTransaction();
83cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        try {
84cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            // If the fields have not been initialized from the database,
85cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            // then read the database.
86cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            if (!mInitialized) {
87cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                readLocked(db);
88cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            }
89cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            fields.timezone = mFields.timezone;
90cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            fields.minInstance = mFields.minInstance;
91cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            fields.maxInstance = mFields.maxInstance;
92cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.setTransactionSuccessful();
93cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        } finally {
94cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.endTransaction();
95cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
96cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        return fields;
97cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
98cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
99cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
100cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * This method must be called only while holding a database lock.
1016db535b458146a279bebd4a51d56c1bdfc204528Erik     *
102cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * <p>
103cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Returns a copy of all the MetaData fields.  This method assumes
104cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * the database lock has already been acquired.
105cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * </p>
1066db535b458146a279bebd4a51d56c1bdfc204528Erik     *
107cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @return a copy of all the MetaData fields.
108cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
109cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public Fields getFieldsLocked() {
110cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        Fields fields = new Fields();
111cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
112cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // If the fields have not been initialized from the database,
113cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // then read the database.
114cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        if (!mInitialized) {
115cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            SQLiteDatabase db = mOpenHelper.getReadableDatabase();
116cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            readLocked(db);
117cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
118cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        fields.timezone = mFields.timezone;
119cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        fields.minInstance = mFields.minInstance;
120cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        fields.maxInstance = mFields.maxInstance;
121cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        return fields;
122cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
1236db535b458146a279bebd4a51d56c1bdfc204528Erik
124cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
125cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Reads the meta-data for the CalendarProvider from the database and
126cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * updates the member variables.  This method executes while the database
127cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * lock is held.  If there were no exceptions reading the database,
128cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * mInitialized is set to true.
129cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
130cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    private void readLocked(SQLiteDatabase db) {
131cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        String timezone = null;
132cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        long minInstance = 0, maxInstance = 0;
133cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
134cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // Read the database directly.  We only do this once to initialize
135cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // the members of this class.
136cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        Cursor cursor = db.query("CalendarMetaData", sCalendarMetaDataProjection,
137cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                null, null, null, null, null);
138cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        try {
139cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            if (cursor.moveToNext()) {
140cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                timezone = cursor.getString(METADATA_INDEX_LOCAL_TIMEZONE);
141cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                minInstance = cursor.getLong(METADATA_INDEX_MIN_INSTANCE);
142cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                maxInstance = cursor.getLong(METADATA_INDEX_MAX_INSTANCE);
143cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            }
144cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        } finally {
145cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            if (cursor != null) {
146cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                cursor.close();
147cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            }
148cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
149cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
150cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // Cache the result of reading the database
151cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.timezone = timezone;
152cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.minInstance = minInstance;
153cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.maxInstance = maxInstance;
1546db535b458146a279bebd4a51d56c1bdfc204528Erik
155cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // Mark the fields as initialized
156cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mInitialized = true;
157cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
158cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
159cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
160cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Writes the meta-data for the CalendarProvider.  The values to write are
161cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * passed in as parameters.  All of the values are updated atomically,
162cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * including the cached copy of the meta-data.
1636db535b458146a279bebd4a51d56c1bdfc204528Erik     *
164cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param timezone the local timezone used for Instance expansion
165cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param begin the start of the Instance expansion in UTC milliseconds
166cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param end the end of the Instance expansion in UTC milliseconds
167cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param startDay the start of the BusyBit expansion (the start Julian day)
168cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param endDay the end of the BusyBit expansion (the end Julian day)
169cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
170cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public void write(String timezone, long begin, long end, int startDay, int endDay) {
171cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
172cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        db.beginTransaction();
173cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        try {
174dbd797d59294d72d7ea9226d10128674b634aaadErik            writeLocked(timezone, begin, end);
175cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.setTransactionSuccessful();
176cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        } finally {
177cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.endTransaction();
178cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
179cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
180cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
181cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
182cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * This method must be called only while holding a database lock.
1836db535b458146a279bebd4a51d56c1bdfc204528Erik     *
184cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * <p>
185cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Writes the meta-data for the CalendarProvider.  The values to write are
186cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * passed in as parameters.  All of the values are updated atomically,
187cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * including the cached copy of the meta-data.
188cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * </p>
1896db535b458146a279bebd4a51d56c1bdfc204528Erik     *
190cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param timezone the local timezone used for Instance expansion
191cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param begin the start of the Instance expansion in UTC milliseconds
192cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * @param end the end of the Instance expansion in UTC milliseconds
193cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
194dbd797d59294d72d7ea9226d10128674b634aaadErik    public void writeLocked(String timezone, long begin, long end) {
195cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        ContentValues values = new ContentValues();
196cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        values.put("_id", 1);
197cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        values.put(CalendarMetaData.LOCAL_TIMEZONE, timezone);
198cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        values.put(CalendarMetaData.MIN_INSTANCE, begin);
199cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        values.put(CalendarMetaData.MAX_INSTANCE, end);
200cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
201cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // Atomically update the database and the cached members.
202cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        try {
203cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
204cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.replace("CalendarMetaData", null, values);
205cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        } catch (RuntimeException e) {
206cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            // Failed: zero the in-memory fields to force recomputation.
207cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            mFields.timezone = null;
208cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            mFields.minInstance = mFields.maxInstance = 0;
209cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            throw e;
210cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
211cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
212cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        // Update the cached members last in case the database update fails
213cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.timezone = timezone;
214cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.minInstance = begin;
215cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        mFields.maxInstance = end;
216cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
217cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project
218cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    /**
219cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Clears the time range for the Instances table.  The rows in the
220cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Instances table will be deleted (and regenerated) the next time
221cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * that the Instances table is queried.
2226db535b458146a279bebd4a51d56c1bdfc204528Erik     *
223cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * Also clears the time range for the BusyBits table because that depends
224cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     * on the Instances table.
225cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project     */
226cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    public void clearInstanceRange() {
227cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
228cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        db.beginTransaction();
229cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        try {
230cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            // If the fields have not been initialized from the database,
231cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            // then read the database.
232cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            if (!mInitialized) {
233cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project                readLocked(db);
234cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            }
235dbd797d59294d72d7ea9226d10128674b634aaadErik            writeLocked(mFields.timezone, 0 /* begin */, 0 /* end */);
236cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.setTransactionSuccessful();
237cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        } finally {
238cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project            db.endTransaction();
239cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project        }
240cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project    }
241cf013ece751816a07396845858f1c7037ead464fThe Android Open Source Project}
242