1/*
2 * Copyright (C) 2015 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.providers.contacts;
18
19import static com.android.providers.contacts.TestUtils.createDatabaseSnapshot;
20import static com.android.providers.contacts.TestUtils.cv;
21import static com.android.providers.contacts.TestUtils.executeSqlFromAssetFile;
22
23import android.database.Cursor;
24import android.database.sqlite.SQLiteDatabase;
25import android.provider.BaseColumns;
26import android.provider.CallLog.Calls;
27import android.provider.ContactsContract.AggregationExceptions;
28import android.provider.ContactsContract.Contacts;
29import android.provider.ContactsContract.Data;
30import android.provider.ContactsContract.DeletedContacts;
31import android.provider.ContactsContract.Directory;
32import android.provider.ContactsContract.DisplayNameSources;
33import android.provider.ContactsContract.Groups;
34import android.provider.ContactsContract.MetadataSync;
35import android.provider.ContactsContract.MetadataSyncState;
36import android.provider.ContactsContract.PhotoFiles;
37import android.provider.ContactsContract.PinnedPositions;
38import android.provider.ContactsContract.RawContacts;
39import android.provider.ContactsContract.Settings;
40import android.provider.ContactsContract.StatusUpdates;
41import android.provider.ContactsContract.StreamItemPhotos;
42import android.provider.ContactsContract.StreamItems;
43import android.provider.VoicemailContract.Status;
44import android.provider.VoicemailContract.Voicemails;
45import android.test.suitebuilder.annotation.LargeTest;
46
47import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
48import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
49import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
50import com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns;
51import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
52import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
53import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
54import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
55import com.android.providers.contacts.ContactsDatabaseHelper.MetadataSyncColumns;
56import com.android.providers.contacts.ContactsDatabaseHelper.MetadataSyncStateColumns;
57import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
58import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
59import com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns;
60import com.android.providers.contacts.ContactsDatabaseHelper.PackagesColumns;
61import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
62import com.android.providers.contacts.ContactsDatabaseHelper.PreAuthorizedUris;
63import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
64import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
65import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
66import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
67import com.android.providers.contacts.testutil.TestUtil;
68import com.android.providers.contacts.util.PropertyUtils;
69
70import junit.framework.AssertionFailedError;
71
72import java.io.BufferedReader;
73import java.io.IOException;
74import java.io.InputStream;
75import java.io.InputStreamReader;
76import java.util.HashMap;
77
78/**
79 * Unit tests for database create/upgrade operations in  {@link ContactsDatabaseHelper}.
80 *
81 * Tests are only performed after version 1108, based on the sql dump asset in
82 * ContactsDatabaseHelperUpgradeTest#CONTACTS2_DB_1108_ASSET_NAME
83 *
84 * Run the test like this: <code> runtest -c com.android.providers.contacts.ContactsDatabaseHelperUpgradeTest
85 * contactsprov </code>
86 */
87@LargeTest
88public class ContactsDatabaseHelperUpgradeTest extends BaseDatabaseHelperUpgradeTest {
89
90    private static final String CONTACTS2_DB_1108_ASSET_NAME = "upgradeTest/contacts2_1108.sql";
91
92    /**
93     * The helper instance.  Note we just use it to call the upgrade method.  The database
94     * hold by this instance is not used in this test.
95     */
96    private ContactsDatabaseHelper mHelper;
97
98    @Override
99    protected void setUp() throws Exception {
100        super.setUp();
101        mHelper = ContactsDatabaseHelper.getNewInstanceForTest(getContext(),
102                TestUtils.getContactsDatabaseFilename(getContext()));
103        mHelper.onConfigure(mDb);
104    }
105
106    @Override
107    protected void tearDown() throws Exception {
108        mHelper.close();
109        super.tearDown();
110    }
111
112    @Override
113    protected String getDatabaseFilename() {
114        return TestUtils.getContactsDatabaseFilename(getContext(), "-upgrade-test");
115    }
116
117    public void testDatabaseCreate() {
118        mHelper.onCreate(mDb);
119        assertDatabaseStructureSameAsList(TABLE_LIST, /* isNewDatabase =*/ true);
120    }
121
122    public void testDatabaseUpgrade_UpgradeToCurrent() {
123        create1108(mDb);
124        int oldVersion = upgrade(1108, 1200);
125        oldVersion = upgradeTo1201(oldVersion);
126        oldVersion = upgrade(oldVersion, ContactsDatabaseHelper.DATABASE_VERSION);
127
128        assertDatabaseStructureSameAsList(TABLE_LIST, /* isNewDatabase =*/ false);
129    }
130
131    /**
132     * Upgrade the database version by version, and test it in each step
133     */
134    public void testDatabaseUpgrade_Incremental() {
135        create1108(mDb);
136
137        int oldVersion = 1108;
138        oldVersion = upgradeTo1109(oldVersion);
139        oldVersion = upgrade(oldVersion, ContactsDatabaseHelper.DATABASE_VERSION);
140        assertEquals(ContactsDatabaseHelper.DATABASE_VERSION, oldVersion);
141        assertDatabaseStructureSameAsList(TABLE_LIST, /* isNewDatabase =*/ false);
142    }
143
144    private int upgradeTo1109(int upgradeFrom) {
145        final int MY_VERSION = 1109;
146        mHelper.onUpgrade(mDb, upgradeFrom, MY_VERSION);
147        TableStructure calls = new TableStructure(mDb, "calls");
148        calls.assertHasColumn(Calls.LAST_MODIFIED, INTEGER, false, "0");
149
150        TableStructure voicemailStatus = new TableStructure(mDb, "voicemail_status");
151        voicemailStatus.assertHasColumn(Status.QUOTA_OCCUPIED, INTEGER, false, "-1");
152        voicemailStatus.assertHasColumn(Status.QUOTA_TOTAL, INTEGER, false, "-1");
153
154        return MY_VERSION;
155    }
156
157    private int upgradeTo1201(int upgradeFrom) {
158        final int MY_VERSION = 1201;
159
160        executeSqlFromAssetFile(getTestContext(), mDb, "upgradeTest/pre_upgrade1201.sql");
161
162        mHelper.onUpgrade(mDb, upgradeFrom, MY_VERSION);
163
164        try (Cursor c = mDb.rawQuery("select * from contacts order by _id", null)) {
165            BaseContactsProvider2Test.assertCursorValuesOrderly(c,
166                    cv(Contacts._ID, 1,
167                            "last_time_contacted", 0,
168                            "x_last_time_contacted", 9940760264L,
169                            "times_contacted", 0,
170                            "x_times_contacted", 4
171                            ),
172                    cv(
173                            "last_time_contacted", 0,
174                            "x_last_time_contacted", 0,
175                            "times_contacted", 0,
176                            "x_times_contacted", 0
177                    ));
178        }
179
180        try (Cursor c = mDb.rawQuery("select * from raw_contacts order by _id", null)) {
181            BaseContactsProvider2Test.assertCursorValuesOrderly(c,
182                    cv("_id", 1,
183                            "last_time_contacted", 0,
184                            "x_last_time_contacted", 9940760264L,
185                            "times_contacted", 0,
186                            "x_times_contacted", 4
187                    ),
188                    cv(
189                            "last_time_contacted", 0,
190                            "x_last_time_contacted", 0,
191                            "times_contacted", 0,
192                            "x_times_contacted", 0
193                    ));
194        }
195
196        try (Cursor c = mDb.rawQuery("select * from data_usage_stat", null)) {
197            BaseContactsProvider2Test.assertCursorValuesOrderly(c,
198                    cv(
199                            "last_time_used", 0,
200                            "x_last_time_used", 9940760264L,
201                            "times_used", 0,
202                            "x_times_used", 4
203                    ));
204        }
205
206        return MY_VERSION;
207    }
208
209    private int upgrade(int upgradeFrom, int upgradeTo) {
210        if (upgradeFrom < upgradeTo) {
211            mHelper.onUpgrade(mDb, upgradeFrom, upgradeTo);
212        }
213        return upgradeTo;
214    }
215
216    /**
217     * A snapshot of onCreate() at version 1108, for testing upgrades. Future tests should upgrade
218     * incrementally from this version.
219     */
220    private void create1108(SQLiteDatabase db) {
221        executeSqlFromAssetFile(getTestContext(), db, CONTACTS2_DB_1108_ASSET_NAME);
222    }
223
224    /**
225     * The structure of all tables in current version database.
226     */
227    private static final TableColumn[] PROPERTIES_COLUMNS = new TableColumn[] {
228            new TableColumn(PropertyUtils.PropertiesColumns.PROPERTY_KEY, TEXT, false, null),
229            new TableColumn(PropertyUtils.PropertiesColumns.PROPERTY_VALUE, TEXT, false, null),
230    };
231
232    private static final TableColumn[] ACCOUNTS_COLUMNS = new TableColumn[] {
233            new TableColumn(AccountsColumns._ID, INTEGER, false, null),
234            new TableColumn(AccountsColumns.ACCOUNT_NAME, TEXT, false, null),
235            new TableColumn(AccountsColumns.ACCOUNT_TYPE, TEXT, false, null),
236            new TableColumn(AccountsColumns.DATA_SET, TEXT, false, null),
237    };
238
239    private static final TableColumn[] CONTACTS_COLUMNS = new TableColumn[] {
240            new TableColumn(BaseColumns._ID, INTEGER, false, null),
241            new TableColumn(Contacts.NAME_RAW_CONTACT_ID, INTEGER, false, null),
242            new TableColumn(Contacts.PHOTO_ID, INTEGER, false, null),
243            new TableColumn(Contacts.PHOTO_FILE_ID, INTEGER, false, null),
244            new TableColumn(Contacts.CUSTOM_RINGTONE, TEXT, false, null),
245            new TableColumn(Contacts.SEND_TO_VOICEMAIL, INTEGER, true, "0"),
246            new TableColumn(Contacts.RAW_TIMES_CONTACTED, INTEGER, true, "0"),
247            new TableColumn(Contacts.RAW_LAST_TIME_CONTACTED, INTEGER, false, null),
248            new TableColumn(Contacts.LR_TIMES_CONTACTED, INTEGER, true, "0"),
249            new TableColumn(Contacts.LR_LAST_TIME_CONTACTED, INTEGER, false, null),
250            new TableColumn(Contacts.STARRED, INTEGER, true, "0"),
251            new TableColumn(Contacts.PINNED, INTEGER, true,
252                    String.valueOf(PinnedPositions.UNPINNED)),
253            new TableColumn(Contacts.HAS_PHONE_NUMBER, INTEGER, true, "0"),
254            new TableColumn(Contacts.LOOKUP_KEY, TEXT, false, null),
255            new TableColumn(ContactsColumns.LAST_STATUS_UPDATE_ID, INTEGER, false, null),
256            new TableColumn(Contacts.CONTACT_LAST_UPDATED_TIMESTAMP, INTEGER, false, null),
257    };
258
259    private static final TableColumn[] DELETED_CONTACTS_COLUMNS = new TableColumn[] {
260            new TableColumn(DeletedContacts.CONTACT_ID, INTEGER, false, null),
261            new TableColumn(DeletedContacts.CONTACT_DELETED_TIMESTAMP, INTEGER, true, "0"),
262    };
263
264    private static final TableColumn[] RAW_CONTACTS_COLUMNS = new TableColumn[] {
265            new TableColumn(RawContacts._ID, INTEGER, false, null),
266            new TableColumn(RawContactsColumns.ACCOUNT_ID, INTEGER, false, null),
267            new TableColumn(RawContacts.SOURCE_ID, TEXT, false, null),
268            new TableColumn(RawContacts.BACKUP_ID, TEXT, false, null),
269            new TableColumn(RawContacts.RAW_CONTACT_IS_READ_ONLY, INTEGER, true, "0"),
270            new TableColumn(RawContacts.VERSION, INTEGER, true, "1"),
271            new TableColumn(RawContacts.DIRTY, INTEGER, true, "0"),
272            new TableColumn(RawContacts.DELETED, INTEGER, true, "0"),
273            new TableColumn(RawContacts.METADATA_DIRTY, INTEGER, true, "0"),
274            new TableColumn(RawContacts.CONTACT_ID, INTEGER, false, null),
275            new TableColumn(RawContacts.AGGREGATION_MODE, INTEGER, true,
276                    String.valueOf(RawContacts.AGGREGATION_MODE_DEFAULT)),
277            new TableColumn(RawContactsColumns.AGGREGATION_NEEDED, INTEGER, true, "1"),
278            new TableColumn(RawContacts.CUSTOM_RINGTONE, TEXT, false, null),
279            new TableColumn(RawContacts.SEND_TO_VOICEMAIL, INTEGER, true, "0"),
280            new TableColumn(RawContacts.RAW_TIMES_CONTACTED, INTEGER, true, "0"),
281            new TableColumn(RawContacts.RAW_LAST_TIME_CONTACTED, INTEGER, false, null),
282            new TableColumn(RawContacts.LR_TIMES_CONTACTED, INTEGER, true, "0"),
283            new TableColumn(RawContacts.LR_LAST_TIME_CONTACTED, INTEGER, false, null),
284            new TableColumn(RawContacts.STARRED, INTEGER, true, "0"),
285            new TableColumn(RawContacts.PINNED, INTEGER, true,
286                    String.valueOf(PinnedPositions.UNPINNED)),
287            new TableColumn(RawContacts.DISPLAY_NAME_PRIMARY, TEXT, false, null),
288            new TableColumn(RawContacts.DISPLAY_NAME_ALTERNATIVE, TEXT, false, null),
289            new TableColumn(RawContacts.DISPLAY_NAME_SOURCE, INTEGER, true, String.valueOf(
290                    DisplayNameSources.UNDEFINED)),
291            new TableColumn(RawContacts.PHONETIC_NAME, TEXT, false, null),
292            new TableColumn(RawContacts.PHONETIC_NAME_STYLE, TEXT, false, null),
293            new TableColumn(RawContacts.SORT_KEY_PRIMARY, TEXT, false, null),
294            new TableColumn(RawContactsColumns.PHONEBOOK_LABEL_PRIMARY, TEXT, false, null),
295            new TableColumn(RawContactsColumns.PHONEBOOK_BUCKET_PRIMARY, INTEGER, false, null),
296            new TableColumn(RawContacts.SORT_KEY_ALTERNATIVE, TEXT, false, null),
297            new TableColumn(RawContactsColumns.PHONEBOOK_LABEL_ALTERNATIVE, TEXT, false, null),
298            new TableColumn(RawContactsColumns.PHONEBOOK_BUCKET_ALTERNATIVE, INTEGER, false, null),
299            new TableColumn(RawContactsColumns.NAME_VERIFIED_OBSOLETE, INTEGER, true, "0"),
300            new TableColumn(RawContacts.SYNC1, TEXT, false, null),
301            new TableColumn(RawContacts.SYNC2, TEXT, false, null),
302            new TableColumn(RawContacts.SYNC3, TEXT, false, null),
303            new TableColumn(RawContacts.SYNC4, TEXT, false, null),
304    };
305
306    private static final TableColumn[] STREAM_ITEMS_COLUMNS = new TableColumn[] {
307            new TableColumn(StreamItems._ID, INTEGER, false, null),
308            new TableColumn(StreamItems.RAW_CONTACT_ID, INTEGER, true, null),
309            new TableColumn(StreamItems.RES_PACKAGE, TEXT, false, null),
310            new TableColumn(StreamItems.RES_ICON, TEXT, false, null),
311            new TableColumn(StreamItems.RES_LABEL, TEXT, false, null),
312            new TableColumn(StreamItems.TEXT, TEXT, false, null),
313            new TableColumn(StreamItems.TIMESTAMP, INTEGER, true, null),
314            new TableColumn(StreamItems.COMMENTS, TEXT, false, null),
315            new TableColumn(StreamItems.SYNC1, TEXT, false, null),
316            new TableColumn(StreamItems.SYNC2, TEXT, false, null),
317            new TableColumn(StreamItems.SYNC3, TEXT, false, null),
318            new TableColumn(StreamItems.SYNC4, TEXT, false, null),
319    };
320
321    private static final TableColumn[] STREAM_ITEM_PHOTOS_COLUMNS = new TableColumn[] {
322            new TableColumn(StreamItemPhotos._ID, INTEGER, false, null),
323            new TableColumn(StreamItemPhotos.STREAM_ITEM_ID, INTEGER, true, null),
324            new TableColumn(StreamItemPhotos.SORT_INDEX, INTEGER, false, null),
325            new TableColumn(StreamItemPhotos.PHOTO_FILE_ID, INTEGER, true, null),
326            new TableColumn(StreamItemPhotos.SYNC1, TEXT, false, null),
327            new TableColumn(StreamItemPhotos.SYNC2, TEXT, false, null),
328            new TableColumn(StreamItemPhotos.SYNC3, TEXT, false, null),
329            new TableColumn(StreamItemPhotos.SYNC4, TEXT, false, null),
330    };
331
332    private static final TableColumn[] PHOTO_FILES_COLUMNS = new TableColumn[] {
333            new TableColumn(PhotoFiles._ID, INTEGER, false, null),
334            new TableColumn(PhotoFiles.HEIGHT, INTEGER, true, null),
335            new TableColumn(PhotoFiles.WIDTH, INTEGER, true, null),
336            new TableColumn(PhotoFiles.FILESIZE, INTEGER, true, null),
337    };
338
339    private static final TableColumn[] PACKAGES_COLUMNS = new TableColumn[] {
340            new TableColumn(PackagesColumns._ID, INTEGER, false, null),
341            new TableColumn(PackagesColumns.PACKAGE, TEXT, true, null),
342    };
343
344    private static final TableColumn[] MIMETYPES_COLUMNS = new TableColumn[] {
345            new TableColumn(MimetypesColumns._ID, INTEGER, false, null),
346            new TableColumn(MimetypesColumns.MIMETYPE, TEXT, true, null),
347    };
348
349    private static final TableColumn[] DATA_COLUMNS = new TableColumn[] {
350            new TableColumn(Data._ID, INTEGER, false, null),
351            new TableColumn(DataColumns.PACKAGE_ID, INTEGER, false, null),
352            new TableColumn(DataColumns.MIMETYPE_ID, INTEGER, true, null),
353            new TableColumn(Data.RAW_CONTACT_ID, INTEGER, true, null),
354            new TableColumn(Data.HASH_ID, TEXT, false, null),
355            new TableColumn(Data.IS_READ_ONLY, INTEGER, true, "0"),
356            new TableColumn(Data.IS_PRIMARY, INTEGER, true, "0"),
357            new TableColumn(Data.IS_SUPER_PRIMARY, INTEGER, true, "0"),
358            new TableColumn(Data.DATA_VERSION, INTEGER, true, "0"),
359            new TableColumn(Data.DATA1, TEXT, false, null),
360            new TableColumn(Data.DATA2, TEXT, false, null),
361            new TableColumn(Data.DATA3, TEXT, false, null),
362            new TableColumn(Data.DATA4, TEXT, false, null),
363            new TableColumn(Data.DATA5, TEXT, false, null),
364            new TableColumn(Data.DATA6, TEXT, false, null),
365            new TableColumn(Data.DATA7, TEXT, false, null),
366            new TableColumn(Data.DATA8, TEXT, false, null),
367            new TableColumn(Data.DATA9, TEXT, false, null),
368            new TableColumn(Data.DATA10, TEXT, false, null),
369            new TableColumn(Data.DATA11, TEXT, false, null),
370            new TableColumn(Data.DATA12, TEXT, false, null),
371            new TableColumn(Data.DATA13, TEXT, false, null),
372            new TableColumn(Data.DATA14, TEXT, false, null),
373            new TableColumn(Data.DATA15, TEXT, false, null),
374            new TableColumn(Data.SYNC1, TEXT, false, null),
375            new TableColumn(Data.SYNC2, TEXT, false, null),
376            new TableColumn(Data.SYNC3, TEXT, false, null),
377            new TableColumn(Data.SYNC4, TEXT, false, null),
378            new TableColumn(Data.CARRIER_PRESENCE, INTEGER, true, "0"),
379    };
380
381    private static final TableColumn[] PHONE_LOOKUP_COLUMNS = new TableColumn[] {
382            new TableColumn(PhoneLookupColumns.DATA_ID, INTEGER, true, null),
383            new TableColumn(PhoneLookupColumns.RAW_CONTACT_ID, INTEGER, true, null),
384            new TableColumn(PhoneLookupColumns.NORMALIZED_NUMBER, TEXT, true, null),
385            new TableColumn(PhoneLookupColumns.MIN_MATCH, TEXT, true, null),
386    };
387
388    private static final TableColumn[] NAME_LOOKUP_COLUMNS = new TableColumn[] {
389            new TableColumn(NameLookupColumns.DATA_ID, INTEGER, true, null),
390            new TableColumn(NameLookupColumns.RAW_CONTACT_ID, INTEGER, true, null),
391            new TableColumn(NameLookupColumns.NORMALIZED_NAME, TEXT, true, null),
392            new TableColumn(NameLookupColumns.NAME_TYPE, INTEGER, true, null),
393    };
394
395    private static final TableColumn[] NICKNAME_LOOKUP_COLUMNS = new TableColumn[] {
396            new TableColumn(NicknameLookupColumns.NAME, TEXT, false, null),
397            new TableColumn(NicknameLookupColumns.CLUSTER, TEXT, false, null),
398    };
399
400    private static final TableColumn[] GROUPS_COLUMNS = new TableColumn[] {
401            new TableColumn(Groups._ID, INTEGER, false, null),
402            new TableColumn(GroupsColumns.PACKAGE_ID, INTEGER, false, null),
403            new TableColumn(GroupsColumns.ACCOUNT_ID, INTEGER, false, null),
404            new TableColumn(Groups.SOURCE_ID, TEXT, false, null),
405            new TableColumn(Groups.VERSION, INTEGER, true, "1"),
406            new TableColumn(Groups.DIRTY, INTEGER, true, "0"),
407            new TableColumn(Groups.TITLE, TEXT, false, null),
408            new TableColumn(Groups.TITLE_RES, INTEGER, false, null),
409            new TableColumn(Groups.NOTES, TEXT, false, null),
410            new TableColumn(Groups.SYSTEM_ID, TEXT, false, null),
411            new TableColumn(Groups.DELETED, INTEGER, true, "0"),
412            new TableColumn(Groups.GROUP_VISIBLE, INTEGER, true, "0"),
413            new TableColumn(Groups.SHOULD_SYNC, INTEGER, true, "1"),
414            new TableColumn(Groups.AUTO_ADD, INTEGER, true, "0"),
415            new TableColumn(Groups.FAVORITES, INTEGER, true, "0"),
416            new TableColumn(Groups.GROUP_IS_READ_ONLY, INTEGER, true, "0"),
417            new TableColumn(Groups.SYNC1, TEXT, false, null),
418            new TableColumn(Groups.SYNC2, TEXT, false, null),
419            new TableColumn(Groups.SYNC3, TEXT, false, null),
420            new TableColumn(Groups.SYNC4, TEXT, false, null),
421    };
422
423    private static final TableColumn[] AGGREGATION_EXCEPTIONS_COLUMNS = new TableColumn[] {
424            new TableColumn(AggregationExceptionColumns._ID, INTEGER, false, null),
425            new TableColumn(AggregationExceptions.TYPE, INTEGER, true, null),
426            new TableColumn(AggregationExceptions.RAW_CONTACT_ID1, INTEGER, false, null),
427            new TableColumn(AggregationExceptions.RAW_CONTACT_ID2, INTEGER, false, null),
428    };
429
430    private static final TableColumn[] SETTINGS_COLUMNS = new TableColumn[] {
431            new TableColumn(Settings.ACCOUNT_NAME, STRING, true, null),
432            new TableColumn(Settings.ACCOUNT_TYPE, STRING, true, null),
433            new TableColumn(Settings.DATA_SET, STRING, false, null),
434            new TableColumn(Settings.UNGROUPED_VISIBLE, INTEGER, true, "0"),
435            new TableColumn(Settings.SHOULD_SYNC, INTEGER, true, "1"),
436    };
437
438    private static final TableColumn[] VISIBLE_CONTACTS_COLUMNS = new TableColumn[] {
439            new TableColumn(Contacts._ID, INTEGER, false, null),
440    };
441
442    private static final TableColumn[] DEFAULT_DIRECTORY_COLUMNS = new TableColumn[] {
443            new TableColumn(Contacts._ID, INTEGER, false, null),
444    };
445
446    private static final TableColumn[] CALLS_COLUMNS = new TableColumn[] {
447            new TableColumn(Calls._ID, INTEGER, false, null),
448            new TableColumn(Calls.NUMBER, TEXT, false, null),
449            new TableColumn(Calls.NUMBER_PRESENTATION, INTEGER, true,
450                    String.valueOf(Calls.PRESENTATION_ALLOWED)),
451            new TableColumn(Calls.POST_DIAL_DIGITS, TEXT, true, "''"),
452            new TableColumn(Calls.DATE, INTEGER, false, null),
453            new TableColumn(Calls.DURATION, INTEGER, false, null),
454            new TableColumn(Calls.DATA_USAGE, INTEGER, false, null),
455            new TableColumn(Calls.TYPE, INTEGER, false, null),
456            new TableColumn(Calls.FEATURES, INTEGER, true, "0"),
457            new TableColumn(Calls.PHONE_ACCOUNT_COMPONENT_NAME, TEXT, false, null),
458            new TableColumn(Calls.PHONE_ACCOUNT_ID, TEXT, false, null),
459            new TableColumn(Calls.PHONE_ACCOUNT_ADDRESS, TEXT, false, null),
460            new TableColumn(Calls.PHONE_ACCOUNT_HIDDEN, INTEGER, true, "0"),
461            new TableColumn(Calls.SUB_ID, INTEGER, false, "-1"),
462            new TableColumn(Calls.NEW, INTEGER, false, null),
463            new TableColumn(Calls.CACHED_NAME, TEXT, false, null),
464            new TableColumn(Calls.CACHED_NUMBER_TYPE, INTEGER, false, null),
465            new TableColumn(Calls.CACHED_NUMBER_LABEL, TEXT, false, null),
466            new TableColumn(Calls.COUNTRY_ISO, TEXT, false, null),
467            new TableColumn(Calls.VOICEMAIL_URI, TEXT, false, null),
468            new TableColumn(Calls.IS_READ, INTEGER, false, null),
469            new TableColumn(Calls.GEOCODED_LOCATION, TEXT, false, null),
470            new TableColumn(Calls.CACHED_LOOKUP_URI, TEXT, false, null),
471            new TableColumn(Calls.CACHED_MATCHED_NUMBER, TEXT, false, null),
472            new TableColumn(Calls.CACHED_NORMALIZED_NUMBER, TEXT, false, null),
473            new TableColumn(Calls.CACHED_PHOTO_ID, INTEGER, true, "0"),
474            new TableColumn(Calls.CACHED_PHOTO_URI, TEXT, false, null),
475            new TableColumn(Calls.CACHED_FORMATTED_NUMBER, TEXT, false, null),
476            new TableColumn(Calls.ADD_FOR_ALL_USERS, INTEGER, true, "1"),
477            new TableColumn(Calls.LAST_MODIFIED, INTEGER, false, "0"),
478            new TableColumn(Voicemails._DATA, TEXT, false, null),
479            new TableColumn(Voicemails.HAS_CONTENT, INTEGER, false, null),
480            new TableColumn(Voicemails.MIME_TYPE, TEXT, false, null),
481            new TableColumn(Voicemails.SOURCE_DATA, TEXT, false, null),
482            new TableColumn(Voicemails.SOURCE_PACKAGE, TEXT, false, null),
483            new TableColumn(Voicemails.TRANSCRIPTION, TEXT, false, null),
484            new TableColumn(Voicemails.STATE, INTEGER, false, null),
485            new TableColumn(Voicemails.DIRTY, INTEGER, true, "0"),
486            new TableColumn(Voicemails.DELETED, INTEGER, true, "0"),
487    };
488
489    private static final TableColumn[] VOICEMAIL_STATUS_COLUMNS = new TableColumn[] {
490            new TableColumn(Status._ID, INTEGER, false, null),
491            new TableColumn(Status.SOURCE_PACKAGE, TEXT, true, null),
492            new TableColumn(Status.PHONE_ACCOUNT_COMPONENT_NAME, TEXT, false, null),
493            new TableColumn(Status.PHONE_ACCOUNT_ID, TEXT, false, null),
494            new TableColumn(Status.SETTINGS_URI, TEXT, false, null),
495            new TableColumn(Status.VOICEMAIL_ACCESS_URI, TEXT, false, null),
496            new TableColumn(Status.CONFIGURATION_STATE, INTEGER, false, null),
497            new TableColumn(Status.DATA_CHANNEL_STATE, INTEGER, false, null),
498            new TableColumn(Status.NOTIFICATION_CHANNEL_STATE, INTEGER, false, null),
499            new TableColumn(Status.QUOTA_OCCUPIED, INTEGER, false, "-1"),
500            new TableColumn(Status.QUOTA_TOTAL, INTEGER, false, "-1"),
501    };
502
503    private static final TableColumn[] STATUS_UPDATES_COLUMNS = new TableColumn[] {
504            new TableColumn(StatusUpdatesColumns.DATA_ID, INTEGER, false, null),
505            new TableColumn(StatusUpdates.STATUS, TEXT, false, null),
506            new TableColumn(StatusUpdates.STATUS_TIMESTAMP, INTEGER, false, null),
507            new TableColumn(StatusUpdates.STATUS_RES_PACKAGE, TEXT, false, null),
508            new TableColumn(StatusUpdates.STATUS_LABEL, INTEGER, false, null),
509            new TableColumn(StatusUpdates.STATUS_ICON, INTEGER, false, null),
510    };
511
512    private static final TableColumn[] DIRECTORIES_COLUMNS = new TableColumn[] {
513            new TableColumn(Directory._ID, INTEGER, false, null),
514            new TableColumn(Directory.PACKAGE_NAME, TEXT, true, null),
515            new TableColumn(Directory.DIRECTORY_AUTHORITY, TEXT, true, null),
516            new TableColumn(Directory.TYPE_RESOURCE_ID, INTEGER, false, null),
517            new TableColumn(DirectoryColumns.TYPE_RESOURCE_NAME, TEXT, false, null),
518            new TableColumn(Directory.ACCOUNT_TYPE, TEXT, false, null),
519            new TableColumn(Directory.ACCOUNT_NAME, TEXT, false, null),
520            new TableColumn(Directory.DISPLAY_NAME, TEXT, false, null),
521            new TableColumn(Directory.EXPORT_SUPPORT, INTEGER, true,
522                    String.valueOf(Directory.EXPORT_SUPPORT_NONE)),
523            new TableColumn(Directory.SHORTCUT_SUPPORT, INTEGER, true,
524                    String.valueOf(Directory.SHORTCUT_SUPPORT_NONE)),
525            new TableColumn(Directory.PHOTO_SUPPORT, INTEGER, true,
526                    String.valueOf(Directory.PHOTO_SUPPORT_NONE)),
527    };
528
529    private static final TableColumn[] DATA_USAGE_STAT_COLUMNS = new TableColumn[] {
530            new TableColumn(DataUsageStatColumns._ID, INTEGER, false, null),
531            new TableColumn(DataUsageStatColumns.DATA_ID, INTEGER, true, null),
532            new TableColumn(DataUsageStatColumns.USAGE_TYPE_INT, INTEGER, true, "0"),
533            new TableColumn(DataUsageStatColumns.RAW_TIMES_USED, INTEGER, true, "0"),
534            new TableColumn(DataUsageStatColumns.RAW_LAST_TIME_USED, INTEGER, true, "0"),
535            new TableColumn(DataUsageStatColumns.LR_TIMES_USED, INTEGER, true, "0"),
536            new TableColumn(DataUsageStatColumns.LR_LAST_TIME_USED, INTEGER, true, "0"),
537    };
538
539    private static final TableColumn[] METADATA_SYNC_COLUMNS = new TableColumn[] {
540            new TableColumn(MetadataSync._ID, INTEGER, false, null),
541            new TableColumn(MetadataSync.RAW_CONTACT_BACKUP_ID, TEXT, true, null),
542            new TableColumn(MetadataSyncColumns.ACCOUNT_ID, INTEGER, true, null),
543            new TableColumn(MetadataSync.DATA, TEXT, false, null),
544            new TableColumn(MetadataSync.DELETED, INTEGER, true, "0"),
545    };
546
547    private static final TableColumn[] PRE_AUTHORIZED_URIS_COLUMNS = new TableColumn[] {
548            new TableColumn(PreAuthorizedUris._ID, INTEGER, false, null),
549            new TableColumn(PreAuthorizedUris.URI, STRING, true, null),
550            new TableColumn(PreAuthorizedUris.EXPIRATION, INTEGER, true, "0"),
551    };
552
553    private static final TableColumn[] METADATA_SYNC_STATE_COLUMNS = new TableColumn[] {
554            new TableColumn(MetadataSyncState._ID, INTEGER, false, null),
555            new TableColumn(MetadataSyncStateColumns.ACCOUNT_ID, INTEGER, true, null),
556            new TableColumn(MetadataSyncState.STATE, BLOB, false, null),
557    };
558
559    private static final TableColumn[] PRESENCE_COLUMNS = new TableColumn[] {
560            new TableColumn(StatusUpdates.DATA_ID, INTEGER, false, null),
561            new TableColumn(StatusUpdates.PROTOCOL, INTEGER, true, null),
562            new TableColumn(StatusUpdates.CUSTOM_PROTOCOL, TEXT, false, null),
563            new TableColumn(StatusUpdates.IM_HANDLE, TEXT, false, null),
564            new TableColumn(StatusUpdates.IM_ACCOUNT, TEXT, false, null),
565            new TableColumn(PresenceColumns.CONTACT_ID, INTEGER, false, null),
566            new TableColumn(PresenceColumns.RAW_CONTACT_ID, INTEGER, false, null),
567            new TableColumn(StatusUpdates.PRESENCE, INTEGER, false, null),
568            new TableColumn(StatusUpdates.CHAT_CAPABILITY, INTEGER, true, "0")
569    };
570
571    private static final TableColumn[] AGGREGATED_PRESENCE_COLUMNS = new TableColumn[] {
572            new TableColumn(AggregatedPresenceColumns.CONTACT_ID, INTEGER, false, null),
573            new TableColumn(StatusUpdates.PRESENCE, INTEGER, false, null),
574            new TableColumn(StatusUpdates.CHAT_CAPABILITY, INTEGER, true, "0")
575    };
576
577    private static final TableListEntry[] TABLE_LIST = {
578            new TableListEntry(PropertyUtils.Tables.PROPERTIES, PROPERTIES_COLUMNS),
579            new TableListEntry(Tables.ACCOUNTS, ACCOUNTS_COLUMNS),
580            new TableListEntry(Tables.CONTACTS, CONTACTS_COLUMNS),
581            new TableListEntry(Tables.DELETED_CONTACTS, DELETED_CONTACTS_COLUMNS),
582            new TableListEntry(Tables.RAW_CONTACTS, RAW_CONTACTS_COLUMNS),
583            new TableListEntry(Tables.STREAM_ITEMS, STREAM_ITEMS_COLUMNS),
584            new TableListEntry(Tables.STREAM_ITEM_PHOTOS, STREAM_ITEM_PHOTOS_COLUMNS),
585            new TableListEntry(Tables.PHOTO_FILES, PHOTO_FILES_COLUMNS),
586            new TableListEntry(Tables.PACKAGES, PACKAGES_COLUMNS),
587            new TableListEntry(Tables.MIMETYPES, MIMETYPES_COLUMNS),
588            new TableListEntry(Tables.DATA, DATA_COLUMNS),
589            new TableListEntry(Tables.PHONE_LOOKUP, PHONE_LOOKUP_COLUMNS),
590            new TableListEntry(Tables.NAME_LOOKUP, NAME_LOOKUP_COLUMNS),
591            new TableListEntry(Tables.NICKNAME_LOOKUP, NICKNAME_LOOKUP_COLUMNS),
592            new TableListEntry(Tables.GROUPS, GROUPS_COLUMNS),
593            new TableListEntry(Tables.AGGREGATION_EXCEPTIONS, AGGREGATION_EXCEPTIONS_COLUMNS),
594            new TableListEntry(Tables.SETTINGS, SETTINGS_COLUMNS),
595            new TableListEntry(Tables.VISIBLE_CONTACTS, VISIBLE_CONTACTS_COLUMNS),
596            new TableListEntry(Tables.DEFAULT_DIRECTORY, DEFAULT_DIRECTORY_COLUMNS),
597            new TableListEntry("calls", CALLS_COLUMNS, false),
598            new TableListEntry("voicemail_status", VOICEMAIL_STATUS_COLUMNS, false),
599            new TableListEntry(Tables.STATUS_UPDATES, STATUS_UPDATES_COLUMNS),
600            new TableListEntry(Tables.DIRECTORIES, DIRECTORIES_COLUMNS),
601            new TableListEntry(Tables.DATA_USAGE_STAT, DATA_USAGE_STAT_COLUMNS),
602            new TableListEntry(Tables.METADATA_SYNC, METADATA_SYNC_COLUMNS),
603            new TableListEntry(Tables.PRE_AUTHORIZED_URIS, PRE_AUTHORIZED_URIS_COLUMNS),
604            new TableListEntry(Tables.METADATA_SYNC_STATE, METADATA_SYNC_STATE_COLUMNS),
605            new TableListEntry(Tables.PRESENCE, PRESENCE_COLUMNS),
606            new TableListEntry(Tables.AGGREGATED_PRESENCE, AGGREGATED_PRESENCE_COLUMNS)
607    };
608
609}
610
611