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