1 /*
2  * Copyright (C) 2021 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.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.Intent;
22 import android.database.Cursor;
23 import android.os.Bundle;
24 
25 import java.util.UUID;
26 
27 /**
28  * Defines the contract between a cloud media provider and the OS.
29  * <p>
30  * To create a cloud media provider, extend {@link CloudMediaProvider}, which
31  * provides a foundational implementation of this contract.
32  *
33  * @see CloudMediaProvider
34  */
35 public final class CloudMediaProviderContract {
36     private static final String TAG = "CloudMediaProviderContract";
37 
CloudMediaProviderContract()38     private CloudMediaProviderContract() {}
39 
40     /**
41      * {@link Intent} action used to identify {@link CloudMediaProvider} instances. This
42      * is used in the {@code <intent-filter>} of the {@code <provider>}.
43      */
44     public static final String PROVIDER_INTERFACE = "android.content.action.CLOUD_MEDIA_PROVIDER";
45 
46     /**
47      * Permission required to protect {@link CloudMediaProvider} instances. Providers should
48      * require this in the {@code permission} attribute in their {@code <provider>} tag.
49      * The OS will not connect to a provider without this protection.
50      */
51     public static final String MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION =
52             "com.android.providers.media.permission.MANAGE_CLOUD_MEDIA_PROVIDERS";
53 
54     /** Constants related to a media item, including {@link Cursor} column names */
55     public static final class MediaColumns {
MediaColumns()56         private MediaColumns() {}
57 
58         /**
59          * Unique ID of a media item. This ID is both provided by and interpreted
60          * by a {@link CloudMediaProvider}, and should be treated as an opaque
61          * value by client applications.
62          *
63          * <p>
64          * Each media item must have a unique ID within a provider.
65          *
66          * <p>
67          * A provider must always return stable IDs, since they will be used to
68          * issue long-term URI permission grants when an application interacts
69          * with {@link MediaStore#ACTION_PICK_IMAGES}.
70          * <p>
71          * Type: STRING
72          */
73         public static final String ID = "id";
74 
75         /**
76          * Timestamp when a media item was capture, in milliseconds since
77          * January 1, 1970 00:00:00.0 UTC.
78          * <p>
79          * Implementations should extract this data from the metadata embedded in the media
80          * file. If this information is not available, a reasonable heuristic can be used, e.g.
81          * the time the media file was added to the media collection.
82          * <p>
83          * Type: LONG
84          *
85          * @see CloudMediaProviderContract.AlbumColumns#DATE_TAKEN_MILLIS
86          * @see System#currentTimeMillis()
87          */
88         public static final String DATE_TAKEN_MILLIS = "date_taken_millis";
89 
90         /**
91          * Non-negative number associated with a media item indicating what generation or batch the
92          * media item was synced into the media collection.
93          * <p>
94          * Providers should associate a monotonically increasing sync generation number to each
95          * media item which is expected to increase for each atomic modification on the media item.
96          * This is useful for the OS to quickly identify that a media item has changed since a
97          * previous point in time. Note that this does not need to be unique across all media items,
98          * i.e. multiple media items can have the same SYNC_GENERATION value. However, the
99          * modification of a media item should increase the
100          * {@link MediaCollectionInfo#LAST_MEDIA_SYNC_GENERATION}.
101          * <p>
102          * Type: LONG
103          *
104          * @see MediaCollectionInfo#LAST_MEDIA_SYNC_GENERATION
105          */
106         public static final String SYNC_GENERATION = "sync_generation";
107 
108         /**
109          * Concrete MIME type of a media file. For example, "image/png" or
110          * "video/mp4".
111          * <p>
112          * Type: STRING
113          */
114         public static final String MIME_TYPE = "mime_type";
115 
116         /**
117          * Mime-type extension representing special format for a media item.
118          *
119          * Photo Picker requires special format tagging for media items.
120          * This is essential as media items can have various formats like
121          * Motion Photos, GIFs etc, which are not identifiable by
122          * {@link #MIME_TYPE}.
123          * <p>
124          * Type: INTEGER
125          */
126         public static final String STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension";
127 
128         /**
129          * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
130          * that the media item doesn't have any special format associated with it.
131          */
132         public static final int STANDARD_MIME_TYPE_EXTENSION_NONE = 0;
133 
134         /**
135          * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
136          * that the media item is a GIF.
137          */
138         public static final int STANDARD_MIME_TYPE_EXTENSION_GIF = 1;
139 
140         /**
141          * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
142          * that the media item is a Motion Photo.
143          */
144         public static final int STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO = 2;
145 
146         /**
147          * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
148          * that the media item is an Animated Webp.
149          */
150         public static final int STANDARD_MIME_TYPE_EXTENSION_ANIMATED_WEBP = 3;
151 
152         /**
153          * Size of a media file, in bytes.
154          * <p>
155          * Type: LONG
156          */
157         public static final String SIZE_BYTES = "size_bytes";
158 
159         /**
160          * {@link MediaStore} URI of a media file if the file is available locally on the device.
161          * <p>
162          * If it's a cloud-only media file, this field should not be set.
163          * Any of the following URIs can be used: {@link MediaStore.Files},
164          * {@link MediaStore.Images} or {@link MediaStore.Video} e.g.
165          * {@code content://media/file/45}.
166          * <p>
167          * Implementations don't need to handle the {@link MediaStore} URI becoming invalid after
168          * the local item has been deleted or modified. If the URI becomes invalid or the
169          * local and cloud file content diverges, the OS will treat the cloud media item as a
170          * cloud-only item.
171          * <p>
172          * Type: STRING
173          */
174         public static final String MEDIA_STORE_URI = "media_store_uri";
175 
176         /**
177          * Duration of a video file in ms. If the file is an image for which duration is not
178          * applicable, this field can be left empty or set to {@code zero}.
179          * <p>
180          * Type: LONG
181          */
182         public static final String DURATION_MILLIS = "duration_millis";
183 
184         /**
185          * Whether the item has been favourited in the media collection. If {@code non-zero}, this
186          * media item will appear in the favourites category in the Photo Picker.
187          * <p>
188          * Type: INTEGER
189          */
190         public static final String IS_FAVORITE = "is_favorite";
191 
192         /**
193          * This column contains the width of the image or video.
194          */
195         public static final String WIDTH = "width";
196 
197         /**
198          * This column contains the height of the image or video.
199          */
200         public static final String HEIGHT = "height";
201 
202         /**
203          * This column contains the orientation, if available.
204          * <p>
205          * For consistency the indexed value is expressed in degrees, such as 0,
206          * 90, 180, or 270.
207          */
208         public static final String ORIENTATION = "orientation";
209 
210         /**
211          * Authority of the media item
212          * <p>
213          * Type: STRING
214          *
215          * @hide
216          */
217         public static final String AUTHORITY = "authority";
218 
219         /**
220          * File path of the media item
221          * <p>
222          * Type: STRING
223          *
224          * @hide
225          */
226         public static final String DATA = "data";
227 
228         /**
229          * Array of all {@link MediaColumn} fields.
230          *
231          * @hide
232          */
233         public static final String[] ALL_PROJECTION = new String[] {
234             ID,
235             DATE_TAKEN_MILLIS,
236             SYNC_GENERATION,
237             MIME_TYPE,
238             STANDARD_MIME_TYPE_EXTENSION,
239             SIZE_BYTES,
240             MEDIA_STORE_URI,
241             DURATION_MILLIS,
242             IS_FAVORITE,
243             WIDTH,
244             HEIGHT,
245             ORIENTATION,
246             DATA,
247             AUTHORITY,
248         };
249     }
250 
251     /**
252      * <p>
253      * {@link Intent#EXTRA_MIME_TYPES} extra can be passed as a {@link Bundle} parameter to
254      * the CloudMediaProvider#onQueryAlbums method. The value is an Array of String Mime types.
255      * The provider should only return items matching at least one of the given Mime types.
256      *
257      * <p>
258      * This may be a pattern, such as *&#47;*,to query for all available MIME types that
259      * match the pattern,e.g.{@code image/*} should match {@code image/jpeg} and
260      * {@code image/png}.
261      *
262      * <p>
263      * Type: String[] (It is an string array of meme type filters)
264      */
265 
266     /** Constants related to an album item, including {@link Cursor} column names */
267     public static final class AlbumColumns {
AlbumColumns()268         private AlbumColumns() {}
269 
270         /**
271          * Unique ID of an album. This ID is both provided by and interpreted
272          * by a {@link CloudMediaProvider}.
273          * <p>
274          * Each album item must have a unique ID within a media collection.
275          * <p>
276          * A provider should return durable IDs, since they will be used to cache
277          * album information in the OS.
278          * <p>
279          * Type: STRING
280          */
281         public static final String ID = "id";
282 
283         /**
284          * Display name of a an album, used as the primary title displayed to a
285          * user.
286          * <p>
287          * Type: STRING
288          */
289         public static final String DISPLAY_NAME = "display_name";
290 
291         /**
292          * Timestamp of the most recently taken photo in an album, in milliseconds since
293          * January 1, 1970 00:00:00.0 UTC.
294          * <p>
295          * Type: LONG
296          *
297          * @see CloudMediaProviderContract.MediaColumns#DATE_TAKEN_MILLIS
298          * @see System#currentTimeMillis()
299          */
300         public static final String DATE_TAKEN_MILLIS = "date_taken_millis";
301 
302         /**
303          * Media id to use as the album cover photo.
304          * <p>
305          * If this field is not provided, albums will be shown in the Photo Picker without a cover
306          * photo.
307          * <p>
308          * Type: LONG
309          *
310          * @see CloudMediaProviderContract.MediaColumns#ID
311          */
312         public static final String MEDIA_COVER_ID = "album_media_cover_id";
313 
314         /**
315          * Total count of all media within the album, including photos and videos.
316          * <p>
317          * If this field is not provided, albums will be shown without a count in the Photo Picker.
318          * <p>
319          * Empty albums should be omitted from the {@link CloudMediaProvider#onQueryAlbums} result,
320          * i.e. zero is not a valid media count.
321          * <p>
322          * Type: LONG
323          */
324         public static final String MEDIA_COUNT = "album_media_count";
325 
326         /**
327          * Authority of the album item
328          * <p>
329          * Type: STRING
330          *
331          * @hide
332          */
333         public static final String AUTHORITY = "authority";
334 
335         /**
336          * Whether the album item was generated locally
337          * <p>
338          * Type: STRING
339          *
340          * @hide
341          */
342         public static final String IS_LOCAL = "is_local";
343 
344         /**
345          * Array of all {@link AlbumColumn} fields.
346          *
347          * @hide
348          */
349         public static final String[] ALL_PROJECTION = new String[] {
350             ID,
351             DATE_TAKEN_MILLIS,
352             DISPLAY_NAME,
353             MEDIA_COVER_ID,
354             MEDIA_COUNT,
355             AUTHORITY,
356         };
357 
358         /**
359          * Includes local media present in any directory containing
360          * {@link Environment#DIRECTORY_SCREENSHOTS} in relative path
361          *
362          * @hide
363          */
364         public static final String ALBUM_ID_SCREENSHOTS = "Screenshots";
365 
366         /**
367          * Includes local images/videos that are present in the
368          * {@link Environment#DIRECTORY_DCIM}/Camera directory.
369          *
370          * @hide
371          */
372         public static final String ALBUM_ID_CAMERA = "Camera";
373 
374         /**
375          * Includes local and cloud videos only.
376          *
377          * @hide
378          */
379         public static final String ALBUM_ID_VIDEOS = "Videos";
380 
381         /**
382          * Includes local images/videos that have {@link MediaStore.MediaColumns#IS_DOWNLOAD} set.
383          *
384          * @hide
385          */
386         public static final String ALBUM_ID_DOWNLOADS = "Downloads";
387 
388         /**
389          * Includes local and cloud images/videos that have been favorited by the user.
390          *
391          * @hide
392          */
393         public static final String ALBUM_ID_FAVORITES = "Favorites";
394     }
395 
396     /** Constants related to a media collection */
397     public static final class MediaCollectionInfo {
MediaCollectionInfo()398         private MediaCollectionInfo() {}
399 
400         /**
401          * Media collection identifier
402          * <p>
403          * The only requirement on the collection ID is uniqueness on a device.
404          * <p>
405          * This value will not be interpreted by the OS, however it will be used to check the
406          * validity of cached data and URI grants to client apps. Anytime the media or album ids
407          * get re-indexed, a new collection with a new and unique id should be created so that the
408          * OS can clear its cache and more importantly, revoke any URI grants to apps.
409          * <p>
410          * Apps are recommended to generate unique collection ids with, {@link UUID#randomUUID}.
411          * This is preferred to using a simple monotonic sequence because the provider data could
412          * get cleared and it might have to re-index media items on the device without any history
413          * of its last ID. With random UUIDs, if data gets cleared, a new one can easily be
414          * generated safely.
415          * <p>
416          * Type: STRING
417          *
418          * @see CloudMediaProvider#onGetMediaCollectionInfo
419          */
420         public static final String MEDIA_COLLECTION_ID = "media_collection_id";
421 
422         /**
423          * Last {@link CloudMediaProviderContract.MediaColumns#SYNC_GENERATION} in the media
424          * collection including deleted media items.
425          * <p>
426          * Providers should associate a monotonically increasing sync generation to each
427          * media item change (insertion/deletion/update). This is useful for the OS to quickly
428          * identify exactly which media items have changed since a previous point in time.
429          * <p>
430          * Type: LONG
431          *
432          * @see CloudMediaProviderContract#EXTRA_SYNC_GENERATION
433          * @see CloudMediaProvider#onGetMediaCollectionInfo
434          * @see CloudMediaProviderContract.MediaColumns#SYNC_GENERATION
435          */
436         public static final String LAST_MEDIA_SYNC_GENERATION = "last_media_sync_generation";
437 
438         /**
439          * Name of the account that owns the media collection.
440          * <p>
441          * Type: STRING
442          *
443          * @see CloudMediaProvider#onGetMediaCollectionInfo
444          */
445         public static final String ACCOUNT_NAME = "account_name";
446 
447         /**
448          * {@link Intent} Intent to launch an {@link Activity} to allow users configure their media
449          * collection account information like the account name.
450          * <p>
451          * Type: PARCELABLE
452          *
453          * @see CloudMediaProvider#onGetMediaCollectionInfo
454          */
455         public static final String ACCOUNT_CONFIGURATION_INTENT = "account_configuration_intent";
456     }
457 
458     /**
459      * Opaque pagination token to retrieve the next page (cursor) from a media or album query.
460      * <p>
461      * Providers can optionally set this token as part of the {@link Cursor#setExtras}
462      * {@link Bundle}. If a token is set, the OS can pass it as a {@link Bundle} parameter when
463      * querying for media or albums to fetch subsequent pages. The provider can keep returning
464      * pagination tokens until the last page at which point it should not set a token on the
465      * {@link Cursor}.
466      * <p>
467      * If the provider handled the page token as part of the query, they must add
468      * the {@link #EXTRA_PAGE_TOKEN} key to the array of {@link ContentResolver#EXTRA_HONORED_ARGS}
469      * as part of the returned {@link Cursor#setExtras} {@link Bundle}.
470      *
471      * @see CloudMediaProvider#onQueryMedia
472      * @see CloudMediaProvider#onQueryAlbums
473      * <p>
474      * Type: STRING
475      */
476     public static final String EXTRA_PAGE_TOKEN = "android.provider.extra.PAGE_TOKEN";
477 
478     /**
479      * {@link MediaCollectionInfo#MEDIA_COLLECTION_ID} on which the media or album query occurred.
480      *
481      * <p>
482      * Providers must set this token as part of the {@link Cursor#setExtras}
483      * {@link Bundle} returned from the cursors on query.
484      * This allows the OS to verify that the returned results match the
485      * {@link MediaCollectionInfo#MEDIA_COLLECTION_ID} queried via
486      * {@link CloudMediaProvider#onGetMediaCollectionInfo}. If the collection differs, the OS will
487      * ignore the result and may try again.
488      *
489      * @see CloudMediaProvider#onQueryMedia
490      * @see CloudMediaProvider#onQueryDeletedMedia
491      * @see CloudMediaProvider#onQueryAlbums
492      * <p>
493      * Type: STRING
494      */
495     public static final String EXTRA_MEDIA_COLLECTION_ID =
496             "android.provider.extra.MEDIA_COLLECTION_ID";
497 
498     /**
499      * Generation number to fetch the latest media or album metadata changes from the media
500      * collection.
501      * <p>
502      * The provider should associate a monotonically increasing sync generation to each media
503      * item change (insertion/deletion/update). This is useful to quickly identify exactly which
504      * media items have changed since a previous point in time.
505      * <p>
506      * Providers should also associate a separate monotonically increasing sync generation
507      * for album changes (insertion/deletion/update). This album sync generation, should record
508      * both changes to the album metadata itself and changes to the media items contained in the
509      * album. E.g. a direct change to an album's
510      * {@link CloudMediaProviderContract.AlbumColumns#DISPLAY_NAME} will increase the
511      * album sync generation, likewise adding a photo to that album should also increase the
512      * sync generation.
513      * <p>
514      * Note that multiple media (or album) items can share a sync generation as long as the entire
515      * change appears atomic from the perspective of the query APIs. E.g. each item in a batch photo
516      * sync from the cloud can have the same sync generation if they were all synced atomically into
517      * the collection from the perspective of an external observer.
518      * <p>
519      * This extra can be passed as a {@link Bundle} parameter to the media or album query methods
520      * and the provider should only return items with a sync generation that is strictly greater
521      * than the one provided in the filter.
522      * <p>
523      * If the provider supports this filter, it must support the respective
524      * {@link CloudMediaProvider#onGetMediaCollectionInfo} methods to return the {@code count} and
525      * {@code max generation} for media or albums.
526      * <p>
527      * If the provider handled the generation, they must add the
528      * {@link #EXTRA_SYNC_GENERATION} key to the array of {@link ContentResolver#EXTRA_HONORED_ARGS}
529      * as part of the returned {@link Cursor#setExtras} {@link Bundle}.
530      *
531      * @see MediaCollectionInfo#LAST_MEDIA_SYNC_GENERATION
532      * @see CloudMediaProvider#onQueryMedia
533      * @see CloudMediaProvider#onQueryAlbums
534      * @see MediaStore.MediaColumns#GENERATION_MODIFIED
535      * <p>
536      * Type: LONG
537      */
538     public static final String EXTRA_SYNC_GENERATION = "android.provider.extra.SYNC_GENERATION";
539 
540     /**
541      * Limits the query results to only media items matching the given album id.
542      * <p>
543      * If the provider handled the album filter, they must also add the {@link #EXTRA_ALBUM_ID}
544      * key to the array of {@link ContentResolver#EXTRA_HONORED_ARGS} as part of the returned
545      * {@link Cursor#setExtras} {@link Bundle}.
546      *
547      * @see CloudMediaProvider#onQueryMedia
548      * <p>
549      * Type: STRING
550      */
551     public static final String EXTRA_ALBUM_ID = "android.provider.extra.ALBUM_ID";
552 
553     /**
554      * The maximum number of query results that should be included in a batch when syncing metadata
555      * with cloud provider.
556      *
557      * This extra can be passed as a {@link Bundle} parameter to the media or album query methods.
558      *
559      * It is optional for the provider to honor this extra and return results at max page size.
560      *
561      * @see CloudMediaProvider#onQueryMedia
562      * @see CloudMediaProvider#onQueryAlbums
563      *
564      * <p>
565      * Type: INTEGER
566      */
567     public static final String EXTRA_PAGE_SIZE = "android.provider.extra.PAGE_SIZE";
568 
569     /**
570      * Limits the query results to only media items less than the given file size in bytes.
571      * <p>
572      * This is only intended for the MediaProvider to implement for cross-user communication. Not
573      * for third party apps.
574      *
575      * @see CloudMediaProvider#onQueryMedia
576      * <p>
577      * Type: LONG
578      * @hide
579      */
580     public static final String EXTRA_SIZE_LIMIT_BYTES =
581             "android.provider.extra.EXTRA_SIZE_LIMIT_BYTES";
582 
583     /**
584      * Forces the {@link CloudMediaProvider#onOpenPreview} file descriptor to return a thumbnail
585      * image. This is only useful for videos where the OS can either request a video or image
586      * for preview.
587      *
588      * @see CloudMediaProvider#onOpenPreview
589      * <p>
590      * Type: BOOLEAN
591      */
592     public static final String EXTRA_PREVIEW_THUMBNAIL =
593             "android.provider.extra.PREVIEW_THUMBNAIL";
594 
595     /**
596      * A boolean to indicate {@link com.android.providers.media.photopicker.PhotoPickerProvider}
597      * this request is requesting a cached thumbnail file from MediaStore.
598      *
599      * Type: BOOLEAN
600      *
601      * {@hide}
602      */
603     public static final String EXTRA_MEDIASTORE_THUMB = "android.provider.extra.MEDIASTORE_THUMB";
604 
605     /**
606      * Constant used to execute {@link CloudMediaProvider#onGetMediaCollectionInfo} via
607      * {@link ContentProvider#call}.
608      *
609      * {@hide}
610      */
611     public static final String METHOD_GET_MEDIA_COLLECTION_INFO = "android:getMediaCollectionInfo";
612 
613     /**
614      * Constant used to execute {@link CloudMediaProvider#onCreateCloudMediaSurfaceController} via
615      * {@link ContentProvider#call}.
616      *
617      * {@hide}
618      */
619     public static final String METHOD_CREATE_SURFACE_CONTROLLER = "android:createSurfaceController";
620 
621     /**
622      * Gets surface controller from {@link CloudMediaProvider#onCreateCloudMediaSurfaceController}.
623      * {@hide}
624      */
625     public static final String EXTRA_SURFACE_CONTROLLER =
626             "android.provider.extra.SURFACE_CONTROLLER";
627 
628     /**
629      * Indicates whether to enable looping playback of media items.
630      * <p>
631      * In case this is not present, the default value should be false.
632      *
633      * @see CloudMediaProvider#onCreateCloudMediaSurfaceController
634      * @see CloudMediaProvider.CloudMediaSurfaceController#onConfigChange
635      * <p>
636      * Type: BOOLEAN
637      * By default, the value is true
638      */
639     public static final String EXTRA_LOOPING_PLAYBACK_ENABLED =
640             "android.provider.extra.LOOPING_PLAYBACK_ENABLED";
641 
642     /**
643      * Indicates whether to mute audio during preview of media items.
644      *
645      * @see CloudMediaProvider#onCreateCloudMediaSurfaceController
646      * @see CloudMediaProvider.CloudMediaSurfaceController#onConfigChange
647      * <p>
648      * Type: BOOLEAN
649      * By default, the value is false
650      */
651     public static final String EXTRA_SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED =
652             "android.provider.extra.SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED";
653 
654     /**
655      * Gets surface state callback from picker launched via
656      * {@link MediaStore#ACTION_PICK_IMAGES}).
657      *
658      * @see MediaStore#ACTION_PICK_IMAGES
659      *
660      * {@hide}
661      */
662     public static final String EXTRA_SURFACE_STATE_CALLBACK =
663             "android.provider.extra.SURFACE_STATE_CALLBACK";
664 
665     /**
666      * Constant used to execute {@link CloudMediaProvider#onGetAsyncContentProvider()} via
667      * {@link android.content.ContentProvider#call}.
668      *
669      * {@hide}
670      */
671     public static final String METHOD_GET_ASYNC_CONTENT_PROVIDER =
672             "android:getAsyncContentProvider";
673 
674     /**
675      * Constant used to get/set {@link IAsyncContentProvider} in {@link Bundle}.
676      *
677      * {@hide}
678      */
679     public static final String EXTRA_ASYNC_CONTENT_PROVIDER =
680             "android.provider.extra.ASYNC_CONTENT_PROVIDER";
681 
682     /**
683      * Constant used to get/set {@link android.os.ParcelFileDescriptor} in {@link Bundle}.
684      *
685      * {@hide}
686      */
687     public static final String EXTRA_FILE_DESCRIPTOR = "android.provider.extra.file_descriptor";
688 
689     /**
690      * Constant used to get/set CMP exception message in {@link Bundle}.
691      *
692      * {@hide}
693      */
694     public static final String EXTRA_ERROR_MESSAGE = "android.provider.extra.error_message";
695 
696     /**
697      * Constant used to get/set the {@link CloudMediaProvider} authority.
698      *
699      * {@hide}
700      */
701     public static final String EXTRA_AUTHORITY = "android.provider.extra.authority";
702 
703     /**
704      * URI path for {@link CloudMediaProvider#onQueryMedia}
705      *
706      * {@hide}
707      */
708     public static final String URI_PATH_MEDIA = "media";
709 
710     /**
711      * URI path for {@link CloudMediaProvider#onQueryDeletedMedia}
712      *
713      * {@hide}
714      */
715     public static final String URI_PATH_DELETED_MEDIA = "deleted_media";
716 
717     /**
718      * URI path for {@link CloudMediaProvider#onQueryAlbums}
719      *
720      * {@hide}
721      */
722     public static final String URI_PATH_ALBUM = "album";
723 
724     /**
725      * URI path for {@link CloudMediaProvider#onGetMediaCollectionInfo}
726      *
727      * {@hide}
728      */
729     public static final String URI_PATH_MEDIA_COLLECTION_INFO = "media_collection_info";
730 
731     /**
732      * URI path for {@link CloudMediaProvider#onCreateCloudMediaSurfaceController}
733      *
734      * {@hide}
735      */
736     public static final String URI_PATH_SURFACE_CONTROLLER = "surface_controller";
737 }
738