ContactsContract.java revision 8f76734d1e9a21618ad9762c0716ee93f60902ec
1/*
2 * Copyright (C) 2009 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 android.provider;
18
19import android.accounts.Account;
20import android.content.ContentProviderClient;
21import android.content.ContentProviderOperation;
22import android.content.ContentResolver;
23import android.content.ContentUris;
24import android.content.ContentValues;
25import android.content.Context;
26import android.content.Intent;
27import android.content.res.Resources;
28import android.database.Cursor;
29import android.graphics.Rect;
30import android.net.Uri;
31import android.os.RemoteException;
32import android.text.TextUtils;
33import android.util.Pair;
34import android.view.View;
35
36import java.io.ByteArrayInputStream;
37import java.io.InputStream;
38
39/**
40 * The contract between the contacts provider and applications. Contains definitions
41 * for the supported URIs and columns. These APIs supersede {@link Contacts}.
42 */
43@SuppressWarnings("unused")
44public final class ContactsContract {
45    /** The authority for the contacts provider */
46    public static final String AUTHORITY = "com.android.contacts";
47    /** A content:// style uri to the authority for the contacts provider */
48    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
49
50    /**
51     * An optional insert, update or delete URI parameter that allows the caller
52     * to specify that it is a sync adapter. The default value is false. If true
53     * the dirty flag is not automatically set and the "syncToNetwork" parameter
54     * is set to false when calling
55     * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
56     */
57    public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
58
59    /**
60     * @hide should be removed when users are updated to refer to SyncState
61     * @deprecated use SyncState instead
62     */
63    @Deprecated
64    public interface SyncStateColumns extends SyncStateContract.Columns {
65    }
66
67    /**
68     * A table provided for sync adapters to use for storing private sync state data.
69     *
70     * @see SyncStateContract
71     */
72    public static final class SyncState implements SyncStateContract.Columns {
73        /**
74         * This utility class cannot be instantiated
75         */
76        private SyncState() {}
77
78        public static final String CONTENT_DIRECTORY =
79                SyncStateContract.Constants.CONTENT_DIRECTORY;
80
81        /**
82         * The content:// style URI for this table
83         */
84        public static final Uri CONTENT_URI =
85                Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY);
86
87        /**
88         * @see android.provider.SyncStateContract.Helpers#get
89         */
90        public static byte[] get(ContentProviderClient provider, Account account)
91                throws RemoteException {
92            return SyncStateContract.Helpers.get(provider, CONTENT_URI, account);
93        }
94
95        /**
96         * @see android.provider.SyncStateContract.Helpers#get
97         */
98        public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account)
99                throws RemoteException {
100            return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account);
101        }
102
103        /**
104         * @see android.provider.SyncStateContract.Helpers#set
105         */
106        public static void set(ContentProviderClient provider, Account account, byte[] data)
107                throws RemoteException {
108            SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data);
109        }
110
111        /**
112         * @see android.provider.SyncStateContract.Helpers#newSetOperation
113         */
114        public static ContentProviderOperation newSetOperation(Account account, byte[] data) {
115            return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data);
116        }
117    }
118
119    /**
120     * Generic columns for use by sync adapters. The specific functions of
121     * these columns are private to the sync adapter. Other clients of the API
122     * should not attempt to either read or write this column.
123     */
124    private interface BaseSyncColumns {
125
126        /** Generic column for use by sync adapters. */
127        public static final String SYNC1 = "sync1";
128        /** Generic column for use by sync adapters. */
129        public static final String SYNC2 = "sync2";
130        /** Generic column for use by sync adapters. */
131        public static final String SYNC3 = "sync3";
132        /** Generic column for use by sync adapters. */
133        public static final String SYNC4 = "sync4";
134    }
135
136    /**
137     * Columns that appear when each row of a table belongs to a specific
138     * account, including sync information that an account may need.
139     */
140    private interface SyncColumns extends BaseSyncColumns {
141        /**
142         * The name of the account instance to which this row belongs, which when paired with
143         * {@link #ACCOUNT_TYPE} identifies a specific account.
144         * <P>Type: TEXT</P>
145         */
146        public static final String ACCOUNT_NAME = "account_name";
147
148        /**
149         * The type of account to which this row belongs, which when paired with
150         * {@link #ACCOUNT_NAME} identifies a specific account.
151         * <P>Type: TEXT</P>
152         */
153        public static final String ACCOUNT_TYPE = "account_type";
154
155        /**
156         * String that uniquely identifies this row to its source account.
157         * <P>Type: TEXT</P>
158         */
159        public static final String SOURCE_ID = "sourceid";
160
161        /**
162         * Version number that is updated whenever this row or its related data
163         * changes.
164         * <P>Type: INTEGER</P>
165         */
166        public static final String VERSION = "version";
167
168        /**
169         * Flag indicating that {@link #VERSION} has changed, and this row needs
170         * to be synchronized by its owning account.
171         * <P>Type: INTEGER (boolean)</P>
172         */
173        public static final String DIRTY = "dirty";
174    }
175
176    private interface ContactOptionsColumns {
177        /**
178         * The number of times a contact has been contacted
179         * <P>Type: INTEGER</P>
180         */
181        public static final String TIMES_CONTACTED = "times_contacted";
182
183        /**
184         * The last time a contact was contacted.
185         * <P>Type: INTEGER</P>
186         */
187        public static final String LAST_TIME_CONTACTED = "last_time_contacted";
188
189        /**
190         * Is the contact starred?
191         * <P>Type: INTEGER (boolean)</P>
192         */
193        public static final String STARRED = "starred";
194
195        /**
196         * A custom ringtone associated with a contact. Not always present.
197         * <P>Type: TEXT (URI to the ringtone)</P>
198         */
199        public static final String CUSTOM_RINGTONE = "custom_ringtone";
200
201        /**
202         * Whether the contact should always be sent to voicemail. Not always
203         * present.
204         * <P>Type: INTEGER (0 for false, 1 for true)</P>
205         */
206        public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
207    }
208
209    private interface ContactsColumns {
210        /**
211         * The display name for the contact.
212         * <P>Type: TEXT</P>
213         */
214        public static final String DISPLAY_NAME = "display_name";
215
216        /**
217         * Reference to the row in the data table holding the photo.
218         * <P>Type: INTEGER REFERENCES data(_id)</P>
219         */
220        public static final String PHOTO_ID = "photo_id";
221
222        /**
223         * Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of
224         * any {@link CommonDataKinds.GroupMembership} for this contact.
225         */
226        public static final String IN_VISIBLE_GROUP = "in_visible_group";
227
228        /**
229         * An indicator of whether this contact has at least one phone number. "1" if there is
230         * at least one phone number, "0" otherwise.
231         * <P>Type: INTEGER</P>
232         */
233        public static final String HAS_PHONE_NUMBER = "has_phone_number";
234
235        /**
236         * An opaque value that contains hints on how to find the contact if
237         * its row id changed as a result of a sync or aggregation.
238         */
239        public static final String LOOKUP_KEY = "lookup";
240    }
241
242    private interface ContactStatusColumns {
243        /**
244         * Contact presence status. See {@link StatusUpdates} for individual status
245         * definitions.
246         * <p>Type: NUMBER</p>
247         */
248        public static final String CONTACT_PRESENCE = "contact_presence";
249
250        /**
251         * Contact's latest status update.
252         * <p>Type: TEXT</p>
253         */
254        public static final String CONTACT_STATUS = "contact_status";
255
256        /**
257         * The absolute time in milliseconds when the latest status was
258         * inserted/updated.
259         * <p>Type: NUMBER</p>
260         */
261        public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts";
262
263        /**
264         * The package containing resources for this status: label and icon.
265         * <p>Type: NUMBER</p>
266         */
267        public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package";
268
269        /**
270         * The resource ID of the label describing the source of contact
271         * status, e.g. "Google Talk". This resource is scoped by the
272         * {@link #CONTACT_STATUS_RES_PACKAGE}.
273         * <p>Type: NUMBER</p>
274         */
275        public static final String CONTACT_STATUS_LABEL = "contact_status_label";
276
277        /**
278         * The resource ID of the icon for the source of contact status. This
279         * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.
280         * <p>Type: NUMBER</p>
281         */
282        public static final String CONTACT_STATUS_ICON = "contact_status_icon";
283    }
284
285    /**
286     * Constants for the contacts table, which contains a record per group
287     * of raw contacts representing the same person.
288     */
289    public static class Contacts implements BaseColumns, ContactsColumns,
290            ContactOptionsColumns, ContactStatusColumns {
291        /**
292         * This utility class cannot be instantiated
293         */
294        private Contacts()  {}
295
296        /**
297         * The content:// style URI for this table
298         */
299        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
300
301        /**
302         * A content:// style URI for this table that should be used to create
303         * shortcuts or otherwise create long-term links to contacts. This URI
304         * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}.
305         * It can optionally also have a "/" and last known contact ID appended after
306         * that. This "complete" format is an important optimization and is highly recommended.
307         * <p>
308         * As long as the contact's row ID remains the same, this URI is
309         * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes
310         * as a result of a sync or aggregation, this URI will look up the
311         * contact using indirect information (sync IDs or constituent raw
312         * contacts).
313         * <p>
314         * Lookup key should be appended unencoded - it is stored in the encoded
315         * form, ready for use in a URI.
316         */
317        public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI,
318                "lookup");
319
320        /**
321         * Base {@link Uri} for referencing a single {@link Contacts} entry,
322         * created by appending {@link #LOOKUP_KEY} using
323         * {@link Uri#withAppendedPath(Uri, String)}. Provides
324         * {@link OpenableColumns} columns when queried, or returns the
325         * referenced contact formatted as a vCard when opened through
326         * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
327         */
328        public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI,
329                "as_vcard");
330
331        /**
332         * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the
333         * requested {@link Contacts} entry.
334         *
335         * @param contactUri A {@link #CONTENT_URI} row, or an existing
336         *            {@link #CONTENT_LOOKUP_URI} to attempt refreshing.
337         */
338        public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) {
339            final Cursor c = resolver.query(contactUri, new String[] {
340                    Contacts.LOOKUP_KEY, Contacts._ID
341            }, null, null, null);
342            if (c == null) {
343                return null;
344            }
345
346            try {
347                if (c.moveToFirst()) {
348                    final String lookupKey = c.getString(0);
349                    final long contactId = c.getLong(1);
350                    return getLookupUri(contactId, lookupKey);
351                }
352            } finally {
353                c.close();
354            }
355            return null;
356        }
357
358        /**
359         * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the
360         * given {@link android.provider.ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}.
361         */
362        public static Uri getLookupUri(long contactId, String lookupKey) {
363            return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
364                    lookupKey), contactId);
365        }
366
367        /**
368         * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI.
369         * <p>
370         * Returns null if the contact cannot be found.
371         */
372        public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) {
373            if (lookupUri == null) {
374                return null;
375            }
376
377            Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null);
378            if (c == null) {
379                return null;
380            }
381
382            try {
383                if (c.moveToFirst()) {
384                    long contactId = c.getLong(0);
385                    return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
386                }
387            } finally {
388                c.close();
389            }
390            return null;
391        }
392
393        /**
394         * Mark a contact as having been contacted.
395         *
396         * @param resolver the ContentResolver to use
397         * @param contactId the person who was contacted
398         */
399        public static void markAsContacted(ContentResolver resolver, long contactId) {
400            Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
401            ContentValues values = new ContentValues();
402            // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified.
403            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
404            resolver.update(uri, values, null, null);
405        }
406
407        /**
408         * The content:// style URI used for "type-to-filter" functionality on the
409         * {@link #CONTENT_URI} URI. The filter string will be used to match
410         * various parts of the contact name. The filter argument should be passed
411         * as an additional path segment after this URI.
412         */
413        public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(
414                CONTENT_URI, "filter");
415
416        /**
417         * The content:// style URI for this table joined with useful data from
418         * {@link Data}, filtered to include only starred contacts
419         * and the most frequently contacted contacts.
420         */
421        public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath(
422                CONTENT_URI, "strequent");
423
424        /**
425         * The content:// style URI used for "type-to-filter" functionality on the
426         * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match
427         * various parts of the contact name. The filter argument should be passed
428         * as an additional path segment after this URI.
429         */
430        public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath(
431                CONTENT_STREQUENT_URI, "filter");
432
433        public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath(
434                CONTENT_URI, "group");
435
436        /**
437         * The MIME type of {@link #CONTENT_URI} providing a directory of
438         * people.
439         */
440        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact";
441
442        /**
443         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
444         * person.
445         */
446        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
447
448        /**
449         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
450         * person.
451         */
452        public static final String CONTENT_VCARD_TYPE = "text/x-vcard";
453
454        /**
455         * A sub-directory of a single contact that contains all of the constituent raw contact
456         * {@link Data} rows.
457         */
458        public static final class Data implements BaseColumns, DataColumns {
459            /**
460             * no public constructor since this is a utility class
461             */
462            private Data() {}
463
464            /**
465             * The directory twig for this sub-table
466             */
467            public static final String CONTENT_DIRECTORY = "data";
468        }
469
470        /**
471         * A sub-directory of a single contact aggregate that contains all aggregation suggestions
472         * (other contacts).  The aggregation suggestions are computed based on approximate
473         * data matches with this contact.
474         */
475        public static final class AggregationSuggestions implements BaseColumns, ContactsColumns {
476            /**
477             * No public constructor since this is a utility class
478             */
479            private AggregationSuggestions() {}
480
481            /**
482             * The directory twig for this sub-table. The URI can be followed by an optional
483             * type-to-filter, similar to
484             * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}.
485             */
486            public static final String CONTENT_DIRECTORY = "suggestions";
487        }
488
489        /**
490         * A sub-directory of a single contact that contains the contact's primary photo.
491         */
492        public static final class Photo implements BaseColumns, DataColumns {
493            /**
494             * no public constructor since this is a utility class
495             */
496            private Photo() {}
497
498            /**
499             * The directory twig for this sub-table
500             */
501            public static final String CONTENT_DIRECTORY = "photo";
502        }
503
504        /**
505         * Opens an InputStream for the contacts's default photo and returns the
506         * photo as a byte stream. If there is not photo null will be returned.
507         *
508         * @param contactUri the contact whose photo should be used
509         * @return an InputStream of the photo, or null if no photo is present
510         */
511        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
512            Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY);
513            if (photoUri == null) {
514                return null;
515            }
516            Cursor cursor = cr.query(photoUri,
517                    new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
518            try {
519                if (cursor == null || !cursor.moveToNext()) {
520                    return null;
521                }
522                byte[] data = cursor.getBlob(0);
523                if (data == null) {
524                    return null;
525                }
526                return new ByteArrayInputStream(data);
527            } finally {
528                if (cursor != null) {
529                    cursor.close();
530                }
531            }
532        }
533    }
534
535    private interface RawContactsColumns {
536        /**
537         * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
538         * data belongs to.
539         * <P>Type: INTEGER</P>
540         */
541        public static final String CONTACT_ID = "contact_id";
542
543        /**
544         * Flag indicating that this {@link RawContacts} entry and its children have
545         * been restricted to specific platform apps.
546         * <P>Type: INTEGER (boolean)</P>
547         *
548         * @hide until finalized in future platform release
549         */
550        public static final String IS_RESTRICTED = "is_restricted";
551
552        /**
553         * The aggregation mode for this contact.
554         * <P>Type: INTEGER</P>
555         */
556        public static final String AGGREGATION_MODE = "aggregation_mode";
557
558        /**
559         * The "deleted" flag: "0" by default, "1" if the row has been marked
560         * for deletion. When {@link android.content.ContentResolver#delete} is
561         * called on a raw contact, it is marked for deletion and removed from its
562         * aggregate contact. The sync adaptor deletes the raw contact on the server and
563         * then calls ContactResolver.delete once more, this time passing the
564         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
565         * the data removal.
566         * <P>Type: INTEGER</P>
567         */
568        public static final String DELETED = "deleted";
569    }
570
571    /**
572     * Constants for the raw contacts table, which contains the base contact
573     * information per sync source. Sync adapters and contact management apps
574     * are the primary consumers of this API.
575     */
576    public static final class RawContacts implements BaseColumns, RawContactsColumns,
577            ContactOptionsColumns, SyncColumns  {
578        /**
579         * This utility class cannot be instantiated
580         */
581        private RawContacts() {
582        }
583
584        /**
585         * The content:// style URI for this table
586         */
587        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts");
588
589        /**
590         * The MIME type of {@link #CONTENT_URI} providing a directory of
591         * people.
592         */
593        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact";
594
595        /**
596         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
597         * person.
598         */
599        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
600
601        /**
602         * Aggregation mode: aggregate asynchronously.
603         */
604        public static final int AGGREGATION_MODE_DEFAULT = 0;
605
606        /**
607         * Aggregation mode: aggregate at the time the raw contact is inserted/updated.
608         */
609        public static final int AGGREGATION_MODE_IMMEDIATE = 1;
610
611        /**
612         * If {@link #AGGREGATION_MODE} is {@link #AGGREGATION_MODE_SUSPENDED}, changes
613         * to the raw contact do not cause its aggregation to be revisited. Note that changing
614         * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to
615         * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass. Any subsequent
616         * change to the raw contact's data will.
617         */
618        public static final int AGGREGATION_MODE_SUSPENDED = 2;
619
620        /**
621         * Aggregation mode: never aggregate this raw contact (note that the raw contact will not
622         * have a corresponding Aggregate and therefore will not be included in Aggregates
623         * query results.)
624         */
625        public static final int AGGREGATION_MODE_DISABLED = 3;
626
627        /**
628         * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
629         * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
630         * entry of the given {@link RawContacts} entry.
631         */
632        public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) {
633            // TODO: use a lighter query by joining rawcontacts with contacts in provider
634            final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY);
635            final Cursor cursor = resolver.query(dataUri, new String[] {
636                    RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY
637            }, null, null, null);
638
639            Uri lookupUri = null;
640            try {
641                if (cursor != null && cursor.moveToFirst()) {
642                    final long contactId = cursor.getLong(0);
643                    final String lookupKey = cursor.getString(1);
644                    return Contacts.getLookupUri(contactId, lookupKey);
645                }
646            } finally {
647                if (cursor != null) cursor.close();
648            }
649            return lookupUri;
650        }
651
652        /**
653         * A sub-directory of a single raw contact that contains all of their {@link Data} rows.
654         * To access this directory append {@link Data#CONTENT_DIRECTORY} to the contact URI.
655         */
656        public static final class Data implements BaseColumns, DataColumns {
657            /**
658             * no public constructor since this is a utility class
659             */
660            private Data() {
661            }
662
663            /**
664             * The directory twig for this sub-table
665             */
666            public static final String CONTENT_DIRECTORY = "data";
667        }
668    }
669
670    private interface StatusColumns extends Im.CommonPresenceColumns {
671        /**
672         * Contact's latest presence level.
673         * <P>Type: INTEGER (one of the values below)</P>
674         */
675        public static final String PRESENCE = PRESENCE_STATUS;
676
677        /**
678         * Contact latest status update.
679         * <p>Type: TEXT</p>
680         */
681        public static final String STATUS = PRESENCE_CUSTOM_STATUS;
682
683        /**
684         * The absolute time in milliseconds when the latest status was inserted/updated.
685         * <p>Type: NUMBER</p>
686         */
687        public static final String STATUS_TIMESTAMP = "status_ts";
688
689        /**
690         * The package containing resources for this status: label and icon.
691         * <p>Type: NUMBER</p>
692         */
693        public static final String STATUS_RES_PACKAGE = "status_res_package";
694
695        /**
696         * The resource ID of the label describing the source of the status update, e.g. "Google
697         * Talk".  This resource should be scoped by the {@link #STATUS_RES_PACKAGE}.
698         * <p>Type: NUMBER</p>
699         */
700        public static final String STATUS_LABEL = "status_label";
701
702        /**
703         * The resource ID of the icon for the source of the status update.
704         * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}.
705         * <p>Type: NUMBER</p>
706         */
707        public static final String STATUS_ICON = "status_icon";
708    }
709
710    private interface DataColumns {
711        /**
712         * The package name to use when creating {@link Resources} objects for
713         * this data row. This value is only designed for use when building user
714         * interfaces, and should not be used to infer the owner.
715         *
716         * @hide
717         */
718        public static final String RES_PACKAGE = "res_package";
719
720        /**
721         * The MIME type of the item represented by this row.
722         */
723        public static final String MIMETYPE = "mimetype";
724
725        /**
726         * A reference to the {@link RawContacts#_ID}
727         * that this data belongs to.
728         */
729        public static final String RAW_CONTACT_ID = "raw_contact_id";
730
731        /**
732         * Whether this is the primary entry of its kind for the raw contact it belongs to
733         * <P>Type: INTEGER (if set, non-0 means true)</P>
734         */
735        public static final String IS_PRIMARY = "is_primary";
736
737        /**
738         * Whether this is the primary entry of its kind for the aggregate
739         * contact it belongs to. Any data record that is "super primary" must
740         * also be "primary".
741         * <P>Type: INTEGER (if set, non-0 means true)</P>
742         */
743        public static final String IS_SUPER_PRIMARY = "is_super_primary";
744
745        /**
746         * The version of this data record. This is a read-only value. The data column is
747         * guaranteed to not change without the version going up. This value is monotonically
748         * increasing.
749         * <P>Type: INTEGER</P>
750         */
751        public static final String DATA_VERSION = "data_version";
752
753        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
754        public static final String DATA1 = "data1";
755        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
756        public static final String DATA2 = "data2";
757        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
758        public static final String DATA3 = "data3";
759        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
760        public static final String DATA4 = "data4";
761        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
762        public static final String DATA5 = "data5";
763        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
764        public static final String DATA6 = "data6";
765        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
766        public static final String DATA7 = "data7";
767        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
768        public static final String DATA8 = "data8";
769        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
770        public static final String DATA9 = "data9";
771        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
772        public static final String DATA10 = "data10";
773        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
774        public static final String DATA11 = "data11";
775        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
776        public static final String DATA12 = "data12";
777        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
778        public static final String DATA13 = "data13";
779        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
780        public static final String DATA14 = "data14";
781        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
782        public static final String DATA15 = "data15";
783
784        /** Generic column for use by sync adapters. */
785        public static final String SYNC1 = "data_sync1";
786        /** Generic column for use by sync adapters. */
787        public static final String SYNC2 = "data_sync2";
788        /** Generic column for use by sync adapters. */
789        public static final String SYNC3 = "data_sync3";
790        /** Generic column for use by sync adapters. */
791        public static final String SYNC4 = "data_sync4";
792    }
793
794    /**
795     * Combines all columns returned by {@link Data} table queries.
796     */
797    private interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
798        RawContactsColumns, ContactsColumns, ContactOptionsColumns, ContactStatusColumns {
799
800    }
801
802    /**
803     * Constants for the data table, which contains data points tied to a raw contact.
804     * For example, a phone number or email address. Each row in this table contains a type
805     * definition and some generic columns. Each data type can define the meaning for each of
806     * the generic columns.
807     */
808    public final static class Data implements DataColumnsWithJoins {
809        /**
810         * This utility class cannot be instantiated
811         */
812        private Data() {}
813
814        /**
815         * The content:// style URI for this table
816         */
817        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data");
818
819        /**
820         * The MIME type of {@link #CONTENT_URI} providing a directory of data.
821         */
822        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data";
823
824        /**
825         * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward
826         * Data.CONTENT_URI contains only exportable data.
827         *
828         * This flag is useful (currently) only for vCard exporter in Contacts app, which
829         * needs to exclude "un-exportable" data from available data to export, while
830         * Contacts app itself has priviledge to access all data including "un-expotable"
831         * ones and providers return all of them regardless of the callers' intention.
832         * <P>Type: INTEGER</p>
833         *
834         * @hide Maybe available only in Eclair and not really ready for public use.
835         * TODO: remove, or implement this feature completely. As of now (Eclair),
836         * we only use this flag in queryEntities(), not query().
837         */
838        public static final String FOR_EXPORT_ONLY = "for_export_only";
839
840        /**
841         * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
842         * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
843         * entry of the given {@link Data} entry.
844         */
845        public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) {
846            final Cursor cursor = resolver.query(dataUri, new String[] {
847                    RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY
848            }, null, null, null);
849
850            Uri lookupUri = null;
851            try {
852                if (cursor != null && cursor.moveToFirst()) {
853                    final long contactId = cursor.getLong(0);
854                    final String lookupKey = cursor.getString(1);
855                    return Contacts.getLookupUri(contactId, lookupKey);
856                }
857            } finally {
858                if (cursor != null) cursor.close();
859            }
860            return lookupUri;
861        }
862    }
863
864    private interface PhoneLookupColumns {
865        /**
866         * The phone number as the user entered it.
867         * <P>Type: TEXT</P>
868         */
869        public static final String NUMBER = "number";
870
871        /**
872         * The type of phone number, for example Home or Work.
873         * <P>Type: INTEGER</P>
874         */
875        public static final String TYPE = "type";
876
877        /**
878         * The user defined label for the phone number.
879         * <P>Type: TEXT</P>
880         */
881        public static final String LABEL = "label";
882    }
883
884    /**
885     * A table that represents the result of looking up a phone number, for
886     * example for caller ID. To perform a lookup you must append the number you
887     * want to find to {@link #CONTENT_FILTER_URI}.
888     */
889    public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns,
890            ContactsColumns, ContactOptionsColumns {
891        /**
892         * This utility class cannot be instantiated
893         */
894        private PhoneLookup() {}
895
896        /**
897         * The content:// style URI for this table. Append the phone number you want to lookup
898         * to this URI and query it to perform a lookup. For example:
899         *
900         * {@code
901         * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, phoneNumber);
902         * }
903         */
904        public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI,
905                "phone_lookup");
906    }
907
908    /**
909     * Additional data mixed in with {@link StatusColumns} to link
910     * back to specific {@link ContactsContract.Data#_ID} entries.
911     */
912    private interface PresenceColumns {
913
914        /**
915         * Reference to the {@link Data#_ID} entry that owns this presence.
916         * <P>Type: INTEGER</P>
917         */
918        public static final String DATA_ID = "presence_data_id";
919
920        /**
921         * <p>Type: NUMBER</p>
922         */
923        public static final String PROTOCOL = "protocol";
924
925        /**
926         * Name of the custom protocol.  Should be supplied along with the {@link #PROTOCOL} value
927         * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.  Should be null or
928         * omitted if {@link #PROTOCOL} value is not
929         * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.
930         *
931         * <p>Type: NUMBER</p>
932         */
933        public static final String CUSTOM_PROTOCOL = "custom_protocol";
934
935        /**
936         * The IM handle the presence item is for. The handle is scoped to
937         * {@link #PROTOCOL}.
938         * <P>Type: TEXT</P>
939         */
940        public static final String IM_HANDLE = "im_handle";
941
942        /**
943         * The IM account for the local user that the presence data came from.
944         * <P>Type: TEXT</P>
945         */
946        public static final String IM_ACCOUNT = "im_account";
947    }
948
949    /**
950     * A status update is linked to a {@link Data} row and captures the user's latest status
951     * update via the corresponding source, e.g. "Having lunch" via "Google Talk".
952     */
953    // TODO make final as soon as Presence is removed
954    public static /*final*/ class StatusUpdates implements StatusColumns, PresenceColumns {
955
956        /**
957         * This utility class cannot be instantiated
958         */
959        private StatusUpdates() {}
960
961        /**
962         * The content:// style URI for this table
963         */
964        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates");
965
966        /**
967         * Gets the resource ID for the proper presence icon.
968         *
969         * @param status the status to get the icon for
970         * @return the resource ID for the proper presence icon
971         */
972        public static final int getPresenceIconResourceId(int status) {
973            switch (status) {
974                case AVAILABLE:
975                    return android.R.drawable.presence_online;
976                case IDLE:
977                case AWAY:
978                    return android.R.drawable.presence_away;
979                case DO_NOT_DISTURB:
980                    return android.R.drawable.presence_busy;
981                case INVISIBLE:
982                    return android.R.drawable.presence_invisible;
983                case OFFLINE:
984                default:
985                    return android.R.drawable.presence_offline;
986            }
987        }
988
989        /**
990         * Returns the precedence of the status code the higher number being the higher precedence.
991         *
992         * @param status The status code.
993         * @return An integer representing the precedence, 0 being the lowest.
994         */
995        public static final int getPresencePrecedence(int status) {
996            // Keep this function here incase we want to enforce a different precedence than the
997            // natural order of the status constants.
998            return status;
999        }
1000
1001        /**
1002         * The MIME type of {@link #CONTENT_URI} providing a directory of
1003         * status update details.
1004         */
1005        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update";
1006
1007        /**
1008         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
1009         * status update detail.
1010         */
1011        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update";
1012    }
1013
1014    @Deprecated
1015    public static final class Presence extends StatusUpdates {
1016
1017    }
1018
1019    /**
1020     * Container for definitions of common data types stored in the {@link Data} table.
1021     */
1022    public static final class CommonDataKinds {
1023        /**
1024         * This utility class cannot be instantiated
1025         */
1026        private CommonDataKinds() {}
1027
1028        /**
1029         * The {@link Data#RES_PACKAGE} value for common data that should be
1030         * shown using a default style.
1031         *
1032         * @hide RES_PACKAGE is hidden
1033         */
1034        public static final String PACKAGE_COMMON = "common";
1035
1036        /**
1037         * The base types that all "Typed" data kinds support.
1038         */
1039        public interface BaseTypes {
1040            /**
1041             * A custom type. The custom label should be supplied by user.
1042             */
1043            public static int TYPE_CUSTOM = 0;
1044        }
1045
1046        /**
1047         * Columns common across the specific types.
1048         */
1049        private interface CommonColumns extends BaseTypes {
1050            /**
1051             * The data for the contact method.
1052             * <P>Type: TEXT</P>
1053             */
1054            public static final String DATA = DataColumns.DATA1;
1055
1056            /**
1057             * The type of data, for example Home or Work.
1058             * <P>Type: INTEGER</P>
1059             */
1060            public static final String TYPE = DataColumns.DATA2;
1061
1062            /**
1063             * The user defined label for the the contact method.
1064             * <P>Type: TEXT</P>
1065             */
1066            public static final String LABEL = DataColumns.DATA3;
1067        }
1068
1069        /**
1070         * Parts of the name.
1071         */
1072        public static final class StructuredName implements DataColumnsWithJoins {
1073            /**
1074             * This utility class cannot be instantiated
1075             */
1076            private StructuredName() {}
1077
1078            /** MIME type used when storing this in data table. */
1079            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
1080
1081            /**
1082             * The name that should be used to display the contact.
1083             * <i>Unstructured component of the name should be consistent with
1084             * its structured representation.</i>
1085             * <p>
1086             * Type: TEXT
1087             */
1088            public static final String DISPLAY_NAME = DATA1;
1089
1090            /**
1091             * The given name for the contact.
1092             * <P>Type: TEXT</P>
1093             */
1094            public static final String GIVEN_NAME = DATA2;
1095
1096            /**
1097             * The family name for the contact.
1098             * <P>Type: TEXT</P>
1099             */
1100            public static final String FAMILY_NAME = DATA3;
1101
1102            /**
1103             * The contact's honorific prefix, e.g. "Sir"
1104             * <P>Type: TEXT</P>
1105             */
1106            public static final String PREFIX = DATA4;
1107
1108            /**
1109             * The contact's middle name
1110             * <P>Type: TEXT</P>
1111             */
1112            public static final String MIDDLE_NAME = DATA5;
1113
1114            /**
1115             * The contact's honorific suffix, e.g. "Jr"
1116             */
1117            public static final String SUFFIX = DATA6;
1118
1119            /**
1120             * The phonetic version of the given name for the contact.
1121             * <P>Type: TEXT</P>
1122             */
1123            public static final String PHONETIC_GIVEN_NAME = DATA7;
1124
1125            /**
1126             * The phonetic version of the additional name for the contact.
1127             * <P>Type: TEXT</P>
1128             */
1129            public static final String PHONETIC_MIDDLE_NAME = DATA8;
1130
1131            /**
1132             * The phonetic version of the family name for the contact.
1133             * <P>Type: TEXT</P>
1134             */
1135            public static final String PHONETIC_FAMILY_NAME = DATA9;
1136        }
1137
1138        /**
1139         * A nickname.
1140         */
1141        public static final class Nickname implements DataColumnsWithJoins, CommonColumns {
1142            /**
1143             * This utility class cannot be instantiated
1144             */
1145            private Nickname() {}
1146
1147            /** MIME type used when storing this in data table. */
1148            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
1149
1150            public static final int TYPE_DEFAULT = 1;
1151            public static final int TYPE_OTHER_NAME = 2;
1152            public static final int TYPE_MAINDEN_NAME = 3;
1153            public static final int TYPE_SHORT_NAME = 4;
1154            public static final int TYPE_INITIALS = 5;
1155
1156            /**
1157             * The name itself
1158             */
1159            public static final String NAME = DATA;
1160        }
1161
1162        /**
1163         * Common data definition for telephone numbers.
1164         */
1165        public static final class Phone implements DataColumnsWithJoins, CommonColumns {
1166            /**
1167             * This utility class cannot be instantiated
1168             */
1169            private Phone() {}
1170
1171            /** MIME type used when storing this in data table. */
1172            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
1173
1174            /**
1175             * The MIME type of {@link #CONTENT_URI} providing a directory of
1176             * phones.
1177             */
1178            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
1179
1180            /**
1181             * The content:// style URI for all data records of the
1182             * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the
1183             * associated raw contact and aggregate contact data.
1184             */
1185            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
1186                    "phones");
1187
1188            /**
1189             * The content:// style URL for phone lookup using a filter. The filter returns
1190             * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied
1191             * to display names as well as phone numbers. The filter argument should be passed
1192             * as an additional path segment after this URI.
1193             */
1194            public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
1195                    "filter");
1196
1197            public static final int TYPE_HOME = 1;
1198            public static final int TYPE_MOBILE = 2;
1199            public static final int TYPE_WORK = 3;
1200            public static final int TYPE_FAX_WORK = 4;
1201            public static final int TYPE_FAX_HOME = 5;
1202            public static final int TYPE_PAGER = 6;
1203            public static final int TYPE_OTHER = 7;
1204            public static final int TYPE_CALLBACK = 8;
1205            public static final int TYPE_CAR = 9;
1206            public static final int TYPE_COMPANY_MAIN = 10;
1207            public static final int TYPE_ISDN = 11;
1208            public static final int TYPE_MAIN = 12;
1209            public static final int TYPE_OTHER_FAX = 13;
1210            public static final int TYPE_RADIO = 14;
1211            public static final int TYPE_TELEX = 15;
1212            public static final int TYPE_TTY_TDD = 16;
1213            public static final int TYPE_WORK_MOBILE = 17;
1214            public static final int TYPE_WORK_PAGER = 18;
1215            public static final int TYPE_ASSISTANT = 19;
1216            public static final int TYPE_MMS = 20;
1217
1218            /**
1219             * The phone number as the user entered it.
1220             * <P>Type: TEXT</P>
1221             */
1222            public static final String NUMBER = DATA;
1223
1224            /**
1225             * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead.
1226             * @hide
1227             */
1228            @Deprecated
1229            public static final CharSequence getDisplayLabel(Context context, int type,
1230                    CharSequence label, CharSequence[] labelArray) {
1231                return getTypeLabel(context.getResources(), type, label);
1232            }
1233
1234            /**
1235             * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead.
1236             * @hide
1237             */
1238            @Deprecated
1239            public static final CharSequence getDisplayLabel(Context context, int type,
1240                    CharSequence label) {
1241                return getTypeLabel(context.getResources(), type, label);
1242            }
1243
1244            /**
1245             * Return the string resource that best describes the given
1246             * {@link #TYPE}. Will always return a valid resource.
1247             */
1248            public static final int getTypeLabelResource(int type) {
1249                switch (type) {
1250                    case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome;
1251                    case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile;
1252                    case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork;
1253                    case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork;
1254                    case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome;
1255                    case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager;
1256                    case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther;
1257                    case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback;
1258                    case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar;
1259                    case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain;
1260                    case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn;
1261                    case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain;
1262                    case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax;
1263                    case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio;
1264                    case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex;
1265                    case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd;
1266                    case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile;
1267                    case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager;
1268                    case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant;
1269                    case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms;
1270                    default: return com.android.internal.R.string.phoneTypeCustom;
1271                }
1272            }
1273
1274            /**
1275             * Return a {@link CharSequence} that best describes the given type,
1276             * possibly substituting the given {@link #LABEL} value
1277             * for {@link #TYPE_CUSTOM}.
1278             */
1279            public static final CharSequence getTypeLabel(Resources res, int type,
1280                    CharSequence label) {
1281                if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) {
1282                    return label;
1283                } else {
1284                    final int labelRes = getTypeLabelResource(type);
1285                    return res.getText(labelRes);
1286                }
1287            }
1288        }
1289
1290        /**
1291         * Common data definition for email addresses.
1292         */
1293        public static final class Email implements DataColumnsWithJoins, CommonColumns {
1294            /**
1295             * This utility class cannot be instantiated
1296             */
1297            private Email() {}
1298
1299            /** MIME type used when storing this in data table. */
1300            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
1301
1302            /**
1303             * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses.
1304             */
1305            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2";
1306
1307            /**
1308             * The content:// style URI for all data records of the
1309             * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the
1310             * associated raw contact and aggregate contact data.
1311             */
1312            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
1313                    "emails");
1314
1315            /**
1316             * The content:// style URL for looking up data rows by email address. The
1317             * lookup argument, an email address, should be passed as an additional path segment
1318             * after this URI.
1319             */
1320            public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI,
1321                    "lookup");
1322
1323            /**
1324             * The content:// style URL for email lookup using a filter. The filter returns
1325             * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied
1326             * to display names as well as email addresses. The filter argument should be passed
1327             * as an additional path segment after this URI.
1328             */
1329            public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
1330                    "filter");
1331
1332            public static final int TYPE_HOME = 1;
1333            public static final int TYPE_WORK = 2;
1334            public static final int TYPE_OTHER = 3;
1335            public static final int TYPE_MOBILE = 4;
1336
1337            /**
1338             * The display name for the email address
1339             * <P>Type: TEXT</P>
1340             */
1341            public static final String DISPLAY_NAME = DATA4;
1342
1343            /**
1344             * Return the string resource that best describes the given
1345             * {@link #TYPE}. Will always return a valid resource.
1346             */
1347            public static final int getTypeLabelResource(int type) {
1348                switch (type) {
1349                    case TYPE_HOME: return com.android.internal.R.string.emailTypeHome;
1350                    case TYPE_WORK: return com.android.internal.R.string.emailTypeWork;
1351                    case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther;
1352                    case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile;
1353                    default: return com.android.internal.R.string.emailTypeCustom;
1354                }
1355            }
1356
1357            /**
1358             * Return a {@link CharSequence} that best describes the given type,
1359             * possibly substituting the given {@link #LABEL} value
1360             * for {@link #TYPE_CUSTOM}.
1361             */
1362            public static final CharSequence getTypeLabel(Resources res, int type,
1363                    CharSequence label) {
1364                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
1365                    return label;
1366                } else {
1367                    final int labelRes = getTypeLabelResource(type);
1368                    return res.getText(labelRes);
1369                }
1370            }
1371        }
1372
1373        /**
1374         * Common data definition for postal addresses.
1375         */
1376        public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns {
1377            /**
1378             * This utility class cannot be instantiated
1379             */
1380            private StructuredPostal() {
1381            }
1382
1383            /** MIME type used when storing this in data table. */
1384            public static final String CONTENT_ITEM_TYPE =
1385                    "vnd.android.cursor.item/postal-address_v2";
1386
1387            /**
1388             * The MIME type of {@link #CONTENT_URI} providing a directory of
1389             * postal addresses.
1390             */
1391            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
1392
1393            /**
1394             * The content:// style URI for all data records of the
1395             * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type.
1396             */
1397            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
1398                    "postals");
1399
1400            public static final int TYPE_HOME = 1;
1401            public static final int TYPE_WORK = 2;
1402            public static final int TYPE_OTHER = 3;
1403
1404            /**
1405             * The full, unstructured postal address. <i>This field must be
1406             * consistent with any structured data.</i>
1407             * <p>
1408             * Type: TEXT
1409             */
1410            public static final String FORMATTED_ADDRESS = DATA;
1411
1412            /**
1413             * Can be street, avenue, road, etc. This element also includes the
1414             * house number and room/apartment/flat/floor number.
1415             * <p>
1416             * Type: TEXT
1417             */
1418            public static final String STREET = DATA4;
1419
1420            /**
1421             * Covers actual P.O. boxes, drawers, locked bags, etc. This is
1422             * usually but not always mutually exclusive with street.
1423             * <p>
1424             * Type: TEXT
1425             */
1426            public static final String POBOX = DATA5;
1427
1428            /**
1429             * This is used to disambiguate a street address when a city
1430             * contains more than one street with the same name, or to specify a
1431             * small place whose mail is routed through a larger postal town. In
1432             * China it could be a county or a minor city.
1433             * <p>
1434             * Type: TEXT
1435             */
1436            public static final String NEIGHBORHOOD = DATA6;
1437
1438            /**
1439             * Can be city, village, town, borough, etc. This is the postal town
1440             * and not necessarily the place of residence or place of business.
1441             * <p>
1442             * Type: TEXT
1443             */
1444            public static final String CITY = DATA7;
1445
1446            /**
1447             * A state, province, county (in Ireland), Land (in Germany),
1448             * departement (in France), etc.
1449             * <p>
1450             * Type: TEXT
1451             */
1452            public static final String REGION = DATA8;
1453
1454            /**
1455             * Postal code. Usually country-wide, but sometimes specific to the
1456             * city (e.g. "2" in "Dublin 2, Ireland" addresses).
1457             * <p>
1458             * Type: TEXT
1459             */
1460            public static final String POSTCODE = DATA9;
1461
1462            /**
1463             * The name or code of the country.
1464             * <p>
1465             * Type: TEXT
1466             */
1467            public static final String COUNTRY = DATA10;
1468
1469            /**
1470             * Return the string resource that best describes the given
1471             * {@link #TYPE}. Will always return a valid resource.
1472             */
1473            public static final int getTypeLabelResource(int type) {
1474                switch (type) {
1475                    case TYPE_HOME: return com.android.internal.R.string.postalTypeHome;
1476                    case TYPE_WORK: return com.android.internal.R.string.postalTypeWork;
1477                    case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther;
1478                    default: return com.android.internal.R.string.postalTypeCustom;
1479                }
1480            }
1481
1482            /**
1483             * Return a {@link CharSequence} that best describes the given type,
1484             * possibly substituting the given {@link #LABEL} value
1485             * for {@link #TYPE_CUSTOM}.
1486             */
1487            public static final CharSequence getTypeLabel(Resources res, int type,
1488                    CharSequence label) {
1489                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
1490                    return label;
1491                } else {
1492                    final int labelRes = getTypeLabelResource(type);
1493                    return res.getText(labelRes);
1494                }
1495            }
1496        }
1497
1498        /**
1499         * Common data definition for IM addresses.
1500         */
1501        public static final class Im implements DataColumnsWithJoins, CommonColumns {
1502            /**
1503             * This utility class cannot be instantiated
1504             */
1505            private Im() {}
1506
1507            /** MIME type used when storing this in data table. */
1508            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
1509
1510            public static final int TYPE_HOME = 1;
1511            public static final int TYPE_WORK = 2;
1512            public static final int TYPE_OTHER = 3;
1513
1514            /**
1515             * This column should be populated with one of the defined
1516             * constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this
1517             * column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL}
1518             * should contain the name of the custom protocol.
1519             */
1520            public static final String PROTOCOL = DATA5;
1521
1522            public static final String CUSTOM_PROTOCOL = DATA6;
1523
1524            /*
1525             * The predefined IM protocol types.
1526             */
1527            public static final int PROTOCOL_CUSTOM = -1;
1528            public static final int PROTOCOL_AIM = 0;
1529            public static final int PROTOCOL_MSN = 1;
1530            public static final int PROTOCOL_YAHOO = 2;
1531            public static final int PROTOCOL_SKYPE = 3;
1532            public static final int PROTOCOL_QQ = 4;
1533            public static final int PROTOCOL_GOOGLE_TALK = 5;
1534            public static final int PROTOCOL_ICQ = 6;
1535            public static final int PROTOCOL_JABBER = 7;
1536            public static final int PROTOCOL_NETMEETING = 8;
1537
1538            /**
1539             * Return the string resource that best describes the given
1540             * {@link #TYPE}. Will always return a valid resource.
1541             */
1542            public static final int getTypeLabelResource(int type) {
1543                switch (type) {
1544                    case TYPE_HOME: return com.android.internal.R.string.imTypeHome;
1545                    case TYPE_WORK: return com.android.internal.R.string.imTypeWork;
1546                    case TYPE_OTHER: return com.android.internal.R.string.imTypeOther;
1547                    default: return com.android.internal.R.string.imTypeCustom;
1548                }
1549            }
1550
1551            /**
1552             * Return a {@link CharSequence} that best describes the given type,
1553             * possibly substituting the given {@link #LABEL} value
1554             * for {@link #TYPE_CUSTOM}.
1555             */
1556            public static final CharSequence getTypeLabel(Resources res, int type,
1557                    CharSequence label) {
1558                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
1559                    return label;
1560                } else {
1561                    final int labelRes = getTypeLabelResource(type);
1562                    return res.getText(labelRes);
1563                }
1564            }
1565
1566            /**
1567             * Return the string resource that best describes the given
1568             * {@link #PROTOCOL}. Will always return a valid resource.
1569             */
1570            public static final int getProtocolLabelResource(int type) {
1571                switch (type) {
1572                    case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim;
1573                    case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn;
1574                    case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo;
1575                    case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype;
1576                    case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq;
1577                    case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk;
1578                    case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq;
1579                    case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber;
1580                    case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting;
1581                    default: return com.android.internal.R.string.imProtocolCustom;
1582                }
1583            }
1584
1585            /**
1586             * Return a {@link CharSequence} that best describes the given
1587             * protocol, possibly substituting the given
1588             * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}.
1589             */
1590            public static final CharSequence getProtocolLabel(Resources res, int type,
1591                    CharSequence label) {
1592                if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) {
1593                    return label;
1594                } else {
1595                    final int labelRes = getProtocolLabelResource(type);
1596                    return res.getText(labelRes);
1597                }
1598            }
1599        }
1600
1601        /**
1602         * Common data definition for organizations.
1603         */
1604        public static final class Organization implements DataColumnsWithJoins, CommonColumns {
1605            /**
1606             * This utility class cannot be instantiated
1607             */
1608            private Organization() {}
1609
1610            /** MIME type used when storing this in data table. */
1611            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
1612
1613            public static final int TYPE_WORK = 1;
1614            public static final int TYPE_OTHER = 2;
1615
1616            /**
1617             * The company as the user entered it.
1618             * <P>Type: TEXT</P>
1619             */
1620            public static final String COMPANY = DATA;
1621
1622            /**
1623             * The position title at this company as the user entered it.
1624             * <P>Type: TEXT</P>
1625             */
1626            public static final String TITLE = DATA4;
1627
1628            /**
1629             * The department at this company as the user entered it.
1630             * <P>Type: TEXT</P>
1631             */
1632            public static final String DEPARTMENT = DATA5;
1633
1634            /**
1635             * The job description at this company as the user entered it.
1636             * <P>Type: TEXT</P>
1637             */
1638            public static final String JOB_DESCRIPTION = DATA6;
1639
1640            /**
1641             * The symbol of this company as the user entered it.
1642             * <P>Type: TEXT</P>
1643             */
1644            public static final String SYMBOL = DATA7;
1645
1646            /**
1647             * The phonetic name of this company as the user entered it.
1648             * <P>Type: TEXT</P>
1649             */
1650            public static final String PHONETIC_NAME = DATA8;
1651
1652            /**
1653             * The office location of this organization.
1654             * <P>Type: TEXT</P>
1655             */
1656            public static final String OFFICE_LOCATION = DATA9;
1657
1658            /**
1659             * Return the string resource that best describes the given
1660             * {@link #TYPE}. Will always return a valid resource.
1661             */
1662            public static final int getTypeLabelResource(int type) {
1663                switch (type) {
1664                    case TYPE_WORK: return com.android.internal.R.string.orgTypeWork;
1665                    case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther;
1666                    default: return com.android.internal.R.string.orgTypeCustom;
1667                }
1668            }
1669
1670            /**
1671             * Return a {@link CharSequence} that best describes the given type,
1672             * possibly substituting the given {@link #LABEL} value
1673             * for {@link #TYPE_CUSTOM}.
1674             */
1675            public static final CharSequence getTypeLabel(Resources res, int type,
1676                    CharSequence label) {
1677                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
1678                    return label;
1679                } else {
1680                    final int labelRes = getTypeLabelResource(type);
1681                    return res.getText(labelRes);
1682                }
1683            }
1684        }
1685
1686        /**
1687         * Common data definition for birthdays.
1688         */
1689        public static final class Birthday implements DataColumnsWithJoins {
1690            /**
1691             * This utility class cannot be instantiated
1692             */
1693            private Birthday() {}
1694
1695            /** MIME type used when storing this in data table. */
1696            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/birthday";
1697
1698            /**
1699             * The birthday. This must be of the form YYYY-MM-DD or YYYY-MM-DDThh:mm:ss
1700             * These are xs:date and xs:dateTime
1701             * <P>Type: TEXT</P>
1702             */
1703            public static final String BIRTHDAY = DATA1;
1704        }
1705
1706        /**
1707         * Common data definition for relations.
1708         */
1709        public static final class Relation implements DataColumnsWithJoins, CommonColumns {
1710            /**
1711             * This utility class cannot be instantiated
1712             */
1713            private Relation() {}
1714
1715            /** MIME type used when storing this in data table. */
1716            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
1717
1718            public static final int TYPE_ASSISTANT = 1;
1719            public static final int TYPE_BROTHER = 2;
1720            public static final int TYPE_CHILD = 3;
1721            public static final int TYPE_DOMESTIC_PARTNER = 4;
1722            public static final int TYPE_FATHER = 5;
1723            public static final int TYPE_FRIEND = 6;
1724            public static final int TYPE_MANAGER = 7;
1725            public static final int TYPE_MOTHER = 8;
1726            public static final int TYPE_PARENT = 9;
1727            public static final int TYPE_PARTNER = 10;
1728            public static final int TYPE_REFERRED_BY = 11;
1729            public static final int TYPE_RELATIVE = 12;
1730            public static final int TYPE_SISTER = 13;
1731            public static final int TYPE_SPOUSE = 14;
1732
1733            /**
1734             * The name of the relative as the user entered it.
1735             * <P>Type: TEXT</P>
1736             */
1737            public static final String NAME = DATA;
1738        }
1739
1740        /**
1741         * Common data definition for events.
1742         */
1743        public static final class Event implements DataColumnsWithJoins, CommonColumns {
1744            /**
1745             * This utility class cannot be instantiated
1746             */
1747            private Event() {}
1748
1749            /** MIME type used when storing this in data table. */
1750            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/event";
1751
1752            public static final int TYPE_ANNIVERSARY = 1;
1753            public static final int TYPE_OTHER = 2;
1754
1755            /**
1756             * The event start date as the user entered it.
1757             * <P>Type: TEXT</P>
1758             */
1759            public static final String START_DATE = DATA;
1760        }
1761
1762        /**
1763         * Photo of the contact.
1764         */
1765        public static final class Photo implements DataColumnsWithJoins {
1766            /**
1767             * This utility class cannot be instantiated
1768             */
1769            private Photo() {}
1770
1771            /** MIME type used when storing this in data table. */
1772            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
1773
1774            /**
1775             * Thumbnail photo of the raw contact. This is the raw bytes of an image
1776             * that could be inflated using {@link android.graphics.BitmapFactory}.
1777             * <p>
1778             * Type: BLOB
1779             */
1780            public static final String PHOTO = DATA15;
1781        }
1782
1783        /**
1784         * Notes about the contact.
1785         */
1786        public static final class Note implements DataColumnsWithJoins {
1787            /**
1788             * This utility class cannot be instantiated
1789             */
1790            private Note() {}
1791
1792            /** MIME type used when storing this in data table. */
1793            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
1794
1795            /**
1796             * The note text.
1797             * <P>Type: TEXT</P>
1798             */
1799            public static final String NOTE = DATA1;
1800        }
1801
1802        /**
1803         * Group Membership.
1804         */
1805        public static final class GroupMembership implements DataColumnsWithJoins {
1806            /**
1807             * This utility class cannot be instantiated
1808             */
1809            private GroupMembership() {}
1810
1811            /** MIME type used when storing this in data table. */
1812            public static final String CONTENT_ITEM_TYPE =
1813                    "vnd.android.cursor.item/group_membership";
1814
1815            /**
1816             * The row id of the group that this group membership refers to. Exactly one of
1817             * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row.
1818             * <P>Type: INTEGER</P>
1819             */
1820            public static final String GROUP_ROW_ID = DATA1;
1821
1822            /**
1823             * The sourceid of the group that this group membership refers to.  Exactly one of
1824             * this or {@link #GROUP_ROW_ID} must be set when inserting a row.
1825             * <P>Type: TEXT</P>
1826             */
1827            public static final String GROUP_SOURCE_ID = "group_sourceid";
1828        }
1829
1830        /**
1831         * Website related to the contact.
1832         */
1833        public static final class Website implements DataColumnsWithJoins, CommonColumns {
1834            /**
1835             * This utility class cannot be instantiated
1836             */
1837            private Website() {}
1838
1839            /** MIME type used when storing this in data table. */
1840            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
1841
1842            public static final int TYPE_HOMEPAGE = 1;
1843            public static final int TYPE_BLOG = 2;
1844            public static final int TYPE_PROFILE = 3;
1845            public static final int TYPE_HOME = 4;
1846            public static final int TYPE_WORK = 5;
1847            public static final int TYPE_FTP = 6;
1848            public static final int TYPE_OTHER = 7;
1849
1850            /**
1851             * The website URL string.
1852             * <P>Type: TEXT</P>
1853             */
1854            public static final String URL = DATA;
1855        }
1856    }
1857
1858    private interface GroupsColumns {
1859        /**
1860         * The display title of this group.
1861         * <p>
1862         * Type: TEXT
1863         */
1864        public static final String TITLE = "title";
1865
1866        /**
1867         * The package name to use when creating {@link Resources} objects for
1868         * this group. This value is only designed for use when building user
1869         * interfaces, and should not be used to infer the owner.
1870         *
1871         * @hide
1872         */
1873        public static final String RES_PACKAGE = "res_package";
1874
1875        /**
1876         * The display title of this group to load as a resource from
1877         * {@link #RES_PACKAGE}, which may be localized.
1878         * <P>Type: TEXT</P>
1879         *
1880         * @hide
1881         */
1882        public static final String TITLE_RES = "title_res";
1883
1884        /**
1885         * Notes about the group.
1886         * <p>
1887         * Type: TEXT
1888         */
1889        public static final String NOTES = "notes";
1890
1891        /**
1892         * The ID of this group if it is a System Group, i.e. a group that has a special meaning
1893         * to the sync adapter, null otherwise.
1894         * <P>Type: TEXT</P>
1895         */
1896        public static final String SYSTEM_ID = "system_id";
1897
1898        /**
1899         * The total number of {@link Contacts} that have
1900         * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only
1901         * present when querying {@link Groups#CONTENT_SUMMARY_URI}.
1902         * <p>
1903         * Type: INTEGER
1904         */
1905        public static final String SUMMARY_COUNT = "summ_count";
1906
1907        /**
1908         * The total number of {@link Contacts} that have both
1909         * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers.
1910         * Read-only value that is only present when querying
1911         * {@link Groups#CONTENT_SUMMARY_URI}.
1912         * <p>
1913         * Type: INTEGER
1914         */
1915        public static final String SUMMARY_WITH_PHONES = "summ_phones";
1916
1917        /**
1918         * Flag indicating if the contacts belonging to this group should be
1919         * visible in any user interface.
1920         * <p>
1921         * Type: INTEGER (boolean)
1922         */
1923        public static final String GROUP_VISIBLE = "group_visible";
1924
1925        /**
1926         * The "deleted" flag: "0" by default, "1" if the row has been marked
1927         * for deletion. When {@link android.content.ContentResolver#delete} is
1928         * called on a raw contact, it is marked for deletion and removed from its
1929         * aggregate contact. The sync adaptor deletes the raw contact on the server and
1930         * then calls ContactResolver.delete once more, this time setting the the
1931         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
1932         * the data removal.
1933         * <P>Type: INTEGER</P>
1934         */
1935        public static final String DELETED = "deleted";
1936
1937        /**
1938         * Whether this group should be synced if the SYNC_EVERYTHING settings
1939         * is false for this group's account.
1940         * <p>
1941         * Type: INTEGER (boolean)
1942         */
1943        public static final String SHOULD_SYNC = "should_sync";
1944    }
1945
1946    /**
1947     * Constants for the groups table.
1948     */
1949    public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns {
1950        /**
1951         * This utility class cannot be instantiated
1952         */
1953        private Groups() {
1954        }
1955
1956        /**
1957         * The content:// style URI for this table
1958         */
1959        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups");
1960
1961        /**
1962         * The content:// style URI for this table joined with details data from
1963         * {@link Data}.
1964         */
1965        public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
1966                "groups_summary");
1967
1968        /**
1969         * The MIME type of a directory of groups.
1970         */
1971        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group";
1972
1973        /**
1974         * The MIME type of a single group.
1975         */
1976        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
1977    }
1978
1979    /**
1980     * Constants for the contact aggregation exceptions table, which contains
1981     * aggregation rules overriding those used by automatic aggregation.  This type only
1982     * supports query and update. Neither insert nor delete are supported.
1983     */
1984    public static final class AggregationExceptions implements BaseColumns {
1985        /**
1986         * This utility class cannot be instantiated
1987         */
1988        private AggregationExceptions() {}
1989
1990        /**
1991         * The content:// style URI for this table
1992         */
1993        public static final Uri CONTENT_URI =
1994                Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions");
1995
1996        /**
1997         * The MIME type of {@link #CONTENT_URI} providing a directory of data.
1998         */
1999        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception";
2000
2001        /**
2002         * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception
2003         */
2004        public static final String CONTENT_ITEM_TYPE =
2005                "vnd.android.cursor.item/aggregation_exception";
2006
2007        /**
2008         * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or
2009         * {@link #TYPE_AUTOMATIC}.
2010         *
2011         * <P>Type: INTEGER</P>
2012         */
2013        public static final String TYPE = "type";
2014
2015        /**
2016         * Allows the provider to automatically decide whether the specified raw contacts should
2017         * be included in the same aggregate contact or not.
2018         */
2019        public static final int TYPE_AUTOMATIC = 0;
2020
2021        /**
2022         * Makes sure that the specified raw contacts are included in the same
2023         * aggregate contact.
2024         */
2025        public static final int TYPE_KEEP_TOGETHER = 1;
2026
2027        /**
2028         * Makes sure that the specified raw contacts are NOT included in the same
2029         * aggregate contact.
2030         */
2031        public static final int TYPE_KEEP_SEPARATE = 2;
2032
2033        /**
2034         * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to.
2035         */
2036        public static final String RAW_CONTACT_ID1 = "raw_contact_id1";
2037
2038        /**
2039         * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule
2040         * applies to.
2041         */
2042        public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
2043    }
2044
2045    private interface SettingsColumns {
2046        /**
2047         * The name of the account instance to which this row belongs.
2048         * <P>Type: TEXT</P>
2049         */
2050        public static final String ACCOUNT_NAME = "account_name";
2051
2052        /**
2053         * The type of account to which this row belongs, which when paired with
2054         * {@link #ACCOUNT_NAME} identifies a specific account.
2055         * <P>Type: TEXT</P>
2056         */
2057        public static final String ACCOUNT_TYPE = "account_type";
2058
2059        /**
2060         * Depending on the mode defined by the sync-adapter, this flag controls
2061         * the top-level sync behavior for this data source.
2062         * <p>
2063         * Type: INTEGER (boolean)
2064         */
2065        public static final String SHOULD_SYNC = "should_sync";
2066
2067        /**
2068         * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership}
2069         * entries should be visible in any user interface.
2070         * <p>
2071         * Type: INTEGER (boolean)
2072         */
2073        public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
2074
2075        /**
2076         * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
2077         * {@link Groups#SHOULD_SYNC} under this account have been marked as
2078         * unsynced.
2079         */
2080        public static final String ANY_UNSYNCED = "any_unsynced";
2081
2082        /**
2083         * Read-only count of {@link Contacts} from a specific source that have
2084         * no {@link CommonDataKinds.GroupMembership} entries.
2085         * <p>
2086         * Type: INTEGER
2087         */
2088        public static final String UNGROUPED_COUNT = "summ_count";
2089
2090        /**
2091         * Read-only count of {@link Contacts} from a specific source that have
2092         * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers.
2093         * <p>
2094         * Type: INTEGER
2095         */
2096        public static final String UNGROUPED_WITH_PHONES = "summ_phones";
2097    }
2098
2099    /**
2100     * Contacts-specific settings for various {@link Account}.
2101     */
2102    public static final class Settings implements SettingsColumns {
2103        /**
2104         * This utility class cannot be instantiated
2105         */
2106        private Settings() {
2107        }
2108
2109        /**
2110         * The content:// style URI for this table
2111         */
2112        public static final Uri CONTENT_URI =
2113                Uri.withAppendedPath(AUTHORITY_URI, "settings");
2114
2115        /**
2116         * The MIME-type of {@link #CONTENT_URI} providing a directory of
2117         * settings.
2118         */
2119        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
2120
2121        /**
2122         * The MIME-type of {@link #CONTENT_URI} providing a single setting.
2123         */
2124        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
2125    }
2126
2127    /**
2128     * Helper methods to display FastTrack dialogs that allow users to pivot on
2129     * a specific {@link Contacts} entry.
2130     *
2131     * @hide
2132     */
2133    public static final class FastTrack {
2134        /**
2135         * Action used to trigger person pivot dialog.
2136         * @hide
2137         */
2138        public static final String ACTION_FAST_TRACK =
2139                "com.android.contacts.action.FAST_TRACK";
2140
2141        /**
2142         * Extra used to specify pivot dialog location in screen coordinates.
2143         * @hide
2144         */
2145        public static final String EXTRA_TARGET_RECT = "target_rect";
2146
2147        /**
2148         * Extra used to specify size of pivot dialog.
2149         * @hide
2150         */
2151        public static final String EXTRA_MODE = "mode";
2152
2153        /**
2154         * Extra used to indicate a list of specific MIME-types to exclude and
2155         * not display. Stored as a {@link String} array.
2156         * @hide
2157         */
2158        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
2159
2160        /**
2161         * Small FastTrack mode, usually presented with minimal actions.
2162         */
2163        public static final int MODE_SMALL = 1;
2164
2165        /**
2166         * Medium FastTrack mode, includes actions and light summary describing
2167         * the {@link Contacts} entry being shown. This may include social
2168         * status and presence details.
2169         */
2170        public static final int MODE_MEDIUM = 2;
2171
2172        /**
2173         * Large FastTrack mode, includes actions and larger, card-like summary
2174         * of the {@link Contacts} entry being shown. This may include detailed
2175         * information, such as a photo.
2176         */
2177        public static final int MODE_LARGE = 3;
2178
2179        /**
2180         * Trigger a dialog that lists the various methods of interacting with
2181         * the requested {@link Contacts} entry. This may be based on available
2182         * {@link Data} rows under that contact, and may also include social
2183         * status and presence details.
2184         *
2185         * @param context The parent {@link Context} that may be used as the
2186         *            parent for this dialog.
2187         * @param target Specific {@link View} from your layout that this dialog
2188         *            should be centered around. In particular, if the dialog
2189         *            has a "callout" arrow, it will be pointed and centered
2190         *            around this {@link View}.
2191         * @param lookupUri A {@link Contacts#CONTENT_LOOKUP_URI} style
2192         *            {@link Uri} that describes a specific contact to feature
2193         *            in this dialog.
2194         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
2195         *            {@link #MODE_LARGE}, indicating the desired dialog size,
2196         *            when supported.
2197         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
2198         *            to exclude when showing this dialog. For example, when
2199         *            already viewing the contact details card, this can be used
2200         *            to omit the details entry from the dialog.
2201         */
2202        public static void showFastTrack(Context context, View target, Uri lookupUri, int mode,
2203                String[] excludeMimes) {
2204            // Find location and bounds of target view
2205            final int[] location = new int[2];
2206            target.getLocationOnScreen(location);
2207
2208            final Rect rect = new Rect();
2209            rect.left = location[0];
2210            rect.top = location[1];
2211            rect.right = rect.left + target.getWidth();
2212            rect.bottom = rect.top + target.getHeight();
2213
2214            // Trigger with obtained rectangle
2215            showFastTrack(context, rect, lookupUri, mode, excludeMimes);
2216        }
2217
2218        /**
2219         * Trigger a dialog that lists the various methods of interacting with
2220         * the requested {@link Contacts} entry. This may be based on available
2221         * {@link Data} rows under that contact, and may also include social
2222         * status and presence details.
2223         *
2224         * @param context The parent {@link Context} that may be used as the
2225         *            parent for this dialog.
2226         * @param target Specific {@link Rect} that this dialog should be
2227         *            centered around, in screen coordinates. In particular, if
2228         *            the dialog has a "callout" arrow, it will be pointed and
2229         *            centered around this {@link Rect}.
2230         * @param lookupUri A {@link Contacts#CONTENT_LOOKUP_URI} style
2231         *            {@link Uri} that describes a specific contact to feature
2232         *            in this dialog.
2233         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
2234         *            {@link #MODE_LARGE}, indicating the desired dialog size,
2235         *            when supported.
2236         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
2237         *            to exclude when showing this dialog. For example, when
2238         *            already viewing the contact details card, this can be used
2239         *            to omit the details entry from the dialog.
2240         */
2241        public static void showFastTrack(Context context, Rect target, Uri lookupUri, int mode,
2242                String[] excludeMimes) {
2243            // Launch pivot dialog through intent for now
2244            final Intent intent = new Intent(ACTION_FAST_TRACK);
2245            intent.setData(lookupUri);
2246            intent.putExtra(EXTRA_TARGET_RECT, target);
2247            intent.putExtra(EXTRA_MODE, mode);
2248            intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
2249            context.startActivity(intent);
2250        }
2251    }
2252
2253    /**
2254     * Contains helper classes used to create or manage {@link android.content.Intent Intents}
2255     * that involve contacts.
2256     */
2257    public static final class Intents {
2258        /**
2259         * This is the intent that is fired when a search suggestion is clicked on.
2260         */
2261        public static final String SEARCH_SUGGESTION_CLICKED =
2262                "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
2263
2264        /**
2265         * This is the intent that is fired when a search suggestion for dialing a number
2266         * is clicked on.
2267         */
2268        public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =
2269                "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
2270
2271        /**
2272         * This is the intent that is fired when a search suggestion for creating a contact
2273         * is clicked on.
2274         */
2275        public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =
2276                "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
2277
2278        /**
2279         * Starts an Activity that lets the user pick a contact to attach an image to.
2280         * After picking the contact it launches the image cropper in face detection mode.
2281         */
2282        public static final String ATTACH_IMAGE =
2283                "com.android.contacts.action.ATTACH_IMAGE";
2284
2285        /**
2286         * Takes as input a data URI with a mailto: or tel: scheme. If a single
2287         * contact exists with the given data it will be shown. If no contact
2288         * exists, a dialog will ask the user if they want to create a new
2289         * contact with the provided details filled in. If multiple contacts
2290         * share the data the user will be prompted to pick which contact they
2291         * want to view.
2292         * <p>
2293         * For <code>mailto:</code> URIs, the scheme specific portion must be a
2294         * raw email address, such as one built using
2295         * {@link Uri#fromParts(String, String, String)}.
2296         * <p>
2297         * For <code>tel:</code> URIs, the scheme specific portion is compared
2298         * to existing numbers using the standard caller ID lookup algorithm.
2299         * The number must be properly encoded, for example using
2300         * {@link Uri#fromParts(String, String, String)}.
2301         * <p>
2302         * Any extras from the {@link Insert} class will be passed along to the
2303         * create activity if there are no contacts to show.
2304         * <p>
2305         * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip
2306         * prompting the user when the contact doesn't exist.
2307         */
2308        public static final String SHOW_OR_CREATE_CONTACT =
2309                "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
2310
2311        /**
2312         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
2313         * contact if no matching contact found. Otherwise, default behavior is
2314         * to prompt user with dialog before creating.
2315         * <p>
2316         * Type: BOOLEAN
2317         */
2318        public static final String EXTRA_FORCE_CREATE =
2319                "com.android.contacts.action.FORCE_CREATE";
2320
2321        /**
2322         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact
2323         * description to be shown when prompting user about creating a new
2324         * contact.
2325         * <p>
2326         * Type: STRING
2327         */
2328        public static final String EXTRA_CREATE_DESCRIPTION =
2329            "com.android.contacts.action.CREATE_DESCRIPTION";
2330
2331        /**
2332         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
2333         * dialog location using screen coordinates. When not specified, the
2334         * dialog will be centered.
2335         *
2336         * @hide
2337         */
2338        @Deprecated
2339        public static final String EXTRA_TARGET_RECT = "target_rect";
2340
2341        /**
2342         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
2343         * desired dialog style, usually a variation on size. One of
2344         * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}.
2345         *
2346         * @hide
2347         */
2348        @Deprecated
2349        public static final String EXTRA_MODE = "mode";
2350
2351        /**
2352         * Value for {@link #EXTRA_MODE} to show a small-sized dialog.
2353         *
2354         * @hide
2355         */
2356        @Deprecated
2357        public static final int MODE_SMALL = 1;
2358
2359        /**
2360         * Value for {@link #EXTRA_MODE} to show a medium-sized dialog.
2361         *
2362         * @hide
2363         */
2364        @Deprecated
2365        public static final int MODE_MEDIUM = 2;
2366
2367        /**
2368         * Value for {@link #EXTRA_MODE} to show a large-sized dialog.
2369         *
2370         * @hide
2371         */
2372        @Deprecated
2373        public static final int MODE_LARGE = 3;
2374
2375        /**
2376         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate
2377         * a list of specific MIME-types to exclude and not display. Stored as a
2378         * {@link String} array.
2379         *
2380         * @hide
2381         */
2382        @Deprecated
2383        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
2384
2385        /**
2386         * Intents related to the Contacts app UI.
2387         *
2388         * @hide
2389         */
2390        public static final class UI {
2391            /**
2392             * The action for the default contacts list tab.
2393             */
2394            public static final String LIST_DEFAULT =
2395                    "com.android.contacts.action.LIST_DEFAULT";
2396
2397            /**
2398             * The action for the contacts list tab.
2399             */
2400            public static final String LIST_GROUP_ACTION =
2401                    "com.android.contacts.action.LIST_GROUP";
2402
2403            /**
2404             * When in LIST_GROUP_ACTION mode, this is the group to display.
2405             */
2406            public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
2407
2408            /**
2409             * The action for the all contacts list tab.
2410             */
2411            public static final String LIST_ALL_CONTACTS_ACTION =
2412                    "com.android.contacts.action.LIST_ALL_CONTACTS";
2413
2414            /**
2415             * The action for the contacts with phone numbers list tab.
2416             */
2417            public static final String LIST_CONTACTS_WITH_PHONES_ACTION =
2418                    "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
2419
2420            /**
2421             * The action for the starred contacts list tab.
2422             */
2423            public static final String LIST_STARRED_ACTION =
2424                    "com.android.contacts.action.LIST_STARRED";
2425
2426            /**
2427             * The action for the frequent contacts list tab.
2428             */
2429            public static final String LIST_FREQUENT_ACTION =
2430                    "com.android.contacts.action.LIST_FREQUENT";
2431
2432            /**
2433             * The action for the "strequent" contacts list tab. It first lists the starred
2434             * contacts in alphabetical order and then the frequent contacts in descending
2435             * order of the number of times they have been contacted.
2436             */
2437            public static final String LIST_STREQUENT_ACTION =
2438                    "com.android.contacts.action.LIST_STREQUENT";
2439
2440            /**
2441             * A key for to be used as an intent extra to set the activity
2442             * title to a custom String value.
2443             */
2444            public static final String TITLE_EXTRA_KEY =
2445                    "com.android.contacts.extra.TITLE_EXTRA";
2446
2447            /**
2448             * Activity Action: Display a filtered list of contacts
2449             * <p>
2450             * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for
2451             * filtering
2452             * <p>
2453             * Output: Nothing.
2454             */
2455            public static final String FILTER_CONTACTS_ACTION =
2456                    "com.android.contacts.action.FILTER_CONTACTS";
2457
2458            /**
2459             * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}
2460             * intents to supply the text on which to filter.
2461             */
2462            public static final String FILTER_TEXT_EXTRA_KEY =
2463                    "com.android.contacts.extra.FILTER_TEXT";
2464        }
2465
2466        /**
2467         * Convenience class that contains string constants used
2468         * to create contact {@link android.content.Intent Intents}.
2469         */
2470        public static final class Insert {
2471            /** The action code to use when adding a contact */
2472            public static final String ACTION = Intent.ACTION_INSERT;
2473
2474            /**
2475             * If present, forces a bypass of quick insert mode.
2476             */
2477            public static final String FULL_MODE = "full_mode";
2478
2479            /**
2480             * The extra field for the contact name.
2481             * <P>Type: String</P>
2482             */
2483            public static final String NAME = "name";
2484
2485            // TODO add structured name values here.
2486
2487            /**
2488             * The extra field for the contact phonetic name.
2489             * <P>Type: String</P>
2490             */
2491            public static final String PHONETIC_NAME = "phonetic_name";
2492
2493            /**
2494             * The extra field for the contact company.
2495             * <P>Type: String</P>
2496             */
2497            public static final String COMPANY = "company";
2498
2499            /**
2500             * The extra field for the contact job title.
2501             * <P>Type: String</P>
2502             */
2503            public static final String JOB_TITLE = "job_title";
2504
2505            /**
2506             * The extra field for the contact notes.
2507             * <P>Type: String</P>
2508             */
2509            public static final String NOTES = "notes";
2510
2511            /**
2512             * The extra field for the contact phone number.
2513             * <P>Type: String</P>
2514             */
2515            public static final String PHONE = "phone";
2516
2517            /**
2518             * The extra field for the contact phone number type.
2519             * <P>Type: Either an integer value from
2520             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2521             *  or a string specifying a custom label.</P>
2522             */
2523            public static final String PHONE_TYPE = "phone_type";
2524
2525            /**
2526             * The extra field for the phone isprimary flag.
2527             * <P>Type: boolean</P>
2528             */
2529            public static final String PHONE_ISPRIMARY = "phone_isprimary";
2530
2531            /**
2532             * The extra field for an optional second contact phone number.
2533             * <P>Type: String</P>
2534             */
2535            public static final String SECONDARY_PHONE = "secondary_phone";
2536
2537            /**
2538             * The extra field for an optional second contact phone number type.
2539             * <P>Type: Either an integer value from
2540             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2541             *  or a string specifying a custom label.</P>
2542             */
2543            public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
2544
2545            /**
2546             * The extra field for an optional third contact phone number.
2547             * <P>Type: String</P>
2548             */
2549            public static final String TERTIARY_PHONE = "tertiary_phone";
2550
2551            /**
2552             * The extra field for an optional third contact phone number type.
2553             * <P>Type: Either an integer value from
2554             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2555             *  or a string specifying a custom label.</P>
2556             */
2557            public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
2558
2559            /**
2560             * The extra field for the contact email address.
2561             * <P>Type: String</P>
2562             */
2563            public static final String EMAIL = "email";
2564
2565            /**
2566             * The extra field for the contact email type.
2567             * <P>Type: Either an integer value from
2568             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2569             *  or a string specifying a custom label.</P>
2570             */
2571            public static final String EMAIL_TYPE = "email_type";
2572
2573            /**
2574             * The extra field for the email isprimary flag.
2575             * <P>Type: boolean</P>
2576             */
2577            public static final String EMAIL_ISPRIMARY = "email_isprimary";
2578
2579            /**
2580             * The extra field for an optional second contact email address.
2581             * <P>Type: String</P>
2582             */
2583            public static final String SECONDARY_EMAIL = "secondary_email";
2584
2585            /**
2586             * The extra field for an optional second contact email type.
2587             * <P>Type: Either an integer value from
2588             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2589             *  or a string specifying a custom label.</P>
2590             */
2591            public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
2592
2593            /**
2594             * The extra field for an optional third contact email address.
2595             * <P>Type: String</P>
2596             */
2597            public static final String TERTIARY_EMAIL = "tertiary_email";
2598
2599            /**
2600             * The extra field for an optional third contact email type.
2601             * <P>Type: Either an integer value from
2602             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2603             *  or a string specifying a custom label.</P>
2604             */
2605            public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
2606
2607            /**
2608             * The extra field for the contact postal address.
2609             * <P>Type: String</P>
2610             */
2611            public static final String POSTAL = "postal";
2612
2613            /**
2614             * The extra field for the contact postal address type.
2615             * <P>Type: Either an integer value from
2616             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2617             *  or a string specifying a custom label.</P>
2618             */
2619            public static final String POSTAL_TYPE = "postal_type";
2620
2621            /**
2622             * The extra field for the postal isprimary flag.
2623             * <P>Type: boolean</P>
2624             */
2625            public static final String POSTAL_ISPRIMARY = "postal_isprimary";
2626
2627            /**
2628             * The extra field for an IM handle.
2629             * <P>Type: String</P>
2630             */
2631            public static final String IM_HANDLE = "im_handle";
2632
2633            /**
2634             * The extra field for the IM protocol
2635             */
2636            public static final String IM_PROTOCOL = "im_protocol";
2637
2638            /**
2639             * The extra field for the IM isprimary flag.
2640             * <P>Type: boolean</P>
2641             */
2642            public static final String IM_ISPRIMARY = "im_isprimary";
2643        }
2644    }
2645
2646}
2647