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