• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 package com.android.wallpaper.model;
17 
18 
19 import static com.android.wallpaper.model.WallpaperInfoContract.WALLPAPER_EFFECTS_CLEAR_URI;
20 import static com.android.wallpaper.model.WallpaperInfoContract.WALLPAPER_EFFECTS_CURRENT_ID;
21 import static com.android.wallpaper.model.WallpaperInfoContract.WALLPAPER_EFFECTS_SECTION_SUBTITLE;
22 import static com.android.wallpaper.model.WallpaperInfoContract.WALLPAPER_EFFECTS_SECTION_TITLE;
23 
24 import android.annotation.Nullable;
25 import android.content.ContentProviderClient;
26 import android.content.Context;
27 import android.database.Cursor;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.text.TextUtils;
31 import android.util.Log;
32 
33 import com.android.wallpaper.asset.CreativeWallpaperThumbAsset;
34 
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 /** The {@link WallpaperCategory} implements category for user created wallpapers. */
39 public class CreativeCategory extends WallpaperCategory {
40 
41     private static final String TAG = "CreativeCategory";
42     public static final String KEY_WALLPAPER_CREATIVE_CATEGORY =
43             "android.service.wallpaper.category";
44 
45     public static final String KEY_WALLPAPER_CREATIVE_WALLPAPERS =
46             "android.service.wallpaper.categorizedwallpapers";
47     public static final String KEY_WALLPAPER_CREATIVE_WALLPAPER_EFFECTS =
48             "android.service.wallpaper.effects";
49 
50     public final android.app.WallpaperInfo mWallpaperInfo;
51 
52     public static final String KEY_WALLPAPER_SAVE_CREATIVE_CATEGORY_WALLPAPER =
53             "android.service.wallpaper.savewallpaper";
54 
55     /** Return true for CreativeCategories since we support user generated wallpapers here. */
56     @Override
supportsUserCreatedWallpapers()57     public boolean supportsUserCreatedWallpapers() {
58         return true;
59     }
60 
61     /**
62      * This function aims at saving a creative category wallpaper by calling the relevant URI
63      * of the creative category wallpaper provider.
64      *
65      * @param context Context of calling activity
66      * @param wallpaper instance of the WallpaperInfo that we want to save
67      * @param saveWallpaperUri the URI to be used for saving the wallpaper
68      * @param destination depicts the destination of the wallpaper being saved
69      */
70     @Nullable
saveCreativeCategoryWallpaper(Context context, LiveWallpaperInfo wallpaper, Uri saveWallpaperUri, int destination)71     public static CreativeWallpaperInfo saveCreativeCategoryWallpaper(Context context,
72             LiveWallpaperInfo wallpaper, Uri saveWallpaperUri, int destination) {
73 
74         // Adding destination field which depicts whether it is home-screen or lock-screen.
75         Uri updatedSaveWallpaperUri = saveWallpaperUri.buildUpon()
76                 .appendQueryParameter("destination", String.valueOf(destination))
77                 .build();
78         try (ContentProviderClient client =
79                      context.getContentResolver().acquireContentProviderClient(
80                              updatedSaveWallpaperUri.getAuthority())) {
81             if (client == null) {
82                 Log.w(TAG, "Couldn't resolve content provider for " + updatedSaveWallpaperUri);
83                 return null;
84             }
85             try (Cursor cursor = client.query(updatedSaveWallpaperUri, /* projection= */ null,
86                     /* selection= */ null, /* selectionArgs= */ null, /* sortOrder= */ null)) {
87                 if (cursor == null || !cursor.moveToFirst()) {
88                     return null;
89                 }
90                 return CreativeWallpaperInfo.buildFromCursor(wallpaper.getWallpaperComponent(),
91                         cursor);
92             } catch (Throwable e) {
93                 Log.e(TAG, "Couldn't read creative category.", e);
94             }
95         }
96         return null;
97     }
98 
CreativeCategory(Context context, String title, String collectionId, Uri thumbUri, List<WallpaperInfo> wallpaperInfos, int priority, android.app.WallpaperInfo wallpaperInfo)99     public CreativeCategory(Context context, String title, String collectionId, Uri thumbUri,
100             List<WallpaperInfo> wallpaperInfos, int priority,
101             android.app.WallpaperInfo wallpaperInfo) {
102         super(title,
103                 collectionId,
104                 wallpaperInfos.isEmpty() ? null : new CreativeWallpaperThumbAsset(context,
105                         wallpaperInfos.get(0).getWallpaperComponent(), thumbUri),
106                 wallpaperInfos,
107                 priority);
108         mWallpaperInfo = wallpaperInfo;
109     }
110 
111     @Override
supportsWallpaperSetUpdates()112     public boolean supportsWallpaperSetUpdates() {
113         return true;
114     }
115 
116     @Override
fetchWallpapers(Context context, WallpaperReceiver receiver, boolean forceReload)117     public void fetchWallpapers(Context context, WallpaperReceiver receiver, boolean forceReload) {
118         if (!forceReload) {
119             super.fetchWallpapers(context, receiver, forceReload);
120             return;
121         }
122         List<WallpaperInfo> wallpapers = readCreativeWallpapers(
123                 context, getCollectionId(), mWallpaperInfo);
124         synchronized (this) {
125             getMutableWallpapers().clear();
126             getMutableWallpapers().addAll(wallpapers);
127         }
128         if (receiver != null) {
129             receiver.onWallpapersReceived(wallpapers);
130         }
131     }
132 
133     /**
134      * Returns a list of [CreativeWallpaperInfo] objects by creating them using the relevant
135      * info. obtained from creative-category APK on device.
136      *
137      * @param context context of the hosting activity
138      * @param collectionId ID of the collection to which these wallpapers belong to
139      * @param wallpaperInfo contains relevant metadata information about creative-category wallpaper
140      * @return list of CreativeWallpaperInfo objects
141      */
readCreativeWallpapers(Context context, String collectionId, android.app.WallpaperInfo wallpaperInfo)142     public static List<WallpaperInfo> readCreativeWallpapers(Context context,
143             String collectionId, android.app.WallpaperInfo wallpaperInfo) {
144         List<WallpaperInfo> wallpapers = new ArrayList<>();
145         Bundle metaData = wallpaperInfo.getServiceInfo().metaData;
146         Uri wallpapersUri = Uri.parse((String) metaData.get(KEY_WALLPAPER_CREATIVE_WALLPAPERS));
147         try (ContentProviderClient client =
148                      context.getContentResolver().acquireContentProviderClient(
149                              wallpapersUri.getAuthority())) {
150             try (Cursor cursor = client.query(wallpapersUri, /* projection= */ null,
151                     /* selection= */ null, /* selectionArgs= */ null, /* sortOrder= */ null)) {
152                 if (cursor == null || !cursor.moveToFirst()) {
153                     return wallpapers;
154                 }
155                 do {
156                     String categoryId = cursor.getString(
157                             cursor.getColumnIndex(WallpaperInfoContract.CATEGORY_ID));
158                     if (!TextUtils.equals(categoryId, collectionId)) {
159                         continue;
160                     }
161                     CreativeWallpaperInfo creativeWallpaperInfo =
162                             CreativeWallpaperInfo.buildFromCursor(wallpaperInfo, cursor);
163                     // If the meta data for wallpaper actions exists, only then can we query the
164                     // action fields and action table.
165                     if (metaData.get(KEY_WALLPAPER_CREATIVE_WALLPAPER_EFFECTS) != null) {
166                         String effectsBottomSheetTitle = cursor.getString(
167                                 cursor.getColumnIndex(WALLPAPER_EFFECTS_SECTION_TITLE));
168                         String effectsBottomSheetSubtitle = cursor.getString(
169                                 cursor.getColumnIndex(WALLPAPER_EFFECTS_SECTION_SUBTITLE));
170                         String currentEffectId = cursor.getString(
171                                 cursor.getColumnIndex(WALLPAPER_EFFECTS_CURRENT_ID));
172                         Uri clearActionUri = Uri.parse(cursor.getString(
173                                 cursor.getColumnIndex(WALLPAPER_EFFECTS_CLEAR_URI)));
174 
175                         creativeWallpaperInfo.setEffectsBottomSheetTitle(
176                                 effectsBottomSheetTitle);
177                         creativeWallpaperInfo.setEffectsBottomSheetSubtitle(
178                                 effectsBottomSheetSubtitle);
179                         creativeWallpaperInfo.setClearActionsUri(clearActionUri);
180                         creativeWallpaperInfo.setCurrentlyAppliedEffectId(currentEffectId);
181 
182                         Uri effectsUri = Uri.parse((String) metaData.get(
183                                 KEY_WALLPAPER_CREATIVE_WALLPAPER_EFFECTS));
184                         creativeWallpaperInfo.setEffectsUri(effectsUri);
185                     }
186                     wallpapers.add(creativeWallpaperInfo);
187                 } while (cursor.moveToNext());
188             }
189         } catch (Throwable e) {
190             Log.e(TAG, "Exception reading creative wallpapers", e);
191         }
192         return wallpapers;
193     }
194 
195     @Override
supportsThirdParty()196     public boolean supportsThirdParty() {
197         return true;
198     }
199 
200     @Override
isSingleWallpaperCategory()201     public boolean isSingleWallpaperCategory() {
202         // if the category is empty then we go directly to the creation screen
203         // if there is at least one wallpaper then we show the collection of wallpapers
204         // NOTE: don't count the "add walpapper button" wallpaper. This is why <= 1 is being used
205         // as opposed to <= 0
206         return getMutableWallpapers() == null || getMutableWallpapers().size() <= 1;
207     }
208 }
209