ContactsContract.java revision 49da15f34daa314c392b36ac346ac8a2d9f177d4
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 birthdays.
1696         */
1697        public static final class Birthday implements DataColumnsWithJoins {
1698            /**
1699             * This utility class cannot be instantiated
1700             */
1701            private Birthday() {}
1702
1703            /** MIME type used when storing this in data table. */
1704            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/birthday";
1705
1706            /**
1707             * The birthday. This must be of the form YYYY-MM-DD or YYYY-MM-DDThh:mm:ss
1708             * These are xs:date and xs:dateTime
1709             * <P>Type: TEXT</P>
1710             */
1711            public static final String BIRTHDAY = DATA1;
1712        }
1713
1714        /**
1715         * Common data definition for relations.
1716         */
1717        public static final class Relation implements DataColumnsWithJoins, CommonColumns {
1718            /**
1719             * This utility class cannot be instantiated
1720             */
1721            private Relation() {}
1722
1723            /** MIME type used when storing this in data table. */
1724            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
1725
1726            public static final int TYPE_ASSISTANT = 1;
1727            public static final int TYPE_BROTHER = 2;
1728            public static final int TYPE_CHILD = 3;
1729            public static final int TYPE_DOMESTIC_PARTNER = 4;
1730            public static final int TYPE_FATHER = 5;
1731            public static final int TYPE_FRIEND = 6;
1732            public static final int TYPE_MANAGER = 7;
1733            public static final int TYPE_MOTHER = 8;
1734            public static final int TYPE_PARENT = 9;
1735            public static final int TYPE_PARTNER = 10;
1736            public static final int TYPE_REFERRED_BY = 11;
1737            public static final int TYPE_RELATIVE = 12;
1738            public static final int TYPE_SISTER = 13;
1739            public static final int TYPE_SPOUSE = 14;
1740
1741            /**
1742             * The name of the relative as the user entered it.
1743             * <P>Type: TEXT</P>
1744             */
1745            public static final String NAME = DATA;
1746        }
1747
1748        /**
1749         * Common data definition for events.
1750         */
1751        public static final class Event implements DataColumnsWithJoins, CommonColumns {
1752            /**
1753             * This utility class cannot be instantiated
1754             */
1755            private Event() {}
1756
1757            /** MIME type used when storing this in data table. */
1758            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/event";
1759
1760            public static final int TYPE_ANNIVERSARY = 1;
1761            public static final int TYPE_OTHER = 2;
1762
1763            /**
1764             * The event start date as the user entered it.
1765             * <P>Type: TEXT</P>
1766             */
1767            public static final String START_DATE = DATA;
1768        }
1769
1770        /**
1771         * Photo of the contact.
1772         */
1773        public static final class Photo implements DataColumnsWithJoins {
1774            /**
1775             * This utility class cannot be instantiated
1776             */
1777            private Photo() {}
1778
1779            /** MIME type used when storing this in data table. */
1780            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
1781
1782            /**
1783             * Thumbnail photo of the raw contact. This is the raw bytes of an image
1784             * that could be inflated using {@link android.graphics.BitmapFactory}.
1785             * <p>
1786             * Type: BLOB
1787             */
1788            public static final String PHOTO = DATA15;
1789        }
1790
1791        /**
1792         * Notes about the contact.
1793         */
1794        public static final class Note implements DataColumnsWithJoins {
1795            /**
1796             * This utility class cannot be instantiated
1797             */
1798            private Note() {}
1799
1800            /** MIME type used when storing this in data table. */
1801            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
1802
1803            /**
1804             * The note text.
1805             * <P>Type: TEXT</P>
1806             */
1807            public static final String NOTE = DATA1;
1808        }
1809
1810        /**
1811         * Group Membership.
1812         */
1813        public static final class GroupMembership implements DataColumnsWithJoins {
1814            /**
1815             * This utility class cannot be instantiated
1816             */
1817            private GroupMembership() {}
1818
1819            /** MIME type used when storing this in data table. */
1820            public static final String CONTENT_ITEM_TYPE =
1821                    "vnd.android.cursor.item/group_membership";
1822
1823            /**
1824             * The row id of the group that this group membership refers to. Exactly one of
1825             * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row.
1826             * <P>Type: INTEGER</P>
1827             */
1828            public static final String GROUP_ROW_ID = DATA1;
1829
1830            /**
1831             * The sourceid of the group that this group membership refers to.  Exactly one of
1832             * this or {@link #GROUP_ROW_ID} must be set when inserting a row.
1833             * <P>Type: TEXT</P>
1834             */
1835            public static final String GROUP_SOURCE_ID = "group_sourceid";
1836        }
1837
1838        /**
1839         * Website related to the contact.
1840         */
1841        public static final class Website implements DataColumnsWithJoins, CommonColumns {
1842            /**
1843             * This utility class cannot be instantiated
1844             */
1845            private Website() {}
1846
1847            /** MIME type used when storing this in data table. */
1848            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
1849
1850            public static final int TYPE_HOMEPAGE = 1;
1851            public static final int TYPE_BLOG = 2;
1852            public static final int TYPE_PROFILE = 3;
1853            public static final int TYPE_HOME = 4;
1854            public static final int TYPE_WORK = 5;
1855            public static final int TYPE_FTP = 6;
1856            public static final int TYPE_OTHER = 7;
1857
1858            /**
1859             * The website URL string.
1860             * <P>Type: TEXT</P>
1861             */
1862            public static final String URL = DATA;
1863        }
1864    }
1865
1866    private interface GroupsColumns {
1867        /**
1868         * The display title of this group.
1869         * <p>
1870         * Type: TEXT
1871         */
1872        public static final String TITLE = "title";
1873
1874        /**
1875         * The package name to use when creating {@link Resources} objects for
1876         * this group. This value is only designed for use when building user
1877         * interfaces, and should not be used to infer the owner.
1878         *
1879         * @hide
1880         */
1881        public static final String RES_PACKAGE = "res_package";
1882
1883        /**
1884         * The display title of this group to load as a resource from
1885         * {@link #RES_PACKAGE}, which may be localized.
1886         * <P>Type: TEXT</P>
1887         *
1888         * @hide
1889         */
1890        public static final String TITLE_RES = "title_res";
1891
1892        /**
1893         * Notes about the group.
1894         * <p>
1895         * Type: TEXT
1896         */
1897        public static final String NOTES = "notes";
1898
1899        /**
1900         * The ID of this group if it is a System Group, i.e. a group that has a special meaning
1901         * to the sync adapter, null otherwise.
1902         * <P>Type: TEXT</P>
1903         */
1904        public static final String SYSTEM_ID = "system_id";
1905
1906        /**
1907         * The total number of {@link Contacts} that have
1908         * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only
1909         * present when querying {@link Groups#CONTENT_SUMMARY_URI}.
1910         * <p>
1911         * Type: INTEGER
1912         */
1913        public static final String SUMMARY_COUNT = "summ_count";
1914
1915        /**
1916         * The total number of {@link Contacts} that have both
1917         * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers.
1918         * Read-only value that is only present when querying
1919         * {@link Groups#CONTENT_SUMMARY_URI}.
1920         * <p>
1921         * Type: INTEGER
1922         */
1923        public static final String SUMMARY_WITH_PHONES = "summ_phones";
1924
1925        /**
1926         * Flag indicating if the contacts belonging to this group should be
1927         * visible in any user interface.
1928         * <p>
1929         * Type: INTEGER (boolean)
1930         */
1931        public static final String GROUP_VISIBLE = "group_visible";
1932
1933        /**
1934         * The "deleted" flag: "0" by default, "1" if the row has been marked
1935         * for deletion. When {@link android.content.ContentResolver#delete} is
1936         * called on a raw contact, it is marked for deletion and removed from its
1937         * aggregate contact. The sync adaptor deletes the raw contact on the server and
1938         * then calls ContactResolver.delete once more, this time setting the the
1939         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
1940         * the data removal.
1941         * <P>Type: INTEGER</P>
1942         */
1943        public static final String DELETED = "deleted";
1944
1945        /**
1946         * Whether this group should be synced if the SYNC_EVERYTHING settings
1947         * is false for this group's account.
1948         * <p>
1949         * Type: INTEGER (boolean)
1950         */
1951        public static final String SHOULD_SYNC = "should_sync";
1952    }
1953
1954    /**
1955     * Constants for the groups table.
1956     */
1957    public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns {
1958        /**
1959         * This utility class cannot be instantiated
1960         */
1961        private Groups() {
1962        }
1963
1964        /**
1965         * The content:// style URI for this table
1966         */
1967        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups");
1968
1969        /**
1970         * The content:// style URI for this table joined with details data from
1971         * {@link Data}.
1972         */
1973        public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
1974                "groups_summary");
1975
1976        /**
1977         * The MIME type of a directory of groups.
1978         */
1979        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group";
1980
1981        /**
1982         * The MIME type of a single group.
1983         */
1984        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
1985    }
1986
1987    /**
1988     * Constants for the contact aggregation exceptions table, which contains
1989     * aggregation rules overriding those used by automatic aggregation.  This type only
1990     * supports query and update. Neither insert nor delete are supported.
1991     */
1992    public static final class AggregationExceptions implements BaseColumns {
1993        /**
1994         * This utility class cannot be instantiated
1995         */
1996        private AggregationExceptions() {}
1997
1998        /**
1999         * The content:// style URI for this table
2000         */
2001        public static final Uri CONTENT_URI =
2002                Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions");
2003
2004        /**
2005         * The MIME type of {@link #CONTENT_URI} providing a directory of data.
2006         */
2007        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception";
2008
2009        /**
2010         * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception
2011         */
2012        public static final String CONTENT_ITEM_TYPE =
2013                "vnd.android.cursor.item/aggregation_exception";
2014
2015        /**
2016         * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or
2017         * {@link #TYPE_AUTOMATIC}.
2018         *
2019         * <P>Type: INTEGER</P>
2020         */
2021        public static final String TYPE = "type";
2022
2023        /**
2024         * Allows the provider to automatically decide whether the specified raw contacts should
2025         * be included in the same aggregate contact or not.
2026         */
2027        public static final int TYPE_AUTOMATIC = 0;
2028
2029        /**
2030         * Makes sure that the specified raw contacts are included in the same
2031         * aggregate contact.
2032         */
2033        public static final int TYPE_KEEP_TOGETHER = 1;
2034
2035        /**
2036         * Makes sure that the specified raw contacts are NOT included in the same
2037         * aggregate contact.
2038         */
2039        public static final int TYPE_KEEP_SEPARATE = 2;
2040
2041        /**
2042         * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to.
2043         */
2044        public static final String RAW_CONTACT_ID1 = "raw_contact_id1";
2045
2046        /**
2047         * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule
2048         * applies to.
2049         */
2050        public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
2051    }
2052
2053    private interface SettingsColumns {
2054        /**
2055         * The name of the account instance to which this row belongs.
2056         * <P>Type: TEXT</P>
2057         */
2058        public static final String ACCOUNT_NAME = "account_name";
2059
2060        /**
2061         * The type of account to which this row belongs, which when paired with
2062         * {@link #ACCOUNT_NAME} identifies a specific account.
2063         * <P>Type: TEXT</P>
2064         */
2065        public static final String ACCOUNT_TYPE = "account_type";
2066
2067        /**
2068         * Depending on the mode defined by the sync-adapter, this flag controls
2069         * the top-level sync behavior for this data source.
2070         * <p>
2071         * Type: INTEGER (boolean)
2072         */
2073        public static final String SHOULD_SYNC = "should_sync";
2074
2075        /**
2076         * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership}
2077         * entries should be visible in any user interface.
2078         * <p>
2079         * Type: INTEGER (boolean)
2080         */
2081        public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
2082
2083        /**
2084         * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
2085         * {@link Groups#SHOULD_SYNC} under this account have been marked as
2086         * unsynced.
2087         */
2088        public static final String ANY_UNSYNCED = "any_unsynced";
2089
2090        /**
2091         * Read-only count of {@link Contacts} from a specific source that have
2092         * no {@link CommonDataKinds.GroupMembership} entries.
2093         * <p>
2094         * Type: INTEGER
2095         */
2096        public static final String UNGROUPED_COUNT = "summ_count";
2097
2098        /**
2099         * Read-only count of {@link Contacts} from a specific source that have
2100         * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers.
2101         * <p>
2102         * Type: INTEGER
2103         */
2104        public static final String UNGROUPED_WITH_PHONES = "summ_phones";
2105    }
2106
2107    /**
2108     * Contacts-specific settings for various {@link Account}.
2109     */
2110    public static final class Settings implements SettingsColumns {
2111        /**
2112         * This utility class cannot be instantiated
2113         */
2114        private Settings() {
2115        }
2116
2117        /**
2118         * The content:// style URI for this table
2119         */
2120        public static final Uri CONTENT_URI =
2121                Uri.withAppendedPath(AUTHORITY_URI, "settings");
2122
2123        /**
2124         * The MIME-type of {@link #CONTENT_URI} providing a directory of
2125         * settings.
2126         */
2127        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
2128
2129        /**
2130         * The MIME-type of {@link #CONTENT_URI} providing a single setting.
2131         */
2132        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
2133    }
2134
2135    /**
2136     * Helper methods to display FastTrack dialogs that allow users to pivot on
2137     * a specific {@link Contacts} entry.
2138     *
2139     * @hide
2140     */
2141    public static final class FastTrack {
2142        /**
2143         * Action used to trigger person pivot dialog.
2144         * @hide
2145         */
2146        public static final String ACTION_FAST_TRACK =
2147                "com.android.contacts.action.FAST_TRACK";
2148
2149        /**
2150         * Extra used to specify pivot dialog location in screen coordinates.
2151         * @hide
2152         */
2153        public static final String EXTRA_TARGET_RECT = "target_rect";
2154
2155        /**
2156         * Extra used to specify size of pivot dialog.
2157         * @hide
2158         */
2159        public static final String EXTRA_MODE = "mode";
2160
2161        /**
2162         * Extra used to indicate a list of specific MIME-types to exclude and
2163         * not display. Stored as a {@link String} array.
2164         * @hide
2165         */
2166        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
2167
2168        /**
2169         * Small FastTrack mode, usually presented with minimal actions.
2170         */
2171        public static final int MODE_SMALL = 1;
2172
2173        /**
2174         * Medium FastTrack mode, includes actions and light summary describing
2175         * the {@link Contacts} entry being shown. This may include social
2176         * status and presence details.
2177         */
2178        public static final int MODE_MEDIUM = 2;
2179
2180        /**
2181         * Large FastTrack mode, includes actions and larger, card-like summary
2182         * of the {@link Contacts} entry being shown. This may include detailed
2183         * information, such as a photo.
2184         */
2185        public static final int MODE_LARGE = 3;
2186
2187        /**
2188         * Trigger a dialog that lists the various methods of interacting with
2189         * the requested {@link Contacts} entry. This may be based on available
2190         * {@link Data} rows under that contact, and may also include social
2191         * status and presence details.
2192         *
2193         * @param context The parent {@link Context} that may be used as the
2194         *            parent for this dialog.
2195         * @param target Specific {@link View} from your layout that this dialog
2196         *            should be centered around. In particular, if the dialog
2197         *            has a "callout" arrow, it will be pointed and centered
2198         *            around this {@link View}.
2199         * @param lookupUri A {@link Contacts#CONTENT_LOOKUP_URI} style
2200         *            {@link Uri} that describes a specific contact to feature
2201         *            in this dialog.
2202         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
2203         *            {@link #MODE_LARGE}, indicating the desired dialog size,
2204         *            when supported.
2205         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
2206         *            to exclude when showing this dialog. For example, when
2207         *            already viewing the contact details card, this can be used
2208         *            to omit the details entry from the dialog.
2209         */
2210        public static void showFastTrack(Context context, View target, Uri lookupUri, int mode,
2211                String[] excludeMimes) {
2212            // Find location and bounds of target view
2213            final int[] location = new int[2];
2214            target.getLocationOnScreen(location);
2215
2216            final Rect rect = new Rect();
2217            rect.left = location[0];
2218            rect.top = location[1];
2219            rect.right = rect.left + target.getWidth();
2220            rect.bottom = rect.top + target.getHeight();
2221
2222            // Trigger with obtained rectangle
2223            showFastTrack(context, rect, lookupUri, mode, excludeMimes);
2224        }
2225
2226        /**
2227         * Trigger a dialog that lists the various methods of interacting with
2228         * the requested {@link Contacts} entry. This may be based on available
2229         * {@link Data} rows under that contact, and may also include social
2230         * status and presence details.
2231         *
2232         * @param context The parent {@link Context} that may be used as the
2233         *            parent for this dialog.
2234         * @param target Specific {@link Rect} that this dialog should be
2235         *            centered around, in screen coordinates. In particular, if
2236         *            the dialog has a "callout" arrow, it will be pointed and
2237         *            centered around this {@link Rect}.
2238         * @param lookupUri A {@link Contacts#CONTENT_LOOKUP_URI} style
2239         *            {@link Uri} that describes a specific contact to feature
2240         *            in this dialog.
2241         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
2242         *            {@link #MODE_LARGE}, indicating the desired dialog size,
2243         *            when supported.
2244         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
2245         *            to exclude when showing this dialog. For example, when
2246         *            already viewing the contact details card, this can be used
2247         *            to omit the details entry from the dialog.
2248         */
2249        public static void showFastTrack(Context context, Rect target, Uri lookupUri, int mode,
2250                String[] excludeMimes) {
2251            // Launch pivot dialog through intent for now
2252            final Intent intent = new Intent(ACTION_FAST_TRACK);
2253            intent.setData(lookupUri);
2254            intent.putExtra(EXTRA_TARGET_RECT, target);
2255            intent.putExtra(EXTRA_MODE, mode);
2256            intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
2257            context.startActivity(intent);
2258        }
2259    }
2260
2261    /**
2262     * Contains helper classes used to create or manage {@link android.content.Intent Intents}
2263     * that involve contacts.
2264     */
2265    public static final class Intents {
2266        /**
2267         * This is the intent that is fired when a search suggestion is clicked on.
2268         */
2269        public static final String SEARCH_SUGGESTION_CLICKED =
2270                "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
2271
2272        /**
2273         * This is the intent that is fired when a search suggestion for dialing a number
2274         * is clicked on.
2275         */
2276        public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =
2277                "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
2278
2279        /**
2280         * This is the intent that is fired when a search suggestion for creating a contact
2281         * is clicked on.
2282         */
2283        public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =
2284                "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
2285
2286        /**
2287         * Starts an Activity that lets the user pick a contact to attach an image to.
2288         * After picking the contact it launches the image cropper in face detection mode.
2289         */
2290        public static final String ATTACH_IMAGE =
2291                "com.android.contacts.action.ATTACH_IMAGE";
2292
2293        /**
2294         * Takes as input a data URI with a mailto: or tel: scheme. If a single
2295         * contact exists with the given data it will be shown. If no contact
2296         * exists, a dialog will ask the user if they want to create a new
2297         * contact with the provided details filled in. If multiple contacts
2298         * share the data the user will be prompted to pick which contact they
2299         * want to view.
2300         * <p>
2301         * For <code>mailto:</code> URIs, the scheme specific portion must be a
2302         * raw email address, such as one built using
2303         * {@link Uri#fromParts(String, String, String)}.
2304         * <p>
2305         * For <code>tel:</code> URIs, the scheme specific portion is compared
2306         * to existing numbers using the standard caller ID lookup algorithm.
2307         * The number must be properly encoded, for example using
2308         * {@link Uri#fromParts(String, String, String)}.
2309         * <p>
2310         * Any extras from the {@link Insert} class will be passed along to the
2311         * create activity if there are no contacts to show.
2312         * <p>
2313         * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip
2314         * prompting the user when the contact doesn't exist.
2315         */
2316        public static final String SHOW_OR_CREATE_CONTACT =
2317                "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
2318
2319        /**
2320         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
2321         * contact if no matching contact found. Otherwise, default behavior is
2322         * to prompt user with dialog before creating.
2323         * <p>
2324         * Type: BOOLEAN
2325         */
2326        public static final String EXTRA_FORCE_CREATE =
2327                "com.android.contacts.action.FORCE_CREATE";
2328
2329        /**
2330         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact
2331         * description to be shown when prompting user about creating a new
2332         * contact.
2333         * <p>
2334         * Type: STRING
2335         */
2336        public static final String EXTRA_CREATE_DESCRIPTION =
2337            "com.android.contacts.action.CREATE_DESCRIPTION";
2338
2339        /**
2340         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
2341         * dialog location using screen coordinates. When not specified, the
2342         * dialog will be centered.
2343         *
2344         * @hide
2345         */
2346        @Deprecated
2347        public static final String EXTRA_TARGET_RECT = "target_rect";
2348
2349        /**
2350         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
2351         * desired dialog style, usually a variation on size. One of
2352         * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}.
2353         *
2354         * @hide
2355         */
2356        @Deprecated
2357        public static final String EXTRA_MODE = "mode";
2358
2359        /**
2360         * Value for {@link #EXTRA_MODE} to show a small-sized dialog.
2361         *
2362         * @hide
2363         */
2364        @Deprecated
2365        public static final int MODE_SMALL = 1;
2366
2367        /**
2368         * Value for {@link #EXTRA_MODE} to show a medium-sized dialog.
2369         *
2370         * @hide
2371         */
2372        @Deprecated
2373        public static final int MODE_MEDIUM = 2;
2374
2375        /**
2376         * Value for {@link #EXTRA_MODE} to show a large-sized dialog.
2377         *
2378         * @hide
2379         */
2380        @Deprecated
2381        public static final int MODE_LARGE = 3;
2382
2383        /**
2384         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate
2385         * a list of specific MIME-types to exclude and not display. Stored as a
2386         * {@link String} array.
2387         *
2388         * @hide
2389         */
2390        @Deprecated
2391        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
2392
2393        /**
2394         * Intents related to the Contacts app UI.
2395         *
2396         * @hide
2397         */
2398        public static final class UI {
2399            /**
2400             * The action for the default contacts list tab.
2401             */
2402            public static final String LIST_DEFAULT =
2403                    "com.android.contacts.action.LIST_DEFAULT";
2404
2405            /**
2406             * The action for the contacts list tab.
2407             */
2408            public static final String LIST_GROUP_ACTION =
2409                    "com.android.contacts.action.LIST_GROUP";
2410
2411            /**
2412             * When in LIST_GROUP_ACTION mode, this is the group to display.
2413             */
2414            public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
2415
2416            /**
2417             * The action for the all contacts list tab.
2418             */
2419            public static final String LIST_ALL_CONTACTS_ACTION =
2420                    "com.android.contacts.action.LIST_ALL_CONTACTS";
2421
2422            /**
2423             * The action for the contacts with phone numbers list tab.
2424             */
2425            public static final String LIST_CONTACTS_WITH_PHONES_ACTION =
2426                    "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
2427
2428            /**
2429             * The action for the starred contacts list tab.
2430             */
2431            public static final String LIST_STARRED_ACTION =
2432                    "com.android.contacts.action.LIST_STARRED";
2433
2434            /**
2435             * The action for the frequent contacts list tab.
2436             */
2437            public static final String LIST_FREQUENT_ACTION =
2438                    "com.android.contacts.action.LIST_FREQUENT";
2439
2440            /**
2441             * The action for the "strequent" contacts list tab. It first lists the starred
2442             * contacts in alphabetical order and then the frequent contacts in descending
2443             * order of the number of times they have been contacted.
2444             */
2445            public static final String LIST_STREQUENT_ACTION =
2446                    "com.android.contacts.action.LIST_STREQUENT";
2447
2448            /**
2449             * A key for to be used as an intent extra to set the activity
2450             * title to a custom String value.
2451             */
2452            public static final String TITLE_EXTRA_KEY =
2453                    "com.android.contacts.extra.TITLE_EXTRA";
2454
2455            /**
2456             * Activity Action: Display a filtered list of contacts
2457             * <p>
2458             * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for
2459             * filtering
2460             * <p>
2461             * Output: Nothing.
2462             */
2463            public static final String FILTER_CONTACTS_ACTION =
2464                    "com.android.contacts.action.FILTER_CONTACTS";
2465
2466            /**
2467             * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}
2468             * intents to supply the text on which to filter.
2469             */
2470            public static final String FILTER_TEXT_EXTRA_KEY =
2471                    "com.android.contacts.extra.FILTER_TEXT";
2472        }
2473
2474        /**
2475         * Convenience class that contains string constants used
2476         * to create contact {@link android.content.Intent Intents}.
2477         */
2478        public static final class Insert {
2479            /** The action code to use when adding a contact */
2480            public static final String ACTION = Intent.ACTION_INSERT;
2481
2482            /**
2483             * If present, forces a bypass of quick insert mode.
2484             */
2485            public static final String FULL_MODE = "full_mode";
2486
2487            /**
2488             * The extra field for the contact name.
2489             * <P>Type: String</P>
2490             */
2491            public static final String NAME = "name";
2492
2493            // TODO add structured name values here.
2494
2495            /**
2496             * The extra field for the contact phonetic name.
2497             * <P>Type: String</P>
2498             */
2499            public static final String PHONETIC_NAME = "phonetic_name";
2500
2501            /**
2502             * The extra field for the contact company.
2503             * <P>Type: String</P>
2504             */
2505            public static final String COMPANY = "company";
2506
2507            /**
2508             * The extra field for the contact job title.
2509             * <P>Type: String</P>
2510             */
2511            public static final String JOB_TITLE = "job_title";
2512
2513            /**
2514             * The extra field for the contact notes.
2515             * <P>Type: String</P>
2516             */
2517            public static final String NOTES = "notes";
2518
2519            /**
2520             * The extra field for the contact phone number.
2521             * <P>Type: String</P>
2522             */
2523            public static final String PHONE = "phone";
2524
2525            /**
2526             * The extra field for the contact phone number type.
2527             * <P>Type: Either an integer value from
2528             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2529             *  or a string specifying a custom label.</P>
2530             */
2531            public static final String PHONE_TYPE = "phone_type";
2532
2533            /**
2534             * The extra field for the phone isprimary flag.
2535             * <P>Type: boolean</P>
2536             */
2537            public static final String PHONE_ISPRIMARY = "phone_isprimary";
2538
2539            /**
2540             * The extra field for an optional second contact phone number.
2541             * <P>Type: String</P>
2542             */
2543            public static final String SECONDARY_PHONE = "secondary_phone";
2544
2545            /**
2546             * The extra field for an optional second contact phone number type.
2547             * <P>Type: Either an integer value from
2548             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2549             *  or a string specifying a custom label.</P>
2550             */
2551            public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
2552
2553            /**
2554             * The extra field for an optional third contact phone number.
2555             * <P>Type: String</P>
2556             */
2557            public static final String TERTIARY_PHONE = "tertiary_phone";
2558
2559            /**
2560             * The extra field for an optional third contact phone number type.
2561             * <P>Type: Either an integer value from
2562             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
2563             *  or a string specifying a custom label.</P>
2564             */
2565            public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
2566
2567            /**
2568             * The extra field for the contact email address.
2569             * <P>Type: String</P>
2570             */
2571            public static final String EMAIL = "email";
2572
2573            /**
2574             * The extra field for the contact email type.
2575             * <P>Type: Either an integer value from
2576             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2577             *  or a string specifying a custom label.</P>
2578             */
2579            public static final String EMAIL_TYPE = "email_type";
2580
2581            /**
2582             * The extra field for the email isprimary flag.
2583             * <P>Type: boolean</P>
2584             */
2585            public static final String EMAIL_ISPRIMARY = "email_isprimary";
2586
2587            /**
2588             * The extra field for an optional second contact email address.
2589             * <P>Type: String</P>
2590             */
2591            public static final String SECONDARY_EMAIL = "secondary_email";
2592
2593            /**
2594             * The extra field for an optional second contact email type.
2595             * <P>Type: Either an integer value from
2596             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2597             *  or a string specifying a custom label.</P>
2598             */
2599            public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
2600
2601            /**
2602             * The extra field for an optional third contact email address.
2603             * <P>Type: String</P>
2604             */
2605            public static final String TERTIARY_EMAIL = "tertiary_email";
2606
2607            /**
2608             * The extra field for an optional third contact email type.
2609             * <P>Type: Either an integer value from
2610             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2611             *  or a string specifying a custom label.</P>
2612             */
2613            public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
2614
2615            /**
2616             * The extra field for the contact postal address.
2617             * <P>Type: String</P>
2618             */
2619            public static final String POSTAL = "postal";
2620
2621            /**
2622             * The extra field for the contact postal address type.
2623             * <P>Type: Either an integer value from
2624             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
2625             *  or a string specifying a custom label.</P>
2626             */
2627            public static final String POSTAL_TYPE = "postal_type";
2628
2629            /**
2630             * The extra field for the postal isprimary flag.
2631             * <P>Type: boolean</P>
2632             */
2633            public static final String POSTAL_ISPRIMARY = "postal_isprimary";
2634
2635            /**
2636             * The extra field for an IM handle.
2637             * <P>Type: String</P>
2638             */
2639            public static final String IM_HANDLE = "im_handle";
2640
2641            /**
2642             * The extra field for the IM protocol
2643             */
2644            public static final String IM_PROTOCOL = "im_protocol";
2645
2646            /**
2647             * The extra field for the IM isprimary flag.
2648             * <P>Type: boolean</P>
2649             */
2650            public static final String IM_ISPRIMARY = "im_isprimary";
2651        }
2652    }
2653
2654}
2655