1 /*
2  * Copyright (C) 2024 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.photopicker.v2;
18 
19 import static java.util.Objects.requireNonNull;
20 
21 import android.content.Context;
22 import android.content.UriMatcher;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.provider.MediaStore;
27 
28 import androidx.annotation.IntDef;
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 
35 public class PickerUriResolverV2 {
36     public static final String PICKER_INTERNAL_PATH_SEGMENT = "picker_internal";
37     public static final String PICKER_V2_PATH_SEGMENT = "v2";
38     public static final String BASE_PICKER_PATH =
39             PICKER_INTERNAL_PATH_SEGMENT + "/" + PICKER_V2_PATH_SEGMENT + "/";
40     public static final String AVAILABLE_PROVIDERS_PATH_SEGMENT = "available_providers";
41     public static final String MEDIA_PATH_SEGMENT = "media";
42     public static final String ALBUM_PATH_SEGMENT = "album";
43     public static final String UPDATE_PATH_SEGMENT = "update";
44 
45     static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
46     static final int PICKER_INTERNAL_MEDIA = 1;
47     static final int PICKER_INTERNAL_ALBUM = 2;
48     static final int PICKER_INTERNAL_ALBUM_CONTENT = 3;
49     static final int PICKER_INTERNAL_AVAILABLE_PROVIDERS = 4;
50 
51     @Retention(RetentionPolicy.SOURCE)
52     @IntDef({
53             UriMatcher.NO_MATCH,
54             PICKER_INTERNAL_MEDIA,
55             PICKER_INTERNAL_ALBUM,
56             PICKER_INTERNAL_ALBUM_CONTENT,
57             PICKER_INTERNAL_AVAILABLE_PROVIDERS,
58     })
59     private @interface PickerQuery {}
60 
61     static {
sUriMatcher.addURI(MediaStore.AUTHORITY, BASE_PICKER_PATH + MEDIA_PATH_SEGMENT, PICKER_INTERNAL_MEDIA)62         sUriMatcher.addURI(MediaStore.AUTHORITY, BASE_PICKER_PATH + MEDIA_PATH_SEGMENT,
63                 PICKER_INTERNAL_MEDIA);
sUriMatcher.addURI(MediaStore.AUTHORITY, BASE_PICKER_PATH + ALBUM_PATH_SEGMENT, PICKER_INTERNAL_ALBUM)64         sUriMatcher.addURI(MediaStore.AUTHORITY, BASE_PICKER_PATH + ALBUM_PATH_SEGMENT,
65                 PICKER_INTERNAL_ALBUM);
sUriMatcher.addURI( MediaStore.AUTHORITY, BASE_PICKER_PATH + ALBUM_PATH_SEGMENT + "/*", PICKER_INTERNAL_ALBUM_CONTENT )66         sUriMatcher.addURI(
67                 MediaStore.AUTHORITY,
68                 BASE_PICKER_PATH + ALBUM_PATH_SEGMENT + "/*",
69                 PICKER_INTERNAL_ALBUM_CONTENT
70         );
sUriMatcher.addURI( MediaStore.AUTHORITY, BASE_PICKER_PATH + AVAILABLE_PROVIDERS_PATH_SEGMENT, PICKER_INTERNAL_AVAILABLE_PROVIDERS )71         sUriMatcher.addURI(
72                 MediaStore.AUTHORITY,
73                 BASE_PICKER_PATH + AVAILABLE_PROVIDERS_PATH_SEGMENT,
74                 PICKER_INTERNAL_AVAILABLE_PROVIDERS
75         );
76     }
77 
78     /**
79      * Redirect a Picker internal query to the right {@link PickerDataLayerV2} method to serve the
80      * request.
81      */
82     @Nullable
query( @onNull Context appContext, @NonNull Uri uri, @Nullable Bundle queryArgs)83     public static Cursor query(
84             @NonNull Context appContext,
85             @NonNull Uri uri,
86             @Nullable Bundle queryArgs) {
87         @PickerQuery
88         final int query = sUriMatcher.match(uri);
89 
90         switch (query) {
91             case PICKER_INTERNAL_MEDIA:
92                 return PickerDataLayerV2.queryMedia(appContext, requireNonNull(queryArgs));
93             case PICKER_INTERNAL_ALBUM:
94                 return PickerDataLayerV2.queryAlbums(appContext, requireNonNull(queryArgs));
95             case PICKER_INTERNAL_ALBUM_CONTENT:
96                 final String albumId = uri.getLastPathSegment();
97                 return PickerDataLayerV2.queryAlbumMedia(
98                         appContext,
99                         requireNonNull(queryArgs),
100                         requireNonNull(albumId));
101             case PICKER_INTERNAL_AVAILABLE_PROVIDERS:
102                 return PickerDataLayerV2.queryAvailableProviders(appContext);
103             default:
104                 throw new UnsupportedOperationException("Could not recognize content URI " + uri);
105         }
106     }
107 }
108