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