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