• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 com.android.providers.media;
18 
19 import android.content.UriMatcher;
20 import android.net.Uri;
21 
22 class LocalUriMatcher {
23 
24     // WARNING: the values of IMAGES_MEDIA, AUDIO_MEDIA, and VIDEO_MEDIA and AUDIO_PLAYLISTS
25     // are stored in the "files" table, so do not renumber them unless you also add
26     // a corresponding database upgrade step for it.
27     static final int IMAGES_MEDIA = 1;
28     static final int IMAGES_MEDIA_ID = 2;
29     static final int IMAGES_MEDIA_ID_THUMBNAIL = 3;
30     static final int IMAGES_THUMBNAILS = 4;
31     static final int IMAGES_THUMBNAILS_ID = 5;
32 
33     static final int AUDIO_MEDIA = 100;
34     static final int AUDIO_MEDIA_ID = 101;
35     static final int AUDIO_MEDIA_ID_GENRES = 102;
36     static final int AUDIO_MEDIA_ID_GENRES_ID = 103;
37     static final int AUDIO_GENRES = 106;
38     static final int AUDIO_GENRES_ID = 107;
39     static final int AUDIO_GENRES_ID_MEMBERS = 108;
40     static final int AUDIO_GENRES_ALL_MEMBERS = 109;
41     static final int AUDIO_PLAYLISTS = 110;
42     static final int AUDIO_PLAYLISTS_ID = 111;
43     static final int AUDIO_PLAYLISTS_ID_MEMBERS = 112;
44     static final int AUDIO_PLAYLISTS_ID_MEMBERS_ID = 113;
45     static final int AUDIO_ARTISTS = 114;
46     static final int AUDIO_ARTISTS_ID = 115;
47     static final int AUDIO_ALBUMS = 116;
48     static final int AUDIO_ALBUMS_ID = 117;
49     static final int AUDIO_ARTISTS_ID_ALBUMS = 118;
50     static final int AUDIO_ALBUMART = 119;
51     static final int AUDIO_ALBUMART_ID = 120;
52     static final int AUDIO_ALBUMART_FILE_ID = 121;
53 
54     static final int VIDEO_MEDIA = 200;
55     static final int VIDEO_MEDIA_ID = 201;
56     static final int VIDEO_MEDIA_ID_THUMBNAIL = 202;
57     static final int VIDEO_THUMBNAILS = 203;
58     static final int VIDEO_THUMBNAILS_ID = 204;
59 
60     static final int VOLUMES = 300;
61     static final int VOLUMES_ID = 301;
62 
63     static final int MEDIA_SCANNER = 500;
64 
65     static final int FS_ID = 600;
66     static final int VERSION = 601;
67 
68     static final int FILES = 700;
69     static final int FILES_ID = 701;
70 
71     static final int DOWNLOADS = 800;
72     static final int DOWNLOADS_ID = 801;
73 
74     static final int PICKER = 900;
75     static final int PICKER_ID = 901;
76     static final int PICKER_INTERNAL_MEDIA_ALL = 902;
77     static final int PICKER_INTERNAL_MEDIA_LOCAL = 903;
78     static final int PICKER_INTERNAL_ALBUMS_ALL = 904;
79     static final int PICKER_INTERNAL_ALBUMS_LOCAL = 905;
80 
81     // MediaProvider Command Line Interface
82     static final int CLI = 100_000;
83 
84     private final UriMatcher mPublic = new UriMatcher(UriMatcher.NO_MATCH);
85     private final UriMatcher mHidden = new UriMatcher(UriMatcher.NO_MATCH);
86 
matchUri(Uri uri, boolean allowHidden)87     int matchUri(Uri uri, boolean allowHidden) {
88         final int publicMatch = mPublic.match(uri);
89         if (publicMatch != UriMatcher.NO_MATCH) {
90             return publicMatch;
91         }
92 
93         final int hiddenMatch = mHidden.match(uri);
94         if (hiddenMatch != UriMatcher.NO_MATCH) {
95             // Detect callers asking about hidden behavior by looking closer when
96             // the matchers diverge; we only care about apps that are explicitly
97             // targeting a specific public API level.
98             if (!allowHidden) {
99                 throw new IllegalStateException("Unknown URL: " + uri + " is hidden API");
100             }
101             return hiddenMatch;
102         }
103 
104         return UriMatcher.NO_MATCH;
105     }
106 
LocalUriMatcher(String auth)107     LocalUriMatcher(String auth) {
108         // Warning: Do not move these exact string matches below "*/.." matches.
109         // If "*/.." match is added to mPublic children before "picker/#/#", then while matching
110         // "picker/0/10", UriMatcher matches "*" node with "picker" and tries to match "0/10"
111         // with children of "*".
112         // UriMatcher does not look for exact "picker" string match if it finds * node before
113         // it. It finds the first best child match and proceeds the match from there without
114         // looking at other siblings.
115         mPublic.addURI(auth, "picker", PICKER);
116         // TODO(b/195009139): Remove after switching picker URI to new format
117         // content://media/picker/<user-id>/<media-id>
118         mPublic.addURI(auth, "picker/#/#", PICKER_ID);
119         // content://media/picker/<user-id>/<authority>/media/<media-id>
120         mPublic.addURI(auth, "picker/#/*/media/*", PICKER_ID);
121 
122         mPublic.addURI(auth, "cli", CLI);
123 
124         mPublic.addURI(auth, "*/images/media", IMAGES_MEDIA);
125         mPublic.addURI(auth, "*/images/media/#", IMAGES_MEDIA_ID);
126         mPublic.addURI(auth, "*/images/media/#/thumbnail", IMAGES_MEDIA_ID_THUMBNAIL);
127         mPublic.addURI(auth, "*/images/thumbnails", IMAGES_THUMBNAILS);
128         mPublic.addURI(auth, "*/images/thumbnails/#", IMAGES_THUMBNAILS_ID);
129 
130         mPublic.addURI(auth, "*/audio/media", AUDIO_MEDIA);
131         mPublic.addURI(auth, "*/audio/media/#", AUDIO_MEDIA_ID);
132         mPublic.addURI(auth, "*/audio/media/#/genres", AUDIO_MEDIA_ID_GENRES);
133         mPublic.addURI(auth, "*/audio/media/#/genres/#", AUDIO_MEDIA_ID_GENRES_ID);
134         mPublic.addURI(auth, "*/audio/genres", AUDIO_GENRES);
135         mPublic.addURI(auth, "*/audio/genres/#", AUDIO_GENRES_ID);
136         mPublic.addURI(auth, "*/audio/genres/#/members", AUDIO_GENRES_ID_MEMBERS);
137         // TODO: not actually defined in API, but CTS tested
138         mPublic.addURI(auth, "*/audio/genres/all/members", AUDIO_GENRES_ALL_MEMBERS);
139         mPublic.addURI(auth, "*/audio/playlists", AUDIO_PLAYLISTS);
140         mPublic.addURI(auth, "*/audio/playlists/#", AUDIO_PLAYLISTS_ID);
141         mPublic.addURI(auth, "*/audio/playlists/#/members", AUDIO_PLAYLISTS_ID_MEMBERS);
142         mPublic.addURI(auth, "*/audio/playlists/#/members/#", AUDIO_PLAYLISTS_ID_MEMBERS_ID);
143         mPublic.addURI(auth, "*/audio/artists", AUDIO_ARTISTS);
144         mPublic.addURI(auth, "*/audio/artists/#", AUDIO_ARTISTS_ID);
145         mPublic.addURI(auth, "*/audio/artists/#/albums", AUDIO_ARTISTS_ID_ALBUMS);
146         mPublic.addURI(auth, "*/audio/albums", AUDIO_ALBUMS);
147         mPublic.addURI(auth, "*/audio/albums/#", AUDIO_ALBUMS_ID);
148         // TODO: not actually defined in API, but CTS tested
149         mPublic.addURI(auth, "*/audio/albumart", AUDIO_ALBUMART);
150         // TODO: not actually defined in API, but CTS tested
151         mPublic.addURI(auth, "*/audio/albumart/#", AUDIO_ALBUMART_ID);
152         // TODO: not actually defined in API, but CTS tested
153         mPublic.addURI(auth, "*/audio/media/#/albumart", AUDIO_ALBUMART_FILE_ID);
154 
155         mPublic.addURI(auth, "*/video/media", VIDEO_MEDIA);
156         mPublic.addURI(auth, "*/video/media/#", VIDEO_MEDIA_ID);
157         mPublic.addURI(auth, "*/video/media/#/thumbnail", VIDEO_MEDIA_ID_THUMBNAIL);
158         mPublic.addURI(auth, "*/video/thumbnails", VIDEO_THUMBNAILS);
159         mPublic.addURI(auth, "*/video/thumbnails/#", VIDEO_THUMBNAILS_ID);
160 
161         mPublic.addURI(auth, "*/media_scanner", MEDIA_SCANNER);
162 
163         // NOTE: technically hidden, since Uri is never exposed
164         mPublic.addURI(auth, "*/fs_id", FS_ID);
165         // NOTE: technically hidden, since Uri is never exposed
166         mPublic.addURI(auth, "*/version", VERSION);
167 
168         mHidden.addURI(auth, "picker_internal/media/all", PICKER_INTERNAL_MEDIA_ALL);
169         mHidden.addURI(auth, "picker_internal/media/local", PICKER_INTERNAL_MEDIA_LOCAL);
170         mHidden.addURI(auth, "picker_internal/albums/all", PICKER_INTERNAL_ALBUMS_ALL);
171         mHidden.addURI(auth, "picker_internal/albums/local", PICKER_INTERNAL_ALBUMS_LOCAL);
172         mHidden.addURI(auth, "*", VOLUMES_ID);
173         mHidden.addURI(auth, null, VOLUMES);
174 
175         mPublic.addURI(auth, "*/file", FILES);
176         mPublic.addURI(auth, "*/file/#", FILES_ID);
177 
178         mPublic.addURI(auth, "*/downloads", DOWNLOADS);
179         mPublic.addURI(auth, "*/downloads/#", DOWNLOADS_ID);
180     }
181 }
182