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