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