ContactsContract.java revision cb2bb4f70f36e925921b3ca79fc221bcca9a7225
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.CursorEntityIterator;
27import android.content.Entity;
28import android.content.EntityIterator;
29import android.content.Intent;
30import android.content.res.Resources;
31import android.database.Cursor;
32import android.database.DatabaseUtils;
33import android.graphics.Rect;
34import android.net.Uri;
35import android.os.RemoteException;
36import android.text.TextUtils;
37import android.util.DisplayMetrics;
38import android.util.Pair;
39import android.view.View;
40
41import java.io.ByteArrayInputStream;
42import java.io.InputStream;
43import java.util.ArrayList;
44
45/**
46 * <p>
47 * The contract between the contacts provider and applications. Contains
48 * definitions for the supported URIs and columns. These APIs supersede
49 * {@link Contacts}.
50 * </p>
51 * <h3>Overview</h3>
52 * <p>
53 * ContactsContract defines an extensible database of contact-related
54 * information. Contact information is stored in a three-tier data model:
55 * </p>
56 * <ul>
57 * <li>
58 * A row in the {@link Data} table can store any kind of personal data, such
59 * as a phone number or email addresses.  The set of data kinds that can be
60 * stored in this table is open-ended. There is a predefined set of common
61 * kinds, but any application can add its own data kinds.
62 * </li>
63 * <li>
64 * A row in the {@link RawContacts} table represents a set of data describing a
65 * person and associated with a single account (for example, one of the user's
66 * Gmail accounts).
67 * </li>
68 * <li>
69 * A row in the {@link Contacts} table represents an aggregate of one or more
70 * RawContacts presumably describing the same person.  When data in or associated with
71 * the RawContacts table is changed, the affected aggregate contacts are updated as
72 * necessary.
73 * </li>
74 * </ul>
75 * <p>
76 * Other tables include:
77 * </p>
78 * <ul>
79 * <li>
80 * {@link Groups}, which contains information about raw contact groups
81 * such as Gmail contact groups.  The
82 * current API does not support the notion of groups spanning multiple accounts.
83 * </li>
84 * <li>
85 * {@link StatusUpdates}, which contains social status updates including IM
86 * availability.
87 * </li>
88 * <li>
89 * {@link AggregationExceptions}, which is used for manual aggregation and
90 * disaggregation of raw contacts
91 * </li>
92 * <li>
93 * {@link Settings}, which contains visibility and sync settings for accounts
94 * and groups.
95 * </li>
96 * <li>
97 * {@link SyncState}, which contains free-form data maintained on behalf of sync
98 * adapters
99 * </li>
100 * <li>
101 * {@link PhoneLookup}, which is used for quick caller-ID lookup</li>
102 * </ul>
103 */
104@SuppressWarnings("unused")
105public final class ContactsContract {
106    /** The authority for the contacts provider */
107    public static final String AUTHORITY = "com.android.contacts";
108    /** A content:// style uri to the authority for the contacts provider */
109    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
110
111    /**
112     * An optional URI parameter for insert, update, or delete queries
113     * that allows the caller
114     * to specify that it is a sync adapter. The default value is false. If true
115     * {@link RawContacts#DIRTY} is not automatically set and the
116     * "syncToNetwork" parameter is set to false when calling
117     * {@link
118     * ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
119     * This prevents an unnecessary extra synchronization, see the discussion of
120     * the delete operation in {@link RawContacts}.
121     */
122    public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
123
124    /**
125     * An optional URI parameter for selection queries that instructs the
126     * provider to allow the user's personal profile contact entry (if any)
127     * to appear in a list of contact results.  It is only useful when issuing
128     * a query that may retrieve more than one contact.  If present, the user's
129     * profile will always be the first entry returned.  The default value is
130     * false.
131     *
132     * Specifying this parameter will result in a security error if the calling
133     * application does not have android.permission.READ_PROFILE permission.
134     */
135    public static final String ALLOW_PROFILE = "allow_profile";
136
137    /**
138     * A query parameter key used to specify the package that is requesting a query.
139     * This is used for restricting data based on package name.
140     *
141     * @hide
142     */
143    public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package";
144
145    /**
146     * Query parameter that should be used by the client to access a specific
147     * {@link Directory}. The parameter value should be the _ID of the corresponding
148     * directory, e.g.
149     * {@code content://com.android.contacts/data/emails/filter/acme?directory=3}
150     */
151    public static final String DIRECTORY_PARAM_KEY = "directory";
152
153    /**
154     * A query parameter that limits the number of results returned. The
155     * parameter value should be an integer.
156     */
157    public static final String LIMIT_PARAM_KEY = "limit";
158
159    /**
160     * A query parameter specifing a primary account. This parameter should be used with
161     * {@link #PRIMARY_ACCOUNT_TYPE}. The contacts provider handling a query may rely on
162     * this information to optimize its query results.
163     *
164     * For example, in an email composition screen, its implementation can specify an account when
165     * obtaining possible recipients, letting the provider know which account is selected during
166     * the composition. The provider may use the "primary account" information to optimize
167     * the search result.
168     */
169    public static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
170
171    /**
172     * A query parameter specifing a primary account. This parameter should be used with
173     * {@link #PRIMARY_ACCOUNT_NAME}. See the doc in {@link #PRIMARY_ACCOUNT_NAME}.
174     */
175    public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
176
177
178    /**
179     * @hide
180     */
181    public static final class Preferences {
182
183        /**
184         * A key in the {@link android.provider.Settings android.provider.Settings} provider
185         * that stores the preferred sorting order for contacts (by given name vs. by family name).
186         *
187         * @hide
188         */
189        public static final String SORT_ORDER = "android.contacts.SORT_ORDER";
190
191        /**
192         * The value for the SORT_ORDER key corresponding to sorting by given name first.
193         *
194         * @hide
195         */
196        public static final int SORT_ORDER_PRIMARY = 1;
197
198        /**
199         * The value for the SORT_ORDER key corresponding to sorting by family name first.
200         *
201         * @hide
202         */
203        public static final int SORT_ORDER_ALTERNATIVE = 2;
204
205        /**
206         * A key in the {@link android.provider.Settings android.provider.Settings} provider
207         * that stores the preferred display order for contacts (given name first vs. family
208         * name first).
209         *
210         * @hide
211         */
212        public static final String DISPLAY_ORDER = "android.contacts.DISPLAY_ORDER";
213
214        /**
215         * The value for the DISPLAY_ORDER key corresponding to showing the given name first.
216         *
217         * @hide
218         */
219        public static final int DISPLAY_ORDER_PRIMARY = 1;
220
221        /**
222         * The value for the DISPLAY_ORDER key corresponding to showing the family name first.
223         *
224         * @hide
225         */
226        public static final int DISPLAY_ORDER_ALTERNATIVE = 2;
227    }
228
229    /**
230     * A Directory represents a contacts corpus, e.g. Local contacts,
231     * Google Apps Global Address List or Corporate Global Address List.
232     * <p>
233     * A Directory is implemented as a content provider with its unique authority and
234     * the same API as the main Contacts Provider.  However, there is no expectation that
235     * every directory provider will implement this Contract in its entirety.  If a
236     * directory provider does not have an implementation for a specific request, it
237     * should throw an UnsupportedOperationException.
238     * </p>
239     * <p>
240     * The most important use case for Directories is search.  A Directory provider is
241     * expected to support at least {@link ContactsContract.Contacts#CONTENT_FILTER_URI
242     * Contacts.CONTENT_FILTER_URI}.  If a Directory provider wants to participate
243     * in email and phone lookup functionalities, it should also implement
244     * {@link CommonDataKinds.Email#CONTENT_FILTER_URI CommonDataKinds.Email.CONTENT_FILTER_URI}
245     * and
246     * {@link CommonDataKinds.Phone#CONTENT_FILTER_URI CommonDataKinds.Phone.CONTENT_FILTER_URI}.
247     * </p>
248     * <p>
249     * A directory provider should return NULL for every projection field it does not
250     * recognize, rather than throwing an exception.  This way it will not be broken
251     * if ContactsContract is extended with new fields in the future.
252     * </p>
253     * <p>
254     * The client interacts with a directory via Contacts Provider by supplying an
255     * optional {@code directory=} query parameter.
256     * <p>
257     * <p>
258     * When the Contacts Provider receives the request, it transforms the URI and forwards
259     * the request to the corresponding directory content provider.
260     * The URI is transformed in the following fashion:
261     * <ul>
262     * <li>The URI authority is replaced with the corresponding {@link #DIRECTORY_AUTHORITY}.</li>
263     * <li>The {@code accountName=} and {@code accountType=} parameters are added or
264     * replaced using the corresponding {@link #ACCOUNT_TYPE} and {@link #ACCOUNT_NAME} values.</li>
265     * <li>If the URI is missing a ContactsContract.REQUESTING_PACKAGE_PARAM_KEY
266     * parameter, this parameter is added.</li>
267     * </ul>
268     * </p>
269     * <p>
270     * Clients should send directory requests to Contacts Provider and let it
271     * forward them to the respective providers rather than constructing
272     * directory provider URIs by themselves. This level of indirection allows
273     * Contacts Provider to implement additional system-level features and
274     * optimizations. Access to Contacts Provider is protected by the
275     * READ_CONTACTS permission, but access to the directory provider is not.
276     * Therefore directory providers must reject requests coming from clients
277     * other than the Contacts Provider itself. An easy way to prevent such
278     * unauthorized access is to check the name of the calling package:
279     * <pre>
280     * private boolean isCallerAllowed() {
281     *   PackageManager pm = getContext().getPackageManager();
282     *   for (String packageName: pm.getPackagesForUid(Binder.getCallingUid())) {
283     *     if (packageName.equals("com.android.providers.contacts")) {
284     *       return true;
285     *     }
286     *   }
287     *   return false;
288     * }
289     * </pre>
290     * </p>
291     * <p>
292     * The Directory table is read-only and is maintained by the Contacts Provider
293     * automatically.
294     * </p>
295     * <p>It always has at least these two rows:
296     * <ul>
297     * <li>
298     * The local directory. It has {@link Directory#_ID Directory._ID} =
299     * {@link Directory#DEFAULT Directory.DEFAULT}. This directory can be used to access locally
300     * stored contacts. The same can be achieved by omitting the {@code directory=}
301     * parameter altogether.
302     * </li>
303     * <li>
304     * The local invisible contacts. The corresponding directory ID is
305     * {@link Directory#LOCAL_INVISIBLE Directory.LOCAL_INVISIBLE}.
306     * </li>
307     * </ul>
308     * </p>
309     * <p>Custom Directories are discovered by the Contacts Provider following this procedure:
310     * <ul>
311     * <li>It finds all installed content providers with meta data identifying them
312     * as directory providers in AndroidManifest.xml:
313     * <code>
314     * &lt;meta-data android:name="android.content.ContactDirectory"
315     *               android:value="true" /&gt;
316     * </code>
317     * <p>
318     * This tag should be placed inside the corresponding content provider declaration.
319     * </p>
320     * </li>
321     * <li>
322     * Then Contacts Provider sends a {@link Directory#CONTENT_URI Directory.CONTENT_URI}
323     * query to each of the directory authorities.  A directory provider must implement
324     * this query and return a list of directories.  Each directory returned by
325     * the provider must have a unique combination for the {@link #ACCOUNT_NAME} and
326     * {@link #ACCOUNT_TYPE} columns (nulls are allowed).  Since directory IDs are assigned
327     * automatically, the _ID field will not be part of the query projection.
328     * </li>
329     * <li>Contacts Provider compiles directory lists received from all directory
330     * providers into one, assigns each individual directory a globally unique ID and
331     * stores all directory records in the Directory table.
332     * </li>
333     * </ul>
334     * </p>
335     * <p>Contacts Provider automatically interrogates newly installed or replaced packages.
336     * Thus simply installing a package containing a directory provider is sufficient
337     * to have that provider registered.  A package supplying a directory provider does
338     * not have to contain launchable activities.
339     * </p>
340     * <p>
341     * Every row in the Directory table is automatically associated with the corresponding package
342     * (apk).  If the package is later uninstalled, all corresponding directory rows
343     * are automatically removed from the Contacts Provider.
344     * </p>
345     * <p>
346     * When the list of directories handled by a directory provider changes
347     * (for instance when the user adds a new Directory account), the directory provider
348     * should call {@link #notifyDirectoryChange} to notify the Contacts Provider of the change.
349     * In response, the Contacts Provider will requery the directory provider to obtain the
350     * new list of directories.
351     * </p>
352     * <p>
353     * A directory row can be optionally associated with an existing account
354     * (see {@link android.accounts.AccountManager}). If the account is later removed,
355     * the corresponding directory rows are automatically removed from the Contacts Provider.
356     * </p>
357     */
358    public static final class Directory implements BaseColumns {
359
360        /**
361         * Not instantiable.
362         */
363        private Directory() {
364        }
365
366        /**
367         * The content:// style URI for this table.  Requests to this URI can be
368         * performed on the UI thread because they are always unblocking.
369         */
370        public static final Uri CONTENT_URI =
371                Uri.withAppendedPath(AUTHORITY_URI, "directories");
372
373        /**
374         * The MIME-type of {@link #CONTENT_URI} providing a directory of
375         * contact directories.
376         */
377        public static final String CONTENT_TYPE =
378                "vnd.android.cursor.dir/contact_directories";
379
380        /**
381         * The MIME type of a {@link #CONTENT_URI} item.
382         */
383        public static final String CONTENT_ITEM_TYPE =
384                "vnd.android.cursor.item/contact_directory";
385
386        /**
387         * _ID of the default directory, which represents locally stored contacts.
388         */
389        public static final long DEFAULT = 0;
390
391        /**
392         * _ID of the directory that represents locally stored invisible contacts.
393         */
394        public static final long LOCAL_INVISIBLE = 1;
395
396        /**
397         * The name of the package that owns this directory. Contacts Provider
398         * fill it in with the name of the package containing the directory provider.
399         * If the package is later uninstalled, the directories it owns are
400         * automatically removed from this table.
401         *
402         * <p>TYPE: TEXT</p>
403         */
404        public static final String PACKAGE_NAME = "packageName";
405
406        /**
407         * The type of directory captured as a resource ID in the context of the
408         * package {@link #PACKAGE_NAME}, e.g. "Corporate Directory"
409         *
410         * <p>TYPE: INTEGER</p>
411         */
412        public static final String TYPE_RESOURCE_ID = "typeResourceId";
413
414        /**
415         * An optional name that can be used in the UI to represent this directory,
416         * e.g. "Acme Corp"
417         * <p>TYPE: text</p>
418         */
419        public static final String DISPLAY_NAME = "displayName";
420
421        /**
422         * <p>
423         * The authority of the Directory Provider. Contacts Provider will
424         * use this authority to forward requests to the directory provider.
425         * A directory provider can leave this column empty - Contacts Provider will fill it in.
426         * </p>
427         * <p>
428         * Clients of this API should not send requests directly to this authority.
429         * All directory requests must be routed through Contacts Provider.
430         * </p>
431         *
432         * <p>TYPE: text</p>
433         */
434        public static final String DIRECTORY_AUTHORITY = "authority";
435
436        /**
437         * The account type which this directory is associated.
438         *
439         * <p>TYPE: text</p>
440         */
441        public static final String ACCOUNT_TYPE = "accountType";
442
443        /**
444         * The account with which this directory is associated. If the account is later
445         * removed, the directories it owns are automatically removed from this table.
446         *
447         * <p>TYPE: text</p>
448         */
449        public static final String ACCOUNT_NAME = "accountName";
450
451        /**
452         * One of {@link #EXPORT_SUPPORT_NONE}, {@link #EXPORT_SUPPORT_ANY_ACCOUNT},
453         * {@link #EXPORT_SUPPORT_SAME_ACCOUNT_ONLY}. This is the expectation the
454         * directory has for data exported from it.  Clients must obey this setting.
455         */
456        public static final String EXPORT_SUPPORT = "exportSupport";
457
458        /**
459         * An {@link #EXPORT_SUPPORT} setting that indicates that the directory
460         * does not allow any data to be copied out of it.
461         */
462        public static final int EXPORT_SUPPORT_NONE = 0;
463
464        /**
465         * An {@link #EXPORT_SUPPORT} setting that indicates that the directory
466         * allow its data copied only to the account specified by
467         * {@link #ACCOUNT_TYPE}/{@link #ACCOUNT_NAME}.
468         */
469        public static final int EXPORT_SUPPORT_SAME_ACCOUNT_ONLY = 1;
470
471        /**
472         * An {@link #EXPORT_SUPPORT} setting that indicates that the directory
473         * allow its data copied to any contacts account.
474         */
475        public static final int EXPORT_SUPPORT_ANY_ACCOUNT = 2;
476
477        /**
478         * One of {@link #SHORTCUT_SUPPORT_NONE}, {@link #SHORTCUT_SUPPORT_DATA_ITEMS_ONLY},
479         * {@link #SHORTCUT_SUPPORT_FULL}. This is the expectation the directory
480         * has for shortcuts created for its elements. Clients must obey this setting.
481         */
482        public static final String SHORTCUT_SUPPORT = "shortcutSupport";
483
484        /**
485         * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory
486         * does not allow any shortcuts created for its contacts.
487         */
488        public static final int SHORTCUT_SUPPORT_NONE = 0;
489
490        /**
491         * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory
492         * allow creation of shortcuts for data items like email, phone or postal address,
493         * but not the entire contact.
494         */
495        public static final int SHORTCUT_SUPPORT_DATA_ITEMS_ONLY = 1;
496
497        /**
498         * An {@link #SHORTCUT_SUPPORT} setting that indicates that the directory
499         * allow creation of shortcuts for contact as well as their constituent elements.
500         */
501        public static final int SHORTCUT_SUPPORT_FULL = 2;
502
503        /**
504         * One of {@link #PHOTO_SUPPORT_NONE}, {@link #PHOTO_SUPPORT_THUMBNAIL_ONLY},
505         * {@link #PHOTO_SUPPORT_FULL}. This is a feature flag indicating the extent
506         * to which the directory supports contact photos.
507         */
508        public static final String PHOTO_SUPPORT = "photoSupport";
509
510        /**
511         * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
512         * does not provide any photos.
513         */
514        public static final int PHOTO_SUPPORT_NONE = 0;
515
516        /**
517         * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
518         * can only produce small size thumbnails of contact photos.
519         */
520        public static final int PHOTO_SUPPORT_THUMBNAIL_ONLY = 1;
521
522        /**
523         * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
524         * has full-size contact photos, but cannot provide scaled thumbnails.
525         */
526        public static final int PHOTO_SUPPORT_FULL_SIZE_ONLY = 2;
527
528        /**
529         * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
530         * can produce thumbnails as well as full-size contact photos.
531         */
532        public static final int PHOTO_SUPPORT_FULL = 3;
533
534        /**
535         * Notifies the system of a change in the list of directories handled by
536         * a particular directory provider. The Contacts provider will turn around
537         * and send a query to the directory provider for the full list of directories,
538         * which will replace the previous list.
539         */
540        public static void notifyDirectoryChange(ContentResolver resolver) {
541            // This is done to trigger a query by Contacts Provider back to the directory provider.
542            // No data needs to be sent back, because the provider can infer the calling
543            // package from binder.
544            ContentValues contentValues = new ContentValues();
545            resolver.update(Directory.CONTENT_URI, contentValues, null, null);
546        }
547    }
548
549    /**
550     * @hide should be removed when users are updated to refer to SyncState
551     * @deprecated use SyncState instead
552     */
553    @Deprecated
554    public interface SyncStateColumns extends SyncStateContract.Columns {
555    }
556
557    /**
558     * A table provided for sync adapters to use for storing private sync state data.
559     *
560     * @see SyncStateContract
561     */
562    public static final class SyncState implements SyncStateContract.Columns {
563        /**
564         * This utility class cannot be instantiated
565         */
566        private SyncState() {}
567
568        public static final String CONTENT_DIRECTORY =
569                SyncStateContract.Constants.CONTENT_DIRECTORY;
570
571        /**
572         * The content:// style URI for this table
573         */
574        public static final Uri CONTENT_URI =
575                Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY);
576
577        /**
578         * @see android.provider.SyncStateContract.Helpers#get
579         */
580        public static byte[] get(ContentProviderClient provider, Account account)
581                throws RemoteException {
582            return SyncStateContract.Helpers.get(provider, CONTENT_URI, account);
583        }
584
585        /**
586         * @see android.provider.SyncStateContract.Helpers#get
587         */
588        public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account)
589                throws RemoteException {
590            return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account);
591        }
592
593        /**
594         * @see android.provider.SyncStateContract.Helpers#set
595         */
596        public static void set(ContentProviderClient provider, Account account, byte[] data)
597                throws RemoteException {
598            SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data);
599        }
600
601        /**
602         * @see android.provider.SyncStateContract.Helpers#newSetOperation
603         */
604        public static ContentProviderOperation newSetOperation(Account account, byte[] data) {
605            return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data);
606        }
607    }
608
609    /**
610     * Generic columns for use by sync adapters. The specific functions of
611     * these columns are private to the sync adapter. Other clients of the API
612     * should not attempt to either read or write this column.
613     *
614     * @see RawContacts
615     * @see Groups
616     */
617    protected interface BaseSyncColumns {
618
619        /** Generic column for use by sync adapters. */
620        public static final String SYNC1 = "sync1";
621        /** Generic column for use by sync adapters. */
622        public static final String SYNC2 = "sync2";
623        /** Generic column for use by sync adapters. */
624        public static final String SYNC3 = "sync3";
625        /** Generic column for use by sync adapters. */
626        public static final String SYNC4 = "sync4";
627    }
628
629    /**
630     * Columns that appear when each row of a table belongs to a specific
631     * account, including sync information that an account may need.
632     *
633     * @see RawContacts
634     * @see Groups
635     */
636    protected interface SyncColumns extends BaseSyncColumns {
637        /**
638         * The name of the account instance to which this row belongs, which when paired with
639         * {@link #ACCOUNT_TYPE} identifies a specific account.
640         * <P>Type: TEXT</P>
641         */
642        public static final String ACCOUNT_NAME = "account_name";
643
644        /**
645         * The type of account to which this row belongs, which when paired with
646         * {@link #ACCOUNT_NAME} identifies a specific account.
647         * <P>Type: TEXT</P>
648         */
649        public static final String ACCOUNT_TYPE = "account_type";
650
651        /**
652         * String that uniquely identifies this row to its source account.
653         * <P>Type: TEXT</P>
654         */
655        public static final String SOURCE_ID = "sourceid";
656
657        /**
658         * Version number that is updated whenever this row or its related data
659         * changes.
660         * <P>Type: INTEGER</P>
661         */
662        public static final String VERSION = "version";
663
664        /**
665         * Flag indicating that {@link #VERSION} has changed, and this row needs
666         * to be synchronized by its owning account.
667         * <P>Type: INTEGER (boolean)</P>
668         */
669        public static final String DIRTY = "dirty";
670    }
671
672    /**
673     * Columns of {@link ContactsContract.Contacts} that track the user's
674     * preferences for, or interactions with, the contact.
675     *
676     * @see Contacts
677     * @see RawContacts
678     * @see ContactsContract.Data
679     * @see PhoneLookup
680     * @see ContactsContract.Contacts.AggregationSuggestions
681     */
682    protected interface ContactOptionsColumns {
683        /**
684         * The number of times a contact has been contacted
685         * <P>Type: INTEGER</P>
686         */
687        public static final String TIMES_CONTACTED = "times_contacted";
688
689        /**
690         * The last time a contact was contacted.
691         * <P>Type: INTEGER</P>
692         */
693        public static final String LAST_TIME_CONTACTED = "last_time_contacted";
694
695        /**
696         * Is the contact starred?
697         * <P>Type: INTEGER (boolean)</P>
698         */
699        public static final String STARRED = "starred";
700
701        /**
702         * URI for a custom ringtone associated with the contact. If null or missing,
703         * the default ringtone is used.
704         * <P>Type: TEXT (URI to the ringtone)</P>
705         */
706        public static final String CUSTOM_RINGTONE = "custom_ringtone";
707
708        /**
709         * Whether the contact should always be sent to voicemail. If missing,
710         * defaults to false.
711         * <P>Type: INTEGER (0 for false, 1 for true)</P>
712         */
713        public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
714    }
715
716    /**
717     * Columns of {@link ContactsContract.Contacts} that refer to intrinsic
718     * properties of the contact, as opposed to the user-specified options
719     * found in {@link ContactOptionsColumns}.
720     *
721     * @see Contacts
722     * @see ContactsContract.Data
723     * @see PhoneLookup
724     * @see ContactsContract.Contacts.AggregationSuggestions
725     */
726    protected interface ContactsColumns {
727        /**
728         * The display name for the contact.
729         * <P>Type: TEXT</P>
730         */
731        public static final String DISPLAY_NAME = ContactNameColumns.DISPLAY_NAME_PRIMARY;
732
733        /**
734         * Reference to the row in the RawContacts table holding the contact name.
735         * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P>
736         * @hide
737         */
738        public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id";
739
740        /**
741         * Reference to the row in the data table holding the photo.  A photo can
742         * be referred to either by ID (this field) or by URI (see {@link #PHOTO_THUMBNAIL_URI}
743         * and {@link #PHOTO_URI}).
744         * If PHOTO_ID is null, consult {@link #PHOTO_URI} or {@link #PHOTO_THUMBNAIL_URI},
745         * which is a more generic mechanism for referencing the contact photo, especially for
746         * contacts returned by non-local directories (see {@link Directory}).
747         *
748         * <P>Type: INTEGER REFERENCES data(_id)</P>
749         */
750        public static final String PHOTO_ID = "photo_id";
751
752        /**
753         * A URI that can be used to retrieve the contact's full-size photo.
754         * A photo can be referred to either by a URI (this field) or by ID
755         * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
756         * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
757         * Thus using PHOTO_URI is a more robust method of retrieving contact photos.
758         *
759         * <P>Type: TEXT</P>
760         */
761        public static final String PHOTO_URI = "photo_uri";
762
763        /**
764         * A URI that can be used to retrieve a thumbnail of the contact's photo.
765         * A photo can be referred to either by a URI (this field or {@link #PHOTO_URI})
766         * or by ID (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
767         * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
768         * If the content provider does not differentiate between full-size photos
769         * and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain
770         * the same value, but either both shell be null or both not null.
771         *
772         * <P>Type: TEXT</P>
773         */
774        public static final String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
775
776        /**
777         * Flag that reflects the {@link Groups#GROUP_VISIBLE} state of any
778         * {@link CommonDataKinds.GroupMembership} for this contact.
779         */
780        public static final String IN_VISIBLE_GROUP = "in_visible_group";
781
782        /**
783         * Flag that reflects whether this contact represents the user's
784         * personal profile entry.
785         */
786        public static final String IS_USER_PROFILE = "is_user_profile";
787
788        /**
789         * An indicator of whether this contact has at least one phone number. "1" if there is
790         * at least one phone number, "0" otherwise.
791         * <P>Type: INTEGER</P>
792         */
793        public static final String HAS_PHONE_NUMBER = "has_phone_number";
794
795        /**
796         * An opaque value that contains hints on how to find the contact if
797         * its row id changed as a result of a sync or aggregation.
798         */
799        public static final String LOOKUP_KEY = "lookup";
800    }
801
802    /**
803     * @see Contacts
804     */
805    protected interface ContactStatusColumns {
806        /**
807         * Contact presence status. See {@link StatusUpdates} for individual status
808         * definitions.
809         * <p>Type: NUMBER</p>
810         */
811        public static final String CONTACT_PRESENCE = "contact_presence";
812
813        /**
814         * Contact Chat Capabilities. See {@link StatusUpdates} for individual
815         * definitions.
816         * <p>Type: NUMBER</p>
817         */
818        public static final String CONTACT_CHAT_CAPABILITY = "contact_chat_capability";
819
820        /**
821         * Contact's latest status update.
822         * <p>Type: TEXT</p>
823         */
824        public static final String CONTACT_STATUS = "contact_status";
825
826        /**
827         * The absolute time in milliseconds when the latest status was
828         * inserted/updated.
829         * <p>Type: NUMBER</p>
830         */
831        public static final String CONTACT_STATUS_TIMESTAMP = "contact_status_ts";
832
833        /**
834         * The package containing resources for this status: label and icon.
835         * <p>Type: TEXT</p>
836         */
837        public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package";
838
839        /**
840         * The resource ID of the label describing the source of contact
841         * status, e.g. "Google Talk". This resource is scoped by the
842         * {@link #CONTACT_STATUS_RES_PACKAGE}.
843         * <p>Type: NUMBER</p>
844         */
845        public static final String CONTACT_STATUS_LABEL = "contact_status_label";
846
847        /**
848         * The resource ID of the icon for the source of contact status. This
849         * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.
850         * <p>Type: NUMBER</p>
851         */
852        public static final String CONTACT_STATUS_ICON = "contact_status_icon";
853    }
854
855    /**
856     * Constants for various styles of combining given name, family name etc into
857     * a full name.  For example, the western tradition follows the pattern
858     * 'given name' 'middle name' 'family name' with the alternative pattern being
859     * 'family name', 'given name' 'middle name'.  The CJK tradition is
860     * 'family name' 'middle name' 'given name', with Japanese favoring a space between
861     * the names and Chinese omitting the space.
862     */
863    public interface FullNameStyle {
864        public static final int UNDEFINED = 0;
865        public static final int WESTERN = 1;
866
867        /**
868         * Used if the name is written in Hanzi/Kanji/Hanja and we could not determine
869         * which specific language it belongs to: Chinese, Japanese or Korean.
870         */
871        public static final int CJK = 2;
872
873        public static final int CHINESE = 3;
874        public static final int JAPANESE = 4;
875        public static final int KOREAN = 5;
876    }
877
878    /**
879     * Constants for various styles of capturing the pronunciation of a person's name.
880     */
881    public interface PhoneticNameStyle {
882        public static final int UNDEFINED = 0;
883
884        /**
885         * Pinyin is a phonetic method of entering Chinese characters. Typically not explicitly
886         * shown in UIs, but used for searches and sorting.
887         */
888        public static final int PINYIN = 3;
889
890        /**
891         * Hiragana and Katakana are two common styles of writing out the pronunciation
892         * of a Japanese names.
893         */
894        public static final int JAPANESE = 4;
895
896        /**
897         * Hangul is the Korean phonetic alphabet.
898         */
899        public static final int KOREAN = 5;
900    }
901
902    /**
903     * Types of data used to produce the display name for a contact. In the order
904     * of increasing priority: {@link #EMAIL}, {@link #PHONE},
905     * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_NAME}.
906     */
907    public interface DisplayNameSources {
908        public static final int UNDEFINED = 0;
909        public static final int EMAIL = 10;
910        public static final int PHONE = 20;
911        public static final int ORGANIZATION = 30;
912        public static final int NICKNAME = 35;
913        public static final int STRUCTURED_NAME = 40;
914    }
915
916    /**
917     * Contact name and contact name metadata columns in the RawContacts table.
918     *
919     * @see Contacts
920     * @see RawContacts
921     */
922    protected interface ContactNameColumns {
923
924        /**
925         * The kind of data that is used as the display name for the contact, such as
926         * structured name or email address.  See {@link DisplayNameSources}.
927         */
928        public static final String DISPLAY_NAME_SOURCE = "display_name_source";
929
930        /**
931         * <p>
932         * The standard text shown as the contact's display name, based on the best
933         * available information for the contact (for example, it might be the email address
934         * if the name is not available).
935         * The information actually used to compute the name is stored in
936         * {@link #DISPLAY_NAME_SOURCE}.
937         * </p>
938         * <p>
939         * A contacts provider is free to choose whatever representation makes most
940         * sense for its target market.
941         * For example in the default Android Open Source Project implementation,
942         * if the display name is
943         * based on the structured name and the structured name follows
944         * the Western full-name style, then this field contains the "given name first"
945         * version of the full name.
946         * <p>
947         *
948         * @see ContactsContract.ContactNameColumns#DISPLAY_NAME_ALTERNATIVE
949         */
950        public static final String DISPLAY_NAME_PRIMARY = "display_name";
951
952        /**
953         * <p>
954         * An alternative representation of the display name, such as "family name first"
955         * instead of "given name first" for Western names.  If an alternative is not
956         * available, the values should be the same as {@link #DISPLAY_NAME_PRIMARY}.
957         * </p>
958         * <p>
959         * A contacts provider is free to provide alternatives as necessary for
960         * its target market.
961         * For example the default Android Open Source Project contacts provider
962         * currently provides an
963         * alternative in a single case:  if the display name is
964         * based on the structured name and the structured name follows
965         * the Western full name style, then the field contains the "family name first"
966         * version of the full name.
967         * Other cases may be added later.
968         * </p>
969         */
970        public static final String DISPLAY_NAME_ALTERNATIVE = "display_name_alt";
971
972        /**
973         * The phonetic alphabet used to represent the {@link #PHONETIC_NAME}.  See
974         * {@link PhoneticNameStyle}.
975         */
976        public static final String PHONETIC_NAME_STYLE = "phonetic_name_style";
977
978        /**
979         * <p>
980         * Pronunciation of the full name in the phonetic alphabet specified by
981         * {@link #PHONETIC_NAME_STYLE}.
982         * </p>
983         * <p>
984         * The value may be set manually by the user. This capability is of
985         * interest only in countries with commonly used phonetic alphabets,
986         * such as Japan and Korea. See {@link PhoneticNameStyle}.
987         * </p>
988         */
989        public static final String PHONETIC_NAME = "phonetic_name";
990
991        /**
992         * Sort key that takes into account locale-based traditions for sorting
993         * names in address books.  The default
994         * sort key is {@link #DISPLAY_NAME_PRIMARY}.  For Chinese names
995         * the sort key is the name's Pinyin spelling, and for Japanese names
996         * it is the Hiragana version of the phonetic name.
997         */
998        public static final String SORT_KEY_PRIMARY = "sort_key";
999
1000        /**
1001         * Sort key based on the alternative representation of the full name,
1002         * {@link #DISPLAY_NAME_ALTERNATIVE}.  Thus for Western names,
1003         * it is the one using the "family name first" format.
1004         */
1005        public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt";
1006    }
1007
1008    /**
1009     * URI parameter and cursor extras that return counts of rows grouped by the
1010     * address book index, which is usually the first letter of the sort key.
1011     * When this parameter is supplied, the row counts are returned in the
1012     * cursor extras bundle.
1013     *
1014     * @hide
1015     */
1016    public final static class ContactCounts {
1017
1018        /**
1019         * Add this query parameter to a URI to get back row counts grouped by
1020         * the address book index as cursor extras. For most languages it is the
1021         * first letter of the sort key. This parameter does not affect the main
1022         * content of the cursor.
1023         *
1024         * @hide
1025         */
1026        public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
1027
1028        /**
1029         * The array of address book index titles, which are returned in the
1030         * same order as the data in the cursor.
1031         * <p>TYPE: String[]</p>
1032         *
1033         * @hide
1034         */
1035        public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
1036
1037        /**
1038         * The array of group counts for the corresponding group.  Contains the same number
1039         * of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array.
1040         * <p>TYPE: int[]</p>
1041         *
1042         * @hide
1043         */
1044        public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
1045    }
1046
1047    /**
1048     * Constants for the contacts table, which contains a record per aggregate
1049     * of raw contacts representing the same person.
1050     * <h3>Operations</h3>
1051     * <dl>
1052     * <dt><b>Insert</b></dt>
1053     * <dd>A Contact cannot be created explicitly. When a raw contact is
1054     * inserted, the provider will first try to find a Contact representing the
1055     * same person. If one is found, the raw contact's
1056     * {@link RawContacts#CONTACT_ID} column gets the _ID of the aggregate
1057     * Contact. If no match is found, the provider automatically inserts a new
1058     * Contact and puts its _ID into the {@link RawContacts#CONTACT_ID} column
1059     * of the newly inserted raw contact.</dd>
1060     * <dt><b>Update</b></dt>
1061     * <dd>Only certain columns of Contact are modifiable:
1062     * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED},
1063     * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
1064     * these columns on the Contact also changes them on all constituent raw
1065     * contacts.</dd>
1066     * <dt><b>Delete</b></dt>
1067     * <dd>Be careful with deleting Contacts! Deleting an aggregate contact
1068     * deletes all constituent raw contacts. The corresponding sync adapters
1069     * will notice the deletions of their respective raw contacts and remove
1070     * them from their back end storage.</dd>
1071     * <dt><b>Query</b></dt>
1072     * <dd>
1073     * <ul>
1074     * <li>If you need to read an individual contact, consider using
1075     * {@link #CONTENT_LOOKUP_URI} instead of {@link #CONTENT_URI}.</li>
1076     * <li>If you need to look up a contact by the phone number, use
1077     * {@link PhoneLookup#CONTENT_FILTER_URI PhoneLookup.CONTENT_FILTER_URI},
1078     * which is optimized for this purpose.</li>
1079     * <li>If you need to look up a contact by partial name, e.g. to produce
1080     * filter-as-you-type suggestions, use the {@link #CONTENT_FILTER_URI} URI.
1081     * <li>If you need to look up a contact by some data element like email
1082     * address, nickname, etc, use a query against the {@link ContactsContract.Data} table.
1083     * The result will contain contact ID, name etc.
1084     * </ul>
1085     * </dd>
1086     * </dl>
1087     * <h2>Columns</h2>
1088     * <table class="jd-sumtable">
1089     * <tr>
1090     * <th colspan='4'>Contacts</th>
1091     * </tr>
1092     * <tr>
1093     * <td>long</td>
1094     * <td>{@link #_ID}</td>
1095     * <td>read-only</td>
1096     * <td>Row ID. Consider using {@link #LOOKUP_KEY} instead.</td>
1097     * </tr>
1098     * <tr>
1099     * <td>String</td>
1100     * <td>{@link #LOOKUP_KEY}</td>
1101     * <td>read-only</td>
1102     * <td>An opaque value that contains hints on how to find the contact if its
1103     * row id changed as a result of a sync or aggregation.</td>
1104     * </tr>
1105     * <tr>
1106     * <td>long</td>
1107     * <td>NAME_RAW_CONTACT_ID</td>
1108     * <td>read-only</td>
1109     * <td>The ID of the raw contact that contributes the display name
1110     * to the aggregate contact. During aggregation one of the constituent
1111     * raw contacts is chosen using a heuristic: a longer name or a name
1112     * with more diacritic marks or more upper case characters is chosen.</td>
1113     * </tr>
1114     * <tr>
1115     * <td>String</td>
1116     * <td>DISPLAY_NAME_PRIMARY</td>
1117     * <td>read-only</td>
1118     * <td>The display name for the contact. It is the display name
1119     * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID
1120     * column.</td>
1121     * </tr>
1122     * <tr>
1123     * <td>long</td>
1124     * <td>{@link #PHOTO_ID}</td>
1125     * <td>read-only</td>
1126     * <td>Reference to the row in the {@link ContactsContract.Data} table holding the photo.
1127     * That row has the mime type
1128     * {@link CommonDataKinds.Photo#CONTENT_ITEM_TYPE}. The value of this field
1129     * is computed automatically based on the
1130     * {@link CommonDataKinds.Photo#IS_SUPER_PRIMARY} field of the data rows of
1131     * that mime type.</td>
1132     * </tr>
1133     * <tr>
1134     * <td>long</td>
1135     * <td>{@link #PHOTO_URI}</td>
1136     * <td>read-only</td>
1137     * <td>A URI that can be used to retrieve the contact's full-size photo. This
1138     * column is the preferred method of retrieving the contact photo.</td>
1139     * </tr>
1140     * <tr>
1141     * <td>long</td>
1142     * <td>{@link #PHOTO_THUMBNAIL_URI}</td>
1143     * <td>read-only</td>
1144     * <td>A URI that can be used to retrieve the thumbnail of contact's photo.  This
1145     * column is the preferred method of retrieving the contact photo.</td>
1146     * </tr>
1147     * <tr>
1148     * <td>int</td>
1149     * <td>{@link #IN_VISIBLE_GROUP}</td>
1150     * <td>read-only</td>
1151     * <td>An indicator of whether this contact is supposed to be visible in the
1152     * UI. "1" if the contact has at least one raw contact that belongs to a
1153     * visible group; "0" otherwise.</td>
1154     * </tr>
1155     * <tr>
1156     * <td>int</td>
1157     * <td>{@link #HAS_PHONE_NUMBER}</td>
1158     * <td>read-only</td>
1159     * <td>An indicator of whether this contact has at least one phone number.
1160     * "1" if there is at least one phone number, "0" otherwise.</td>
1161     * </tr>
1162     * <tr>
1163     * <td>int</td>
1164     * <td>{@link #TIMES_CONTACTED}</td>
1165     * <td>read/write</td>
1166     * <td>The number of times the contact has been contacted. See
1167     * {@link #markAsContacted}. When raw contacts are aggregated, this field is
1168     * computed automatically as the maximum number of times contacted among all
1169     * constituent raw contacts. Setting this field automatically changes the
1170     * corresponding field on all constituent raw contacts.</td>
1171     * </tr>
1172     * <tr>
1173     * <td>long</td>
1174     * <td>{@link #LAST_TIME_CONTACTED}</td>
1175     * <td>read/write</td>
1176     * <td>The timestamp of the last time the contact was contacted. See
1177     * {@link #markAsContacted}. Setting this field also automatically
1178     * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated,
1179     * this field is computed automatically as the latest time contacted of all
1180     * constituent raw contacts. Setting this field automatically changes the
1181     * corresponding field on all constituent raw contacts.</td>
1182     * </tr>
1183     * <tr>
1184     * <td>int</td>
1185     * <td>{@link #STARRED}</td>
1186     * <td>read/write</td>
1187     * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
1188     * When raw contacts are aggregated, this field is automatically computed:
1189     * if any constituent raw contacts are starred, then this field is set to
1190     * '1'. Setting this field automatically changes the corresponding field on
1191     * all constituent raw contacts.</td>
1192     * </tr>
1193     * <tr>
1194     * <td>String</td>
1195     * <td>{@link #CUSTOM_RINGTONE}</td>
1196     * <td>read/write</td>
1197     * <td>A custom ringtone associated with a contact. Typically this is the
1198     * URI returned by an activity launched with the
1199     * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.</td>
1200     * </tr>
1201     * <tr>
1202     * <td>int</td>
1203     * <td>{@link #SEND_TO_VOICEMAIL}</td>
1204     * <td>read/write</td>
1205     * <td>An indicator of whether calls from this contact should be forwarded
1206     * directly to voice mail ('1') or not ('0'). When raw contacts are
1207     * aggregated, this field is automatically computed: if <i>all</i>
1208     * constituent raw contacts have SEND_TO_VOICEMAIL=1, then this field is set
1209     * to '1'. Setting this field automatically changes the corresponding field
1210     * on all constituent raw contacts.</td>
1211     * </tr>
1212     * <tr>
1213     * <td>int</td>
1214     * <td>{@link #CONTACT_PRESENCE}</td>
1215     * <td>read-only</td>
1216     * <td>Contact IM presence status. See {@link StatusUpdates} for individual
1217     * status definitions. Automatically computed as the highest presence of all
1218     * constituent raw contacts. The provider may choose not to store this value
1219     * in persistent storage. The expectation is that presence status will be
1220     * updated on a regular basic.</td>
1221     * </tr>
1222     * <tr>
1223     * <td>String</td>
1224     * <td>{@link #CONTACT_STATUS}</td>
1225     * <td>read-only</td>
1226     * <td>Contact's latest status update. Automatically computed as the latest
1227     * of all constituent raw contacts' status updates.</td>
1228     * </tr>
1229     * <tr>
1230     * <td>long</td>
1231     * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td>
1232     * <td>read-only</td>
1233     * <td>The absolute time in milliseconds when the latest status was
1234     * inserted/updated.</td>
1235     * </tr>
1236     * <tr>
1237     * <td>String</td>
1238     * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td>
1239     * <td>read-only</td>
1240     * <td> The package containing resources for this status: label and icon.</td>
1241     * </tr>
1242     * <tr>
1243     * <td>long</td>
1244     * <td>{@link #CONTACT_STATUS_LABEL}</td>
1245     * <td>read-only</td>
1246     * <td>The resource ID of the label describing the source of contact status,
1247     * e.g. "Google Talk". This resource is scoped by the
1248     * {@link #CONTACT_STATUS_RES_PACKAGE}.</td>
1249     * </tr>
1250     * <tr>
1251     * <td>long</td>
1252     * <td>{@link #CONTACT_STATUS_ICON}</td>
1253     * <td>read-only</td>
1254     * <td>The resource ID of the icon for the source of contact status. This
1255     * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.</td>
1256     * </tr>
1257     * </table>
1258     */
1259    public static class Contacts implements BaseColumns, ContactsColumns,
1260            ContactOptionsColumns, ContactNameColumns, ContactStatusColumns {
1261        /**
1262         * This utility class cannot be instantiated
1263         */
1264        private Contacts()  {}
1265
1266        /**
1267         * The content:// style URI for this table
1268         */
1269        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
1270
1271        /**
1272         * A content:// style URI for this table that should be used to create
1273         * shortcuts or otherwise create long-term links to contacts. This URI
1274         * should always be followed by a "/" and the contact's {@link #LOOKUP_KEY}.
1275         * It can optionally also have a "/" and last known contact ID appended after
1276         * that. This "complete" format is an important optimization and is highly recommended.
1277         * <p>
1278         * As long as the contact's row ID remains the same, this URI is
1279         * equivalent to {@link #CONTENT_URI}. If the contact's row ID changes
1280         * as a result of a sync or aggregation, this URI will look up the
1281         * contact using indirect information (sync IDs or constituent raw
1282         * contacts).
1283         * <p>
1284         * Lookup key should be appended unencoded - it is stored in the encoded
1285         * form, ready for use in a URI.
1286         */
1287        public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI,
1288                "lookup");
1289
1290        /**
1291         * Base {@link Uri} for referencing a single {@link Contacts} entry,
1292         * created by appending {@link #LOOKUP_KEY} using
1293         * {@link Uri#withAppendedPath(Uri, String)}. Provides
1294         * {@link OpenableColumns} columns when queried, or returns the
1295         * referenced contact formatted as a vCard when opened through
1296         * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
1297         */
1298        public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI,
1299                "as_vcard");
1300
1301       /**
1302        * Boolean parameter that may be used with {@link #CONTENT_VCARD_URI}
1303        * and {@link #CONTENT_MULTI_VCARD_URI} to indicate that the returned
1304        * vcard should not contain a photo.
1305        *
1306        * @hide
1307        */
1308        public static final String QUERY_PARAMETER_VCARD_NO_PHOTO = "nophoto";
1309
1310        /**
1311         * Base {@link Uri} for referencing multiple {@link Contacts} entry,
1312         * created by appending {@link #LOOKUP_KEY} using
1313         * {@link Uri#withAppendedPath(Uri, String)}. The lookup keys have to be
1314         * encoded and joined with the colon (":") separator. The resulting string
1315         * has to be encoded again. Provides
1316         * {@link OpenableColumns} columns when queried, or returns the
1317         * referenced contact formatted as a vCard when opened through
1318         * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
1319         *
1320         * This is private API because we do not have a well-defined way to
1321         * specify several entities yet. The format of this Uri might change in the future
1322         * or the Uri might be completely removed.
1323         *
1324         * @hide
1325         */
1326        public static final Uri CONTENT_MULTI_VCARD_URI = Uri.withAppendedPath(CONTENT_URI,
1327                "as_multi_vcard");
1328
1329        /**
1330         * Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the
1331         * requested {@link Contacts} entry.
1332         *
1333         * @param contactUri A {@link #CONTENT_URI} row, or an existing
1334         *            {@link #CONTENT_LOOKUP_URI} to attempt refreshing.
1335         */
1336        public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) {
1337            final Cursor c = resolver.query(contactUri, new String[] {
1338                    Contacts.LOOKUP_KEY, Contacts._ID
1339            }, null, null, null);
1340            if (c == null) {
1341                return null;
1342            }
1343
1344            try {
1345                if (c.moveToFirst()) {
1346                    final String lookupKey = c.getString(0);
1347                    final long contactId = c.getLong(1);
1348                    return getLookupUri(contactId, lookupKey);
1349                }
1350            } finally {
1351                c.close();
1352            }
1353            return null;
1354        }
1355
1356        /**
1357         * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the
1358         * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}.
1359         */
1360        public static Uri getLookupUri(long contactId, String lookupKey) {
1361            return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
1362                    lookupKey), contactId);
1363        }
1364
1365        /**
1366         * Computes a content URI (see {@link #CONTENT_URI}) given a lookup URI.
1367         * <p>
1368         * Returns null if the contact cannot be found.
1369         */
1370        public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) {
1371            if (lookupUri == null) {
1372                return null;
1373            }
1374
1375            Cursor c = resolver.query(lookupUri, new String[]{Contacts._ID}, null, null, null);
1376            if (c == null) {
1377                return null;
1378            }
1379
1380            try {
1381                if (c.moveToFirst()) {
1382                    long contactId = c.getLong(0);
1383                    return ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
1384                }
1385            } finally {
1386                c.close();
1387            }
1388            return null;
1389        }
1390
1391        /**
1392         * Mark a contact as having been contacted. Updates two fields:
1393         * {@link #TIMES_CONTACTED} and {@link #LAST_TIME_CONTACTED}. The
1394         * TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED
1395         * field is populated with the current system time.
1396         *
1397         * @param resolver the ContentResolver to use
1398         * @param contactId the person who was contacted
1399         */
1400        public static void markAsContacted(ContentResolver resolver, long contactId) {
1401            Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
1402            ContentValues values = new ContentValues();
1403            // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified.
1404            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
1405            resolver.update(uri, values, null, null);
1406        }
1407
1408        /**
1409         * The content:// style URI used for "type-to-filter" functionality on the
1410         * {@link #CONTENT_URI} URI. The filter string will be used to match
1411         * various parts of the contact name. The filter argument should be passed
1412         * as an additional path segment after this URI.
1413         */
1414        public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(
1415                CONTENT_URI, "filter");
1416
1417        /**
1418         * The content:// style URI for this table joined with useful data from
1419         * {@link ContactsContract.Data}, filtered to include only starred contacts
1420         * and the most frequently contacted contacts.
1421         */
1422        public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath(
1423                CONTENT_URI, "strequent");
1424
1425        /**
1426         * The content:// style URI used for "type-to-filter" functionality on the
1427         * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match
1428         * various parts of the contact name. The filter argument should be passed
1429         * as an additional path segment after this URI.
1430         */
1431        public static final Uri CONTENT_STREQUENT_FILTER_URI = Uri.withAppendedPath(
1432                CONTENT_STREQUENT_URI, "filter");
1433
1434        public static final Uri CONTENT_GROUP_URI = Uri.withAppendedPath(
1435                CONTENT_URI, "group");
1436
1437        /**
1438         * The MIME type of {@link #CONTENT_URI} providing a directory of
1439         * people.
1440         */
1441        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact";
1442
1443        /**
1444         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
1445         * person.
1446         */
1447        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
1448
1449        /**
1450         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
1451         * person.
1452         */
1453        public static final String CONTENT_VCARD_TYPE = "text/x-vcard";
1454
1455        /**
1456         * A sub-directory of a single contact that contains all of the constituent raw contact
1457         * {@link ContactsContract.Data} rows.  This directory can be used either
1458         * with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}.
1459         */
1460        public static final class Data implements BaseColumns, DataColumns {
1461            /**
1462             * no public constructor since this is a utility class
1463             */
1464            private Data() {}
1465
1466            /**
1467             * The directory twig for this sub-table
1468             */
1469            public static final String CONTENT_DIRECTORY = "data";
1470        }
1471
1472        /**
1473         * <p>
1474         * A sub-directory of a contact that contains all of its
1475         * {@link ContactsContract.RawContacts} as well as
1476         * {@link ContactsContract.Data} rows. To access this directory append
1477         * {@link #CONTENT_DIRECTORY} to the contact URI.
1478         * </p>
1479         * <p>
1480         * Entity has three ID fields: {@link #CONTACT_ID} for the contact,
1481         * {@link #RAW_CONTACT_ID} for the raw contact and {@link #DATA_ID} for
1482         * the data rows. Entity always contains at least one row per
1483         * constituent raw contact, even if there are no actual data rows. In
1484         * this case the {@link #DATA_ID} field will be null.
1485         * </p>
1486         * <p>
1487         * Entity reads all data for the entire contact in one transaction, to
1488         * guarantee consistency.  There is significant data duplication
1489         * in the Entity (each row repeats all Contact columns and all RawContact
1490         * columns), so the benefits of transactional consistency should be weighed
1491         * against the cost of transferring large amounts of denormalized data
1492         * from the Provider.
1493         * </p>
1494         * <p>
1495         * To reduce the amount of data duplication the contacts provider and directory
1496         * providers implementing this protocol are allowed to provide common Contacts
1497         * and RawContacts fields in the first row returned for each raw contact only and
1498         * leave them as null in subsequent rows.
1499         * </p>
1500         */
1501        public static final class Entity implements BaseColumns, ContactsColumns,
1502                ContactNameColumns, RawContactsColumns, BaseSyncColumns, SyncColumns, DataColumns,
1503                StatusColumns, ContactOptionsColumns, ContactStatusColumns {
1504            /**
1505             * no public constructor since this is a utility class
1506             */
1507            private Entity() {
1508            }
1509
1510            /**
1511             * The directory twig for this sub-table
1512             */
1513            public static final String CONTENT_DIRECTORY = "entities";
1514
1515            /**
1516             * The ID of the raw contact row.
1517             * <P>Type: INTEGER</P>
1518             */
1519            public static final String RAW_CONTACT_ID = "raw_contact_id";
1520
1521            /**
1522             * The ID of the data row. The value will be null if this raw contact has no
1523             * data rows.
1524             * <P>Type: INTEGER</P>
1525             */
1526            public static final String DATA_ID = "data_id";
1527        }
1528
1529        /**
1530         * <p>
1531         * A <i>read-only</i> sub-directory of a single contact aggregate that
1532         * contains all aggregation suggestions (other contacts). The
1533         * aggregation suggestions are computed based on approximate data
1534         * matches with this contact.
1535         * </p>
1536         * <p>
1537         * <i>Note: this query may be expensive! If you need to use it in bulk,
1538         * make sure the user experience is acceptable when the query runs for a
1539         * long time.</i>
1540         * <p>
1541         * Usage example:
1542         *
1543         * <pre>
1544         * Uri uri = Contacts.CONTENT_URI.buildUpon()
1545         *          .appendEncodedPath(String.valueOf(contactId))
1546         *          .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY)
1547         *          .appendQueryParameter(&quot;limit&quot;, &quot;3&quot;)
1548         *          .build()
1549         * Cursor cursor = getContentResolver().query(suggestionsUri,
1550         *          new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY},
1551         *          null, null, null);
1552         * </pre>
1553         *
1554         * </p>
1555         * <p>
1556         * This directory can be used either with a {@link #CONTENT_URI} or
1557         * {@link #CONTENT_LOOKUP_URI}.
1558         * </p>
1559         */
1560        public static final class AggregationSuggestions implements BaseColumns, ContactsColumns,
1561                ContactOptionsColumns, ContactStatusColumns {
1562            /**
1563             * No public constructor since this is a utility class
1564             */
1565            private AggregationSuggestions() {}
1566
1567            /**
1568             * The directory twig for this sub-table. The URI can be followed by an optional
1569             * type-to-filter, similar to
1570             * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}.
1571             */
1572            public static final String CONTENT_DIRECTORY = "suggestions";
1573
1574            /**
1575             * Used with {@link Builder#addParameter} to specify what kind of data is
1576             * supplied for the suggestion query.
1577             *
1578             * @hide
1579             */
1580            public static final String PARAMETER_MATCH_NAME = "name";
1581
1582            /**
1583             * Used with {@link Builder#addParameter} to specify what kind of data is
1584             * supplied for the suggestion query.
1585             *
1586             * @hide
1587             */
1588            public static final String PARAMETER_MATCH_EMAIL = "email";
1589
1590            /**
1591             * Used with {@link Builder#addParameter} to specify what kind of data is
1592             * supplied for the suggestion query.
1593             *
1594             * @hide
1595             */
1596            public static final String PARAMETER_MATCH_PHONE = "phone";
1597
1598            /**
1599             * Used with {@link Builder#addParameter} to specify what kind of data is
1600             * supplied for the suggestion query.
1601             *
1602             * @hide
1603             */
1604            public static final String PARAMETER_MATCH_NICKNAME = "nickname";
1605
1606            /**
1607             * A convenience builder for aggregation suggestion content URIs.
1608             *
1609             * TODO: change documentation for this class to use the builder.
1610             * @hide
1611             */
1612            public static final class Builder {
1613                private long mContactId;
1614                private ArrayList<String> mKinds = new ArrayList<String>();
1615                private ArrayList<String> mValues = new ArrayList<String>();
1616                private int mLimit;
1617
1618                /**
1619                 * Optional existing contact ID.  If it is not provided, the search
1620                 * will be based exclusively on the values supplied with {@link #addParameter}.
1621                 */
1622                public Builder setContactId(long contactId) {
1623                    this.mContactId = contactId;
1624                    return this;
1625                }
1626
1627                /**
1628                 * A value that can be used when searching for an aggregation
1629                 * suggestion.
1630                 *
1631                 * @param kind can be one of
1632                 *            {@link AggregationSuggestions#PARAMETER_MATCH_NAME},
1633                 *            {@link AggregationSuggestions#PARAMETER_MATCH_EMAIL},
1634                 *            {@link AggregationSuggestions#PARAMETER_MATCH_NICKNAME},
1635                 *            {@link AggregationSuggestions#PARAMETER_MATCH_PHONE}
1636                 */
1637                public Builder addParameter(String kind, String value) {
1638                    if (!TextUtils.isEmpty(value)) {
1639                        mKinds.add(kind);
1640                        mValues.add(value);
1641                    }
1642                    return this;
1643                }
1644
1645                public Builder setLimit(int limit) {
1646                    mLimit = limit;
1647                    return this;
1648                }
1649
1650                public Uri build() {
1651                    android.net.Uri.Builder builder = Contacts.CONTENT_URI.buildUpon();
1652                    builder.appendEncodedPath(String.valueOf(mContactId));
1653                    builder.appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY);
1654                    if (mLimit != 0) {
1655                        builder.appendQueryParameter("limit", String.valueOf(mLimit));
1656                    }
1657
1658                    int count = mKinds.size();
1659                    for (int i = 0; i < count; i++) {
1660                        builder.appendQueryParameter("query", mKinds.get(i) + ":" + mValues.get(i));
1661                    }
1662
1663                    return builder.build();
1664                }
1665            }
1666
1667            /**
1668             * @hide
1669             */
1670            public static final Builder builder() {
1671                return new Builder();
1672            }
1673        }
1674
1675        /**
1676         * A <i>read-only</i> sub-directory of a single contact that contains
1677         * the contact's primary photo.
1678         * <p>
1679         * Usage example:
1680         *
1681         * <pre>
1682         * public InputStream openPhoto(long contactId) {
1683         *     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
1684         *     Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
1685         *     Cursor cursor = getContentResolver().query(photoUri,
1686         *          new String[] {Contacts.Photo.PHOTO}, null, null, null);
1687         *     if (cursor == null) {
1688         *         return null;
1689         *     }
1690         *     try {
1691         *         if (cursor.moveToFirst()) {
1692         *             byte[] data = cursor.getBlob(0);
1693         *             if (data != null) {
1694         *                 return new ByteArrayInputStream(data);
1695         *             }
1696         *         }
1697         *     } finally {
1698         *         cursor.close();
1699         *     }
1700         *     return null;
1701         * }
1702         * </pre>
1703         *
1704         * </p>
1705         * <p>You should also consider using the convenience method
1706         * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)}
1707         * </p>
1708         * <p>
1709         * This directory can be used either with a {@link #CONTENT_URI} or
1710         * {@link #CONTENT_LOOKUP_URI}.
1711         * </p>
1712         */
1713        public static final class Photo implements BaseColumns, DataColumnsWithJoins {
1714            /**
1715             * no public constructor since this is a utility class
1716             */
1717            private Photo() {}
1718
1719            /**
1720             * The directory twig for this sub-table
1721             */
1722            public static final String CONTENT_DIRECTORY = "photo";
1723
1724            /**
1725             * Thumbnail photo of the raw contact. This is the raw bytes of an image
1726             * that could be inflated using {@link android.graphics.BitmapFactory}.
1727             * <p>
1728             * Type: BLOB
1729             */
1730            public static final String PHOTO = DATA15;
1731        }
1732
1733        /**
1734         * Opens an InputStream for the contacts's default photo and returns the
1735         * photo as a byte stream. If there is not photo null will be returned.
1736         *
1737         * @param contactUri the contact whose photo should be used. This can be used with
1738         * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI.
1739         * </p>
1740
1741         * @return an InputStream of the photo, or null if no photo is present
1742         */
1743        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
1744            Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY);
1745            if (photoUri == null) {
1746                return null;
1747            }
1748            Cursor cursor = cr.query(photoUri,
1749                    new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
1750            try {
1751                if (cursor == null || !cursor.moveToNext()) {
1752                    return null;
1753                }
1754                byte[] data = cursor.getBlob(0);
1755                if (data == null) {
1756                    return null;
1757                }
1758                return new ByteArrayInputStream(data);
1759            } finally {
1760                if (cursor != null) {
1761                    cursor.close();
1762                }
1763            }
1764        }
1765    }
1766
1767    /**
1768     * <p>
1769     * Constants for the user's profile data, which is represented as a single contact on
1770     * the device that represents the user.  The profile contact is not aggregated
1771     * together automatically in the same way that normal contacts are; instead, each
1772     * account on the device may contribute a single raw contact representing the user's
1773     * personal profile data from that source.
1774     * </p>
1775     * <p>
1776     * Access to the profile entry through these URIs (or incidental access to parts of
1777     * the profile if retrieved directly via ID) requires additional permissions beyond
1778     * the read/write contact permissions required by the provider.  Querying for profile
1779     * data requires android.permission.READ_PROFILE permission, and inserting or
1780     * updating profile data requires android.permission.WRITE_PROFILE permission.
1781     * </p>
1782     * <h3>Operations</h3>
1783     * <dl>
1784     * <dt><b>Insert</b></dt>
1785     * <dd>The user's profile entry cannot be created explicitly (attempting to do so
1786     * will throw an exception). When a raw contact is inserted into the profile, the
1787     * provider will check for the existence of a profile on the device.  If one is
1788     * found, the raw contact's {@link RawContacts#CONTACT_ID} column gets the _ID of
1789     * the profile Contact. If no match is found, the profile Contact is created and
1790     * its _ID is put into the {@link RawContacts#CONTACT_ID} column of the newly
1791     * inserted raw contact.</dd>
1792     * <dt><b>Update</b></dt>
1793     * <dd>The profile Contact has the same update restrictions as Contacts in general,
1794     * but requires the android.permission.WRITE_PROFILE permission.</dd>
1795     * <dt><b>Delete</b></dt>
1796     * <dd>The profile Contact cannot be explicitly deleted.  It will be removed
1797     * automatically if all of its constituent raw contact entries are deleted.</dd>
1798     * <dt><b>Query</b></dt>
1799     * <dd>
1800     * <ul>
1801     * <li>The {@link #CONTENT_URI} for profiles behaves in much the same way as
1802     * retrieving a contact by ID, except that it will only ever return the user's
1803     * profile contact.
1804     * </li>
1805     * <li>
1806     * The profile contact supports all of the same sub-paths as an individual contact
1807     * does - the content of the profile contact can be retrieved as entities or
1808     * data rows.  Similarly, specific raw contact entries can be retrieved by appending
1809     * the desired raw contact ID within the profile.
1810     * </li>
1811     * </ul>
1812     * </dd>
1813     * </dl>
1814     */
1815    public static final class Profile implements BaseColumns, ContactsColumns,
1816            ContactOptionsColumns, ContactNameColumns, ContactStatusColumns {
1817        /**
1818         * This utility class cannot be instantiated
1819         */
1820        private Profile() {
1821        }
1822
1823        /**
1824         * The content:// style URI for this table, which requests the contact entry
1825         * representing the user's personal profile data.
1826         */
1827        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "profile");
1828
1829        /**
1830         * {@link Uri} for referencing the user's profile {@link Contacts} entry,
1831         * Provides {@link OpenableColumns} columns when queried, or returns the
1832         * user's profile contact formatted as a vCard when opened through
1833         * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
1834         */
1835        public static final Uri CONTENT_VCARD_URI = Uri.withAppendedPath(CONTENT_URI,
1836                "as_vcard");
1837
1838        /**
1839         * {@link Uri} for referencing the raw contacts that make up the user's profile
1840         * {@link Contacts} entry.  An individual raw contact entry within the profile
1841         * can be addressed by appending the raw contact ID.  The entities or data within
1842         * that specific raw contact can be requested by appending the entity or data
1843         * path as well.
1844         */
1845        public static final Uri CONTENT_RAW_CONTACTS_URI = Uri.withAppendedPath(CONTENT_URI,
1846                "raw_contacts");
1847    }
1848
1849    protected interface RawContactsColumns {
1850        /**
1851         * A reference to the {@link ContactsContract.Contacts#_ID} that this
1852         * data belongs to.
1853         * <P>Type: INTEGER</P>
1854         */
1855        public static final String CONTACT_ID = "contact_id";
1856
1857        /**
1858         * Flag indicating that this {@link RawContacts} entry and its children have
1859         * been restricted to specific platform apps.
1860         * <P>Type: INTEGER (boolean)</P>
1861         *
1862         * @hide until finalized in future platform release
1863         */
1864        public static final String IS_RESTRICTED = "is_restricted";
1865
1866        /**
1867         * The aggregation mode for this contact.
1868         * <P>Type: INTEGER</P>
1869         */
1870        public static final String AGGREGATION_MODE = "aggregation_mode";
1871
1872        /**
1873         * The "deleted" flag: "0" by default, "1" if the row has been marked
1874         * for deletion. When {@link android.content.ContentResolver#delete} is
1875         * called on a raw contact, it is marked for deletion and removed from its
1876         * aggregate contact. The sync adaptor deletes the raw contact on the server and
1877         * then calls ContactResolver.delete once more, this time passing the
1878         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
1879         * the data removal.
1880         * <P>Type: INTEGER</P>
1881         */
1882        public static final String DELETED = "deleted";
1883
1884        /**
1885         * The "name_verified" flag: "1" means that the name fields on this raw
1886         * contact can be trusted and therefore should be used for the entire
1887         * aggregated contact.
1888         * <p>
1889         * If an aggregated contact contains more than one raw contact with a
1890         * verified name, one of those verified names is chosen at random.
1891         * If an aggregated contact contains no verified names, the
1892         * name is chosen randomly from the constituent raw contacts.
1893         * </p>
1894         * <p>
1895         * Updating this flag from "0" to "1" automatically resets it to "0" on
1896         * all other raw contacts in the same aggregated contact.
1897         * </p>
1898         * <p>
1899         * Sync adapters should only specify a value for this column when
1900         * inserting a raw contact and leave it out when doing an update.
1901         * </p>
1902         * <p>
1903         * The default value is "0"
1904         * </p>
1905         * <p>Type: INTEGER</p>
1906         *
1907         * @hide
1908         */
1909        public static final String NAME_VERIFIED = "name_verified";
1910
1911        /**
1912         * The "read-only" flag: "0" by default, "1" if the row cannot be modified or
1913         * deleted except by a sync adapter.  See {@link ContactsContract#CALLER_IS_SYNCADAPTER}.
1914         * <P>Type: INTEGER</P>
1915         */
1916        public static final String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only";
1917
1918        /**
1919         * Flag that reflects whether this raw contact belongs to the user's
1920         * personal profile entry.
1921         */
1922        public static final String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile";
1923    }
1924
1925    /**
1926     * Constants for the raw contacts table, which contains one row of contact
1927     * information for each person in each synced account. Sync adapters and
1928     * contact management apps
1929     * are the primary consumers of this API.
1930     *
1931     * <h3>Aggregation</h3>
1932     * <p>
1933     * As soon as a raw contact is inserted or whenever its constituent data
1934     * changes, the provider will check if the raw contact matches other
1935     * existing raw contacts and if so will aggregate it with those. The
1936     * aggregation is reflected in the {@link RawContacts} table by the change of the
1937     * {@link #CONTACT_ID} field, which is the reference to the aggregate contact.
1938     * </p>
1939     * <p>
1940     * Changes to the structured name, organization, phone number, email address,
1941     * or nickname trigger a re-aggregation.
1942     * </p>
1943     * <p>
1944     * See also {@link AggregationExceptions} for a mechanism to control
1945     * aggregation programmatically.
1946     * </p>
1947     *
1948     * <h3>Operations</h3>
1949     * <dl>
1950     * <dt><b>Insert</b></dt>
1951     * <dd>
1952     * <p>
1953     * Raw contacts can be inserted incrementally or in a batch.
1954     * The incremental method is more traditional but less efficient.
1955     * It should be used
1956     * only if no {@link Data} values are available at the time the raw contact is created:
1957     * <pre>
1958     * ContentValues values = new ContentValues();
1959     * values.put(RawContacts.ACCOUNT_TYPE, accountType);
1960     * values.put(RawContacts.ACCOUNT_NAME, accountName);
1961     * Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);
1962     * long rawContactId = ContentUris.parseId(rawContactUri);
1963     * </pre>
1964     * </p>
1965     * <p>
1966     * Once {@link Data} values become available, insert those.
1967     * For example, here's how you would insert a name:
1968     *
1969     * <pre>
1970     * values.clear();
1971     * values.put(Data.RAW_CONTACT_ID, rawContactId);
1972     * values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
1973     * values.put(StructuredName.DISPLAY_NAME, &quot;Mike Sullivan&quot;);
1974     * getContentResolver().insert(Data.CONTENT_URI, values);
1975     * </pre>
1976     * </p>
1977     * <p>
1978     * The batch method is by far preferred.  It inserts the raw contact and its
1979     * constituent data rows in a single database transaction
1980     * and causes at most one aggregation pass.
1981     * <pre>
1982     * ArrayList&lt;ContentProviderOperation&gt; ops =
1983     *          new ArrayList&lt;ContentProviderOperation&gt;();
1984     * ...
1985     * int rawContactInsertIndex = ops.size();
1986     * ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
1987     *          .withValue(RawContacts.ACCOUNT_TYPE, accountType)
1988     *          .withValue(RawContacts.ACCOUNT_NAME, accountName)
1989     *          .build());
1990     *
1991     * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
1992     *          .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
1993     *          .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
1994     *          .withValue(StructuredName.DISPLAY_NAME, &quot;Mike Sullivan&quot;)
1995     *          .build());
1996     *
1997     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
1998     * </pre>
1999     * </p>
2000     * <p>
2001     * Note the use of {@link ContentProviderOperation.Builder#withValueBackReference(String, int)}
2002     * to refer to the as-yet-unknown index value of the raw contact inserted in the
2003     * first operation.
2004     * </p>
2005     *
2006     * <dt><b>Update</b></dt>
2007     * <dd><p>
2008     * Raw contacts can be updated incrementally or in a batch.
2009     * Batch mode should be used whenever possible.
2010     * The procedures and considerations are analogous to those documented above for inserts.
2011     * </p></dd>
2012     * <dt><b>Delete</b></dt>
2013     * <dd><p>When a raw contact is deleted, all of its Data rows as well as StatusUpdates,
2014     * AggregationExceptions, PhoneLookup rows are deleted automatically. When all raw
2015     * contacts associated with a {@link Contacts} row are deleted, the {@link Contacts} row
2016     * itself is also deleted automatically.
2017     * </p>
2018     * <p>
2019     * The invocation of {@code resolver.delete(...)}, does not immediately delete
2020     * a raw contacts row.
2021     * Instead, it sets the {@link #DELETED} flag on the raw contact and
2022     * removes the raw contact from its aggregate contact.
2023     * The sync adapter then deletes the raw contact from the server and
2024     * finalizes phone-side deletion by calling {@code resolver.delete(...)}
2025     * again and passing the {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter.<p>
2026     * <p>Some sync adapters are read-only, meaning that they only sync server-side
2027     * changes to the phone, but not the reverse.  If one of those raw contacts
2028     * is marked for deletion, it will remain on the phone.  However it will be
2029     * effectively invisible, because it will not be part of any aggregate contact.
2030     * </dd>
2031     *
2032     * <dt><b>Query</b></dt>
2033     * <dd>
2034     * <p>
2035     * It is easy to find all raw contacts in a Contact:
2036     * <pre>
2037     * Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,
2038     *          new String[]{RawContacts._ID},
2039     *          RawContacts.CONTACT_ID + "=?",
2040     *          new String[]{String.valueOf(contactId)}, null);
2041     * </pre>
2042     * </p>
2043     * <p>
2044     * To find raw contacts within a specific account,
2045     * you can either put the account name and type in the selection or pass them as query
2046     * parameters.  The latter approach is preferable, especially when you can reuse the
2047     * URI:
2048     * <pre>
2049     * Uri rawContactUri = RawContacts.URI.buildUpon()
2050     *          .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
2051     *          .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
2052     *          .build();
2053     * Cursor c1 = getContentResolver().query(rawContactUri,
2054     *          RawContacts.STARRED + "&lt;&gt;0", null, null, null);
2055     * ...
2056     * Cursor c2 = getContentResolver().query(rawContactUri,
2057     *          RawContacts.DELETED + "&lt;&gt;0", null, null, null);
2058     * </pre>
2059     * </p>
2060     * <p>The best way to read a raw contact along with all the data associated with it is
2061     * by using the {@link Entity} directory. If the raw contact has data rows,
2062     * the Entity cursor will contain a row for each data row.  If the raw contact has no
2063     * data rows, the cursor will still contain one row with the raw contact-level information.
2064     * <pre>
2065     * Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
2066     * Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
2067     * Cursor c = getContentResolver().query(entityUri,
2068     *          new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1},
2069     *          null, null, null);
2070     * try {
2071     *     while (c.moveToNext()) {
2072     *         String sourceId = c.getString(0);
2073     *         if (!c.isNull(1)) {
2074     *             String mimeType = c.getString(2);
2075     *             String data = c.getString(3);
2076     *             ...
2077     *         }
2078     *     }
2079     * } finally {
2080     *     c.close();
2081     * }
2082     * </pre>
2083     * </p>
2084     * </dd>
2085     * </dl>
2086     * <h2>Columns</h2>
2087     *
2088     * <table class="jd-sumtable">
2089     * <tr>
2090     * <th colspan='4'>RawContacts</th>
2091     * </tr>
2092     * <tr>
2093     * <td>long</td>
2094     * <td>{@link #_ID}</td>
2095     * <td>read-only</td>
2096     * <td>Row ID. Sync adapters should try to preserve row IDs during updates. In other words,
2097     * it is much better for a sync adapter to update a raw contact rather than to delete and
2098     * re-insert it.</td>
2099     * </tr>
2100     * <tr>
2101     * <td>long</td>
2102     * <td>{@link #CONTACT_ID}</td>
2103     * <td>read-only</td>
2104     * <td>The ID of the row in the {@link ContactsContract.Contacts} table
2105     * that this raw contact belongs
2106     * to. Raw contacts are linked to contacts by the aggregation process, which can be controlled
2107     * by the {@link #AGGREGATION_MODE} field and {@link AggregationExceptions}.</td>
2108     * </tr>
2109     * <tr>
2110     * <td>int</td>
2111     * <td>{@link #AGGREGATION_MODE}</td>
2112     * <td>read/write</td>
2113     * <td>A mechanism that allows programmatic control of the aggregation process. The allowed
2114     * values are {@link #AGGREGATION_MODE_DEFAULT}, {@link #AGGREGATION_MODE_DISABLED}
2115     * and {@link #AGGREGATION_MODE_SUSPENDED}. See also {@link AggregationExceptions}.</td>
2116     * </tr>
2117     * <tr>
2118     * <td>int</td>
2119     * <td>{@link #DELETED}</td>
2120     * <td>read/write</td>
2121     * <td>The "deleted" flag: "0" by default, "1" if the row has been marked
2122     * for deletion. When {@link android.content.ContentResolver#delete} is
2123     * called on a raw contact, it is marked for deletion and removed from its
2124     * aggregate contact. The sync adaptor deletes the raw contact on the server and
2125     * then calls ContactResolver.delete once more, this time passing the
2126     * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
2127     * the data removal.</td>
2128     * </tr>
2129     * <tr>
2130     * <td>int</td>
2131     * <td>{@link #TIMES_CONTACTED}</td>
2132     * <td>read/write</td>
2133     * <td>The number of times the contact has been contacted. To have an effect
2134     * on the corresponding value of the aggregate contact, this field
2135     * should be set at the time the raw contact is inserted.
2136     * After that, this value is typically updated via
2137     * {@link ContactsContract.Contacts#markAsContacted}.</td>
2138     * </tr>
2139     * <tr>
2140     * <td>long</td>
2141     * <td>{@link #LAST_TIME_CONTACTED}</td>
2142     * <td>read/write</td>
2143     * <td>The timestamp of the last time the contact was contacted. To have an effect
2144     * on the corresponding value of the aggregate contact, this field
2145     * should be set at the time the raw contact is inserted.
2146     * After that, this value is typically updated via
2147     * {@link ContactsContract.Contacts#markAsContacted}.
2148     * </td>
2149     * </tr>
2150     * <tr>
2151     * <td>int</td>
2152     * <td>{@link #STARRED}</td>
2153     * <td>read/write</td>
2154     * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
2155     * Changing this field immediately affects the corresponding aggregate contact:
2156     * if any raw contacts in that aggregate contact are starred, then the contact
2157     * itself is marked as starred.</td>
2158     * </tr>
2159     * <tr>
2160     * <td>String</td>
2161     * <td>{@link #CUSTOM_RINGTONE}</td>
2162     * <td>read/write</td>
2163     * <td>A custom ringtone associated with a raw contact. Typically this is the
2164     * URI returned by an activity launched with the
2165     * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.
2166     * To have an effect on the corresponding value of the aggregate contact, this field
2167     * should be set at the time the raw contact is inserted. To set a custom
2168     * ringtone on a contact, use the field {@link ContactsContract.Contacts#CUSTOM_RINGTONE
2169     * Contacts.CUSTOM_RINGTONE}
2170     * instead.</td>
2171     * </tr>
2172     * <tr>
2173     * <td>int</td>
2174     * <td>{@link #SEND_TO_VOICEMAIL}</td>
2175     * <td>read/write</td>
2176     * <td>An indicator of whether calls from this raw contact should be forwarded
2177     * directly to voice mail ('1') or not ('0'). To have an effect
2178     * on the corresponding value of the aggregate contact, this field
2179     * should be set at the time the raw contact is inserted.</td>
2180     * </tr>
2181     * <tr>
2182     * <td>String</td>
2183     * <td>{@link #ACCOUNT_NAME}</td>
2184     * <td>read/write-once</td>
2185     * <td>The name of the account instance to which this row belongs, which when paired with
2186     * {@link #ACCOUNT_TYPE} identifies a specific account.
2187     * For example, this will be the Gmail address if it is a Google account.
2188     * It should be set at the time
2189     * the raw contact is inserted and never changed afterwards.</td>
2190     * </tr>
2191     * <tr>
2192     * <td>String</td>
2193     * <td>{@link #ACCOUNT_TYPE}</td>
2194     * <td>read/write-once</td>
2195     * <td>
2196     * <p>
2197     * The type of account to which this row belongs, which when paired with
2198     * {@link #ACCOUNT_NAME} identifies a specific account.
2199     * It should be set at the time
2200     * the raw contact is inserted and never changed afterwards.
2201     * </p>
2202     * <p>
2203     * To ensure uniqueness, new account types should be chosen according to the
2204     * Java package naming convention.  Thus a Google account is of type "com.google".
2205     * </p>
2206     * </td>
2207     * </tr>
2208     * <tr>
2209     * <td>String</td>
2210     * <td>{@link #SOURCE_ID}</td>
2211     * <td>read/write</td>
2212     * <td>String that uniquely identifies this row to its source account.
2213     * Typically it is set at the time the raw contact is inserted and never
2214     * changed afterwards. The one notable exception is a new raw contact: it
2215     * will have an account name and type, but no source id. This
2216     * indicates to the sync adapter that a new contact needs to be created
2217     * server-side and its ID stored in the corresponding SOURCE_ID field on
2218     * the phone.
2219     * </td>
2220     * </tr>
2221     * <tr>
2222     * <td>int</td>
2223     * <td>{@link #VERSION}</td>
2224     * <td>read-only</td>
2225     * <td>Version number that is updated whenever this row or its related data
2226     * changes. This field can be used for optimistic locking of a raw contact.
2227     * </td>
2228     * </tr>
2229     * <tr>
2230     * <td>int</td>
2231     * <td>{@link #DIRTY}</td>
2232     * <td>read/write</td>
2233     * <td>Flag indicating that {@link #VERSION} has changed, and this row needs
2234     * to be synchronized by its owning account.  The value is set to "1" automatically
2235     * whenever the raw contact changes, unless the URI has the
2236     * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter specified.
2237     * The sync adapter should always supply this query parameter to prevent
2238     * unnecessary synchronization: user changes some data on the server,
2239     * the sync adapter updates the contact on the phone (without the
2240     * CALLER_IS_SYNCADAPTER flag) flag, which sets the DIRTY flag,
2241     * which triggers a sync to bring the changes to the server.
2242     * </td>
2243     * </tr>
2244     * <tr>
2245     * <td>String</td>
2246     * <td>{@link #SYNC1}</td>
2247     * <td>read/write</td>
2248     * <td>Generic column provided for arbitrary use by sync adapters.
2249     * The content provider
2250     * stores this information on behalf of the sync adapter but does not
2251     * interpret it in any way.
2252     * </td>
2253     * </tr>
2254     * <tr>
2255     * <td>String</td>
2256     * <td>{@link #SYNC2}</td>
2257     * <td>read/write</td>
2258     * <td>Generic column for use by sync adapters.
2259     * </td>
2260     * </tr>
2261     * <tr>
2262     * <td>String</td>
2263     * <td>{@link #SYNC3}</td>
2264     * <td>read/write</td>
2265     * <td>Generic column for use by sync adapters.
2266     * </td>
2267     * </tr>
2268     * <tr>
2269     * <td>String</td>
2270     * <td>{@link #SYNC4}</td>
2271     * <td>read/write</td>
2272     * <td>Generic column for use by sync adapters.
2273     * </td>
2274     * </tr>
2275     * </table>
2276     */
2277    public static final class RawContacts implements BaseColumns, RawContactsColumns,
2278            ContactOptionsColumns, ContactNameColumns, SyncColumns  {
2279        /**
2280         * This utility class cannot be instantiated
2281         */
2282        private RawContacts() {
2283        }
2284
2285        /**
2286         * The content:// style URI for this table, which requests a directory of
2287         * raw contact rows matching the selection criteria.
2288         */
2289        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts");
2290
2291        /**
2292         * The MIME type of the results from {@link #CONTENT_URI} when a specific
2293         * ID value is not provided, and multiple raw contacts may be returned.
2294         */
2295        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact";
2296
2297        /**
2298         * The MIME type of the results when a raw contact ID is appended to {@link #CONTENT_URI},
2299         * yielding a subdirectory of a single person.
2300         */
2301        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
2302
2303        /**
2304         * Aggregation mode: aggregate immediately after insert or update operation(s) are complete.
2305         */
2306        public static final int AGGREGATION_MODE_DEFAULT = 0;
2307
2308        /**
2309         * Aggregation mode: aggregate at the time the raw contact is inserted/updated.
2310         * @deprecated Aggregation is synchronous, this historic value is a no-op
2311         */
2312        @Deprecated
2313        public static final int AGGREGATION_MODE_IMMEDIATE = 1;
2314
2315        /**
2316         * <p>
2317         * Aggregation mode: aggregation suspended temporarily, and is likely to be resumed later.
2318         * Changes to the raw contact will update the associated aggregate contact but will not
2319         * result in any change in how the contact is aggregated. Similar to
2320         * {@link #AGGREGATION_MODE_DISABLED}, but maintains a link to the corresponding
2321         * {@link Contacts} aggregate.
2322         * </p>
2323         * <p>
2324         * This can be used to postpone aggregation until after a series of updates, for better
2325         * performance and/or user experience.
2326         * </p>
2327         * <p>
2328         * Note that changing
2329         * {@link #AGGREGATION_MODE} from {@link #AGGREGATION_MODE_SUSPENDED} to
2330         * {@link #AGGREGATION_MODE_DEFAULT} does not trigger an aggregation pass, but any
2331         * subsequent
2332         * change to the raw contact's data will.
2333         * </p>
2334         */
2335        public static final int AGGREGATION_MODE_SUSPENDED = 2;
2336
2337        /**
2338         * <p>
2339         * Aggregation mode: never aggregate this raw contact.  The raw contact will not
2340         * have a corresponding {@link Contacts} aggregate and therefore will not be included in
2341         * {@link Contacts} query results.
2342         * </p>
2343         * <p>
2344         * For example, this mode can be used for a raw contact that is marked for deletion while
2345         * waiting for the deletion to occur on the server side.
2346         * </p>
2347         *
2348         * @see #AGGREGATION_MODE_SUSPENDED
2349         */
2350        public static final int AGGREGATION_MODE_DISABLED = 3;
2351
2352        /**
2353         * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
2354         * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
2355         * entry of the given {@link RawContacts} entry.
2356         */
2357        public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) {
2358            // TODO: use a lighter query by joining rawcontacts with contacts in provider
2359            final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY);
2360            final Cursor cursor = resolver.query(dataUri, new String[] {
2361                    RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY
2362            }, null, null, null);
2363
2364            Uri lookupUri = null;
2365            try {
2366                if (cursor != null && cursor.moveToFirst()) {
2367                    final long contactId = cursor.getLong(0);
2368                    final String lookupKey = cursor.getString(1);
2369                    return Contacts.getLookupUri(contactId, lookupKey);
2370                }
2371            } finally {
2372                if (cursor != null) cursor.close();
2373            }
2374            return lookupUri;
2375        }
2376
2377        /**
2378         * A sub-directory of a single raw contact that contains all of its
2379         * {@link ContactsContract.Data} rows. To access this directory
2380         * append {@link Data#CONTENT_DIRECTORY} to the raw contact URI.
2381         */
2382        public static final class Data implements BaseColumns, DataColumns {
2383            /**
2384             * no public constructor since this is a utility class
2385             */
2386            private Data() {
2387            }
2388
2389            /**
2390             * The directory twig for this sub-table
2391             */
2392            public static final String CONTENT_DIRECTORY = "data";
2393        }
2394
2395        /**
2396         * <p>
2397         * A sub-directory of a single raw contact that contains all of its
2398         * {@link ContactsContract.Data} rows. To access this directory append
2399         * {@link RawContacts.Entity#CONTENT_DIRECTORY} to the raw contact URI. See
2400         * {@link RawContactsEntity} for a stand-alone table containing the same
2401         * data.
2402         * </p>
2403         * <p>
2404         * Entity has two ID fields: {@link #_ID} for the raw contact
2405         * and {@link #DATA_ID} for the data rows.
2406         * Entity always contains at least one row, even if there are no
2407         * actual data rows. In this case the {@link #DATA_ID} field will be
2408         * null.
2409         * </p>
2410         * <p>
2411         * Using Entity should be preferred to using two separate queries:
2412         * RawContacts followed by Data. The reason is that Entity reads all
2413         * data for a raw contact in one transaction, so there is no possibility
2414         * of the data changing between the two queries.
2415         */
2416        public static final class Entity implements BaseColumns, DataColumns {
2417            /**
2418             * no public constructor since this is a utility class
2419             */
2420            private Entity() {
2421            }
2422
2423            /**
2424             * The directory twig for this sub-table
2425             */
2426            public static final String CONTENT_DIRECTORY = "entity";
2427
2428            /**
2429             * The ID of the data row. The value will be null if this raw contact has no
2430             * data rows.
2431             * <P>Type: INTEGER</P>
2432             */
2433            public static final String DATA_ID = "data_id";
2434        }
2435
2436        /**
2437         * TODO: javadoc
2438         * @param cursor
2439         * @return
2440         */
2441        public static EntityIterator newEntityIterator(Cursor cursor) {
2442            return new EntityIteratorImpl(cursor);
2443        }
2444
2445        private static class EntityIteratorImpl extends CursorEntityIterator {
2446            private static final String[] DATA_KEYS = new String[]{
2447                    Data.DATA1,
2448                    Data.DATA2,
2449                    Data.DATA3,
2450                    Data.DATA4,
2451                    Data.DATA5,
2452                    Data.DATA6,
2453                    Data.DATA7,
2454                    Data.DATA8,
2455                    Data.DATA9,
2456                    Data.DATA10,
2457                    Data.DATA11,
2458                    Data.DATA12,
2459                    Data.DATA13,
2460                    Data.DATA14,
2461                    Data.DATA15,
2462                    Data.SYNC1,
2463                    Data.SYNC2,
2464                    Data.SYNC3,
2465                    Data.SYNC4};
2466
2467            public EntityIteratorImpl(Cursor cursor) {
2468                super(cursor);
2469            }
2470
2471            @Override
2472            public android.content.Entity getEntityAndIncrementCursor(Cursor cursor)
2473                    throws RemoteException {
2474                final int columnRawContactId = cursor.getColumnIndexOrThrow(RawContacts._ID);
2475                final long rawContactId = cursor.getLong(columnRawContactId);
2476
2477                // we expect the cursor is already at the row we need to read from
2478                ContentValues cv = new ContentValues();
2479                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_NAME);
2480                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_TYPE);
2481                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, _ID);
2482                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY);
2483                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, VERSION);
2484                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SOURCE_ID);
2485                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC1);
2486                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC2);
2487                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC3);
2488                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, SYNC4);
2489                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED);
2490                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID);
2491                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED);
2492                DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED);
2493                DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED);
2494                android.content.Entity contact = new android.content.Entity(cv);
2495
2496                // read data rows until the contact id changes
2497                do {
2498                    if (rawContactId != cursor.getLong(columnRawContactId)) {
2499                        break;
2500                    }
2501                    // add the data to to the contact
2502                    cv = new ContentValues();
2503                    cv.put(Data._ID, cursor.getLong(cursor.getColumnIndexOrThrow(Entity.DATA_ID)));
2504                    DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
2505                            Data.RES_PACKAGE);
2506                    DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Data.MIMETYPE);
2507                    DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.IS_PRIMARY);
2508                    DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv,
2509                            Data.IS_SUPER_PRIMARY);
2510                    DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, Data.DATA_VERSION);
2511                    DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
2512                            CommonDataKinds.GroupMembership.GROUP_SOURCE_ID);
2513                    DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
2514                            Data.DATA_VERSION);
2515                    for (String key : DATA_KEYS) {
2516                        final int columnIndex = cursor.getColumnIndexOrThrow(key);
2517                        switch (cursor.getType(columnIndex)) {
2518                            case Cursor.FIELD_TYPE_NULL:
2519                                // don't put anything
2520                                break;
2521                            case Cursor.FIELD_TYPE_INTEGER:
2522                            case Cursor.FIELD_TYPE_FLOAT:
2523                            case Cursor.FIELD_TYPE_STRING:
2524                                cv.put(key, cursor.getString(columnIndex));
2525                                break;
2526                            case Cursor.FIELD_TYPE_BLOB:
2527                                cv.put(key, cursor.getBlob(columnIndex));
2528                                break;
2529                            default:
2530                                throw new IllegalStateException("Invalid or unhandled data type");
2531                        }
2532                    }
2533                    contact.addSubValue(ContactsContract.Data.CONTENT_URI, cv);
2534                } while (cursor.moveToNext());
2535
2536                return contact;
2537            }
2538
2539        }
2540    }
2541
2542    /**
2543     * Social status update columns.
2544     *
2545     * @see StatusUpdates
2546     * @see ContactsContract.Data
2547     */
2548    protected interface StatusColumns {
2549        /**
2550         * Contact's latest presence level.
2551         * <P>Type: INTEGER (one of the values below)</P>
2552         */
2553        public static final String PRESENCE = "mode";
2554
2555        /**
2556         * @deprecated use {@link #PRESENCE}
2557         */
2558        @Deprecated
2559        public static final String PRESENCE_STATUS = PRESENCE;
2560
2561        /**
2562         * An allowed value of {@link #PRESENCE}.
2563         */
2564        int OFFLINE = 0;
2565
2566        /**
2567         * An allowed value of {@link #PRESENCE}.
2568         */
2569        int INVISIBLE = 1;
2570
2571        /**
2572         * An allowed value of {@link #PRESENCE}.
2573         */
2574        int AWAY = 2;
2575
2576        /**
2577         * An allowed value of {@link #PRESENCE}.
2578         */
2579        int IDLE = 3;
2580
2581        /**
2582         * An allowed value of {@link #PRESENCE}.
2583         */
2584        int DO_NOT_DISTURB = 4;
2585
2586        /**
2587         * An allowed value of {@link #PRESENCE}.
2588         */
2589        int AVAILABLE = 5;
2590
2591        /**
2592         * Contact latest status update.
2593         * <p>Type: TEXT</p>
2594         */
2595        public static final String STATUS = "status";
2596
2597        /**
2598         * @deprecated use {@link #STATUS}
2599         */
2600        @Deprecated
2601        public static final String PRESENCE_CUSTOM_STATUS = STATUS;
2602
2603        /**
2604         * The absolute time in milliseconds when the latest status was inserted/updated.
2605         * <p>Type: NUMBER</p>
2606         */
2607        public static final String STATUS_TIMESTAMP = "status_ts";
2608
2609        /**
2610         * The package containing resources for this status: label and icon.
2611         * <p>Type: NUMBER</p>
2612         */
2613        public static final String STATUS_RES_PACKAGE = "status_res_package";
2614
2615        /**
2616         * The resource ID of the label describing the source of the status update, e.g. "Google
2617         * Talk".  This resource should be scoped by the {@link #STATUS_RES_PACKAGE}.
2618         * <p>Type: NUMBER</p>
2619         */
2620        public static final String STATUS_LABEL = "status_label";
2621
2622        /**
2623         * The resource ID of the icon for the source of the status update.
2624         * This resource should be scoped by the {@link #STATUS_RES_PACKAGE}.
2625         * <p>Type: NUMBER</p>
2626         */
2627        public static final String STATUS_ICON = "status_icon";
2628
2629        /**
2630         * Contact's audio/video chat capability level.
2631         * <P>Type: INTEGER (one of the values below)</P>
2632         */
2633        public static final String CHAT_CAPABILITY = "chat_capability";
2634
2635        /**
2636         * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates audio-chat capability (microphone
2637         * and speaker)
2638         */
2639        public static final int CAPABILITY_HAS_VOICE = 1;
2640
2641        /**
2642         * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device can
2643         * display a video feed.
2644         */
2645        public static final int CAPABILITY_HAS_VIDEO = 2;
2646
2647        /**
2648         * An allowed flag of {@link #CHAT_CAPABILITY}. Indicates that the contact's device has a
2649         * camera that can be used for video chat (e.g. a front-facing camera on a phone).
2650         */
2651        public static final int CAPABILITY_HAS_CAMERA = 4;
2652    }
2653
2654    /**
2655     * Columns in the Data table.
2656     *
2657     * @see ContactsContract.Data
2658     */
2659    protected interface DataColumns {
2660        /**
2661         * The package name to use when creating {@link Resources} objects for
2662         * this data row. This value is only designed for use when building user
2663         * interfaces, and should not be used to infer the owner.
2664         *
2665         * @hide
2666         */
2667        public static final String RES_PACKAGE = "res_package";
2668
2669        /**
2670         * The MIME type of the item represented by this row.
2671         */
2672        public static final String MIMETYPE = "mimetype";
2673
2674        /**
2675         * A reference to the {@link RawContacts#_ID}
2676         * that this data belongs to.
2677         */
2678        public static final String RAW_CONTACT_ID = "raw_contact_id";
2679
2680        /**
2681         * Whether this is the primary entry of its kind for the raw contact it belongs to.
2682         * <P>Type: INTEGER (if set, non-0 means true)</P>
2683         */
2684        public static final String IS_PRIMARY = "is_primary";
2685
2686        /**
2687         * Whether this is the primary entry of its kind for the aggregate
2688         * contact it belongs to. Any data record that is "super primary" must
2689         * also be "primary".
2690         * <P>Type: INTEGER (if set, non-0 means true)</P>
2691         */
2692        public static final String IS_SUPER_PRIMARY = "is_super_primary";
2693
2694        /**
2695         * The "read-only" flag: "0" by default, "1" if the row cannot be modified or
2696         * deleted except by a sync adapter.  See {@link ContactsContract#CALLER_IS_SYNCADAPTER}.
2697         * <P>Type: INTEGER</P>
2698         */
2699        public static final String IS_READ_ONLY = "is_read_only";
2700
2701        /**
2702         * The version of this data record. This is a read-only value. The data column is
2703         * guaranteed to not change without the version going up. This value is monotonically
2704         * increasing.
2705         * <P>Type: INTEGER</P>
2706         */
2707        public static final String DATA_VERSION = "data_version";
2708
2709        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2710        public static final String DATA1 = "data1";
2711        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2712        public static final String DATA2 = "data2";
2713        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2714        public static final String DATA3 = "data3";
2715        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2716        public static final String DATA4 = "data4";
2717        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2718        public static final String DATA5 = "data5";
2719        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2720        public static final String DATA6 = "data6";
2721        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2722        public static final String DATA7 = "data7";
2723        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2724        public static final String DATA8 = "data8";
2725        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2726        public static final String DATA9 = "data9";
2727        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2728        public static final String DATA10 = "data10";
2729        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2730        public static final String DATA11 = "data11";
2731        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2732        public static final String DATA12 = "data12";
2733        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2734        public static final String DATA13 = "data13";
2735        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
2736        public static final String DATA14 = "data14";
2737        /**
2738         * Generic data column, the meaning is {@link #MIMETYPE} specific. By convention,
2739         * this field is used to store BLOBs (binary data).
2740         */
2741        public static final String DATA15 = "data15";
2742
2743        /** Generic column for use by sync adapters. */
2744        public static final String SYNC1 = "data_sync1";
2745        /** Generic column for use by sync adapters. */
2746        public static final String SYNC2 = "data_sync2";
2747        /** Generic column for use by sync adapters. */
2748        public static final String SYNC3 = "data_sync3";
2749        /** Generic column for use by sync adapters. */
2750        public static final String SYNC4 = "data_sync4";
2751    }
2752
2753    /**
2754     * Combines all columns returned by {@link ContactsContract.Data} table queries.
2755     *
2756     * @see ContactsContract.Data
2757     */
2758    protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
2759            RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns,
2760            ContactStatusColumns {
2761    }
2762
2763    /**
2764     * <p>
2765     * Constants for the data table, which contains data points tied to a raw
2766     * contact.  Each row of the data table is typically used to store a single
2767     * piece of contact
2768     * information (such as a phone number) and its
2769     * associated metadata (such as whether it is a work or home number).
2770     * </p>
2771     * <h3>Data kinds</h3>
2772     * <p>
2773     * Data is a generic table that can hold any kind of contact data.
2774     * The kind of data stored in a given row is specified by the row's
2775     * {@link #MIMETYPE} value, which determines the meaning of the
2776     * generic columns {@link #DATA1} through
2777     * {@link #DATA15}.
2778     * For example, if the data kind is
2779     * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then the column
2780     * {@link #DATA1} stores the
2781     * phone number, but if the data kind is
2782     * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then {@link #DATA1}
2783     * stores the email address.
2784     * Sync adapters and applications can introduce their own data kinds.
2785     * </p>
2786     * <p>
2787     * ContactsContract defines a small number of pre-defined data kinds, e.g.
2788     * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a
2789     * convenience, these classes define data kind specific aliases for DATA1 etc.
2790     * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as
2791     * {@link ContactsContract.Data Data.DATA1}.
2792     * </p>
2793     * <p>
2794     * {@link #DATA1} is an indexed column and should be used for the data element that is
2795     * expected to be most frequently used in query selections. For example, in the
2796     * case of a row representing email addresses {@link #DATA1} should probably
2797     * be used for the email address itself, while {@link #DATA2} etc can be
2798     * used for auxiliary information like type of email address.
2799     * <p>
2800     * <p>
2801     * By convention, {@link #DATA15} is used for storing BLOBs (binary data).
2802     * </p>
2803     * <p>
2804     * The sync adapter for a given account type must correctly handle every data type
2805     * used in the corresponding raw contacts.  Otherwise it could result in lost or
2806     * corrupted data.
2807     * </p>
2808     * <p>
2809     * Similarly, you should refrain from introducing new kinds of data for an other
2810     * party's account types. For example, if you add a data row for
2811     * "favorite song" to a raw contact owned by a Google account, it will not
2812     * get synced to the server, because the Google sync adapter does not know
2813     * how to handle this data kind. Thus new data kinds are typically
2814     * introduced along with new account types, i.e. new sync adapters.
2815     * </p>
2816     * <h3>Batch operations</h3>
2817     * <p>
2818     * Data rows can be inserted/updated/deleted using the traditional
2819     * {@link ContentResolver#insert}, {@link ContentResolver#update} and
2820     * {@link ContentResolver#delete} methods, however the newer mechanism based
2821     * on a batch of {@link ContentProviderOperation} will prove to be a better
2822     * choice in almost all cases. All operations in a batch are executed in a
2823     * single transaction, which ensures that the phone-side and server-side
2824     * state of a raw contact are always consistent. Also, the batch-based
2825     * approach is far more efficient: not only are the database operations
2826     * faster when executed in a single transaction, but also sending a batch of
2827     * commands to the content provider saves a lot of time on context switching
2828     * between your process and the process in which the content provider runs.
2829     * </p>
2830     * <p>
2831     * The flip side of using batched operations is that a large batch may lock
2832     * up the database for a long time preventing other applications from
2833     * accessing data and potentially causing ANRs ("Application Not Responding"
2834     * dialogs.)
2835     * </p>
2836     * <p>
2837     * To avoid such lockups of the database, make sure to insert "yield points"
2838     * in the batch. A yield point indicates to the content provider that before
2839     * executing the next operation it can commit the changes that have already
2840     * been made, yield to other requests, open another transaction and continue
2841     * processing operations. A yield point will not automatically commit the
2842     * transaction, but only if there is another request waiting on the
2843     * database. Normally a sync adapter should insert a yield point at the
2844     * beginning of each raw contact operation sequence in the batch. See
2845     * {@link ContentProviderOperation.Builder#withYieldAllowed(boolean)}.
2846     * </p>
2847     * <h3>Operations</h3>
2848     * <dl>
2849     * <dt><b>Insert</b></dt>
2850     * <dd>
2851     * <p>
2852     * An individual data row can be inserted using the traditional
2853     * {@link ContentResolver#insert(Uri, ContentValues)} method. Multiple rows
2854     * should always be inserted as a batch.
2855     * </p>
2856     * <p>
2857     * An example of a traditional insert:
2858     * <pre>
2859     * ContentValues values = new ContentValues();
2860     * values.put(Data.RAW_CONTACT_ID, rawContactId);
2861     * values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
2862     * values.put(Phone.NUMBER, "1-800-GOOG-411");
2863     * values.put(Phone.TYPE, Phone.TYPE_CUSTOM);
2864     * values.put(Phone.LABEL, "free directory assistance");
2865     * Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values);
2866     * </pre>
2867     * <p>
2868     * The same done using ContentProviderOperations:
2869     * <pre>
2870     * ArrayList&lt;ContentProviderOperation&gt; ops =
2871     *          new ArrayList&lt;ContentProviderOperation&gt;();
2872     *
2873     * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
2874     *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
2875     *          .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
2876     *          .withValue(Phone.NUMBER, "1-800-GOOG-411")
2877     *          .withValue(Phone.TYPE, Phone.TYPE_CUSTOM)
2878     *          .withValue(Phone.LABEL, "free directory assistance")
2879     *          .build());
2880     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
2881     * </pre>
2882     * </p>
2883     * <dt><b>Update</b></dt>
2884     * <dd>
2885     * <p>
2886     * Just as with insert, update can be done incrementally or as a batch,
2887     * the batch mode being the preferred method:
2888     * <pre>
2889     * ArrayList&lt;ContentProviderOperation&gt; ops =
2890     *          new ArrayList&lt;ContentProviderOperation&gt;();
2891     *
2892     * ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
2893     *          .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
2894     *          .withValue(Email.DATA, "somebody@android.com")
2895     *          .build());
2896     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
2897     * </pre>
2898     * </p>
2899     * </dd>
2900     * <dt><b>Delete</b></dt>
2901     * <dd>
2902     * <p>
2903     * Just as with insert and update, deletion can be done either using the
2904     * {@link ContentResolver#delete} method or using a ContentProviderOperation:
2905     * <pre>
2906     * ArrayList&lt;ContentProviderOperation&gt; ops =
2907     *          new ArrayList&lt;ContentProviderOperation&gt;();
2908     *
2909     * ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
2910     *          .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
2911     *          .build());
2912     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
2913     * </pre>
2914     * </p>
2915     * </dd>
2916     * <dt><b>Query</b></dt>
2917     * <dd>
2918     * <p>
2919     * <dl>
2920     * <dt>Finding all Data of a given type for a given contact</dt>
2921     * <dd>
2922     * <pre>
2923     * Cursor c = getContentResolver().query(Data.CONTENT_URI,
2924     *          new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
2925     *          Data.CONTACT_ID + &quot;=?&quot; + " AND "
2926     *                  + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
2927     *          new String[] {String.valueOf(contactId)}, null);
2928     * </pre>
2929     * </p>
2930     * <p>
2931     * </dd>
2932     * <dt>Finding all Data of a given type for a given raw contact</dt>
2933     * <dd>
2934     * <pre>
2935     * Cursor c = getContentResolver().query(Data.CONTENT_URI,
2936     *          new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
2937     *          Data.RAW_CONTACT_ID + &quot;=?&quot; + " AND "
2938     *                  + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
2939     *          new String[] {String.valueOf(rawContactId)}, null);
2940     * </pre>
2941     * </dd>
2942     * <dt>Finding all Data for a given raw contact</dt>
2943     * <dd>
2944     * Most sync adapters will want to read all data rows for a raw contact
2945     * along with the raw contact itself.  For that you should use the
2946     * {@link RawContactsEntity}. See also {@link RawContacts}.
2947     * </dd>
2948     * </dl>
2949     * </p>
2950     * </dd>
2951     * </dl>
2952     * <h2>Columns</h2>
2953     * <p>
2954     * Many columns are available via a {@link Data#CONTENT_URI} query.  For best performance you
2955     * should explicitly specify a projection to only those columns that you need.
2956     * </p>
2957     * <table class="jd-sumtable">
2958     * <tr>
2959     * <th colspan='4'>Data</th>
2960     * </tr>
2961     * <tr>
2962     * <td style="width: 7em;">long</td>
2963     * <td style="width: 20em;">{@link #_ID}</td>
2964     * <td style="width: 5em;">read-only</td>
2965     * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words,
2966     * it would be a bad idea to delete and reinsert a data row. A sync adapter should
2967     * always do an update instead.</td>
2968     * </tr>
2969     * <tr>
2970     * <td>String</td>
2971     * <td>{@link #MIMETYPE}</td>
2972     * <td>read/write-once</td>
2973     * <td>
2974     * <p>The MIME type of the item represented by this row. Examples of common
2975     * MIME types are:
2976     * <ul>
2977     * <li>{@link CommonDataKinds.StructuredName StructuredName.CONTENT_ITEM_TYPE}</li>
2978     * <li>{@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}</li>
2979     * <li>{@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}</li>
2980     * <li>{@link CommonDataKinds.Photo Photo.CONTENT_ITEM_TYPE}</li>
2981     * <li>{@link CommonDataKinds.Organization Organization.CONTENT_ITEM_TYPE}</li>
2982     * <li>{@link CommonDataKinds.Im Im.CONTENT_ITEM_TYPE}</li>
2983     * <li>{@link CommonDataKinds.Nickname Nickname.CONTENT_ITEM_TYPE}</li>
2984     * <li>{@link CommonDataKinds.Note Note.CONTENT_ITEM_TYPE}</li>
2985     * <li>{@link CommonDataKinds.StructuredPostal StructuredPostal.CONTENT_ITEM_TYPE}</li>
2986     * <li>{@link CommonDataKinds.GroupMembership GroupMembership.CONTENT_ITEM_TYPE}</li>
2987     * <li>{@link CommonDataKinds.Website Website.CONTENT_ITEM_TYPE}</li>
2988     * <li>{@link CommonDataKinds.Event Event.CONTENT_ITEM_TYPE}</li>
2989     * <li>{@link CommonDataKinds.Relation Relation.CONTENT_ITEM_TYPE}</li>
2990     * <li>{@link CommonDataKinds.SipAddress SipAddress.CONTENT_ITEM_TYPE}</li>
2991     * </ul>
2992     * </p>
2993     * </td>
2994     * </tr>
2995     * <tr>
2996     * <td>long</td>
2997     * <td>{@link #RAW_CONTACT_ID}</td>
2998     * <td>read/write-once</td>
2999     * <td>The id of the row in the {@link RawContacts} table that this data belongs to.</td>
3000     * </tr>
3001     * <tr>
3002     * <td>int</td>
3003     * <td>{@link #IS_PRIMARY}</td>
3004     * <td>read/write</td>
3005     * <td>Whether this is the primary entry of its kind for the raw contact it belongs to.
3006     * "1" if true, "0" if false.
3007     * </td>
3008     * </tr>
3009     * <tr>
3010     * <td>int</td>
3011     * <td>{@link #IS_SUPER_PRIMARY}</td>
3012     * <td>read/write</td>
3013     * <td>Whether this is the primary entry of its kind for the aggregate
3014     * contact it belongs to. Any data record that is "super primary" must
3015     * also be "primary".  For example, the super-primary entry may be
3016     * interpreted as the default contact value of its kind (for example,
3017     * the default phone number to use for the contact).</td>
3018     * </tr>
3019     * <tr>
3020     * <td>int</td>
3021     * <td>{@link #DATA_VERSION}</td>
3022     * <td>read-only</td>
3023     * <td>The version of this data record. Whenever the data row changes
3024     * the version goes up. This value is monotonically increasing.</td>
3025     * </tr>
3026     * <tr>
3027     * <td>Any type</td>
3028     * <td>
3029     * {@link #DATA1}<br>
3030     * {@link #DATA2}<br>
3031     * {@link #DATA3}<br>
3032     * {@link #DATA4}<br>
3033     * {@link #DATA5}<br>
3034     * {@link #DATA6}<br>
3035     * {@link #DATA7}<br>
3036     * {@link #DATA8}<br>
3037     * {@link #DATA9}<br>
3038     * {@link #DATA10}<br>
3039     * {@link #DATA11}<br>
3040     * {@link #DATA12}<br>
3041     * {@link #DATA13}<br>
3042     * {@link #DATA14}<br>
3043     * {@link #DATA15}
3044     * </td>
3045     * <td>read/write</td>
3046     * <td>
3047     * <p>
3048     * Generic data columns.  The meaning of each column is determined by the
3049     * {@link #MIMETYPE}.  By convention, {@link #DATA15} is used for storing
3050     * BLOBs (binary data).
3051     * </p>
3052     * <p>
3053     * Data columns whose meaning is not explicitly defined for a given MIMETYPE
3054     * should not be used.  There is no guarantee that any sync adapter will
3055     * preserve them.  Sync adapters themselves should not use such columns either,
3056     * but should instead use {@link #SYNC1}-{@link #SYNC4}.
3057     * </p>
3058     * </td>
3059     * </tr>
3060     * <tr>
3061     * <td>Any type</td>
3062     * <td>
3063     * {@link #SYNC1}<br>
3064     * {@link #SYNC2}<br>
3065     * {@link #SYNC3}<br>
3066     * {@link #SYNC4}
3067     * </td>
3068     * <td>read/write</td>
3069     * <td>Generic columns for use by sync adapters. For example, a Photo row
3070     * may store the image URL in SYNC1, a status (not loaded, loading, loaded, error)
3071     * in SYNC2, server-side version number in SYNC3 and error code in SYNC4.</td>
3072     * </tr>
3073     * </table>
3074     *
3075     * <p>
3076     * Some columns from the most recent associated status update are also available
3077     * through an implicit join.
3078     * </p>
3079     * <table class="jd-sumtable">
3080     * <tr>
3081     * <th colspan='4'>Join with {@link StatusUpdates}</th>
3082     * </tr>
3083     * <tr>
3084     * <td style="width: 7em;">int</td>
3085     * <td style="width: 20em;">{@link #PRESENCE}</td>
3086     * <td style="width: 5em;">read-only</td>
3087     * <td>IM presence status linked to this data row. Compare with
3088     * {@link #CONTACT_PRESENCE}, which contains the contact's presence across
3089     * all IM rows. See {@link StatusUpdates} for individual status definitions.
3090     * The provider may choose not to store this value
3091     * in persistent storage. The expectation is that presence status will be
3092     * updated on a regular basic.
3093     * </td>
3094     * </tr>
3095     * <tr>
3096     * <td>String</td>
3097     * <td>{@link #STATUS}</td>
3098     * <td>read-only</td>
3099     * <td>Latest status update linked with this data row.</td>
3100     * </tr>
3101     * <tr>
3102     * <td>long</td>
3103     * <td>{@link #STATUS_TIMESTAMP}</td>
3104     * <td>read-only</td>
3105     * <td>The absolute time in milliseconds when the latest status was
3106     * inserted/updated for this data row.</td>
3107     * </tr>
3108     * <tr>
3109     * <td>String</td>
3110     * <td>{@link #STATUS_RES_PACKAGE}</td>
3111     * <td>read-only</td>
3112     * <td>The package containing resources for this status: label and icon.</td>
3113     * </tr>
3114     * <tr>
3115     * <td>long</td>
3116     * <td>{@link #STATUS_LABEL}</td>
3117     * <td>read-only</td>
3118     * <td>The resource ID of the label describing the source of status update linked
3119     * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
3120     * </tr>
3121     * <tr>
3122     * <td>long</td>
3123     * <td>{@link #STATUS_ICON}</td>
3124     * <td>read-only</td>
3125     * <td>The resource ID of the icon for the source of the status update linked
3126     * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
3127     * </tr>
3128     * </table>
3129     *
3130     * <p>
3131     * Some columns from the associated raw contact are also available through an
3132     * implicit join.  The other columns are excluded as uninteresting in this
3133     * context.
3134     * </p>
3135     *
3136     * <table class="jd-sumtable">
3137     * <tr>
3138     * <th colspan='4'>Join with {@link ContactsContract.RawContacts}</th>
3139     * </tr>
3140     * <tr>
3141     * <td style="width: 7em;">long</td>
3142     * <td style="width: 20em;">{@link #CONTACT_ID}</td>
3143     * <td style="width: 5em;">read-only</td>
3144     * <td>The id of the row in the {@link Contacts} table that this data belongs
3145     * to.</td>
3146     * </tr>
3147     * <tr>
3148     * <td>int</td>
3149     * <td>{@link #AGGREGATION_MODE}</td>
3150     * <td>read-only</td>
3151     * <td>See {@link RawContacts}.</td>
3152     * </tr>
3153     * <tr>
3154     * <td>int</td>
3155     * <td>{@link #DELETED}</td>
3156     * <td>read-only</td>
3157     * <td>See {@link RawContacts}.</td>
3158     * </tr>
3159     * </table>
3160     *
3161     * <p>
3162     * The ID column for the associated aggregated contact table
3163     * {@link ContactsContract.Contacts} is available
3164     * via the implicit join to the {@link RawContacts} table, see above.
3165     * The remaining columns from this table are also
3166     * available, through an implicit join.  This
3167     * facilitates lookup by
3168     * the value of a single data element, such as the email address.
3169     * </p>
3170     *
3171     * <table class="jd-sumtable">
3172     * <tr>
3173     * <th colspan='4'>Join with {@link ContactsContract.Contacts}</th>
3174     * </tr>
3175     * <tr>
3176     * <td style="width: 7em;">String</td>
3177     * <td style="width: 20em;">{@link #LOOKUP_KEY}</td>
3178     * <td style="width: 5em;">read-only</td>
3179     * <td>See {@link ContactsContract.Contacts}</td>
3180     * </tr>
3181     * <tr>
3182     * <td>String</td>
3183     * <td>{@link #DISPLAY_NAME}</td>
3184     * <td>read-only</td>
3185     * <td>See {@link ContactsContract.Contacts}</td>
3186     * </tr>
3187     * <tr>
3188     * <td>long</td>
3189     * <td>{@link #PHOTO_ID}</td>
3190     * <td>read-only</td>
3191     * <td>See {@link ContactsContract.Contacts}.</td>
3192     * </tr>
3193     * <tr>
3194     * <td>int</td>
3195     * <td>{@link #IN_VISIBLE_GROUP}</td>
3196     * <td>read-only</td>
3197     * <td>See {@link ContactsContract.Contacts}.</td>
3198     * </tr>
3199     * <tr>
3200     * <td>int</td>
3201     * <td>{@link #HAS_PHONE_NUMBER}</td>
3202     * <td>read-only</td>
3203     * <td>See {@link ContactsContract.Contacts}.</td>
3204     * </tr>
3205     * <tr>
3206     * <td>int</td>
3207     * <td>{@link #TIMES_CONTACTED}</td>
3208     * <td>read-only</td>
3209     * <td>See {@link ContactsContract.Contacts}.</td>
3210     * </tr>
3211     * <tr>
3212     * <td>long</td>
3213     * <td>{@link #LAST_TIME_CONTACTED}</td>
3214     * <td>read-only</td>
3215     * <td>See {@link ContactsContract.Contacts}.</td>
3216     * </tr>
3217     * <tr>
3218     * <td>int</td>
3219     * <td>{@link #STARRED}</td>
3220     * <td>read-only</td>
3221     * <td>See {@link ContactsContract.Contacts}.</td>
3222     * </tr>
3223     * <tr>
3224     * <td>String</td>
3225     * <td>{@link #CUSTOM_RINGTONE}</td>
3226     * <td>read-only</td>
3227     * <td>See {@link ContactsContract.Contacts}.</td>
3228     * </tr>
3229     * <tr>
3230     * <td>int</td>
3231     * <td>{@link #SEND_TO_VOICEMAIL}</td>
3232     * <td>read-only</td>
3233     * <td>See {@link ContactsContract.Contacts}.</td>
3234     * </tr>
3235     * <tr>
3236     * <td>int</td>
3237     * <td>{@link #CONTACT_PRESENCE}</td>
3238     * <td>read-only</td>
3239     * <td>See {@link ContactsContract.Contacts}.</td>
3240     * </tr>
3241     * <tr>
3242     * <td>String</td>
3243     * <td>{@link #CONTACT_STATUS}</td>
3244     * <td>read-only</td>
3245     * <td>See {@link ContactsContract.Contacts}.</td>
3246     * </tr>
3247     * <tr>
3248     * <td>long</td>
3249     * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td>
3250     * <td>read-only</td>
3251     * <td>See {@link ContactsContract.Contacts}.</td>
3252     * </tr>
3253     * <tr>
3254     * <td>String</td>
3255     * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td>
3256     * <td>read-only</td>
3257     * <td>See {@link ContactsContract.Contacts}.</td>
3258     * </tr>
3259     * <tr>
3260     * <td>long</td>
3261     * <td>{@link #CONTACT_STATUS_LABEL}</td>
3262     * <td>read-only</td>
3263     * <td>See {@link ContactsContract.Contacts}.</td>
3264     * </tr>
3265     * <tr>
3266     * <td>long</td>
3267     * <td>{@link #CONTACT_STATUS_ICON}</td>
3268     * <td>read-only</td>
3269     * <td>See {@link ContactsContract.Contacts}.</td>
3270     * </tr>
3271     * </table>
3272     */
3273    public final static class Data implements DataColumnsWithJoins {
3274        /**
3275         * This utility class cannot be instantiated
3276         */
3277        private Data() {}
3278
3279        /**
3280         * The content:// style URI for this table, which requests a directory
3281         * of data rows matching the selection criteria.
3282         */
3283        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data");
3284
3285        /**
3286         * The MIME type of the results from {@link #CONTENT_URI}.
3287         */
3288        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data";
3289
3290        /**
3291         * <p>
3292         * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward
3293         * Data.CONTENT_URI contains only exportable data.
3294         * </p>
3295         * <p>
3296         * This flag is useful (currently) only for vCard exporter in Contacts app, which
3297         * needs to exclude "un-exportable" data from available data to export, while
3298         * Contacts app itself has priviledge to access all data including "un-exportable"
3299         * ones and providers return all of them regardless of the callers' intention.
3300         * </p>
3301         * <p>
3302         * Type: INTEGER
3303         * </p>
3304         *
3305         * @hide Maybe available only in Eclair and not really ready for public use.
3306         * TODO: remove, or implement this feature completely. As of now (Eclair),
3307         * we only use this flag in queryEntities(), not query().
3308         */
3309        public static final String FOR_EXPORT_ONLY = "for_export_only";
3310
3311        /**
3312         * <p>
3313         * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
3314         * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
3315         * entry of the given {@link ContactsContract.Data} entry.
3316         * </p>
3317         * <p>
3318         * Returns the Uri for the contact in the first entry returned by
3319         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
3320         * for the provided {@code dataUri}.  If the query returns null or empty
3321         * results, silently returns null.
3322         * </p>
3323         */
3324        public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) {
3325            final Cursor cursor = resolver.query(dataUri, new String[] {
3326                    RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY
3327            }, null, null, null);
3328
3329            Uri lookupUri = null;
3330            try {
3331                if (cursor != null && cursor.moveToFirst()) {
3332                    final long contactId = cursor.getLong(0);
3333                    final String lookupKey = cursor.getString(1);
3334                    return Contacts.getLookupUri(contactId, lookupKey);
3335                }
3336            } finally {
3337                if (cursor != null) cursor.close();
3338            }
3339            return lookupUri;
3340        }
3341    }
3342
3343    /**
3344     * <p>
3345     * Constants for the raw contacts entities table, which can be thought of as
3346     * an outer join of the raw_contacts table with the data table.  It is a strictly
3347     * read-only table.
3348     * </p>
3349     * <p>
3350     * If a raw contact has data rows, the RawContactsEntity cursor will contain
3351     * a one row for each data row. If the raw contact has no data rows, the
3352     * cursor will still contain one row with the raw contact-level information
3353     * and nulls for data columns.
3354     *
3355     * <pre>
3356     * Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId);
3357     * Cursor c = getContentResolver().query(entityUri,
3358     *          new String[]{
3359     *              RawContactsEntity.SOURCE_ID,
3360     *              RawContactsEntity.DATA_ID,
3361     *              RawContactsEntity.MIMETYPE,
3362     *              RawContactsEntity.DATA1
3363     *          }, null, null, null);
3364     * try {
3365     *     while (c.moveToNext()) {
3366     *         String sourceId = c.getString(0);
3367     *         if (!c.isNull(1)) {
3368     *             String mimeType = c.getString(2);
3369     *             String data = c.getString(3);
3370     *             ...
3371     *         }
3372     *     }
3373     * } finally {
3374     *     c.close();
3375     * }
3376     * </pre>
3377     *
3378     * <h3>Columns</h3>
3379     * RawContactsEntity has a combination of RawContact and Data columns.
3380     *
3381     * <table class="jd-sumtable">
3382     * <tr>
3383     * <th colspan='4'>RawContacts</th>
3384     * </tr>
3385     * <tr>
3386     * <td style="width: 7em;">long</td>
3387     * <td style="width: 20em;">{@link #_ID}</td>
3388     * <td style="width: 5em;">read-only</td>
3389     * <td>Raw contact row ID. See {@link RawContacts}.</td>
3390     * </tr>
3391     * <tr>
3392     * <td>long</td>
3393     * <td>{@link #CONTACT_ID}</td>
3394     * <td>read-only</td>
3395     * <td>See {@link RawContacts}.</td>
3396     * </tr>
3397     * <tr>
3398     * <td>int</td>
3399     * <td>{@link #AGGREGATION_MODE}</td>
3400     * <td>read-only</td>
3401     * <td>See {@link RawContacts}.</td>
3402     * </tr>
3403     * <tr>
3404     * <td>int</td>
3405     * <td>{@link #DELETED}</td>
3406     * <td>read-only</td>
3407     * <td>See {@link RawContacts}.</td>
3408     * </tr>
3409     * </table>
3410     *
3411     * <table class="jd-sumtable">
3412     * <tr>
3413     * <th colspan='4'>Data</th>
3414     * </tr>
3415     * <tr>
3416     * <td style="width: 7em;">long</td>
3417     * <td style="width: 20em;">{@link #DATA_ID}</td>
3418     * <td style="width: 5em;">read-only</td>
3419     * <td>Data row ID. It will be null if the raw contact has no data rows.</td>
3420     * </tr>
3421     * <tr>
3422     * <td>String</td>
3423     * <td>{@link #MIMETYPE}</td>
3424     * <td>read-only</td>
3425     * <td>See {@link ContactsContract.Data}.</td>
3426     * </tr>
3427     * <tr>
3428     * <td>int</td>
3429     * <td>{@link #IS_PRIMARY}</td>
3430     * <td>read-only</td>
3431     * <td>See {@link ContactsContract.Data}.</td>
3432     * </tr>
3433     * <tr>
3434     * <td>int</td>
3435     * <td>{@link #IS_SUPER_PRIMARY}</td>
3436     * <td>read-only</td>
3437     * <td>See {@link ContactsContract.Data}.</td>
3438     * </tr>
3439     * <tr>
3440     * <td>int</td>
3441     * <td>{@link #DATA_VERSION}</td>
3442     * <td>read-only</td>
3443     * <td>See {@link ContactsContract.Data}.</td>
3444     * </tr>
3445     * <tr>
3446     * <td>Any type</td>
3447     * <td>
3448     * {@link #DATA1}<br>
3449     * {@link #DATA2}<br>
3450     * {@link #DATA3}<br>
3451     * {@link #DATA4}<br>
3452     * {@link #DATA5}<br>
3453     * {@link #DATA6}<br>
3454     * {@link #DATA7}<br>
3455     * {@link #DATA8}<br>
3456     * {@link #DATA9}<br>
3457     * {@link #DATA10}<br>
3458     * {@link #DATA11}<br>
3459     * {@link #DATA12}<br>
3460     * {@link #DATA13}<br>
3461     * {@link #DATA14}<br>
3462     * {@link #DATA15}
3463     * </td>
3464     * <td>read-only</td>
3465     * <td>See {@link ContactsContract.Data}.</td>
3466     * </tr>
3467     * <tr>
3468     * <td>Any type</td>
3469     * <td>
3470     * {@link #SYNC1}<br>
3471     * {@link #SYNC2}<br>
3472     * {@link #SYNC3}<br>
3473     * {@link #SYNC4}
3474     * </td>
3475     * <td>read-only</td>
3476     * <td>See {@link ContactsContract.Data}.</td>
3477     * </tr>
3478     * </table>
3479     */
3480    public final static class RawContactsEntity
3481            implements BaseColumns, DataColumns, RawContactsColumns {
3482        /**
3483         * This utility class cannot be instantiated
3484         */
3485        private RawContactsEntity() {}
3486
3487        /**
3488         * The content:// style URI for this table
3489         */
3490        public static final Uri CONTENT_URI =
3491                Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities");
3492
3493        /**
3494         * The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities.
3495         */
3496        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity";
3497
3498        /**
3499         * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward
3500         * Data.CONTENT_URI contains only exportable data.
3501         *
3502         * This flag is useful (currently) only for vCard exporter in Contacts app, which
3503         * needs to exclude "un-exportable" data from available data to export, while
3504         * Contacts app itself has priviledge to access all data including "un-expotable"
3505         * ones and providers return all of them regardless of the callers' intention.
3506         * <P>Type: INTEGER</p>
3507         *
3508         * @hide Maybe available only in Eclair and not really ready for public use.
3509         * TODO: remove, or implement this feature completely. As of now (Eclair),
3510         * we only use this flag in queryEntities(), not query().
3511         */
3512        public static final String FOR_EXPORT_ONLY = "for_export_only";
3513
3514        /**
3515         * The ID of the data column. The value will be null if this raw contact has no data rows.
3516         * <P>Type: INTEGER</P>
3517         */
3518        public static final String DATA_ID = "data_id";
3519    }
3520
3521    /**
3522     * @see PhoneLookup
3523     */
3524    protected interface PhoneLookupColumns {
3525        /**
3526         * The phone number as the user entered it.
3527         * <P>Type: TEXT</P>
3528         */
3529        public static final String NUMBER = "number";
3530
3531        /**
3532         * The type of phone number, for example Home or Work.
3533         * <P>Type: INTEGER</P>
3534         */
3535        public static final String TYPE = "type";
3536
3537        /**
3538         * The user defined label for the phone number.
3539         * <P>Type: TEXT</P>
3540         */
3541        public static final String LABEL = "label";
3542
3543        /**
3544         * The phone number's E164 representation.
3545         * <P>Type: TEXT</P>
3546         *
3547         * @hide
3548         */
3549        public static final String NORMALIZED_NUMBER = "normalized_number";
3550    }
3551
3552    /**
3553     * A table that represents the result of looking up a phone number, for
3554     * example for caller ID. To perform a lookup you must append the number you
3555     * want to find to {@link #CONTENT_FILTER_URI}.  This query is highly
3556     * optimized.
3557     * <pre>
3558     * Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
3559     * resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...
3560     * </pre>
3561     *
3562     * <h3>Columns</h3>
3563     *
3564     * <table class="jd-sumtable">
3565     * <tr>
3566     * <th colspan='4'>PhoneLookup</th>
3567     * </tr>
3568     * <tr>
3569     * <td>String</td>
3570     * <td>{@link #NUMBER}</td>
3571     * <td>read-only</td>
3572     * <td>Phone number.</td>
3573     * </tr>
3574     * <tr>
3575     * <td>String</td>
3576     * <td>{@link #TYPE}</td>
3577     * <td>read-only</td>
3578     * <td>Phone number type. See {@link CommonDataKinds.Phone}.</td>
3579     * </tr>
3580     * <tr>
3581     * <td>String</td>
3582     * <td>{@link #LABEL}</td>
3583     * <td>read-only</td>
3584     * <td>Custom label for the phone number. See {@link CommonDataKinds.Phone}.</td>
3585     * </tr>
3586     * </table>
3587     * <p>
3588     * Columns from the Contacts table are also available through a join.
3589     * </p>
3590     * <table class="jd-sumtable">
3591     * <tr>
3592     * <th colspan='4'>Join with {@link Contacts}</th>
3593     * </tr>
3594     * <tr>
3595     * <td>long</td>
3596     * <td>{@link #_ID}</td>
3597     * <td>read-only</td>
3598     * <td>Contact ID.</td>
3599     * </tr>
3600     * <tr>
3601     * <td>String</td>
3602     * <td>{@link #LOOKUP_KEY}</td>
3603     * <td>read-only</td>
3604     * <td>See {@link ContactsContract.Contacts}</td>
3605     * </tr>
3606     * <tr>
3607     * <td>String</td>
3608     * <td>{@link #DISPLAY_NAME}</td>
3609     * <td>read-only</td>
3610     * <td>See {@link ContactsContract.Contacts}</td>
3611     * </tr>
3612     * <tr>
3613     * <td>long</td>
3614     * <td>{@link #PHOTO_ID}</td>
3615     * <td>read-only</td>
3616     * <td>See {@link ContactsContract.Contacts}.</td>
3617     * </tr>
3618     * <tr>
3619     * <td>int</td>
3620     * <td>{@link #IN_VISIBLE_GROUP}</td>
3621     * <td>read-only</td>
3622     * <td>See {@link ContactsContract.Contacts}.</td>
3623     * </tr>
3624     * <tr>
3625     * <td>int</td>
3626     * <td>{@link #HAS_PHONE_NUMBER}</td>
3627     * <td>read-only</td>
3628     * <td>See {@link ContactsContract.Contacts}.</td>
3629     * </tr>
3630     * <tr>
3631     * <td>int</td>
3632     * <td>{@link #TIMES_CONTACTED}</td>
3633     * <td>read-only</td>
3634     * <td>See {@link ContactsContract.Contacts}.</td>
3635     * </tr>
3636     * <tr>
3637     * <td>long</td>
3638     * <td>{@link #LAST_TIME_CONTACTED}</td>
3639     * <td>read-only</td>
3640     * <td>See {@link ContactsContract.Contacts}.</td>
3641     * </tr>
3642     * <tr>
3643     * <td>int</td>
3644     * <td>{@link #STARRED}</td>
3645     * <td>read-only</td>
3646     * <td>See {@link ContactsContract.Contacts}.</td>
3647     * </tr>
3648     * <tr>
3649     * <td>String</td>
3650     * <td>{@link #CUSTOM_RINGTONE}</td>
3651     * <td>read-only</td>
3652     * <td>See {@link ContactsContract.Contacts}.</td>
3653     * </tr>
3654     * <tr>
3655     * <td>int</td>
3656     * <td>{@link #SEND_TO_VOICEMAIL}</td>
3657     * <td>read-only</td>
3658     * <td>See {@link ContactsContract.Contacts}.</td>
3659     * </tr>
3660     * </table>
3661     */
3662    public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns,
3663            ContactsColumns, ContactOptionsColumns {
3664        /**
3665         * This utility class cannot be instantiated
3666         */
3667        private PhoneLookup() {}
3668
3669        /**
3670         * The content:// style URI for this table. Append the phone number you want to lookup
3671         * to this URI and query it to perform a lookup. For example:
3672         * <pre>
3673         * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, Uri.encode(phoneNumber));
3674         * </pre>
3675         */
3676        public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI,
3677                "phone_lookup");
3678
3679        /**
3680         * The MIME type of {@link #CONTENT_FILTER_URI} providing a directory of phone lookup rows.
3681         *
3682         * @hide
3683         */
3684        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_lookup";
3685    }
3686
3687    /**
3688     * Additional data mixed in with {@link StatusColumns} to link
3689     * back to specific {@link ContactsContract.Data#_ID} entries.
3690     *
3691     * @see StatusUpdates
3692     */
3693    protected interface PresenceColumns {
3694
3695        /**
3696         * Reference to the {@link Data#_ID} entry that owns this presence.
3697         * <P>Type: INTEGER</P>
3698         */
3699        public static final String DATA_ID = "presence_data_id";
3700
3701        /**
3702         * See {@link CommonDataKinds.Im} for a list of defined protocol constants.
3703         * <p>Type: NUMBER</p>
3704         */
3705        public static final String PROTOCOL = "protocol";
3706
3707        /**
3708         * Name of the custom protocol.  Should be supplied along with the {@link #PROTOCOL} value
3709         * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.  Should be null or
3710         * omitted if {@link #PROTOCOL} value is not
3711         * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.
3712         *
3713         * <p>Type: NUMBER</p>
3714         */
3715        public static final String CUSTOM_PROTOCOL = "custom_protocol";
3716
3717        /**
3718         * The IM handle the presence item is for. The handle is scoped to
3719         * {@link #PROTOCOL}.
3720         * <P>Type: TEXT</P>
3721         */
3722        public static final String IM_HANDLE = "im_handle";
3723
3724        /**
3725         * The IM account for the local user that the presence data came from.
3726         * <P>Type: TEXT</P>
3727         */
3728        public static final String IM_ACCOUNT = "im_account";
3729    }
3730
3731    /**
3732     * <p>
3733     * A status update is linked to a {@link ContactsContract.Data} row and captures
3734     * the user's latest status update via the corresponding source, e.g.
3735     * "Having lunch" via "Google Talk".
3736     * </p>
3737     * <p>
3738     * There are two ways a status update can be inserted: by explicitly linking
3739     * it to a Data row using {@link #DATA_ID} or indirectly linking it to a data row
3740     * using a combination of {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and
3741     * {@link #IM_HANDLE}.  There is no difference between insert and update, you can use
3742     * either.
3743     * </p>
3744     * <p>
3745     * You cannot use {@link ContentResolver#update} to change a status, but
3746     * {@link ContentResolver#insert} will replace the latests status if it already
3747     * exists.
3748     * </p>
3749     * <p>
3750     * Use {@link ContentResolver#bulkInsert(Uri, ContentValues[])} to insert/update statuses
3751     * for multiple contacts at once.
3752     * </p>
3753     *
3754     * <h3>Columns</h3>
3755     * <table class="jd-sumtable">
3756     * <tr>
3757     * <th colspan='4'>StatusUpdates</th>
3758     * </tr>
3759     * <tr>
3760     * <td>long</td>
3761     * <td>{@link #DATA_ID}</td>
3762     * <td>read/write</td>
3763     * <td>Reference to the {@link Data#_ID} entry that owns this presence. If this
3764     * field is <i>not</i> specified, the provider will attempt to find a data row
3765     * that matches the {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and
3766     * {@link #IM_HANDLE} columns.
3767     * </td>
3768     * </tr>
3769     * <tr>
3770     * <td>long</td>
3771     * <td>{@link #PROTOCOL}</td>
3772     * <td>read/write</td>
3773     * <td>See {@link CommonDataKinds.Im} for a list of defined protocol constants.</td>
3774     * </tr>
3775     * <tr>
3776     * <td>String</td>
3777     * <td>{@link #CUSTOM_PROTOCOL}</td>
3778     * <td>read/write</td>
3779     * <td>Name of the custom protocol.  Should be supplied along with the {@link #PROTOCOL} value
3780     * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.  Should be null or
3781     * omitted if {@link #PROTOCOL} value is not
3782     * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.</td>
3783     * </tr>
3784     * <tr>
3785     * <td>String</td>
3786     * <td>{@link #IM_HANDLE}</td>
3787     * <td>read/write</td>
3788     * <td> The IM handle the presence item is for. The handle is scoped to
3789     * {@link #PROTOCOL}.</td>
3790     * </tr>
3791     * <tr>
3792     * <td>String</td>
3793     * <td>{@link #IM_ACCOUNT}</td>
3794     * <td>read/write</td>
3795     * <td>The IM account for the local user that the presence data came from.</td>
3796     * </tr>
3797     * <tr>
3798     * <td>int</td>
3799     * <td>{@link #PRESENCE}</td>
3800     * <td>read/write</td>
3801     * <td>Contact IM presence status. The allowed values are:
3802     * <p>
3803     * <ul>
3804     * <li>{@link #OFFLINE}</li>
3805     * <li>{@link #INVISIBLE}</li>
3806     * <li>{@link #AWAY}</li>
3807     * <li>{@link #IDLE}</li>
3808     * <li>{@link #DO_NOT_DISTURB}</li>
3809     * <li>{@link #AVAILABLE}</li>
3810     * </ul>
3811     * </p>
3812     * <p>
3813     * Since presence status is inherently volatile, the content provider
3814     * may choose not to store this field in long-term storage.
3815     * </p>
3816     * </td>
3817     * </tr>
3818     * <tr>
3819     * <td>int</td>
3820     * <td>{@link #CHAT_CAPABILITY}</td>
3821     * <td>read/write</td>
3822     * <td>Contact IM chat compatibility value. The allowed values combinations of the following
3823     * flags. If None of these flags is set, the device can only do text messaging.
3824     * <p>
3825     * <ul>
3826     * <li>{@link #CAPABILITY_HAS_VIDEO}</li>
3827     * <li>{@link #CAPABILITY_HAS_VOICE}</li>
3828     * <li>{@link #CAPABILITY_HAS_CAMERA}</li>
3829     * </ul>
3830     * </p>
3831     * <p>
3832     * Since chat compatibility is inherently volatile as the contact's availability moves from
3833     * one device to another, the content provider may choose not to store this field in long-term
3834     * storage.
3835     * </p>
3836     * </td>
3837     * </tr>
3838     * <tr>
3839     * <td>String</td>
3840     * <td>{@link #STATUS}</td>
3841     * <td>read/write</td>
3842     * <td>Contact's latest status update, e.g. "having toast for breakfast"</td>
3843     * </tr>
3844     * <tr>
3845     * <td>long</td>
3846     * <td>{@link #STATUS_TIMESTAMP}</td>
3847     * <td>read/write</td>
3848     * <td>The absolute time in milliseconds when the status was
3849     * entered by the user. If this value is not provided, the provider will follow
3850     * this logic: if there was no prior status update, the value will be left as null.
3851     * If there was a prior status update, the provider will default this field
3852     * to the current time.</td>
3853     * </tr>
3854     * <tr>
3855     * <td>String</td>
3856     * <td>{@link #STATUS_RES_PACKAGE}</td>
3857     * <td>read/write</td>
3858     * <td> The package containing resources for this status: label and icon.</td>
3859     * </tr>
3860     * <tr>
3861     * <td>long</td>
3862     * <td>{@link #STATUS_LABEL}</td>
3863     * <td>read/write</td>
3864     * <td>The resource ID of the label describing the source of contact status,
3865     * e.g. "Google Talk". This resource is scoped by the
3866     * {@link #STATUS_RES_PACKAGE}.</td>
3867     * </tr>
3868     * <tr>
3869     * <td>long</td>
3870     * <td>{@link #STATUS_ICON}</td>
3871     * <td>read/write</td>
3872     * <td>The resource ID of the icon for the source of contact status. This
3873     * resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
3874     * </tr>
3875     * </table>
3876     */
3877    public static class StatusUpdates implements StatusColumns, PresenceColumns {
3878
3879        /**
3880         * This utility class cannot be instantiated
3881         */
3882        private StatusUpdates() {}
3883
3884        /**
3885         * The content:// style URI for this table
3886         */
3887        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates");
3888
3889        /**
3890         * Gets the resource ID for the proper presence icon.
3891         *
3892         * @param status the status to get the icon for
3893         * @return the resource ID for the proper presence icon
3894         */
3895        public static final int getPresenceIconResourceId(int status) {
3896            switch (status) {
3897                case AVAILABLE:
3898                    return android.R.drawable.presence_online;
3899                case IDLE:
3900                case AWAY:
3901                    return android.R.drawable.presence_away;
3902                case DO_NOT_DISTURB:
3903                    return android.R.drawable.presence_busy;
3904                case INVISIBLE:
3905                    return android.R.drawable.presence_invisible;
3906                case OFFLINE:
3907                default:
3908                    return android.R.drawable.presence_offline;
3909            }
3910        }
3911
3912        /**
3913         * Returns the precedence of the status code the higher number being the higher precedence.
3914         *
3915         * @param status The status code.
3916         * @return An integer representing the precedence, 0 being the lowest.
3917         */
3918        public static final int getPresencePrecedence(int status) {
3919            // Keep this function here incase we want to enforce a different precedence than the
3920            // natural order of the status constants.
3921            return status;
3922        }
3923
3924        /**
3925         * The MIME type of {@link #CONTENT_URI} providing a directory of
3926         * status update details.
3927         */
3928        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/status-update";
3929
3930        /**
3931         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
3932         * status update detail.
3933         */
3934        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update";
3935    }
3936
3937    /**
3938     * @deprecated This old name was never meant to be made public. Do not use.
3939     */
3940    @Deprecated
3941    public static final class Presence extends StatusUpdates {
3942
3943    }
3944
3945    /**
3946     * Additional column returned by the {@link Contacts#CONTENT_FILTER_URI} providing the
3947     * explanation of why the filter matched the contact.  Specifically, it contains the
3948     * data elements that matched the query.  The overall number of words in the snippet
3949     * can be capped.
3950     *
3951     * @hide
3952     */
3953    public static class SearchSnippetColumns {
3954
3955        /**
3956         * The search snippet constructed according to the SQLite rules, see
3957         * http://www.sqlite.org/fts3.html#snippet
3958         * <p>
3959         * The snippet may contain (parts of) several data elements comprising
3960         * the contact.
3961         *
3962         * @hide
3963         */
3964        public static final String SNIPPET = "snippet";
3965
3966
3967        /**
3968         * Comma-separated parameters for the generation of the snippet:
3969         * <ul>
3970         * <li>The "start match" text. Default is &lt;b&gt;</li>
3971         * <li>The "end match" text. Default is &lt;/b&gt;</li>
3972         * <li>The "ellipsis" text. Default is &lt;b&gt;...&lt;/b&gt;</li>
3973         * <li>Maximum number of tokens to include in the snippet. Can be either
3974         * a positive or a negative number: A positive number indicates how many
3975         * tokens can be returned in total. A negative number indicates how many
3976         * tokens can be returned per occurrence of the search terms.</li>
3977         * </ul>
3978         *
3979         * @hide
3980         */
3981        public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args";
3982    }
3983
3984    /**
3985     * Container for definitions of common data types stored in the {@link ContactsContract.Data}
3986     * table.
3987     */
3988    public static final class CommonDataKinds {
3989        /**
3990         * This utility class cannot be instantiated
3991         */
3992        private CommonDataKinds() {}
3993
3994        /**
3995         * The {@link Data#RES_PACKAGE} value for common data that should be
3996         * shown using a default style.
3997         *
3998         * @hide RES_PACKAGE is hidden
3999         */
4000        public static final String PACKAGE_COMMON = "common";
4001
4002        /**
4003         * The base types that all "Typed" data kinds support.
4004         */
4005        public interface BaseTypes {
4006            /**
4007             * A custom type. The custom label should be supplied by user.
4008             */
4009            public static int TYPE_CUSTOM = 0;
4010        }
4011
4012        /**
4013         * Columns common across the specific types.
4014         */
4015        protected interface CommonColumns extends BaseTypes {
4016            /**
4017             * The data for the contact method.
4018             * <P>Type: TEXT</P>
4019             */
4020            public static final String DATA = DataColumns.DATA1;
4021
4022            /**
4023             * The type of data, for example Home or Work.
4024             * <P>Type: INTEGER</P>
4025             */
4026            public static final String TYPE = DataColumns.DATA2;
4027
4028            /**
4029             * The user defined label for the the contact method.
4030             * <P>Type: TEXT</P>
4031             */
4032            public static final String LABEL = DataColumns.DATA3;
4033        }
4034
4035        /**
4036         * A data kind representing the contact's proper name. You can use all
4037         * columns defined for {@link ContactsContract.Data} as well as the following aliases.
4038         *
4039         * <h2>Column aliases</h2>
4040         * <table class="jd-sumtable">
4041         * <tr>
4042         * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th>
4043         * </tr>
4044         * <tr>
4045         * <td>String</td>
4046         * <td>{@link #DISPLAY_NAME}</td>
4047         * <td>{@link #DATA1}</td>
4048         * <td></td>
4049         * </tr>
4050         * <tr>
4051         * <td>String</td>
4052         * <td>{@link #GIVEN_NAME}</td>
4053         * <td>{@link #DATA2}</td>
4054         * <td></td>
4055         * </tr>
4056         * <tr>
4057         * <td>String</td>
4058         * <td>{@link #FAMILY_NAME}</td>
4059         * <td>{@link #DATA3}</td>
4060         * <td></td>
4061         * </tr>
4062         * <tr>
4063         * <td>String</td>
4064         * <td>{@link #PREFIX}</td>
4065         * <td>{@link #DATA4}</td>
4066         * <td>Common prefixes in English names are "Mr", "Ms", "Dr" etc.</td>
4067         * </tr>
4068         * <tr>
4069         * <td>String</td>
4070         * <td>{@link #MIDDLE_NAME}</td>
4071         * <td>{@link #DATA5}</td>
4072         * <td></td>
4073         * </tr>
4074         * <tr>
4075         * <td>String</td>
4076         * <td>{@link #SUFFIX}</td>
4077         * <td>{@link #DATA6}</td>
4078         * <td>Common suffixes in English names are "Sr", "Jr", "III" etc.</td>
4079         * </tr>
4080         * <tr>
4081         * <td>String</td>
4082         * <td>{@link #PHONETIC_GIVEN_NAME}</td>
4083         * <td>{@link #DATA7}</td>
4084         * <td>Used for phonetic spelling of the name, e.g. Pinyin, Katakana, Hiragana</td>
4085         * </tr>
4086         * <tr>
4087         * <td>String</td>
4088         * <td>{@link #PHONETIC_MIDDLE_NAME}</td>
4089         * <td>{@link #DATA8}</td>
4090         * <td></td>
4091         * </tr>
4092         * <tr>
4093         * <td>String</td>
4094         * <td>{@link #PHONETIC_FAMILY_NAME}</td>
4095         * <td>{@link #DATA9}</td>
4096         * <td></td>
4097         * </tr>
4098         * </table>
4099         */
4100        public static final class StructuredName implements DataColumnsWithJoins {
4101            /**
4102             * This utility class cannot be instantiated
4103             */
4104            private StructuredName() {}
4105
4106            /** MIME type used when storing this in data table. */
4107            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
4108
4109            /**
4110             * The name that should be used to display the contact.
4111             * <i>Unstructured component of the name should be consistent with
4112             * its structured representation.</i>
4113             * <p>
4114             * Type: TEXT
4115             */
4116            public static final String DISPLAY_NAME = DATA1;
4117
4118            /**
4119             * The given name for the contact.
4120             * <P>Type: TEXT</P>
4121             */
4122            public static final String GIVEN_NAME = DATA2;
4123
4124            /**
4125             * The family name for the contact.
4126             * <P>Type: TEXT</P>
4127             */
4128            public static final String FAMILY_NAME = DATA3;
4129
4130            /**
4131             * The contact's honorific prefix, e.g. "Sir"
4132             * <P>Type: TEXT</P>
4133             */
4134            public static final String PREFIX = DATA4;
4135
4136            /**
4137             * The contact's middle name
4138             * <P>Type: TEXT</P>
4139             */
4140            public static final String MIDDLE_NAME = DATA5;
4141
4142            /**
4143             * The contact's honorific suffix, e.g. "Jr"
4144             */
4145            public static final String SUFFIX = DATA6;
4146
4147            /**
4148             * The phonetic version of the given name for the contact.
4149             * <P>Type: TEXT</P>
4150             */
4151            public static final String PHONETIC_GIVEN_NAME = DATA7;
4152
4153            /**
4154             * The phonetic version of the additional name for the contact.
4155             * <P>Type: TEXT</P>
4156             */
4157            public static final String PHONETIC_MIDDLE_NAME = DATA8;
4158
4159            /**
4160             * The phonetic version of the family name for the contact.
4161             * <P>Type: TEXT</P>
4162             */
4163            public static final String PHONETIC_FAMILY_NAME = DATA9;
4164
4165            /**
4166             * The style used for combining given/middle/family name into a full name.
4167             * See {@link ContactsContract.FullNameStyle}.
4168             *
4169             * @hide
4170             */
4171            public static final String FULL_NAME_STYLE = DATA10;
4172
4173            /**
4174             * The alphabet used for capturing the phonetic name.
4175             * See ContactsContract.PhoneticNameStyle.
4176             * @hide
4177             */
4178            public static final String PHONETIC_NAME_STYLE = DATA11;
4179        }
4180
4181        /**
4182         * <p>A data kind representing the contact's nickname. For example, for
4183         * Bob Parr ("Mr. Incredible"):
4184         * <pre>
4185         * ArrayList&lt;ContentProviderOperation&gt; ops =
4186         *          new ArrayList&lt;ContentProviderOperation&gt;();
4187         *
4188         * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
4189         *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
4190         *          .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
4191         *          .withValue(StructuredName.DISPLAY_NAME, &quot;Bob Parr&quot;)
4192         *          .build());
4193         *
4194         * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
4195         *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
4196         *          .withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE)
4197         *          .withValue(Nickname.NAME, "Mr. Incredible")
4198         *          .withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM)
4199         *          .withValue(Nickname.LABEL, "Superhero")
4200         *          .build());
4201         *
4202         * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
4203         * </pre>
4204         * </p>
4205         * <p>
4206         * You can use all columns defined for {@link ContactsContract.Data} as well as the
4207         * following aliases.
4208         * </p>
4209         *
4210         * <h2>Column aliases</h2>
4211         * <table class="jd-sumtable">
4212         * <tr>
4213         * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th>
4214         * </tr>
4215         * <tr>
4216         * <td>String</td>
4217         * <td>{@link #NAME}</td>
4218         * <td>{@link #DATA1}</td>
4219         * <td></td>
4220         * </tr>
4221         * <tr>
4222         * <td>int</td>
4223         * <td>{@link #TYPE}</td>
4224         * <td>{@link #DATA2}</td>
4225         * <td>
4226         * Allowed values are:
4227         * <p>
4228         * <ul>
4229         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
4230         * <li>{@link #TYPE_DEFAULT}</li>
4231         * <li>{@link #TYPE_OTHER_NAME}</li>
4232         * <li>{@link #TYPE_MAIDEN_NAME}</li>
4233         * <li>{@link #TYPE_SHORT_NAME}</li>
4234         * <li>{@link #TYPE_INITIALS}</li>
4235         * </ul>
4236         * </p>
4237         * </td>
4238         * </tr>
4239         * <tr>
4240         * <td>String</td>
4241         * <td>{@link #LABEL}</td>
4242         * <td>{@link #DATA3}</td>
4243         * <td></td>
4244         * </tr>
4245         * </table>
4246         */
4247        public static final class Nickname implements DataColumnsWithJoins, CommonColumns {
4248            /**
4249             * This utility class cannot be instantiated
4250             */
4251            private Nickname() {}
4252
4253            /** MIME type used when storing this in data table. */
4254            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
4255
4256            public static final int TYPE_DEFAULT = 1;
4257            public static final int TYPE_OTHER_NAME = 2;
4258            public static final int TYPE_MAIDEN_NAME = 3;
4259            /** @deprecated Use TYPE_MAIDEN_NAME instead. */
4260            @Deprecated
4261            public static final int TYPE_MAINDEN_NAME = 3;
4262            public static final int TYPE_SHORT_NAME = 4;
4263            public static final int TYPE_INITIALS = 5;
4264
4265            /**
4266             * The name itself
4267             */
4268            public static final String NAME = DATA;
4269        }
4270
4271        /**
4272         * <p>
4273         * A data kind representing a telephone number.
4274         * </p>
4275         * <p>
4276         * You can use all columns defined for {@link ContactsContract.Data} as
4277         * well as the following aliases.
4278         * </p>
4279         * <h2>Column aliases</h2>
4280         * <table class="jd-sumtable">
4281         * <tr>
4282         * <th>Type</th>
4283         * <th>Alias</th><th colspan='2'>Data column</th>
4284         * </tr>
4285         * <tr>
4286         * <td>String</td>
4287         * <td>{@link #NUMBER}</td>
4288         * <td>{@link #DATA1}</td>
4289         * <td></td>
4290         * </tr>
4291         * <tr>
4292         * <td>int</td>
4293         * <td>{@link #TYPE}</td>
4294         * <td>{@link #DATA2}</td>
4295         * <td>Allowed values are:
4296         * <p>
4297         * <ul>
4298         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
4299         * <li>{@link #TYPE_HOME}</li>
4300         * <li>{@link #TYPE_MOBILE}</li>
4301         * <li>{@link #TYPE_WORK}</li>
4302         * <li>{@link #TYPE_FAX_WORK}</li>
4303         * <li>{@link #TYPE_FAX_HOME}</li>
4304         * <li>{@link #TYPE_PAGER}</li>
4305         * <li>{@link #TYPE_OTHER}</li>
4306         * <li>{@link #TYPE_CALLBACK}</li>
4307         * <li>{@link #TYPE_CAR}</li>
4308         * <li>{@link #TYPE_COMPANY_MAIN}</li>
4309         * <li>{@link #TYPE_ISDN}</li>
4310         * <li>{@link #TYPE_MAIN}</li>
4311         * <li>{@link #TYPE_OTHER_FAX}</li>
4312         * <li>{@link #TYPE_RADIO}</li>
4313         * <li>{@link #TYPE_TELEX}</li>
4314         * <li>{@link #TYPE_TTY_TDD}</li>
4315         * <li>{@link #TYPE_WORK_MOBILE}</li>
4316         * <li>{@link #TYPE_WORK_PAGER}</li>
4317         * <li>{@link #TYPE_ASSISTANT}</li>
4318         * <li>{@link #TYPE_MMS}</li>
4319         * </ul>
4320         * </p>
4321         * </td>
4322         * </tr>
4323         * <tr>
4324         * <td>String</td>
4325         * <td>{@link #LABEL}</td>
4326         * <td>{@link #DATA3}</td>
4327         * <td></td>
4328         * </tr>
4329         * </table>
4330         */
4331        public static final class Phone implements DataColumnsWithJoins, CommonColumns {
4332            /**
4333             * This utility class cannot be instantiated
4334             */
4335            private Phone() {}
4336
4337            /** MIME type used when storing this in data table. */
4338            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
4339
4340            /**
4341             * The MIME type of {@link #CONTENT_URI} providing a directory of
4342             * phones.
4343             */
4344            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
4345
4346            /**
4347             * The content:// style URI for all data records of the
4348             * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the
4349             * associated raw contact and aggregate contact data.
4350             */
4351            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
4352                    "phones");
4353
4354            /**
4355             * The content:// style URL for phone lookup using a filter. The filter returns
4356             * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied
4357             * to display names as well as phone numbers. The filter argument should be passed
4358             * as an additional path segment after this URI.
4359             */
4360            public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
4361                    "filter");
4362
4363            public static final int TYPE_HOME = 1;
4364            public static final int TYPE_MOBILE = 2;
4365            public static final int TYPE_WORK = 3;
4366            public static final int TYPE_FAX_WORK = 4;
4367            public static final int TYPE_FAX_HOME = 5;
4368            public static final int TYPE_PAGER = 6;
4369            public static final int TYPE_OTHER = 7;
4370            public static final int TYPE_CALLBACK = 8;
4371            public static final int TYPE_CAR = 9;
4372            public static final int TYPE_COMPANY_MAIN = 10;
4373            public static final int TYPE_ISDN = 11;
4374            public static final int TYPE_MAIN = 12;
4375            public static final int TYPE_OTHER_FAX = 13;
4376            public static final int TYPE_RADIO = 14;
4377            public static final int TYPE_TELEX = 15;
4378            public static final int TYPE_TTY_TDD = 16;
4379            public static final int TYPE_WORK_MOBILE = 17;
4380            public static final int TYPE_WORK_PAGER = 18;
4381            public static final int TYPE_ASSISTANT = 19;
4382            public static final int TYPE_MMS = 20;
4383
4384            /**
4385             * The phone number as the user entered it.
4386             * <P>Type: TEXT</P>
4387             */
4388            public static final String NUMBER = DATA;
4389
4390            /**
4391             * The phone number's E164 representation.
4392             * <P>Type: TEXT</P>
4393             *
4394             * @hide
4395             */
4396            public static final String NORMALIZED_NUMBER = DATA4;
4397
4398            /**
4399             * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead.
4400             * @hide
4401             */
4402            @Deprecated
4403            public static final CharSequence getDisplayLabel(Context context, int type,
4404                    CharSequence label, CharSequence[] labelArray) {
4405                return getTypeLabel(context.getResources(), type, label);
4406            }
4407
4408            /**
4409             * @deprecated use {@link #getTypeLabel(Resources, int, CharSequence)} instead.
4410             * @hide
4411             */
4412            @Deprecated
4413            public static final CharSequence getDisplayLabel(Context context, int type,
4414                    CharSequence label) {
4415                return getTypeLabel(context.getResources(), type, label);
4416            }
4417
4418            /**
4419             * Return the string resource that best describes the given
4420             * {@link #TYPE}. Will always return a valid resource.
4421             */
4422            public static final int getTypeLabelResource(int type) {
4423                switch (type) {
4424                    case TYPE_HOME: return com.android.internal.R.string.phoneTypeHome;
4425                    case TYPE_MOBILE: return com.android.internal.R.string.phoneTypeMobile;
4426                    case TYPE_WORK: return com.android.internal.R.string.phoneTypeWork;
4427                    case TYPE_FAX_WORK: return com.android.internal.R.string.phoneTypeFaxWork;
4428                    case TYPE_FAX_HOME: return com.android.internal.R.string.phoneTypeFaxHome;
4429                    case TYPE_PAGER: return com.android.internal.R.string.phoneTypePager;
4430                    case TYPE_OTHER: return com.android.internal.R.string.phoneTypeOther;
4431                    case TYPE_CALLBACK: return com.android.internal.R.string.phoneTypeCallback;
4432                    case TYPE_CAR: return com.android.internal.R.string.phoneTypeCar;
4433                    case TYPE_COMPANY_MAIN: return com.android.internal.R.string.phoneTypeCompanyMain;
4434                    case TYPE_ISDN: return com.android.internal.R.string.phoneTypeIsdn;
4435                    case TYPE_MAIN: return com.android.internal.R.string.phoneTypeMain;
4436                    case TYPE_OTHER_FAX: return com.android.internal.R.string.phoneTypeOtherFax;
4437                    case TYPE_RADIO: return com.android.internal.R.string.phoneTypeRadio;
4438                    case TYPE_TELEX: return com.android.internal.R.string.phoneTypeTelex;
4439                    case TYPE_TTY_TDD: return com.android.internal.R.string.phoneTypeTtyTdd;
4440                    case TYPE_WORK_MOBILE: return com.android.internal.R.string.phoneTypeWorkMobile;
4441                    case TYPE_WORK_PAGER: return com.android.internal.R.string.phoneTypeWorkPager;
4442                    case TYPE_ASSISTANT: return com.android.internal.R.string.phoneTypeAssistant;
4443                    case TYPE_MMS: return com.android.internal.R.string.phoneTypeMms;
4444                    default: return com.android.internal.R.string.phoneTypeCustom;
4445                }
4446            }
4447
4448            /**
4449             * Return a {@link CharSequence} that best describes the given type,
4450             * possibly substituting the given {@link #LABEL} value
4451             * for {@link #TYPE_CUSTOM}.
4452             */
4453            public static final CharSequence getTypeLabel(Resources res, int type,
4454                    CharSequence label) {
4455                if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) {
4456                    return label;
4457                } else {
4458                    final int labelRes = getTypeLabelResource(type);
4459                    return res.getText(labelRes);
4460                }
4461            }
4462        }
4463
4464        /**
4465         * <p>
4466         * A data kind representing an email address.
4467         * </p>
4468         * <p>
4469         * You can use all columns defined for {@link ContactsContract.Data} as
4470         * well as the following aliases.
4471         * </p>
4472         * <h2>Column aliases</h2>
4473         * <table class="jd-sumtable">
4474         * <tr>
4475         * <th>Type</th>
4476         * <th>Alias</th><th colspan='2'>Data column</th>
4477         * </tr>
4478         * <tr>
4479         * <td>String</td>
4480         * <td>{@link #ADDRESS}</td>
4481         * <td>{@link #DATA1}</td>
4482         * <td>Email address itself.</td>
4483         * </tr>
4484         * <tr>
4485         * <td>int</td>
4486         * <td>{@link #TYPE}</td>
4487         * <td>{@link #DATA2}</td>
4488         * <td>Allowed values are:
4489         * <p>
4490         * <ul>
4491         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
4492         * <li>{@link #TYPE_HOME}</li>
4493         * <li>{@link #TYPE_WORK}</li>
4494         * <li>{@link #TYPE_OTHER}</li>
4495         * <li>{@link #TYPE_MOBILE}</li>
4496         * </ul>
4497         * </p>
4498         * </td>
4499         * </tr>
4500         * <tr>
4501         * <td>String</td>
4502         * <td>{@link #LABEL}</td>
4503         * <td>{@link #DATA3}</td>
4504         * <td></td>
4505         * </tr>
4506         * </table>
4507         */
4508        public static final class Email implements DataColumnsWithJoins, CommonColumns {
4509            /**
4510             * This utility class cannot be instantiated
4511             */
4512            private Email() {}
4513
4514            /** MIME type used when storing this in data table. */
4515            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
4516
4517            /**
4518             * The MIME type of {@link #CONTENT_URI} providing a directory of email addresses.
4519             */
4520            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2";
4521
4522            /**
4523             * The content:// style URI for all data records of the
4524             * {@link #CONTENT_ITEM_TYPE} MIME type, combined with the
4525             * associated raw contact and aggregate contact data.
4526             */
4527            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
4528                    "emails");
4529
4530            /**
4531             * <p>
4532             * The content:// style URL for looking up data rows by email address. The
4533             * lookup argument, an email address, should be passed as an additional path segment
4534             * after this URI.
4535             * </p>
4536             * <p>Example:
4537             * <pre>
4538             * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email));
4539             * Cursor c = getContentResolver().query(uri,
4540             *          new String[]{Email.CONTACT_ID, Email.DISPLAY_NAME, Email.DATA},
4541             *          null, null, null);
4542             * </pre>
4543             * </p>
4544             */
4545            public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI,
4546                    "lookup");
4547
4548            /**
4549             * <p>
4550             * The content:// style URL for email lookup using a filter. The filter returns
4551             * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied
4552             * to display names as well as email addresses. The filter argument should be passed
4553             * as an additional path segment after this URI.
4554             * </p>
4555             * <p>The query in the following example will return "Robert Parr (bob@incredibles.com)"
4556             * as well as "Bob Parr (incredible@android.com)".
4557             * <pre>
4558             * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode("bob"));
4559             * Cursor c = getContentResolver().query(uri,
4560             *          new String[]{Email.DISPLAY_NAME, Email.DATA},
4561             *          null, null, null);
4562             * </pre>
4563             * </p>
4564             */
4565            public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
4566                    "filter");
4567
4568            /**
4569             * The email address.
4570             * <P>Type: TEXT</P>
4571             */
4572            public static final String ADDRESS = DATA1;
4573
4574            public static final int TYPE_HOME = 1;
4575            public static final int TYPE_WORK = 2;
4576            public static final int TYPE_OTHER = 3;
4577            public static final int TYPE_MOBILE = 4;
4578
4579            /**
4580             * The display name for the email address
4581             * <P>Type: TEXT</P>
4582             */
4583            public static final String DISPLAY_NAME = DATA4;
4584
4585            /**
4586             * Return the string resource that best describes the given
4587             * {@link #TYPE}. Will always return a valid resource.
4588             */
4589            public static final int getTypeLabelResource(int type) {
4590                switch (type) {
4591                    case TYPE_HOME: return com.android.internal.R.string.emailTypeHome;
4592                    case TYPE_WORK: return com.android.internal.R.string.emailTypeWork;
4593                    case TYPE_OTHER: return com.android.internal.R.string.emailTypeOther;
4594                    case TYPE_MOBILE: return com.android.internal.R.string.emailTypeMobile;
4595                    default: return com.android.internal.R.string.emailTypeCustom;
4596                }
4597            }
4598
4599            /**
4600             * Return a {@link CharSequence} that best describes the given type,
4601             * possibly substituting the given {@link #LABEL} value
4602             * for {@link #TYPE_CUSTOM}.
4603             */
4604            public static final CharSequence getTypeLabel(Resources res, int type,
4605                    CharSequence label) {
4606                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
4607                    return label;
4608                } else {
4609                    final int labelRes = getTypeLabelResource(type);
4610                    return res.getText(labelRes);
4611                }
4612            }
4613        }
4614
4615        /**
4616         * <p>
4617         * A data kind representing a postal addresses.
4618         * </p>
4619         * <p>
4620         * You can use all columns defined for {@link ContactsContract.Data} as
4621         * well as the following aliases.
4622         * </p>
4623         * <h2>Column aliases</h2>
4624         * <table class="jd-sumtable">
4625         * <tr>
4626         * <th>Type</th>
4627         * <th>Alias</th><th colspan='2'>Data column</th>
4628         * </tr>
4629         * <tr>
4630         * <td>String</td>
4631         * <td>{@link #FORMATTED_ADDRESS}</td>
4632         * <td>{@link #DATA1}</td>
4633         * <td></td>
4634         * </tr>
4635         * <tr>
4636         * <td>int</td>
4637         * <td>{@link #TYPE}</td>
4638         * <td>{@link #DATA2}</td>
4639         * <td>Allowed values are:
4640         * <p>
4641         * <ul>
4642         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
4643         * <li>{@link #TYPE_HOME}</li>
4644         * <li>{@link #TYPE_WORK}</li>
4645         * <li>{@link #TYPE_OTHER}</li>
4646         * </ul>
4647         * </p>
4648         * </td>
4649         * </tr>
4650         * <tr>
4651         * <td>String</td>
4652         * <td>{@link #LABEL}</td>
4653         * <td>{@link #DATA3}</td>
4654         * <td></td>
4655         * </tr>
4656         * <tr>
4657         * <td>String</td>
4658         * <td>{@link #STREET}</td>
4659         * <td>{@link #DATA4}</td>
4660         * <td></td>
4661         * </tr>
4662         * <tr>
4663         * <td>String</td>
4664         * <td>{@link #POBOX}</td>
4665         * <td>{@link #DATA5}</td>
4666         * <td>Post Office Box number</td>
4667         * </tr>
4668         * <tr>
4669         * <td>String</td>
4670         * <td>{@link #NEIGHBORHOOD}</td>
4671         * <td>{@link #DATA6}</td>
4672         * <td></td>
4673         * </tr>
4674         * <tr>
4675         * <td>String</td>
4676         * <td>{@link #CITY}</td>
4677         * <td>{@link #DATA7}</td>
4678         * <td></td>
4679         * </tr>
4680         * <tr>
4681         * <td>String</td>
4682         * <td>{@link #REGION}</td>
4683         * <td>{@link #DATA8}</td>
4684         * <td></td>
4685         * </tr>
4686         * <tr>
4687         * <td>String</td>
4688         * <td>{@link #POSTCODE}</td>
4689         * <td>{@link #DATA9}</td>
4690         * <td></td>
4691         * </tr>
4692         * <tr>
4693         * <td>String</td>
4694         * <td>{@link #COUNTRY}</td>
4695         * <td>{@link #DATA10}</td>
4696         * <td></td>
4697         * </tr>
4698         * </table>
4699         */
4700        public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns {
4701            /**
4702             * This utility class cannot be instantiated
4703             */
4704            private StructuredPostal() {
4705            }
4706
4707            /** MIME type used when storing this in data table. */
4708            public static final String CONTENT_ITEM_TYPE =
4709                    "vnd.android.cursor.item/postal-address_v2";
4710
4711            /**
4712             * The MIME type of {@link #CONTENT_URI} providing a directory of
4713             * postal addresses.
4714             */
4715            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
4716
4717            /**
4718             * The content:// style URI for all data records of the
4719             * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type.
4720             */
4721            public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
4722                    "postals");
4723
4724            public static final int TYPE_HOME = 1;
4725            public static final int TYPE_WORK = 2;
4726            public static final int TYPE_OTHER = 3;
4727
4728            /**
4729             * The full, unstructured postal address. <i>This field must be
4730             * consistent with any structured data.</i>
4731             * <p>
4732             * Type: TEXT
4733             */
4734            public static final String FORMATTED_ADDRESS = DATA;
4735
4736            /**
4737             * Can be street, avenue, road, etc. This element also includes the
4738             * house number and room/apartment/flat/floor number.
4739             * <p>
4740             * Type: TEXT
4741             */
4742            public static final String STREET = DATA4;
4743
4744            /**
4745             * Covers actual P.O. boxes, drawers, locked bags, etc. This is
4746             * usually but not always mutually exclusive with street.
4747             * <p>
4748             * Type: TEXT
4749             */
4750            public static final String POBOX = DATA5;
4751
4752            /**
4753             * This is used to disambiguate a street address when a city
4754             * contains more than one street with the same name, or to specify a
4755             * small place whose mail is routed through a larger postal town. In
4756             * China it could be a county or a minor city.
4757             * <p>
4758             * Type: TEXT
4759             */
4760            public static final String NEIGHBORHOOD = DATA6;
4761
4762            /**
4763             * Can be city, village, town, borough, etc. This is the postal town
4764             * and not necessarily the place of residence or place of business.
4765             * <p>
4766             * Type: TEXT
4767             */
4768            public static final String CITY = DATA7;
4769
4770            /**
4771             * A state, province, county (in Ireland), Land (in Germany),
4772             * departement (in France), etc.
4773             * <p>
4774             * Type: TEXT
4775             */
4776            public static final String REGION = DATA8;
4777
4778            /**
4779             * Postal code. Usually country-wide, but sometimes specific to the
4780             * city (e.g. "2" in "Dublin 2, Ireland" addresses).
4781             * <p>
4782             * Type: TEXT
4783             */
4784            public static final String POSTCODE = DATA9;
4785
4786            /**
4787             * The name or code of the country.
4788             * <p>
4789             * Type: TEXT
4790             */
4791            public static final String COUNTRY = DATA10;
4792
4793            /**
4794             * Return the string resource that best describes the given
4795             * {@link #TYPE}. Will always return a valid resource.
4796             */
4797            public static final int getTypeLabelResource(int type) {
4798                switch (type) {
4799                    case TYPE_HOME: return com.android.internal.R.string.postalTypeHome;
4800                    case TYPE_WORK: return com.android.internal.R.string.postalTypeWork;
4801                    case TYPE_OTHER: return com.android.internal.R.string.postalTypeOther;
4802                    default: return com.android.internal.R.string.postalTypeCustom;
4803                }
4804            }
4805
4806            /**
4807             * Return a {@link CharSequence} that best describes the given type,
4808             * possibly substituting the given {@link #LABEL} value
4809             * for {@link #TYPE_CUSTOM}.
4810             */
4811            public static final CharSequence getTypeLabel(Resources res, int type,
4812                    CharSequence label) {
4813                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
4814                    return label;
4815                } else {
4816                    final int labelRes = getTypeLabelResource(type);
4817                    return res.getText(labelRes);
4818                }
4819            }
4820        }
4821
4822        /**
4823         * <p>
4824         * A data kind representing an IM address
4825         * </p>
4826         * <p>
4827         * You can use all columns defined for {@link ContactsContract.Data} as
4828         * well as the following aliases.
4829         * </p>
4830         * <h2>Column aliases</h2>
4831         * <table class="jd-sumtable">
4832         * <tr>
4833         * <th>Type</th>
4834         * <th>Alias</th><th colspan='2'>Data column</th>
4835         * </tr>
4836         * <tr>
4837         * <td>String</td>
4838         * <td>{@link #DATA}</td>
4839         * <td>{@link #DATA1}</td>
4840         * <td></td>
4841         * </tr>
4842         * <tr>
4843         * <td>int</td>
4844         * <td>{@link #TYPE}</td>
4845         * <td>{@link #DATA2}</td>
4846         * <td>Allowed values are:
4847         * <p>
4848         * <ul>
4849         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
4850         * <li>{@link #TYPE_HOME}</li>
4851         * <li>{@link #TYPE_WORK}</li>
4852         * <li>{@link #TYPE_OTHER}</li>
4853         * </ul>
4854         * </p>
4855         * </td>
4856         * </tr>
4857         * <tr>
4858         * <td>String</td>
4859         * <td>{@link #LABEL}</td>
4860         * <td>{@link #DATA3}</td>
4861         * <td></td>
4862         * </tr>
4863         * <tr>
4864         * <td>String</td>
4865         * <td>{@link #PROTOCOL}</td>
4866         * <td>{@link #DATA5}</td>
4867         * <td>
4868         * <p>
4869         * Allowed values:
4870         * <ul>
4871         * <li>{@link #PROTOCOL_CUSTOM}. Also provide the actual protocol name
4872         * as {@link #CUSTOM_PROTOCOL}.</li>
4873         * <li>{@link #PROTOCOL_AIM}</li>
4874         * <li>{@link #PROTOCOL_MSN}</li>
4875         * <li>{@link #PROTOCOL_YAHOO}</li>
4876         * <li>{@link #PROTOCOL_SKYPE}</li>
4877         * <li>{@link #PROTOCOL_QQ}</li>
4878         * <li>{@link #PROTOCOL_GOOGLE_TALK}</li>
4879         * <li>{@link #PROTOCOL_ICQ}</li>
4880         * <li>{@link #PROTOCOL_JABBER}</li>
4881         * <li>{@link #PROTOCOL_NETMEETING}</li>
4882         * </ul>
4883         * </p>
4884         * </td>
4885         * </tr>
4886         * <tr>
4887         * <td>String</td>
4888         * <td>{@link #CUSTOM_PROTOCOL}</td>
4889         * <td>{@link #DATA6}</td>
4890         * <td></td>
4891         * </tr>
4892         * </table>
4893         */
4894        public static final class Im implements DataColumnsWithJoins, CommonColumns {
4895            /**
4896             * This utility class cannot be instantiated
4897             */
4898            private Im() {}
4899
4900            /** MIME type used when storing this in data table. */
4901            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
4902
4903            public static final int TYPE_HOME = 1;
4904            public static final int TYPE_WORK = 2;
4905            public static final int TYPE_OTHER = 3;
4906
4907            /**
4908             * This column should be populated with one of the defined
4909             * constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this
4910             * column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL}
4911             * should contain the name of the custom protocol.
4912             */
4913            public static final String PROTOCOL = DATA5;
4914
4915            public static final String CUSTOM_PROTOCOL = DATA6;
4916
4917            /*
4918             * The predefined IM protocol types.
4919             */
4920            public static final int PROTOCOL_CUSTOM = -1;
4921            public static final int PROTOCOL_AIM = 0;
4922            public static final int PROTOCOL_MSN = 1;
4923            public static final int PROTOCOL_YAHOO = 2;
4924            public static final int PROTOCOL_SKYPE = 3;
4925            public static final int PROTOCOL_QQ = 4;
4926            public static final int PROTOCOL_GOOGLE_TALK = 5;
4927            public static final int PROTOCOL_ICQ = 6;
4928            public static final int PROTOCOL_JABBER = 7;
4929            public static final int PROTOCOL_NETMEETING = 8;
4930
4931            /**
4932             * Return the string resource that best describes the given
4933             * {@link #TYPE}. Will always return a valid resource.
4934             */
4935            public static final int getTypeLabelResource(int type) {
4936                switch (type) {
4937                    case TYPE_HOME: return com.android.internal.R.string.imTypeHome;
4938                    case TYPE_WORK: return com.android.internal.R.string.imTypeWork;
4939                    case TYPE_OTHER: return com.android.internal.R.string.imTypeOther;
4940                    default: return com.android.internal.R.string.imTypeCustom;
4941                }
4942            }
4943
4944            /**
4945             * Return a {@link CharSequence} that best describes the given type,
4946             * possibly substituting the given {@link #LABEL} value
4947             * for {@link #TYPE_CUSTOM}.
4948             */
4949            public static final CharSequence getTypeLabel(Resources res, int type,
4950                    CharSequence label) {
4951                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
4952                    return label;
4953                } else {
4954                    final int labelRes = getTypeLabelResource(type);
4955                    return res.getText(labelRes);
4956                }
4957            }
4958
4959            /**
4960             * Return the string resource that best describes the given
4961             * {@link #PROTOCOL}. Will always return a valid resource.
4962             */
4963            public static final int getProtocolLabelResource(int type) {
4964                switch (type) {
4965                    case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim;
4966                    case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn;
4967                    case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo;
4968                    case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype;
4969                    case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq;
4970                    case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk;
4971                    case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq;
4972                    case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber;
4973                    case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting;
4974                    default: return com.android.internal.R.string.imProtocolCustom;
4975                }
4976            }
4977
4978            /**
4979             * Return a {@link CharSequence} that best describes the given
4980             * protocol, possibly substituting the given
4981             * {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}.
4982             */
4983            public static final CharSequence getProtocolLabel(Resources res, int type,
4984                    CharSequence label) {
4985                if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) {
4986                    return label;
4987                } else {
4988                    final int labelRes = getProtocolLabelResource(type);
4989                    return res.getText(labelRes);
4990                }
4991            }
4992        }
4993
4994        /**
4995         * <p>
4996         * A data kind representing an organization.
4997         * </p>
4998         * <p>
4999         * You can use all columns defined for {@link ContactsContract.Data} as
5000         * well as the following aliases.
5001         * </p>
5002         * <h2>Column aliases</h2>
5003         * <table class="jd-sumtable">
5004         * <tr>
5005         * <th>Type</th>
5006         * <th>Alias</th><th colspan='2'>Data column</th>
5007         * </tr>
5008         * <tr>
5009         * <td>String</td>
5010         * <td>{@link #COMPANY}</td>
5011         * <td>{@link #DATA1}</td>
5012         * <td></td>
5013         * </tr>
5014         * <tr>
5015         * <td>int</td>
5016         * <td>{@link #TYPE}</td>
5017         * <td>{@link #DATA2}</td>
5018         * <td>Allowed values are:
5019         * <p>
5020         * <ul>
5021         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
5022         * <li>{@link #TYPE_WORK}</li>
5023         * <li>{@link #TYPE_OTHER}</li>
5024         * </ul>
5025         * </p>
5026         * </td>
5027         * </tr>
5028         * <tr>
5029         * <td>String</td>
5030         * <td>{@link #LABEL}</td>
5031         * <td>{@link #DATA3}</td>
5032         * <td></td>
5033         * </tr>
5034         * <tr>
5035         * <td>String</td>
5036         * <td>{@link #TITLE}</td>
5037         * <td>{@link #DATA4}</td>
5038         * <td></td>
5039         * </tr>
5040         * <tr>
5041         * <td>String</td>
5042         * <td>{@link #DEPARTMENT}</td>
5043         * <td>{@link #DATA5}</td>
5044         * <td></td>
5045         * </tr>
5046         * <tr>
5047         * <td>String</td>
5048         * <td>{@link #JOB_DESCRIPTION}</td>
5049         * <td>{@link #DATA6}</td>
5050         * <td></td>
5051         * </tr>
5052         * <tr>
5053         * <td>String</td>
5054         * <td>{@link #SYMBOL}</td>
5055         * <td>{@link #DATA7}</td>
5056         * <td></td>
5057         * </tr>
5058         * <tr>
5059         * <td>String</td>
5060         * <td>{@link #PHONETIC_NAME}</td>
5061         * <td>{@link #DATA8}</td>
5062         * <td></td>
5063         * </tr>
5064         * <tr>
5065         * <td>String</td>
5066         * <td>{@link #OFFICE_LOCATION}</td>
5067         * <td>{@link #DATA9}</td>
5068         * <td></td>
5069         * </tr>
5070         * <tr>
5071         * <td>String</td>
5072         * <td>PHONETIC_NAME_STYLE</td>
5073         * <td>{@link #DATA10}</td>
5074         * <td></td>
5075         * </tr>
5076         * </table>
5077         */
5078        public static final class Organization implements DataColumnsWithJoins, CommonColumns {
5079            /**
5080             * This utility class cannot be instantiated
5081             */
5082            private Organization() {}
5083
5084            /** MIME type used when storing this in data table. */
5085            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
5086
5087            public static final int TYPE_WORK = 1;
5088            public static final int TYPE_OTHER = 2;
5089
5090            /**
5091             * The company as the user entered it.
5092             * <P>Type: TEXT</P>
5093             */
5094            public static final String COMPANY = DATA;
5095
5096            /**
5097             * The position title at this company as the user entered it.
5098             * <P>Type: TEXT</P>
5099             */
5100            public static final String TITLE = DATA4;
5101
5102            /**
5103             * The department at this company as the user entered it.
5104             * <P>Type: TEXT</P>
5105             */
5106            public static final String DEPARTMENT = DATA5;
5107
5108            /**
5109             * The job description at this company as the user entered it.
5110             * <P>Type: TEXT</P>
5111             */
5112            public static final String JOB_DESCRIPTION = DATA6;
5113
5114            /**
5115             * The symbol of this company as the user entered it.
5116             * <P>Type: TEXT</P>
5117             */
5118            public static final String SYMBOL = DATA7;
5119
5120            /**
5121             * The phonetic name of this company as the user entered it.
5122             * <P>Type: TEXT</P>
5123             */
5124            public static final String PHONETIC_NAME = DATA8;
5125
5126            /**
5127             * The office location of this organization.
5128             * <P>Type: TEXT</P>
5129             */
5130            public static final String OFFICE_LOCATION = DATA9;
5131
5132            /**
5133             * The alphabet used for capturing the phonetic name.
5134             * See {@link ContactsContract.PhoneticNameStyle}.
5135             * @hide
5136             */
5137            public static final String PHONETIC_NAME_STYLE = DATA10;
5138
5139            /**
5140             * Return the string resource that best describes the given
5141             * {@link #TYPE}. Will always return a valid resource.
5142             */
5143            public static final int getTypeLabelResource(int type) {
5144                switch (type) {
5145                    case TYPE_WORK: return com.android.internal.R.string.orgTypeWork;
5146                    case TYPE_OTHER: return com.android.internal.R.string.orgTypeOther;
5147                    default: return com.android.internal.R.string.orgTypeCustom;
5148                }
5149            }
5150
5151            /**
5152             * Return a {@link CharSequence} that best describes the given type,
5153             * possibly substituting the given {@link #LABEL} value
5154             * for {@link #TYPE_CUSTOM}.
5155             */
5156            public static final CharSequence getTypeLabel(Resources res, int type,
5157                    CharSequence label) {
5158                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
5159                    return label;
5160                } else {
5161                    final int labelRes = getTypeLabelResource(type);
5162                    return res.getText(labelRes);
5163                }
5164            }
5165        }
5166
5167        /**
5168         * <p>
5169         * A data kind representing a relation.
5170         * </p>
5171         * <p>
5172         * You can use all columns defined for {@link ContactsContract.Data} as
5173         * well as the following aliases.
5174         * </p>
5175         * <h2>Column aliases</h2>
5176         * <table class="jd-sumtable">
5177         * <tr>
5178         * <th>Type</th>
5179         * <th>Alias</th><th colspan='2'>Data column</th>
5180         * </tr>
5181         * <tr>
5182         * <td>String</td>
5183         * <td>{@link #NAME}</td>
5184         * <td>{@link #DATA1}</td>
5185         * <td></td>
5186         * </tr>
5187         * <tr>
5188         * <td>int</td>
5189         * <td>{@link #TYPE}</td>
5190         * <td>{@link #DATA2}</td>
5191         * <td>Allowed values are:
5192         * <p>
5193         * <ul>
5194         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
5195         * <li>{@link #TYPE_ASSISTANT}</li>
5196         * <li>{@link #TYPE_BROTHER}</li>
5197         * <li>{@link #TYPE_CHILD}</li>
5198         * <li>{@link #TYPE_DOMESTIC_PARTNER}</li>
5199         * <li>{@link #TYPE_FATHER}</li>
5200         * <li>{@link #TYPE_FRIEND}</li>
5201         * <li>{@link #TYPE_MANAGER}</li>
5202         * <li>{@link #TYPE_MOTHER}</li>
5203         * <li>{@link #TYPE_PARENT}</li>
5204         * <li>{@link #TYPE_PARTNER}</li>
5205         * <li>{@link #TYPE_REFERRED_BY}</li>
5206         * <li>{@link #TYPE_RELATIVE}</li>
5207         * <li>{@link #TYPE_SISTER}</li>
5208         * <li>{@link #TYPE_SPOUSE}</li>
5209         * </ul>
5210         * </p>
5211         * </td>
5212         * </tr>
5213         * <tr>
5214         * <td>String</td>
5215         * <td>{@link #LABEL}</td>
5216         * <td>{@link #DATA3}</td>
5217         * <td></td>
5218         * </tr>
5219         * </table>
5220         */
5221        public static final class Relation implements DataColumnsWithJoins, CommonColumns {
5222            /**
5223             * This utility class cannot be instantiated
5224             */
5225            private Relation() {}
5226
5227            /** MIME type used when storing this in data table. */
5228            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
5229
5230            public static final int TYPE_ASSISTANT = 1;
5231            public static final int TYPE_BROTHER = 2;
5232            public static final int TYPE_CHILD = 3;
5233            public static final int TYPE_DOMESTIC_PARTNER = 4;
5234            public static final int TYPE_FATHER = 5;
5235            public static final int TYPE_FRIEND = 6;
5236            public static final int TYPE_MANAGER = 7;
5237            public static final int TYPE_MOTHER = 8;
5238            public static final int TYPE_PARENT = 9;
5239            public static final int TYPE_PARTNER = 10;
5240            public static final int TYPE_REFERRED_BY = 11;
5241            public static final int TYPE_RELATIVE = 12;
5242            public static final int TYPE_SISTER = 13;
5243            public static final int TYPE_SPOUSE = 14;
5244
5245            /**
5246             * The name of the relative as the user entered it.
5247             * <P>Type: TEXT</P>
5248             */
5249            public static final String NAME = DATA;
5250
5251            /**
5252             * Return the string resource that best describes the given
5253             * {@link #TYPE}. Will always return a valid resource.
5254             */
5255            public static final int getTypeLabelResource(int type) {
5256                switch (type) {
5257                    case TYPE_ASSISTANT: return com.android.internal.R.string.relationTypeAssistant;
5258                    case TYPE_BROTHER: return com.android.internal.R.string.relationTypeBrother;
5259                    case TYPE_CHILD: return com.android.internal.R.string.relationTypeChild;
5260                    case TYPE_DOMESTIC_PARTNER:
5261                            return com.android.internal.R.string.relationTypeDomesticPartner;
5262                    case TYPE_FATHER: return com.android.internal.R.string.relationTypeFather;
5263                    case TYPE_FRIEND: return com.android.internal.R.string.relationTypeFriend;
5264                    case TYPE_MANAGER: return com.android.internal.R.string.relationTypeManager;
5265                    case TYPE_MOTHER: return com.android.internal.R.string.relationTypeMother;
5266                    case TYPE_PARENT: return com.android.internal.R.string.relationTypeParent;
5267                    case TYPE_PARTNER: return com.android.internal.R.string.relationTypePartner;
5268                    case TYPE_REFERRED_BY:
5269                            return com.android.internal.R.string.relationTypeReferredBy;
5270                    case TYPE_RELATIVE: return com.android.internal.R.string.relationTypeRelative;
5271                    case TYPE_SISTER: return com.android.internal.R.string.relationTypeSister;
5272                    case TYPE_SPOUSE: return com.android.internal.R.string.relationTypeSpouse;
5273                    default: return com.android.internal.R.string.orgTypeCustom;
5274                }
5275            }
5276
5277            /**
5278             * Return a {@link CharSequence} that best describes the given type,
5279             * possibly substituting the given {@link #LABEL} value
5280             * for {@link #TYPE_CUSTOM}.
5281             */
5282            public static final CharSequence getTypeLabel(Resources res, int type,
5283                    CharSequence label) {
5284                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
5285                    return label;
5286                } else {
5287                    final int labelRes = getTypeLabelResource(type);
5288                    return res.getText(labelRes);
5289                }
5290            }
5291        }
5292
5293        /**
5294         * <p>
5295         * A data kind representing an event.
5296         * </p>
5297         * <p>
5298         * You can use all columns defined for {@link ContactsContract.Data} as
5299         * well as the following aliases.
5300         * </p>
5301         * <h2>Column aliases</h2>
5302         * <table class="jd-sumtable">
5303         * <tr>
5304         * <th>Type</th>
5305         * <th>Alias</th><th colspan='2'>Data column</th>
5306         * </tr>
5307         * <tr>
5308         * <td>String</td>
5309         * <td>{@link #START_DATE}</td>
5310         * <td>{@link #DATA1}</td>
5311         * <td></td>
5312         * </tr>
5313         * <tr>
5314         * <td>int</td>
5315         * <td>{@link #TYPE}</td>
5316         * <td>{@link #DATA2}</td>
5317         * <td>Allowed values are:
5318         * <p>
5319         * <ul>
5320         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
5321         * <li>{@link #TYPE_ANNIVERSARY}</li>
5322         * <li>{@link #TYPE_OTHER}</li>
5323         * <li>{@link #TYPE_BIRTHDAY}</li>
5324         * </ul>
5325         * </p>
5326         * </td>
5327         * </tr>
5328         * <tr>
5329         * <td>String</td>
5330         * <td>{@link #LABEL}</td>
5331         * <td>{@link #DATA3}</td>
5332         * <td></td>
5333         * </tr>
5334         * </table>
5335         */
5336        public static final class Event implements DataColumnsWithJoins, CommonColumns {
5337            /**
5338             * This utility class cannot be instantiated
5339             */
5340            private Event() {}
5341
5342            /** MIME type used when storing this in data table. */
5343            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
5344
5345            public static final int TYPE_ANNIVERSARY = 1;
5346            public static final int TYPE_OTHER = 2;
5347            public static final int TYPE_BIRTHDAY = 3;
5348
5349            /**
5350             * The event start date as the user entered it.
5351             * <P>Type: TEXT</P>
5352             */
5353            public static final String START_DATE = DATA;
5354
5355            /**
5356             * Return the string resource that best describes the given
5357             * {@link #TYPE}. Will always return a valid resource.
5358             */
5359            public static int getTypeResource(Integer type) {
5360                if (type == null) {
5361                    return com.android.internal.R.string.eventTypeOther;
5362                }
5363                switch (type) {
5364                    case TYPE_ANNIVERSARY:
5365                        return com.android.internal.R.string.eventTypeAnniversary;
5366                    case TYPE_BIRTHDAY: return com.android.internal.R.string.eventTypeBirthday;
5367                    case TYPE_OTHER: return com.android.internal.R.string.eventTypeOther;
5368                    default: return com.android.internal.R.string.eventTypeCustom;
5369                }
5370            }
5371        }
5372
5373        /**
5374         * <p>
5375         * A data kind representing an photo for the contact.
5376         * </p>
5377         * <p>
5378         * Some sync adapters will choose to download photos in a separate
5379         * pass. A common pattern is to use columns {@link ContactsContract.Data#SYNC1}
5380         * through {@link ContactsContract.Data#SYNC4} to store temporary
5381         * data, e.g. the image URL or ID, state of download, server-side version
5382         * of the image.  It is allowed for the {@link #PHOTO} to be null.
5383         * </p>
5384         * <p>
5385         * You can use all columns defined for {@link ContactsContract.Data} as
5386         * well as the following aliases.
5387         * </p>
5388         * <h2>Column aliases</h2>
5389         * <table class="jd-sumtable">
5390         * <tr>
5391         * <th>Type</th>
5392         * <th>Alias</th><th colspan='2'>Data column</th>
5393         * </tr>
5394         * <tr>
5395         * <td>BLOB</td>
5396         * <td>{@link #PHOTO}</td>
5397         * <td>{@link #DATA15}</td>
5398         * <td>By convention, binary data is stored in DATA15.</td>
5399         * </tr>
5400         * </table>
5401         */
5402        public static final class Photo implements DataColumnsWithJoins {
5403            /**
5404             * This utility class cannot be instantiated
5405             */
5406            private Photo() {}
5407
5408            /** MIME type used when storing this in data table. */
5409            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
5410
5411            /**
5412             * Thumbnail photo of the raw contact. This is the raw bytes of an image
5413             * that could be inflated using {@link android.graphics.BitmapFactory}.
5414             * <p>
5415             * Type: BLOB
5416             */
5417            public static final String PHOTO = DATA15;
5418        }
5419
5420        /**
5421         * <p>
5422         * Notes about the contact.
5423         * </p>
5424         * <p>
5425         * You can use all columns defined for {@link ContactsContract.Data} as
5426         * well as the following aliases.
5427         * </p>
5428         * <h2>Column aliases</h2>
5429         * <table class="jd-sumtable">
5430         * <tr>
5431         * <th>Type</th>
5432         * <th>Alias</th><th colspan='2'>Data column</th>
5433         * </tr>
5434         * <tr>
5435         * <td>String</td>
5436         * <td>{@link #NOTE}</td>
5437         * <td>{@link #DATA1}</td>
5438         * <td></td>
5439         * </tr>
5440         * </table>
5441         */
5442        public static final class Note implements DataColumnsWithJoins {
5443            /**
5444             * This utility class cannot be instantiated
5445             */
5446            private Note() {}
5447
5448            /** MIME type used when storing this in data table. */
5449            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
5450
5451            /**
5452             * The note text.
5453             * <P>Type: TEXT</P>
5454             */
5455            public static final String NOTE = DATA1;
5456        }
5457
5458        /**
5459         * <p>
5460         * Group Membership.
5461         * </p>
5462         * <p>
5463         * You can use all columns defined for {@link ContactsContract.Data} as
5464         * well as the following aliases.
5465         * </p>
5466         * <h2>Column aliases</h2>
5467         * <table class="jd-sumtable">
5468         * <tr>
5469         * <th>Type</th>
5470         * <th>Alias</th><th colspan='2'>Data column</th>
5471         * </tr>
5472         * <tr>
5473         * <td>long</td>
5474         * <td>{@link #GROUP_ROW_ID}</td>
5475         * <td>{@link #DATA1}</td>
5476         * <td></td>
5477         * </tr>
5478         * <tr>
5479         * <td>String</td>
5480         * <td>{@link #GROUP_SOURCE_ID}</td>
5481         * <td>none</td>
5482         * <td>
5483         * <p>
5484         * The sourceid of the group that this group membership refers to.
5485         * Exactly one of this or {@link #GROUP_ROW_ID} must be set when
5486         * inserting a row.
5487         * </p>
5488         * <p>
5489         * If this field is specified, the provider will first try to
5490         * look up a group with this {@link Groups Groups.SOURCE_ID}.  If such a group
5491         * is found, it will use the corresponding row id.  If the group is not
5492         * found, it will create one.
5493         * </td>
5494         * </tr>
5495         * </table>
5496         */
5497        public static final class GroupMembership implements DataColumnsWithJoins {
5498            /**
5499             * This utility class cannot be instantiated
5500             */
5501            private GroupMembership() {}
5502
5503            /** MIME type used when storing this in data table. */
5504            public static final String CONTENT_ITEM_TYPE =
5505                    "vnd.android.cursor.item/group_membership";
5506
5507            /**
5508             * The row id of the group that this group membership refers to. Exactly one of
5509             * this or {@link #GROUP_SOURCE_ID} must be set when inserting a row.
5510             * <P>Type: INTEGER</P>
5511             */
5512            public static final String GROUP_ROW_ID = DATA1;
5513
5514            /**
5515             * The sourceid of the group that this group membership refers to.  Exactly one of
5516             * this or {@link #GROUP_ROW_ID} must be set when inserting a row.
5517             * <P>Type: TEXT</P>
5518             */
5519            public static final String GROUP_SOURCE_ID = "group_sourceid";
5520        }
5521
5522        /**
5523         * <p>
5524         * A data kind representing a website related to the contact.
5525         * </p>
5526         * <p>
5527         * You can use all columns defined for {@link ContactsContract.Data} as
5528         * well as the following aliases.
5529         * </p>
5530         * <h2>Column aliases</h2>
5531         * <table class="jd-sumtable">
5532         * <tr>
5533         * <th>Type</th>
5534         * <th>Alias</th><th colspan='2'>Data column</th>
5535         * </tr>
5536         * <tr>
5537         * <td>String</td>
5538         * <td>{@link #URL}</td>
5539         * <td>{@link #DATA1}</td>
5540         * <td></td>
5541         * </tr>
5542         * <tr>
5543         * <td>int</td>
5544         * <td>{@link #TYPE}</td>
5545         * <td>{@link #DATA2}</td>
5546         * <td>Allowed values are:
5547         * <p>
5548         * <ul>
5549         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
5550         * <li>{@link #TYPE_HOMEPAGE}</li>
5551         * <li>{@link #TYPE_BLOG}</li>
5552         * <li>{@link #TYPE_PROFILE}</li>
5553         * <li>{@link #TYPE_HOME}</li>
5554         * <li>{@link #TYPE_WORK}</li>
5555         * <li>{@link #TYPE_FTP}</li>
5556         * <li>{@link #TYPE_OTHER}</li>
5557         * </ul>
5558         * </p>
5559         * </td>
5560         * </tr>
5561         * <tr>
5562         * <td>String</td>
5563         * <td>{@link #LABEL}</td>
5564         * <td>{@link #DATA3}</td>
5565         * <td></td>
5566         * </tr>
5567         * </table>
5568         */
5569        public static final class Website implements DataColumnsWithJoins, CommonColumns {
5570            /**
5571             * This utility class cannot be instantiated
5572             */
5573            private Website() {}
5574
5575            /** MIME type used when storing this in data table. */
5576            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
5577
5578            public static final int TYPE_HOMEPAGE = 1;
5579            public static final int TYPE_BLOG = 2;
5580            public static final int TYPE_PROFILE = 3;
5581            public static final int TYPE_HOME = 4;
5582            public static final int TYPE_WORK = 5;
5583            public static final int TYPE_FTP = 6;
5584            public static final int TYPE_OTHER = 7;
5585
5586            /**
5587             * The website URL string.
5588             * <P>Type: TEXT</P>
5589             */
5590            public static final String URL = DATA;
5591        }
5592
5593        /**
5594         * <p>
5595         * A data kind representing a SIP address for the contact.
5596         * </p>
5597         * <p>
5598         * You can use all columns defined for {@link ContactsContract.Data} as
5599         * well as the following aliases.
5600         * </p>
5601         * <h2>Column aliases</h2>
5602         * <table class="jd-sumtable">
5603         * <tr>
5604         * <th>Type</th>
5605         * <th>Alias</th><th colspan='2'>Data column</th>
5606         * </tr>
5607         * <tr>
5608         * <td>String</td>
5609         * <td>{@link #SIP_ADDRESS}</td>
5610         * <td>{@link #DATA1}</td>
5611         * <td></td>
5612         * </tr>
5613         * <tr>
5614         * <td>int</td>
5615         * <td>{@link #TYPE}</td>
5616         * <td>{@link #DATA2}</td>
5617         * <td>Allowed values are:
5618         * <p>
5619         * <ul>
5620         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
5621         * <li>{@link #TYPE_HOME}</li>
5622         * <li>{@link #TYPE_WORK}</li>
5623         * <li>{@link #TYPE_OTHER}</li>
5624         * </ul>
5625         * </p>
5626         * </td>
5627         * </tr>
5628         * <tr>
5629         * <td>String</td>
5630         * <td>{@link #LABEL}</td>
5631         * <td>{@link #DATA3}</td>
5632         * <td></td>
5633         * </tr>
5634         * </table>
5635         */
5636        public static final class SipAddress implements DataColumnsWithJoins, CommonColumns {
5637            /**
5638             * This utility class cannot be instantiated
5639             */
5640            private SipAddress() {}
5641
5642            /** MIME type used when storing this in data table. */
5643            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
5644
5645            public static final int TYPE_HOME = 1;
5646            public static final int TYPE_WORK = 2;
5647            public static final int TYPE_OTHER = 3;
5648
5649            /**
5650             * The SIP address.
5651             * <P>Type: TEXT</P>
5652             */
5653            public static final String SIP_ADDRESS = DATA1;
5654            // ...and TYPE and LABEL come from the CommonColumns interface.
5655
5656            /**
5657             * Return the string resource that best describes the given
5658             * {@link #TYPE}. Will always return a valid resource.
5659             */
5660            public static final int getTypeLabelResource(int type) {
5661                switch (type) {
5662                    case TYPE_HOME: return com.android.internal.R.string.sipAddressTypeHome;
5663                    case TYPE_WORK: return com.android.internal.R.string.sipAddressTypeWork;
5664                    case TYPE_OTHER: return com.android.internal.R.string.sipAddressTypeOther;
5665                    default: return com.android.internal.R.string.sipAddressTypeCustom;
5666                }
5667            }
5668
5669            /**
5670             * Return a {@link CharSequence} that best describes the given type,
5671             * possibly substituting the given {@link #LABEL} value
5672             * for {@link #TYPE_CUSTOM}.
5673             */
5674            public static final CharSequence getTypeLabel(Resources res, int type,
5675                    CharSequence label) {
5676                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
5677                    return label;
5678                } else {
5679                    final int labelRes = getTypeLabelResource(type);
5680                    return res.getText(labelRes);
5681                }
5682            }
5683        }
5684    }
5685
5686    /**
5687     * @see Groups
5688     */
5689    protected interface GroupsColumns {
5690        /**
5691         * The display title of this group.
5692         * <p>
5693         * Type: TEXT
5694         */
5695        public static final String TITLE = "title";
5696
5697        /**
5698         * The package name to use when creating {@link Resources} objects for
5699         * this group. This value is only designed for use when building user
5700         * interfaces, and should not be used to infer the owner.
5701         *
5702         * @hide
5703         */
5704        public static final String RES_PACKAGE = "res_package";
5705
5706        /**
5707         * The display title of this group to load as a resource from
5708         * {@link #RES_PACKAGE}, which may be localized.
5709         * <P>Type: TEXT</P>
5710         *
5711         * @hide
5712         */
5713        public static final String TITLE_RES = "title_res";
5714
5715        /**
5716         * Notes about the group.
5717         * <p>
5718         * Type: TEXT
5719         */
5720        public static final String NOTES = "notes";
5721
5722        /**
5723         * The ID of this group if it is a System Group, i.e. a group that has a special meaning
5724         * to the sync adapter, null otherwise.
5725         * <P>Type: TEXT</P>
5726         */
5727        public static final String SYSTEM_ID = "system_id";
5728
5729        /**
5730         * The total number of {@link Contacts} that have
5731         * {@link CommonDataKinds.GroupMembership} in this group. Read-only value that is only
5732         * present when querying {@link Groups#CONTENT_SUMMARY_URI}.
5733         * <p>
5734         * Type: INTEGER
5735         */
5736        public static final String SUMMARY_COUNT = "summ_count";
5737
5738        /**
5739         * The total number of {@link Contacts} that have both
5740         * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers.
5741         * Read-only value that is only present when querying
5742         * {@link Groups#CONTENT_SUMMARY_URI}.
5743         * <p>
5744         * Type: INTEGER
5745         */
5746        public static final String SUMMARY_WITH_PHONES = "summ_phones";
5747
5748        /**
5749         * Flag indicating if the contacts belonging to this group should be
5750         * visible in any user interface.
5751         * <p>
5752         * Type: INTEGER (boolean)
5753         */
5754        public static final String GROUP_VISIBLE = "group_visible";
5755
5756        /**
5757         * The "deleted" flag: "0" by default, "1" if the row has been marked
5758         * for deletion. When {@link android.content.ContentResolver#delete} is
5759         * called on a group, it is marked for deletion. The sync adaptor
5760         * deletes the group on the server and then calls ContactResolver.delete
5761         * once more, this time setting the the
5762         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to
5763         * finalize the data removal.
5764         * <P>Type: INTEGER</P>
5765         */
5766        public static final String DELETED = "deleted";
5767
5768        /**
5769         * Whether this group should be synced if the SYNC_EVERYTHING settings
5770         * is false for this group's account.
5771         * <p>
5772         * Type: INTEGER (boolean)
5773         */
5774        public static final String SHOULD_SYNC = "should_sync";
5775
5776        /**
5777         * Any newly created contacts will automatically be added to groups that have this
5778         * flag set to true.
5779         * <p>
5780         * Type: INTEGER (boolean)
5781         */
5782        public static final String AUTO_ADD = "auto_add";
5783
5784        /**
5785         * When a contacts is marked as a favorites it will be automatically added
5786         * to the groups that have this flag set, and when it is removed from favorites
5787         * it will be removed from these groups.
5788         * <p>
5789         * Type: INTEGER (boolean)
5790         */
5791        public static final String FAVORITES = "favorites";
5792
5793        /**
5794         * The "read-only" flag: "0" by default, "1" if the row cannot be modified or
5795         * deleted except by a sync adapter.  See {@link ContactsContract#CALLER_IS_SYNCADAPTER}.
5796         * <P>Type: INTEGER</P>
5797         */
5798        public static final String GROUP_IS_READ_ONLY = "group_is_read_only";
5799    }
5800
5801    /**
5802     * Constants for the groups table. Only per-account groups are supported.
5803     * <h2>Columns</h2>
5804     * <table class="jd-sumtable">
5805     * <tr>
5806     * <th colspan='4'>Groups</th>
5807     * </tr>
5808     * <tr>
5809     * <td>long</td>
5810     * <td>{@link #_ID}</td>
5811     * <td>read-only</td>
5812     * <td>Row ID. Sync adapter should try to preserve row IDs during updates.
5813     * In other words, it would be a really bad idea to delete and reinsert a
5814     * group. A sync adapter should always do an update instead.</td>
5815     * </tr>
5816     * <tr>
5817     * <td>String</td>
5818     * <td>{@link #TITLE}</td>
5819     * <td>read/write</td>
5820     * <td>The display title of this group.</td>
5821     * </tr>
5822     * <tr>
5823     * <td>String</td>
5824     * <td>{@link #NOTES}</td>
5825     * <td>read/write</td>
5826     * <td>Notes about the group.</td>
5827     * </tr>
5828     * <tr>
5829     * <td>String</td>
5830     * <td>{@link #SYSTEM_ID}</td>
5831     * <td>read/write</td>
5832     * <td>The ID of this group if it is a System Group, i.e. a group that has a
5833     * special meaning to the sync adapter, null otherwise.</td>
5834     * </tr>
5835     * <tr>
5836     * <td>int</td>
5837     * <td>{@link #SUMMARY_COUNT}</td>
5838     * <td>read-only</td>
5839     * <td>The total number of {@link Contacts} that have
5840     * {@link CommonDataKinds.GroupMembership} in this group. Read-only value
5841     * that is only present when querying {@link Groups#CONTENT_SUMMARY_URI}.</td>
5842     * </tr>
5843     * <tr>
5844     * <td>int</td>
5845     * <td>{@link #SUMMARY_WITH_PHONES}</td>
5846     * <td>read-only</td>
5847     * <td>The total number of {@link Contacts} that have both
5848     * {@link CommonDataKinds.GroupMembership} in this group, and also have
5849     * phone numbers. Read-only value that is only present when querying
5850     * {@link Groups#CONTENT_SUMMARY_URI}.</td>
5851     * </tr>
5852     * <tr>
5853     * <td>int</td>
5854     * <td>{@link #GROUP_VISIBLE}</td>
5855     * <td>read-only</td>
5856     * <td>Flag indicating if the contacts belonging to this group should be
5857     * visible in any user interface. Allowed values: 0 and 1.</td>
5858     * </tr>
5859     * <tr>
5860     * <td>int</td>
5861     * <td>{@link #DELETED}</td>
5862     * <td>read/write</td>
5863     * <td>The "deleted" flag: "0" by default, "1" if the row has been marked
5864     * for deletion. When {@link android.content.ContentResolver#delete} is
5865     * called on a group, it is marked for deletion. The sync adaptor deletes
5866     * the group on the server and then calls ContactResolver.delete once more,
5867     * this time setting the the {@link ContactsContract#CALLER_IS_SYNCADAPTER}
5868     * query parameter to finalize the data removal.</td>
5869     * </tr>
5870     * <tr>
5871     * <td>int</td>
5872     * <td>{@link #SHOULD_SYNC}</td>
5873     * <td>read/write</td>
5874     * <td>Whether this group should be synced if the SYNC_EVERYTHING settings
5875     * is false for this group's account.</td>
5876     * </tr>
5877     * </table>
5878     */
5879    public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns {
5880        /**
5881         * This utility class cannot be instantiated
5882         */
5883        private Groups() {
5884        }
5885
5886        /**
5887         * The content:// style URI for this table
5888         */
5889        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "groups");
5890
5891        /**
5892         * The content:// style URI for this table joined with details data from
5893         * {@link ContactsContract.Data}.
5894         */
5895        public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
5896                "groups_summary");
5897
5898        /**
5899         * The MIME type of a directory of groups.
5900         */
5901        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/group";
5902
5903        /**
5904         * The MIME type of a single group.
5905         */
5906        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
5907
5908        public static EntityIterator newEntityIterator(Cursor cursor) {
5909            return new EntityIteratorImpl(cursor);
5910        }
5911
5912        private static class EntityIteratorImpl extends CursorEntityIterator {
5913            public EntityIteratorImpl(Cursor cursor) {
5914                super(cursor);
5915            }
5916
5917            @Override
5918            public Entity getEntityAndIncrementCursor(Cursor cursor) throws RemoteException {
5919                // we expect the cursor is already at the row we need to read from
5920                final ContentValues values = new ContentValues();
5921                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, _ID);
5922                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_NAME);
5923                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, ACCOUNT_TYPE);
5924                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DIRTY);
5925                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, VERSION);
5926                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SOURCE_ID);
5927                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, RES_PACKAGE);
5928                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE);
5929                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, TITLE_RES);
5930                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, GROUP_VISIBLE);
5931                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC1);
5932                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC2);
5933                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC3);
5934                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYNC4);
5935                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SYSTEM_ID);
5936                DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, values, DELETED);
5937                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, NOTES);
5938                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, SHOULD_SYNC);
5939                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, FAVORITES);
5940                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, values, AUTO_ADD);
5941                cursor.moveToNext();
5942                return new Entity(values);
5943            }
5944        }
5945    }
5946
5947    /**
5948     * <p>
5949     * Constants for the contact aggregation exceptions table, which contains
5950     * aggregation rules overriding those used by automatic aggregation. This
5951     * type only supports query and update. Neither insert nor delete are
5952     * supported.
5953     * </p>
5954     * <h2>Columns</h2>
5955     * <table class="jd-sumtable">
5956     * <tr>
5957     * <th colspan='4'>AggregationExceptions</th>
5958     * </tr>
5959     * <tr>
5960     * <td>int</td>
5961     * <td>{@link #TYPE}</td>
5962     * <td>read/write</td>
5963     * <td>The type of exception: {@link #TYPE_KEEP_TOGETHER},
5964     * {@link #TYPE_KEEP_SEPARATE} or {@link #TYPE_AUTOMATIC}.</td>
5965     * </tr>
5966     * <tr>
5967     * <td>long</td>
5968     * <td>{@link #RAW_CONTACT_ID1}</td>
5969     * <td>read/write</td>
5970     * <td>A reference to the {@link RawContacts#_ID} of the raw contact that
5971     * the rule applies to.</td>
5972     * </tr>
5973     * <tr>
5974     * <td>long</td>
5975     * <td>{@link #RAW_CONTACT_ID2}</td>
5976     * <td>read/write</td>
5977     * <td>A reference to the other {@link RawContacts#_ID} of the raw contact
5978     * that the rule applies to.</td>
5979     * </tr>
5980     * </table>
5981     */
5982    public static final class AggregationExceptions implements BaseColumns {
5983        /**
5984         * This utility class cannot be instantiated
5985         */
5986        private AggregationExceptions() {}
5987
5988        /**
5989         * The content:// style URI for this table
5990         */
5991        public static final Uri CONTENT_URI =
5992                Uri.withAppendedPath(AUTHORITY_URI, "aggregation_exceptions");
5993
5994        /**
5995         * The MIME type of {@link #CONTENT_URI} providing a directory of data.
5996         */
5997        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception";
5998
5999        /**
6000         * The MIME type of a {@link #CONTENT_URI} subdirectory of an aggregation exception
6001         */
6002        public static final String CONTENT_ITEM_TYPE =
6003                "vnd.android.cursor.item/aggregation_exception";
6004
6005        /**
6006         * The type of exception: {@link #TYPE_KEEP_TOGETHER}, {@link #TYPE_KEEP_SEPARATE} or
6007         * {@link #TYPE_AUTOMATIC}.
6008         *
6009         * <P>Type: INTEGER</P>
6010         */
6011        public static final String TYPE = "type";
6012
6013        /**
6014         * Allows the provider to automatically decide whether the specified raw contacts should
6015         * be included in the same aggregate contact or not.
6016         */
6017        public static final int TYPE_AUTOMATIC = 0;
6018
6019        /**
6020         * Makes sure that the specified raw contacts are included in the same
6021         * aggregate contact.
6022         */
6023        public static final int TYPE_KEEP_TOGETHER = 1;
6024
6025        /**
6026         * Makes sure that the specified raw contacts are NOT included in the same
6027         * aggregate contact.
6028         */
6029        public static final int TYPE_KEEP_SEPARATE = 2;
6030
6031        /**
6032         * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to.
6033         */
6034        public static final String RAW_CONTACT_ID1 = "raw_contact_id1";
6035
6036        /**
6037         * A reference to the other {@link RawContacts#_ID} of the raw contact that the rule
6038         * applies to.
6039         */
6040        public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
6041    }
6042
6043    /**
6044     * @see Settings
6045     */
6046    protected interface SettingsColumns {
6047        /**
6048         * The name of the account instance to which this row belongs.
6049         * <P>Type: TEXT</P>
6050         */
6051        public static final String ACCOUNT_NAME = "account_name";
6052
6053        /**
6054         * The type of account to which this row belongs, which when paired with
6055         * {@link #ACCOUNT_NAME} identifies a specific account.
6056         * <P>Type: TEXT</P>
6057         */
6058        public static final String ACCOUNT_TYPE = "account_type";
6059
6060        /**
6061         * Depending on the mode defined by the sync-adapter, this flag controls
6062         * the top-level sync behavior for this data source.
6063         * <p>
6064         * Type: INTEGER (boolean)
6065         */
6066        public static final String SHOULD_SYNC = "should_sync";
6067
6068        /**
6069         * Flag indicating if contacts without any {@link CommonDataKinds.GroupMembership}
6070         * entries should be visible in any user interface.
6071         * <p>
6072         * Type: INTEGER (boolean)
6073         */
6074        public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
6075
6076        /**
6077         * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
6078         * {@link Groups#SHOULD_SYNC} under this account have been marked as
6079         * unsynced.
6080         */
6081        public static final String ANY_UNSYNCED = "any_unsynced";
6082
6083        /**
6084         * Read-only count of {@link Contacts} from a specific source that have
6085         * no {@link CommonDataKinds.GroupMembership} entries.
6086         * <p>
6087         * Type: INTEGER
6088         */
6089        public static final String UNGROUPED_COUNT = "summ_count";
6090
6091        /**
6092         * Read-only count of {@link Contacts} from a specific source that have
6093         * no {@link CommonDataKinds.GroupMembership} entries, and also have phone numbers.
6094         * <p>
6095         * Type: INTEGER
6096         */
6097        public static final String UNGROUPED_WITH_PHONES = "summ_phones";
6098    }
6099
6100    /**
6101     * <p>
6102     * Contacts-specific settings for various {@link Account}'s.
6103     * </p>
6104     * <h2>Columns</h2>
6105     * <table class="jd-sumtable">
6106     * <tr>
6107     * <th colspan='4'>Settings</th>
6108     * </tr>
6109     * <tr>
6110     * <td>String</td>
6111     * <td>{@link #ACCOUNT_NAME}</td>
6112     * <td>read/write-once</td>
6113     * <td>The name of the account instance to which this row belongs.</td>
6114     * </tr>
6115     * <tr>
6116     * <td>String</td>
6117     * <td>{@link #ACCOUNT_TYPE}</td>
6118     * <td>read/write-once</td>
6119     * <td>The type of account to which this row belongs, which when paired with
6120     * {@link #ACCOUNT_NAME} identifies a specific account.</td>
6121     * </tr>
6122     * <tr>
6123     * <td>int</td>
6124     * <td>{@link #SHOULD_SYNC}</td>
6125     * <td>read/write</td>
6126     * <td>Depending on the mode defined by the sync-adapter, this flag controls
6127     * the top-level sync behavior for this data source.</td>
6128     * </tr>
6129     * <tr>
6130     * <td>int</td>
6131     * <td>{@link #UNGROUPED_VISIBLE}</td>
6132     * <td>read/write</td>
6133     * <td>Flag indicating if contacts without any
6134     * {@link CommonDataKinds.GroupMembership} entries should be visible in any
6135     * user interface.</td>
6136     * </tr>
6137     * <tr>
6138     * <td>int</td>
6139     * <td>{@link #ANY_UNSYNCED}</td>
6140     * <td>read-only</td>
6141     * <td>Read-only flag indicating if this {@link #SHOULD_SYNC} or any
6142     * {@link Groups#SHOULD_SYNC} under this account have been marked as
6143     * unsynced.</td>
6144     * </tr>
6145     * <tr>
6146     * <td>int</td>
6147     * <td>{@link #UNGROUPED_COUNT}</td>
6148     * <td>read-only</td>
6149     * <td>Read-only count of {@link Contacts} from a specific source that have
6150     * no {@link CommonDataKinds.GroupMembership} entries.</td>
6151     * </tr>
6152     * <tr>
6153     * <td>int</td>
6154     * <td>{@link #UNGROUPED_WITH_PHONES}</td>
6155     * <td>read-only</td>
6156     * <td>Read-only count of {@link Contacts} from a specific source that have
6157     * no {@link CommonDataKinds.GroupMembership} entries, and also have phone
6158     * numbers.</td>
6159     * </tr>
6160     * </table>
6161     */
6162    public static final class Settings implements SettingsColumns {
6163        /**
6164         * This utility class cannot be instantiated
6165         */
6166        private Settings() {
6167        }
6168
6169        /**
6170         * The content:// style URI for this table
6171         */
6172        public static final Uri CONTENT_URI =
6173                Uri.withAppendedPath(AUTHORITY_URI, "settings");
6174
6175        /**
6176         * The MIME-type of {@link #CONTENT_URI} providing a directory of
6177         * settings.
6178         */
6179        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
6180
6181        /**
6182         * The MIME-type of {@link #CONTENT_URI} providing a single setting.
6183         */
6184        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
6185    }
6186
6187    /**
6188     * Private API for inquiring about the general status of the provider.
6189     *
6190     * @hide
6191     */
6192    public static final class ProviderStatus {
6193
6194        /**
6195         * Not instantiable.
6196         */
6197        private ProviderStatus() {
6198        }
6199
6200        /**
6201         * The content:// style URI for this table.  Requests to this URI can be
6202         * performed on the UI thread because they are always unblocking.
6203         *
6204         * @hide
6205         */
6206        public static final Uri CONTENT_URI =
6207                Uri.withAppendedPath(AUTHORITY_URI, "provider_status");
6208
6209        /**
6210         * The MIME-type of {@link #CONTENT_URI} providing a directory of
6211         * settings.
6212         *
6213         * @hide
6214         */
6215        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status";
6216
6217        /**
6218         * An integer representing the current status of the provider.
6219         *
6220         * @hide
6221         */
6222        public static final String STATUS = "status";
6223
6224        /**
6225         * Default status of the provider.
6226         *
6227         * @hide
6228         */
6229        public static final int STATUS_NORMAL = 0;
6230
6231        /**
6232         * The status used when the provider is in the process of upgrading.  Contacts
6233         * are temporarily unaccessible.
6234         *
6235         * @hide
6236         */
6237        public static final int STATUS_UPGRADING = 1;
6238
6239        /**
6240         * The status used if the provider was in the process of upgrading but ran
6241         * out of storage. The DATA1 column will contain the estimated amount of
6242         * storage required (in bytes). Update status to STATUS_NORMAL to force
6243         * the provider to retry the upgrade.
6244         *
6245         * @hide
6246         */
6247        public static final int STATUS_UPGRADE_OUT_OF_MEMORY = 2;
6248
6249        /**
6250         * The status used during a locale change.
6251         *
6252         * @hide
6253         */
6254        public static final int STATUS_CHANGING_LOCALE = 3;
6255
6256        /**
6257         * The status that indicates that there are no accounts and no contacts
6258         * on the device.
6259         *
6260         * @hide
6261         */
6262        public static final int STATUS_NO_ACCOUNTS_NO_CONTACTS = 4;
6263
6264        /**
6265         * Additional data associated with the status.
6266         *
6267         * @hide
6268         */
6269        public static final String DATA1 = "data1";
6270    }
6271
6272    /**
6273     * <p>
6274     * API allowing applications to send usage information for each {@link Data} row to the
6275     * Contacts Provider.
6276     * </p>
6277     * <p>
6278     * With the feedback, Contacts Provider may return more contextually appropriate results for
6279     * Data listing, typically supplied with
6280     * {@link ContactsContract.Contacts#CONTENT_FILTER_URI},
6281     * {@link ContactsContract.CommonDataKinds.Email#CONTENT_FILTER_URI},
6282     * {@link ContactsContract.CommonDataKinds.Phone#CONTENT_FILTER_URI}, and users can benefit
6283     * from better ranked (sorted) lists in applications that show auto-complete list.
6284     * </p>
6285     * <p>
6286     * There is no guarantee for how this feedback is used, or even whether it is used at all.
6287     * The ranking algorithm will make best efforts to use the feedback data, but the exact
6288     * implementation, the storage data structures as well as the resulting sort order is device
6289     * and version specific and can change over time.
6290     * </p>
6291     * <p>
6292     * When updating usage information, users of this API need to use
6293     * {@link ContentResolver#update(Uri, ContentValues, String, String[])} with a Uri constructed
6294     * from {@link DataUsageFeedback#FEEDBACK_URI}. The Uri must contain one or more data id(s) as
6295     * its last path. They also need to append a query parameter to the Uri, to specify the type of
6296     * the communication, which enables the Contacts Provider to differentiate between kinds of
6297     * interactions using the same contact data field (for example a phone number can be used to
6298     * make phone calls or send SMS).
6299     * </p>
6300     * <p>
6301     * Selection and selectionArgs are ignored and must be set to null. To get data ids,
6302     * you may need to call {@link ContentResolver#query(Uri, String[], String, String[], String)}
6303     * toward {@link Data#CONTENT_URI}.
6304     * </p>
6305     * <p>
6306     * {@link ContentResolver#update(Uri, ContentValues, String, String[])} returns a positive
6307     * integer when successful, and returns 0 if no contact with that id was found.
6308     * </p>
6309     * <p>
6310     * Example:
6311     * <pre>
6312     * Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
6313     *         .appendPath(TextUtils.join(",", dataIds))
6314     *         .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
6315     *                 DataUsageFeedback.USAGE_TYPE_CALL)
6316     *         .build();
6317     * boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0;
6318     * </pre>
6319     * </p>
6320     */
6321    public static final class DataUsageFeedback {
6322
6323        /**
6324         * The content:// style URI for sending usage feedback.
6325         * Must be used with {@link ContentResolver#update(Uri, ContentValues, String, String[])}.
6326         */
6327        public static final Uri FEEDBACK_URI =
6328                Uri.withAppendedPath(Data.CONTENT_URI, "usagefeedback");
6329
6330        /**
6331         * <p>
6332         * Name for query parameter specifying the type of data usage.
6333         * </p>
6334         */
6335        public static final String USAGE_TYPE = "type";
6336
6337        /**
6338         * <p>
6339         * Type of usage for voice interaction, which includes phone call, voice chat, and
6340         * video chat.
6341         * </p>
6342         */
6343        public static final String USAGE_TYPE_CALL = "call";
6344
6345        /**
6346         * <p>
6347         * Type of usage for text interaction involving longer messages, which includes email.
6348         * </p>
6349         */
6350        public static final String USAGE_TYPE_LONG_TEXT = "long_text";
6351
6352        /**
6353         * <p>
6354         * Type of usage for text interaction involving shorter messages, which includes SMS,
6355         * text chat with email addresses.
6356         * </p>
6357         */
6358        public static final String USAGE_TYPE_SHORT_TEXT = "short_text";
6359    }
6360
6361    /**
6362     * Helper methods to display QuickContact dialogs that allow users to pivot on
6363     * a specific {@link Contacts} entry.
6364     */
6365    public static final class QuickContact {
6366        /**
6367         * Action used to trigger person pivot dialog.
6368         * @hide
6369         */
6370        public static final String ACTION_QUICK_CONTACT =
6371                "com.android.contacts.action.QUICK_CONTACT";
6372
6373        /**
6374         * Extra used to specify pivot dialog location in screen coordinates.
6375         * @deprecated Use {@link Intent#setSourceBounds(Rect)} instead.
6376         * @hide
6377         */
6378        @Deprecated
6379        public static final String EXTRA_TARGET_RECT = "target_rect";
6380
6381        /**
6382         * Extra used to specify size of pivot dialog.
6383         * @hide
6384         */
6385        public static final String EXTRA_MODE = "mode";
6386
6387        /**
6388         * Extra used to indicate a list of specific MIME-types to exclude and
6389         * not display. Stored as a {@link String} array.
6390         * @hide
6391         */
6392        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
6393
6394        /**
6395         * Small QuickContact mode, usually presented with minimal actions.
6396         */
6397        public static final int MODE_SMALL = 1;
6398
6399        /**
6400         * Medium QuickContact mode, includes actions and light summary describing
6401         * the {@link Contacts} entry being shown. This may include social
6402         * status and presence details.
6403         */
6404        public static final int MODE_MEDIUM = 2;
6405
6406        /**
6407         * Large QuickContact mode, includes actions and larger, card-like summary
6408         * of the {@link Contacts} entry being shown. This may include detailed
6409         * information, such as a photo.
6410         */
6411        public static final int MODE_LARGE = 3;
6412
6413        /**
6414         * Trigger a dialog that lists the various methods of interacting with
6415         * the requested {@link Contacts} entry. This may be based on available
6416         * {@link ContactsContract.Data} rows under that contact, and may also
6417         * include social status and presence details.
6418         *
6419         * @param context The parent {@link Context} that may be used as the
6420         *            parent for this dialog.
6421         * @param target Specific {@link View} from your layout that this dialog
6422         *            should be centered around. In particular, if the dialog
6423         *            has a "callout" arrow, it will be pointed and centered
6424         *            around this {@link View}.
6425         * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
6426         *            {@link Uri} that describes a specific contact to feature
6427         *            in this dialog.
6428         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
6429         *            {@link #MODE_LARGE}, indicating the desired dialog size,
6430         *            when supported.
6431         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
6432         *            to exclude when showing this dialog. For example, when
6433         *            already viewing the contact details card, this can be used
6434         *            to omit the details entry from the dialog.
6435         */
6436        public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
6437                String[] excludeMimes) {
6438            // Find location and bounds of target view, adjusting based on the
6439            // assumed local density.
6440            final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
6441            final int[] pos = new int[2];
6442            target.getLocationOnScreen(pos);
6443
6444            final Rect rect = new Rect();
6445            rect.left = (int) (pos[0] * appScale + 0.5f);
6446            rect.top = (int) (pos[1] * appScale + 0.5f);
6447            rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
6448            rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
6449
6450            // Trigger with obtained rectangle
6451            showQuickContact(context, rect, lookupUri, mode, excludeMimes);
6452        }
6453
6454        /**
6455         * Trigger a dialog that lists the various methods of interacting with
6456         * the requested {@link Contacts} entry. This may be based on available
6457         * {@link ContactsContract.Data} rows under that contact, and may also
6458         * include social status and presence details.
6459         *
6460         * @param context The parent {@link Context} that may be used as the
6461         *            parent for this dialog.
6462         * @param target Specific {@link Rect} that this dialog should be
6463         *            centered around, in screen coordinates. In particular, if
6464         *            the dialog has a "callout" arrow, it will be pointed and
6465         *            centered around this {@link Rect}. If you are running at a
6466         *            non-native density, you need to manually adjust using
6467         *            {@link DisplayMetrics#density} before calling.
6468         * @param lookupUri A
6469         *            {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
6470         *            {@link Uri} that describes a specific contact to feature
6471         *            in this dialog.
6472         * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
6473         *            {@link #MODE_LARGE}, indicating the desired dialog size,
6474         *            when supported.
6475         * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
6476         *            to exclude when showing this dialog. For example, when
6477         *            already viewing the contact details card, this can be used
6478         *            to omit the details entry from the dialog.
6479         */
6480        public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
6481                String[] excludeMimes) {
6482            // Launch pivot dialog through intent for now
6483            final Intent intent = new Intent(ACTION_QUICK_CONTACT);
6484            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP
6485                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
6486
6487            intent.setData(lookupUri);
6488            intent.setSourceBounds(target);
6489            intent.putExtra(EXTRA_MODE, mode);
6490            intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
6491            context.startActivity(intent);
6492        }
6493    }
6494
6495    /**
6496     * Contains helper classes used to create or manage {@link android.content.Intent Intents}
6497     * that involve contacts.
6498     */
6499    public static final class Intents {
6500        /**
6501         * This is the intent that is fired when a search suggestion is clicked on.
6502         */
6503        public static final String SEARCH_SUGGESTION_CLICKED =
6504                "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
6505
6506        /**
6507         * This is the intent that is fired when a search suggestion for dialing a number
6508         * is clicked on.
6509         */
6510        public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =
6511                "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
6512
6513        /**
6514         * This is the intent that is fired when a search suggestion for creating a contact
6515         * is clicked on.
6516         */
6517        public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =
6518                "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
6519
6520        /**
6521         * Starts an Activity that lets the user pick a contact to attach an image to.
6522         * After picking the contact it launches the image cropper in face detection mode.
6523         */
6524        public static final String ATTACH_IMAGE =
6525                "com.android.contacts.action.ATTACH_IMAGE";
6526
6527        /**
6528         * Takes as input a data URI with a mailto: or tel: scheme. If a single
6529         * contact exists with the given data it will be shown. If no contact
6530         * exists, a dialog will ask the user if they want to create a new
6531         * contact with the provided details filled in. If multiple contacts
6532         * share the data the user will be prompted to pick which contact they
6533         * want to view.
6534         * <p>
6535         * For <code>mailto:</code> URIs, the scheme specific portion must be a
6536         * raw email address, such as one built using
6537         * {@link Uri#fromParts(String, String, String)}.
6538         * <p>
6539         * For <code>tel:</code> URIs, the scheme specific portion is compared
6540         * to existing numbers using the standard caller ID lookup algorithm.
6541         * The number must be properly encoded, for example using
6542         * {@link Uri#fromParts(String, String, String)}.
6543         * <p>
6544         * Any extras from the {@link Insert} class will be passed along to the
6545         * create activity if there are no contacts to show.
6546         * <p>
6547         * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip
6548         * prompting the user when the contact doesn't exist.
6549         */
6550        public static final String SHOW_OR_CREATE_CONTACT =
6551                "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
6552
6553        /**
6554         * Starts an Activity that lets the user select the multiple phones from a
6555         * list of phone numbers which come from the contacts or
6556         * {@link #EXTRA_PHONE_URIS}.
6557         * <p>
6558         * The phone numbers being passed in through {@link #EXTRA_PHONE_URIS}
6559         * could belong to the contacts or not, and will be selected by default.
6560         * <p>
6561         * The user's selection will be returned from
6562         * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)}
6563         * if the resultCode is
6564         * {@link android.app.Activity#RESULT_OK}, the array of picked phone
6565         * numbers are in the Intent's
6566         * {@link #EXTRA_PHONE_URIS}; otherwise, the
6567         * {@link android.app.Activity#RESULT_CANCELED} is returned if the user
6568         * left the Activity without changing the selection.
6569         *
6570         * @hide
6571         */
6572        public static final String ACTION_GET_MULTIPLE_PHONES =
6573                "com.android.contacts.action.GET_MULTIPLE_PHONES";
6574
6575        /**
6576         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
6577         * contact if no matching contact found. Otherwise, default behavior is
6578         * to prompt user with dialog before creating.
6579         * <p>
6580         * Type: BOOLEAN
6581         */
6582        public static final String EXTRA_FORCE_CREATE =
6583                "com.android.contacts.action.FORCE_CREATE";
6584
6585        /**
6586         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact
6587         * description to be shown when prompting user about creating a new
6588         * contact.
6589         * <p>
6590         * Type: STRING
6591         */
6592        public static final String EXTRA_CREATE_DESCRIPTION =
6593            "com.android.contacts.action.CREATE_DESCRIPTION";
6594
6595        /**
6596         * Used with {@link #ACTION_GET_MULTIPLE_PHONES} as the input or output value.
6597         * <p>
6598         * The phone numbers want to be picked by default should be passed in as
6599         * input value. These phone numbers could belong to the contacts or not.
6600         * <p>
6601         * The phone numbers which were picked by the user are returned as output
6602         * value.
6603         * <p>
6604         * Type: array of URIs, the tel URI is used for the phone numbers which don't
6605         * belong to any contact, the content URI is used for phone id in contacts.
6606         *
6607         * @hide
6608         */
6609        public static final String EXTRA_PHONE_URIS =
6610            "com.android.contacts.extra.PHONE_URIS";
6611
6612        /**
6613         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
6614         * dialog location using screen coordinates. When not specified, the
6615         * dialog will be centered.
6616         *
6617         * @hide
6618         */
6619        @Deprecated
6620        public static final String EXTRA_TARGET_RECT = "target_rect";
6621
6622        /**
6623         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
6624         * desired dialog style, usually a variation on size. One of
6625         * {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}.
6626         *
6627         * @hide
6628         */
6629        @Deprecated
6630        public static final String EXTRA_MODE = "mode";
6631
6632        /**
6633         * Value for {@link #EXTRA_MODE} to show a small-sized dialog.
6634         *
6635         * @hide
6636         */
6637        @Deprecated
6638        public static final int MODE_SMALL = 1;
6639
6640        /**
6641         * Value for {@link #EXTRA_MODE} to show a medium-sized dialog.
6642         *
6643         * @hide
6644         */
6645        @Deprecated
6646        public static final int MODE_MEDIUM = 2;
6647
6648        /**
6649         * Value for {@link #EXTRA_MODE} to show a large-sized dialog.
6650         *
6651         * @hide
6652         */
6653        @Deprecated
6654        public static final int MODE_LARGE = 3;
6655
6656        /**
6657         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to indicate
6658         * a list of specific MIME-types to exclude and not display. Stored as a
6659         * {@link String} array.
6660         *
6661         * @hide
6662         */
6663        @Deprecated
6664        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
6665
6666        /**
6667         * Intents related to the Contacts app UI.
6668         *
6669         * @hide
6670         */
6671        public static final class UI {
6672            /**
6673             * The action for the default contacts list tab.
6674             */
6675            public static final String LIST_DEFAULT =
6676                    "com.android.contacts.action.LIST_DEFAULT";
6677
6678            /**
6679             * The action for the contacts list tab.
6680             */
6681            public static final String LIST_GROUP_ACTION =
6682                    "com.android.contacts.action.LIST_GROUP";
6683
6684            /**
6685             * When in LIST_GROUP_ACTION mode, this is the group to display.
6686             */
6687            public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
6688
6689            /**
6690             * The action for the all contacts list tab.
6691             */
6692            public static final String LIST_ALL_CONTACTS_ACTION =
6693                    "com.android.contacts.action.LIST_ALL_CONTACTS";
6694
6695            /**
6696             * The action for the contacts with phone numbers list tab.
6697             */
6698            public static final String LIST_CONTACTS_WITH_PHONES_ACTION =
6699                    "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
6700
6701            /**
6702             * The action for the starred contacts list tab.
6703             */
6704            public static final String LIST_STARRED_ACTION =
6705                    "com.android.contacts.action.LIST_STARRED";
6706
6707            /**
6708             * The action for the frequent contacts list tab.
6709             */
6710            public static final String LIST_FREQUENT_ACTION =
6711                    "com.android.contacts.action.LIST_FREQUENT";
6712
6713            /**
6714             * The action for the "strequent" contacts list tab. It first lists the starred
6715             * contacts in alphabetical order and then the frequent contacts in descending
6716             * order of the number of times they have been contacted.
6717             */
6718            public static final String LIST_STREQUENT_ACTION =
6719                    "com.android.contacts.action.LIST_STREQUENT";
6720
6721            /**
6722             * A key for to be used as an intent extra to set the activity
6723             * title to a custom String value.
6724             */
6725            public static final String TITLE_EXTRA_KEY =
6726                    "com.android.contacts.extra.TITLE_EXTRA";
6727
6728            /**
6729             * Activity Action: Display a filtered list of contacts
6730             * <p>
6731             * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for
6732             * filtering
6733             * <p>
6734             * Output: Nothing.
6735             */
6736            public static final String FILTER_CONTACTS_ACTION =
6737                    "com.android.contacts.action.FILTER_CONTACTS";
6738
6739            /**
6740             * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}
6741             * intents to supply the text on which to filter.
6742             */
6743            public static final String FILTER_TEXT_EXTRA_KEY =
6744                    "com.android.contacts.extra.FILTER_TEXT";
6745        }
6746
6747        /**
6748         * Convenience class that contains string constants used
6749         * to create contact {@link android.content.Intent Intents}.
6750         */
6751        public static final class Insert {
6752            /** The action code to use when adding a contact */
6753            public static final String ACTION = Intent.ACTION_INSERT;
6754
6755            /**
6756             * If present, forces a bypass of quick insert mode.
6757             */
6758            public static final String FULL_MODE = "full_mode";
6759
6760            /**
6761             * The extra field for the contact name.
6762             * <P>Type: String</P>
6763             */
6764            public static final String NAME = "name";
6765
6766            // TODO add structured name values here.
6767
6768            /**
6769             * The extra field for the contact phonetic name.
6770             * <P>Type: String</P>
6771             */
6772            public static final String PHONETIC_NAME = "phonetic_name";
6773
6774            /**
6775             * The extra field for the contact company.
6776             * <P>Type: String</P>
6777             */
6778            public static final String COMPANY = "company";
6779
6780            /**
6781             * The extra field for the contact job title.
6782             * <P>Type: String</P>
6783             */
6784            public static final String JOB_TITLE = "job_title";
6785
6786            /**
6787             * The extra field for the contact notes.
6788             * <P>Type: String</P>
6789             */
6790            public static final String NOTES = "notes";
6791
6792            /**
6793             * The extra field for the contact phone number.
6794             * <P>Type: String</P>
6795             */
6796            public static final String PHONE = "phone";
6797
6798            /**
6799             * The extra field for the contact phone number type.
6800             * <P>Type: Either an integer value from
6801             * {@link CommonDataKinds.Phone},
6802             *  or a string specifying a custom label.</P>
6803             */
6804            public static final String PHONE_TYPE = "phone_type";
6805
6806            /**
6807             * The extra field for the phone isprimary flag.
6808             * <P>Type: boolean</P>
6809             */
6810            public static final String PHONE_ISPRIMARY = "phone_isprimary";
6811
6812            /**
6813             * The extra field for an optional second contact phone number.
6814             * <P>Type: String</P>
6815             */
6816            public static final String SECONDARY_PHONE = "secondary_phone";
6817
6818            /**
6819             * The extra field for an optional second contact phone number type.
6820             * <P>Type: Either an integer value from
6821             * {@link CommonDataKinds.Phone},
6822             *  or a string specifying a custom label.</P>
6823             */
6824            public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
6825
6826            /**
6827             * The extra field for an optional third contact phone number.
6828             * <P>Type: String</P>
6829             */
6830            public static final String TERTIARY_PHONE = "tertiary_phone";
6831
6832            /**
6833             * The extra field for an optional third contact phone number type.
6834             * <P>Type: Either an integer value from
6835             * {@link CommonDataKinds.Phone},
6836             *  or a string specifying a custom label.</P>
6837             */
6838            public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
6839
6840            /**
6841             * The extra field for the contact email address.
6842             * <P>Type: String</P>
6843             */
6844            public static final String EMAIL = "email";
6845
6846            /**
6847             * The extra field for the contact email type.
6848             * <P>Type: Either an integer value from
6849             * {@link CommonDataKinds.Email}
6850             *  or a string specifying a custom label.</P>
6851             */
6852            public static final String EMAIL_TYPE = "email_type";
6853
6854            /**
6855             * The extra field for the email isprimary flag.
6856             * <P>Type: boolean</P>
6857             */
6858            public static final String EMAIL_ISPRIMARY = "email_isprimary";
6859
6860            /**
6861             * The extra field for an optional second contact email address.
6862             * <P>Type: String</P>
6863             */
6864            public static final String SECONDARY_EMAIL = "secondary_email";
6865
6866            /**
6867             * The extra field for an optional second contact email type.
6868             * <P>Type: Either an integer value from
6869             * {@link CommonDataKinds.Email}
6870             *  or a string specifying a custom label.</P>
6871             */
6872            public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
6873
6874            /**
6875             * The extra field for an optional third contact email address.
6876             * <P>Type: String</P>
6877             */
6878            public static final String TERTIARY_EMAIL = "tertiary_email";
6879
6880            /**
6881             * The extra field for an optional third contact email type.
6882             * <P>Type: Either an integer value from
6883             * {@link CommonDataKinds.Email}
6884             *  or a string specifying a custom label.</P>
6885             */
6886            public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
6887
6888            /**
6889             * The extra field for the contact postal address.
6890             * <P>Type: String</P>
6891             */
6892            public static final String POSTAL = "postal";
6893
6894            /**
6895             * The extra field for the contact postal address type.
6896             * <P>Type: Either an integer value from
6897             * {@link CommonDataKinds.StructuredPostal}
6898             *  or a string specifying a custom label.</P>
6899             */
6900            public static final String POSTAL_TYPE = "postal_type";
6901
6902            /**
6903             * The extra field for the postal isprimary flag.
6904             * <P>Type: boolean</P>
6905             */
6906            public static final String POSTAL_ISPRIMARY = "postal_isprimary";
6907
6908            /**
6909             * The extra field for an IM handle.
6910             * <P>Type: String</P>
6911             */
6912            public static final String IM_HANDLE = "im_handle";
6913
6914            /**
6915             * The extra field for the IM protocol
6916             */
6917            public static final String IM_PROTOCOL = "im_protocol";
6918
6919            /**
6920             * The extra field for the IM isprimary flag.
6921             * <P>Type: boolean</P>
6922             */
6923            public static final String IM_ISPRIMARY = "im_isprimary";
6924
6925            /**
6926             * The extra field that allows the client to supply multiple rows of
6927             * arbitrary data for a single contact created using the {@link Intent#ACTION_INSERT}
6928             * or edited using {@link Intent#ACTION_EDIT}. It is an ArrayList of
6929             * {@link ContentValues}, one per data row. Supplying this extra is
6930             * similar to inserting multiple rows into the {@link Data} table,
6931             * except the user gets a chance to see and edit them before saving.
6932             * Each ContentValues object must have a value for {@link Data#MIMETYPE}.
6933             * If supplied values are not visible in the editor UI, they will be
6934             * dropped.  Duplicate data will dropped.  Some fields
6935             * like {@link CommonDataKinds.Email#TYPE Email.TYPE} may be automatically
6936             * adjusted to comply with the constraints of the specific account type.
6937             * For example, an Exchange contact can only have one phone numbers of type Home,
6938             * so the contact editor may choose a different type for this phone number to
6939             * avoid dropping the valueable part of the row, which is the phone number.
6940             * <p>
6941             * Example:
6942             * <pre>
6943             *  ArrayList&lt;ContentValues&gt; data = new ArrayList&lt;ContentValues&gt;();
6944             *
6945             *  ContentValues row1 = new ContentValues();
6946             *  row1.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
6947             *  row1.put(Organization.COMPANY, "Android");
6948             *  data.add(row1);
6949             *
6950             *  ContentValues row2 = new ContentValues();
6951             *  row2.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
6952             *  row2.put(Email.TYPE, Email.TYPE_CUSTOM);
6953             *  row2.put(Email.LABEL, "Green Bot");
6954             *  row2.put(Email.ADDRESS, "android@android.com");
6955             *  data.add(row2);
6956             *
6957             *  Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
6958             *  intent.putParcelableArrayListExtra(Insert.DATA, data);
6959             *
6960             *  startActivity(intent);
6961             * </pre>
6962             */
6963            public static final String DATA = "data";
6964
6965            /**
6966             * Used to specify the account in which to create the new contact.
6967             * <p>
6968             * If this value is not provided, the user is presented with a disambiguation
6969             * dialog to chose an account
6970             * <p>
6971             * Type: {@link Account}
6972             *
6973             * @hide
6974             */
6975            public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
6976        }
6977    }
6978}
6979