• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 import android.app.Activity;
19 import android.app.WallpaperColors;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.graphics.Bitmap;
23 import android.graphics.Color;
24 import android.graphics.Point;
25 import android.graphics.Rect;
26 import android.graphics.drawable.Drawable;
27 import android.net.Uri;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 
31 import androidx.annotation.DrawableRes;
32 import androidx.annotation.IntDef;
33 import androidx.annotation.Nullable;
34 
35 import com.android.wallpaper.asset.Asset;
36 import com.android.wallpaper.config.BaseFlags;
37 import com.android.wallpaper.module.InjectorProvider;
38 
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.PriorityQueue;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.ExecutorService;
46 import java.util.concurrent.Executors;
47 import java.util.concurrent.Future;
48 
49 /**
50  * Interface for wallpaper info model.
51  */
52 public abstract class WallpaperInfo implements Parcelable {
53 
54     private static final ExecutorService sExecutor = Executors.newCachedThreadPool();
55     private ColorInfo mColorInfo = new ColorInfo();
56 
57     private PriorityQueue<String> mEffectNames = new PriorityQueue<>();
58 
59     protected final HashMap<String, String> mCropHints = new HashMap<>();
60 
WallpaperInfo()61     public WallpaperInfo() {
62     }
63 
WallpaperInfo(Parcel in)64     protected WallpaperInfo(Parcel in) {
65         mColorInfo = new ColorInfo(in.readParcelable(WallpaperColors.class.getClassLoader()),
66                 in.readInt());
67     }
68 
69     @Override
writeToParcel(Parcel parcel, int flags)70     public void writeToParcel(Parcel parcel, int flags) {
71         parcel.writeParcelable(mColorInfo.getWallpaperColors(), flags);
72         parcel.writeInt(mColorInfo.getPlaceholderColor());
73     }
74 
75     public static final int BACKUP_NOT_ALLOWED = 0;
76     public static final int BACKUP_ALLOWED = 1;
77 
78     /**
79      * @param context
80      * @return The title for this wallpaper, if applicable (as in a wallpaper "app" or live
81      * wallpaper), or null if not applicable.
82      */
getTitle(Context context)83     public String getTitle(Context context) {
84         return null;
85     }
86 
87     /**
88      * Returns the content description for this wallpaper, or null if none exists.
89      */
getContentDescription(Context context)90     public String getContentDescription(Context context) {
91         return null;
92     }
93 
94     /**
95      * @return The available attributions for this wallpaper, as a list of strings. These represent
96      * the author / website or any other attribution required to be displayed for this wallpaper
97      * regarding authorship, ownership, etc.
98      */
getAttributions(Context context)99     public abstract List<String> getAttributions(Context context);
100 
101     /**
102      * Returns the base (remote) image URL for this wallpaper, or null if none exists.
103      */
getBaseImageUrl()104     public String getBaseImageUrl() {
105         return null;
106     }
107 
108     /**
109      * Returns the action or "explore" URL for the wallpaper, or null if none exists.
110      */
getActionUrl(Context unused)111     public String getActionUrl(Context unused) {
112         return null;
113     }
114 
115     /** Returns the URI corresponding to the wallpaper, or null if none exists. */
116     @Nullable
getImageWallpaperUri()117     public Uri getImageWallpaperUri() {
118         return null;
119     }
120 
121     /**
122      * Returns the icon to use to represent the action link corresponding to
123      * {@link #getActionUrl(Context)}
124      */
125 
126     /**
127      * @param context
128      * @return An overlay icon to be used instead of a thumbnail, if appropriate, or null if not
129      * applicable.
130      */
getOverlayIcon(Context context)131     public Drawable getOverlayIcon(Context context) {
132         return null;
133     }
134 
135     ;
136 
137     @Override
describeContents()138     public int describeContents() {
139         return 0;
140     }
141 
142     /**
143      * @param context The client application's context.
144      * @return The {@link Asset} representing the wallpaper image.
145      */
getAsset(Context context)146     public abstract Asset getAsset(Context context);
147 
148     /**
149      * @param context The client application's context.
150      * @return The {@link Asset} representing the wallpaper's thumbnail.
151      */
getThumbAsset(Context context)152     public abstract Asset getThumbAsset(Context context);
153 
154     /**
155      * @param context The client application's context.
156      * @return An {@link Asset} that is appropriately sized to be directly set to the desktop. By
157      * default, this just the full wallpaper image asset (#getAsset) but subclasses may provide an
158      * Asset sized exactly for the device's primary display (i.e., cropped prior to providing a
159      * bitmap or input stream).
160      */
getDesktopAsset(Context context)161     public Asset getDesktopAsset(Context context) {
162         return getAsset(context);
163     }
164 
165     /**
166      * @return the {@link android.app.WallpaperInfo} associated with this wallpaper, which is
167      * generally present for live wallpapers, or null if there is none.
168      */
getWallpaperComponent()169     public android.app.WallpaperInfo getWallpaperComponent() {
170         return null;
171     }
172 
173     /**
174      * Returns the ID of the collection this image is associated with, if any.
175      */
getCollectionId(Context context)176     public abstract String getCollectionId(Context context);
177 
178     /**
179      * Returns the ID of this wallpaper or null if there is no ID.
180      */
getWallpaperId()181     public String getWallpaperId() {
182         return null;
183     }
184 
185     /**
186      * Returns the distinct ID of the stored wallpaper or null if there is no ID.
187      */
getStoredWallpaperId(Context context)188     public String getStoredWallpaperId(Context context) {
189         if (getWallpaperId() == null) {
190             return null;
191         }
192         return getCollectionId(context) + "-" + getWallpaperId();
193     }
194 
195     /**
196      * Returns whether backup is allowed for this wallpaper.
197      */
198     @BackupPermission
getBackupPermission()199     public int getBackupPermission() {
200         return BACKUP_ALLOWED;
201     }
202 
203     /**
204      * Shows the appropriate preview activity for this WallpaperInfo.
205      *
206      * @param srcActivity
207      * @param factory     A factory for showing the inline preview activity for within this app.
208      *                    Only used for certain WallpaperInfo implementations that require an inline preview
209      *                    (as opposed to some external preview activity).
210      * @param requestCode Request code to pass in when starting the inline preview activity.
211      */
showPreview(Activity srcActivity, InlinePreviewIntentFactory factory, int requestCode, boolean isAssetIdPresent)212     public abstract void showPreview(Activity srcActivity, InlinePreviewIntentFactory factory,
213                                      int requestCode, boolean isAssetIdPresent);
214 
215     /**
216      * Shows the appropriate preview activity for this WallpaperInfo.
217      *
218      * @param factory               A factory for showing the inline preview activity for within
219      *                              this app.
220      *                              Only used for certain WallpaperInfo implementations that
221      *                              require
222      *                              an inline preview
223      *                              (as opposed to some external preview activity).
224      * @param requestCode           Request code to pass in when starting the inline preview
225      *                              activity.
226      * @param shouldRefreshCategory category type to pass in when starting the inline preview
227      *                              activity.
228      */
showPreview(Activity srcActivity, InlinePreviewIntentFactory factory, int requestCode, boolean isAssetIdPresent, boolean shouldRefreshCategory)229     public abstract void showPreview(Activity srcActivity, InlinePreviewIntentFactory factory,
230             int requestCode, boolean isAssetIdPresent,
231             boolean shouldRefreshCategory);
232 
233     /**
234      * Returns a Future to obtain a wallpaper color and a placeholder color calculated in a
235      * background thread for this wallpaper's thumbnail.
236      * If it's already available, the Future will return the color immediately.
237      * This is intended to be a "best effort" attempt and might not obtain a color if no low res
238      * thumbnail is available.
239      */
computeColorInfo(Context context)240     public Future<ColorInfo> computeColorInfo(Context context) {
241         if (mColorInfo.getWallpaperColors() != null
242                 && mColorInfo.getPlaceholderColor() != Color.TRANSPARENT) {
243             return CompletableFuture.completedFuture(mColorInfo);
244         }
245         final Context appContext = context.getApplicationContext();
246         return sExecutor.submit(() -> {
247             synchronized (WallpaperInfo.this) {
248                 if (mColorInfo.getWallpaperColors() != null
249                         && mColorInfo.getPlaceholderColor() != Color.TRANSPARENT) {
250                     return mColorInfo;
251                 }
252 
253                 Asset thumbAsset = getThumbAsset(appContext);
254                 Bitmap lowResBitmap = thumbAsset.getLowResBitmap(appContext);
255                 if (lowResBitmap == null) {
256                     return new ColorInfo(
257                             new WallpaperColors(Color.valueOf(Color.TRANSPARENT), null, null),
258                             Color.TRANSPARENT);
259                 }
260                 mColorInfo = new ColorInfo(WallpaperColors.fromBitmap(lowResBitmap));
261                 return mColorInfo;
262             }
263         });
264     }
265 
266     /**
267      * Remove the effect name from this wallpaper, only use it for logging.
268      */
269     public void removeEffectName(String effect) {
270         mEffectNames.remove(effect);
271     }
272 
273     /**
274      * Add the effect name apply with this wallpaper, only use it for logging.
275      */
276     public void addEffectName(String effect) {
277         mEffectNames.add(effect);
278     }
279 
280     /**
281      * Returns the effects apply with this wallpaper.
282      */
283     public String getEffectNames() {
284         if (mEffectNames.isEmpty()) {
285             return null;
286         }
287         String effectNames = "";
288         Iterator value = mEffectNames.iterator();
289         while (value.hasNext()) {
290             if (!effectNames.isEmpty()) {
291                 effectNames += ",";
292             }
293             effectNames += value.next();
294         }
295 
296         return effectNames;
297     }
298 
299     /**
300      * Whether backup is allowed for this type of wallpaper.
301      */
302     @IntDef({
303             BACKUP_NOT_ALLOWED,
304             BACKUP_ALLOWED
305     })
306     public @interface BackupPermission {
307     }
308 
309     /**
310      * Returns a group name under which this Wallpaper should be grouped when displayed in
311      * a gallery, or an empty String if no grouping is required.
312      */
313     public String getGroupName(Context context) {
314         return "";
315     }
316 
317     /**
318      * Returns the resource id of a drawable to use as a badge when displaying this wallpaper
319      * in a gallery, or {@link Resources#ID_NULL} if no badge is required.
320      */
321     @DrawableRes
322     public int getBadgeDrawableRes() {
323         return Resources.ID_NULL;
324     }
325 
326     /** Sets the crop {@link Rect} of each displaySize for this wallpaper. */
327     public void setWallpaperCropHints(Map<Point, Rect> cropHints) {
328         if (cropHints == null) {
329             return;
330         }
331 
332         cropHints.forEach((displaySize, rect) -> {
333             if (rect != null) {
334                 mCropHints.put(displaySize.flattenToString(),
335                         rect.flattenToString());
336             }
337         });
338     }
339 
340     /** Returns the crop {@link Rect} of each displaySize for this wallpaper. */
341     public @Nullable Map<Point, Rect> getWallpaperCropHints() {
342         BaseFlags flags = InjectorProvider.getInjector().getFlags();
343         if (!flags.isMultiCropEnabled()) {
344             return null;
345         }
346 
347         Map<Point, Rect> cropHints = new HashMap<>();
348         mCropHints.forEach(
349                 (displaySize, rect) -> cropHints.put(
350                         Point.unflattenFromString(displaySize),
351                         Rect.unflattenFromString(rect)));
352         return cropHints;
353     }
354 
355     /**
356      * Inner class to keep wallpaper colors and placeholder color.
357      */
358     public static class ColorInfo {
359         private WallpaperColors mWallpaperColors;
360         private Integer mPlaceholderColor = Color.TRANSPARENT;
361 
362         public ColorInfo() {
363         }
364 
365         public ColorInfo(WallpaperColors wallpaperColors) {
366             mWallpaperColors = wallpaperColors;
367             if (mWallpaperColors != null) {
368                 mPlaceholderColor = mWallpaperColors.getPrimaryColor().toArgb();
369             }
370         }
371 
372         public ColorInfo(WallpaperColors wallpaperColors, Integer placeholderColor) {
373             mWallpaperColors = wallpaperColors;
374             mPlaceholderColor = placeholderColor;
375         }
376 
377         public WallpaperColors getWallpaperColors() {
378             return mWallpaperColors;
379         }
380 
381         public Integer getPlaceholderColor() {
382             return mPlaceholderColor;
383         }
384     }
385 
386     public ColorInfo getColorInfo() {
387         return mColorInfo;
388     }
389 }
390