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 com.android.providers.media.photopicker.v2.PickerUriResolverV2.ALBUM_PATH_SEGMENT;
20 import static com.android.providers.media.photopicker.v2.PickerUriResolverV2.AVAILABLE_PROVIDERS_PATH_SEGMENT;
21 import static com.android.providers.media.photopicker.v2.PickerUriResolverV2.MEDIA_PATH_SEGMENT;
22 import static com.android.providers.media.photopicker.v2.PickerUriResolverV2.PICKER_INTERNAL_PATH_SEGMENT;
23 import static com.android.providers.media.photopicker.v2.PickerUriResolverV2.PICKER_V2_PATH_SEGMENT;
24 import static com.android.providers.media.photopicker.v2.PickerUriResolverV2.UPDATE_PATH_SEGMENT;
25 
26 import static java.util.Objects.requireNonNull;
27 
28 import android.annotation.NonNull;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.net.Uri;
32 import android.provider.MediaStore;
33 import android.util.Log;
34 
35 import com.android.providers.media.photopicker.PickerSyncController;
36 
37 public class PickerNotificationSender {
38     private static final String TAG = "PickerNotificationSender";
39 
40     private static final Uri AVAILABLE_PROVIDERS_UPDATE_URI = new Uri.Builder()
41             .scheme(ContentResolver.SCHEME_CONTENT)
42             .authority(MediaStore.AUTHORITY)
43             .appendPath(PICKER_INTERNAL_PATH_SEGMENT)
44             .appendPath(PICKER_V2_PATH_SEGMENT)
45             .appendPath(AVAILABLE_PROVIDERS_PATH_SEGMENT)
46             .appendPath(UPDATE_PATH_SEGMENT)
47             .build();
48 
49     private static final Uri MEDIA_UPDATE_URI = new Uri.Builder()
50             .scheme(ContentResolver.SCHEME_CONTENT)
51             .authority(MediaStore.AUTHORITY)
52             .appendPath(PICKER_INTERNAL_PATH_SEGMENT)
53             .appendPath(PICKER_V2_PATH_SEGMENT)
54             .appendPath(MEDIA_PATH_SEGMENT)
55             .appendPath(UPDATE_PATH_SEGMENT)
56             .build();
57 
58     private static final Uri ALBUM_UPDATE_URI = new Uri.Builder()
59             .scheme(ContentResolver.SCHEME_CONTENT)
60             .authority(MediaStore.AUTHORITY)
61             .appendPath(PICKER_INTERNAL_PATH_SEGMENT)
62             .appendPath(PICKER_V2_PATH_SEGMENT)
63             .appendPath(ALBUM_PATH_SEGMENT)
64             .appendPath(UPDATE_PATH_SEGMENT)
65             .build();
66 
67     /**
68      * Send media update notification to the registered {@link android.database.ContentObserver}-s.
69      * @param context The application context.
70      */
notifyAvailableProvidersChange(@onNull Context context)71     public static void notifyAvailableProvidersChange(@NonNull Context context) {
72         Log.d(TAG, "Sending a notification for available providers update");
73         context.getContentResolver()
74                 .notifyChange(AVAILABLE_PROVIDERS_UPDATE_URI, /* observer= */ null);
75     }
76 
77     /**
78      * Send media update notification to the registered {@link android.database.ContentObserver}-s.
79      * @param context The application context.
80      */
notifyMediaChange(@onNull Context context)81     public static void notifyMediaChange(@NonNull Context context) {
82         Log.d(TAG, "Sending a notification for media update");
83         context.getContentResolver().notifyChange(MEDIA_UPDATE_URI, /* observer= */ null);
84         notifyMergedAlbumMediaChange(context, PickerSyncController.LOCAL_PICKER_PROVIDER_AUTHORITY);
85     }
86 
87     /**
88      * Send album media update notification to the registered
89      * {@link android.database.ContentObserver}-s.
90      * @param context The application context.
91      * @param albumAuthority authority of the updated album
92      * @param albumId ID of the updated album
93      */
notifyAlbumMediaChange( @onNull Context context, @NonNull String albumAuthority, @NonNull String albumId)94     public static void notifyAlbumMediaChange(
95             @NonNull Context context,
96             @NonNull String albumAuthority,
97             @NonNull String albumId) {
98         Log.d(TAG, "Sending a notification for album media update " + albumId);
99         context.getContentResolver().notifyChange(
100                 getAlbumMediaUpdateUri(albumAuthority, albumId),
101                 /* observer= */ null);
102     }
103 
104     /**
105      * Send album media update notification to the registered
106      * {@link android.database.ContentObserver}-s for all merged album updates.
107      * @param context The application context.
108      * @param localAuthority authority of the local provider.
109      */
notifyMergedAlbumMediaChange( @onNull Context context, @NonNull String localAuthority)110     public static void notifyMergedAlbumMediaChange(
111             @NonNull Context context,
112             @NonNull String localAuthority) {
113         for (String mergedAlbumId: PickerDataLayerV2.sMergedAlbumIds) {
114             Log.d(TAG, "Sending a notification for merged album media update " + mergedAlbumId);
115 
116             // By default, always keep merged album authority as local.
117             notifyAlbumMediaChange(context, localAuthority, mergedAlbumId);
118         }
119     }
120 
getAlbumMediaUpdateUri( @onNull String albumAuthority, @NonNull String albumId)121     private static Uri getAlbumMediaUpdateUri(
122             @NonNull String albumAuthority,
123             @NonNull String albumId) {
124         return ALBUM_UPDATE_URI
125                 .buildUpon()
126                 .appendPath(requireNonNull(albumAuthority))
127                 .appendPath(requireNonNull(albumId))
128                 .build();
129     }
130 }
131