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