1 /*
2  * Copyright (C) 2020 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.content.Context;
20 import android.content.pm.PackageManager;
21 import android.content.res.Resources;
22 import android.os.Parcel;
23 import android.text.TextUtils;
24 import android.util.AttributeSet;
25 import android.util.Log;
26 
27 import androidx.annotation.Nullable;
28 
29 import com.android.wallpaper.asset.Asset;
30 import com.android.wallpaper.asset.ResourceAsset;
31 import com.android.wallpaper.asset.SystemStaticAsset;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * Represents a wallpaper coming from the resources of the partner static wallpaper
38  * container APK.
39  */
40 public class SystemStaticWallpaperInfo extends WallpaperInfo {
41     public static final Creator<SystemStaticWallpaperInfo> CREATOR =
42             new Creator<SystemStaticWallpaperInfo>() {
43                 @Override
44                 public SystemStaticWallpaperInfo createFromParcel(Parcel in) {
45                     return new SystemStaticWallpaperInfo(in);
46                 }
47 
48                 @Override
49                 public SystemStaticWallpaperInfo[] newArray(int size) {
50                     return new SystemStaticWallpaperInfo[size];
51                 }
52             };
53     public static final String TAG_NAME = "static-wallpaper";
54 
55     private static final String TAG = "PartnerStaticWPInfo";
56     private static final String DRAWABLE_DEF_TYPE = "drawable";
57     private static final String STRING_DEF_TYPE = "string";
58     private static final String INTEGER_DEF_TYPE = "integer";
59     private static final String ARRAY_DEF_TYPE = "array";
60     private static final String WALLPAPERS_RES_SUFFIX = "_wallpapers";
61     private static final String TITLE_RES_SUFFIX = "_title";
62     private static final String SUBTITLE1_RES_SUFFIX = "_subtitle1";
63     private static final String SUBTITLE2_RES_SUFFIX = "_subtitle2";
64     private static final String ACTION_TYPE_RES_SUFFIX = "_action_type";
65     private static final String ACTION_URL_RES_SUFFIX = "_action_url";
66     private static final String THUMBNAIL_RES_SUFFIX = "_thumbnail";
67 
68     // Xml parsing attribute names
69     public static final String ATTR_ID = "id";
70     public static final String ATTR_SRC = "src";
71     public static final String ATTR_TITLE_RES = "title";
72     public static final String ATTR_SUBTITLE1_RES = "subtitle1";
73     public static final String ATTR_SUBTITLE2_RES = "subtitle2";
74     public static final String ATTR_ACTION_URL_RES = "actionUrl";
75     public static final String ATTR_THUMBNAIL = "thumbnail";
76 
77     private final int mDrawableResId;
78     private final String mWallpaperId;
79     private final String mCollectionId;
80     private final int mTitleResId;
81     private final int mSubtitle1ResId;
82     private final int mSubtitle2ResId;
83     private final int mActionTypeResId;
84     private final int mActionUrlResId;
85     private ResourceAsset mAsset;
86     private Resources mResources;
87     private final String mPackageName;
88     private List<String> mAttributions;
89     private String mActionUrl;
90     private int mActionType;
91     private final int mThumbnailResId;
92     private ResourceAsset mThumbnailAsset;
93 
94     /**
95      * Create and return a new {@link SystemStaticWallpaperInfo} from the information in the given
96      * XML's {@link AttributeSet}
97      * @param packageName name of the package where the resources are read from
98      * @param categoryId id of the category the new wallpaper will belong to
99      * @param attrs {@link AttributeSet} from the XML with the information for the new wallpaper
100      *                                  info
101      * @return a new {@link SystemStaticWallpaperInfo} or {@code null} if no id could be found in
102      * the given {@link AttributeSet}
103      */
104     @Nullable
fromAttributeSet(String packageName, String categoryId, AttributeSet attrs)105     public static SystemStaticWallpaperInfo fromAttributeSet(String packageName,
106             String categoryId, AttributeSet attrs) {
107         String wallpaperId = attrs.getAttributeValue(null, ATTR_ID);
108         if (TextUtils.isEmpty(wallpaperId)) {
109             return null;
110         }
111         int drawableResId = attrs.getAttributeResourceValue(null, ATTR_SRC, 0);
112         int wallpaperTitleResId = attrs.getAttributeResourceValue(null, ATTR_TITLE_RES, 0);
113         int wallpaperSubtitle1ResId = attrs.getAttributeResourceValue(null, ATTR_SUBTITLE1_RES, 0);
114         int wallpaperSubtitle2ResId = attrs.getAttributeResourceValue(null, ATTR_SUBTITLE2_RES, 0);
115         int actionUrlResId = attrs.getAttributeResourceValue(null, ATTR_ACTION_URL_RES, 0);
116         int thumbnailResId = attrs.getAttributeResourceValue(null, ATTR_THUMBNAIL, 0);
117 
118         return new SystemStaticWallpaperInfo(packageName, wallpaperId,
119                 categoryId, drawableResId, wallpaperTitleResId, wallpaperSubtitle1ResId,
120                 wallpaperSubtitle2ResId, 0, actionUrlResId, thumbnailResId);
121     }
122 
123     /**
124      * Read from the given stub apk the available static categories and wallpapers
125      * @deprecated this is left for backwards compatibility with legacy stub format,
126      * use {@link #fromAttributeSet(String, String, AttributeSet)} instead for
127      * the new stub format.
128      */
129     @Deprecated
getAll(String partnerStubPackageName, Resources stubApkResources, String categoryId)130     public static List<WallpaperInfo> getAll(String partnerStubPackageName,
131             Resources stubApkResources, String categoryId) {
132         ArrayList<WallpaperInfo> wallpapers = new ArrayList<>();
133 
134         int listResId = stubApkResources.getIdentifier(categoryId + WALLPAPERS_RES_SUFFIX,
135                 ARRAY_DEF_TYPE, partnerStubPackageName);
136         String[] wallpaperResNames = stubApkResources.getStringArray(listResId);
137 
138         for (String wallpaperResName : wallpaperResNames) {
139             int drawableResId = stubApkResources.getIdentifier(wallpaperResName, DRAWABLE_DEF_TYPE,
140                     partnerStubPackageName);
141             int wallpaperTitleResId = stubApkResources.getIdentifier(
142                     wallpaperResName + TITLE_RES_SUFFIX, STRING_DEF_TYPE, partnerStubPackageName);
143             int wallpaperSubtitle1ResId = stubApkResources.getIdentifier(
144                     wallpaperResName + SUBTITLE1_RES_SUFFIX, STRING_DEF_TYPE,
145                     partnerStubPackageName);
146             int wallpaperSubtitle2ResId = stubApkResources.getIdentifier(
147                     wallpaperResName + SUBTITLE2_RES_SUFFIX, STRING_DEF_TYPE,
148                     partnerStubPackageName);
149             int actionTypeResId = stubApkResources.getIdentifier(
150                     wallpaperResName + ACTION_TYPE_RES_SUFFIX, INTEGER_DEF_TYPE,
151                     partnerStubPackageName);
152             int actionUrlResId = stubApkResources.getIdentifier(
153                     wallpaperResName + ACTION_URL_RES_SUFFIX, STRING_DEF_TYPE,
154                     partnerStubPackageName);
155             int thumbnailResId = stubApkResources.getIdentifier(
156                     wallpaperResName + THUMBNAIL_RES_SUFFIX, STRING_DEF_TYPE,
157                     partnerStubPackageName);
158 
159             SystemStaticWallpaperInfo wallpaperInfo = new SystemStaticWallpaperInfo(
160                     partnerStubPackageName, wallpaperResName, categoryId,
161                     drawableResId, wallpaperTitleResId, wallpaperSubtitle1ResId,
162                     wallpaperSubtitle2ResId, actionTypeResId, actionUrlResId, thumbnailResId);
163             wallpapers.add(wallpaperInfo);
164         }
165 
166         return wallpapers;
167     }
168 
169     /**
170      * Constructs a new Nexus static wallpaper model object.
171      *
172      * @param resName        The unique name of the wallpaper resource, e.g. "z_wp001".
173      * @param collectionId   Unique name of the collection this wallpaper belongs in;
174      *                       used for logging.
175      * @param drawableResId  Resource ID of the raw wallpaper image.
176      * @param titleResId     Resource ID of the string for the title attribution.
177      * @param subtitle1ResId Resource ID of the string for the first subtitle attribution.
178      * @param subtitle2ResId Resource ID of the string for the second subtitle attribution.
179      * @param thumbnailResId Resource ID of the thumbnail image.
180      */
SystemStaticWallpaperInfo(String packageName, String resName, String collectionId, int drawableResId, int titleResId, int subtitle1ResId, int subtitle2ResId, int actionTypeResId, int actionUrlResId, int thumbnailResId)181     public SystemStaticWallpaperInfo(String packageName, String resName, String collectionId,
182             int drawableResId, int titleResId, int subtitle1ResId, int subtitle2ResId,
183             int actionTypeResId, int actionUrlResId, int thumbnailResId) {
184         mPackageName = packageName;
185         mWallpaperId = resName;
186         mCollectionId = collectionId;
187         mDrawableResId = drawableResId;
188         mTitleResId = titleResId;
189         mSubtitle1ResId = subtitle1ResId;
190         mSubtitle2ResId = subtitle2ResId;
191         mActionTypeResId = actionTypeResId;
192         mActionUrlResId = actionUrlResId;
193         mThumbnailResId = thumbnailResId;
194     }
195 
SystemStaticWallpaperInfo(Parcel in)196     private SystemStaticWallpaperInfo(Parcel in) {
197         super(in);
198         mPackageName = in.readString();
199         mWallpaperId = in.readString();
200         mCollectionId = in.readString();
201         mDrawableResId = in.readInt();
202         mTitleResId = in.readInt();
203         mSubtitle1ResId = in.readInt();
204         mSubtitle2ResId = in.readInt();
205         mActionTypeResId = in.readInt();
206         mActionUrlResId = in.readInt();
207         mThumbnailResId = in.readInt();
208     }
209 
210     @Override
getAsset(Context context)211     public Asset getAsset(Context context) {
212         if (mAsset == null) {
213             Resources res = getPackageResources(context);
214             mAsset = new SystemStaticAsset(res, mDrawableResId, mWallpaperId, false);
215         }
216 
217         return mAsset;
218     }
219 
220     @Override
getThumbAsset(Context context)221     public Asset getThumbAsset(Context context) {
222         if (mThumbnailResId != 0) {
223             if (mThumbnailAsset == null) {
224                 Resources res = getPackageResources(context);
225                 mThumbnailAsset = new SystemStaticAsset(res, mThumbnailResId, mWallpaperId, true);
226             }
227             return mThumbnailAsset;
228         }
229         return getAsset(context);
230     }
231 
232     @Override
getAttributions(Context context)233     public List<String> getAttributions(Context context) {
234         if (mAttributions == null) {
235             Resources res = getPackageResources(context);
236             mAttributions = new ArrayList<>();
237             if (mTitleResId != 0) {
238                 mAttributions.add(res.getString(mTitleResId));
239             }
240             if (mSubtitle1ResId != 0) {
241                 mAttributions.add(res.getString(mSubtitle1ResId));
242             }
243             if (mSubtitle2ResId != 0) {
244                 mAttributions.add(res.getString(mSubtitle2ResId));
245             }
246         }
247 
248         return mAttributions;
249     }
250 
251     @Override
getActionUrl(Context context)252     public String getActionUrl(Context context) {
253         if (mActionUrl == null && mActionUrlResId != 0) {
254             mActionUrl = getPackageResources(context).getString(mActionUrlResId);
255         }
256         return mActionUrl;
257     }
258 
259     @Override
showPreview(Activity srcActivity, InlinePreviewIntentFactory factory, int requestCode, boolean isAssetIdPresent)260     public void showPreview(Activity srcActivity, InlinePreviewIntentFactory factory,
261                             int requestCode, boolean isAssetIdPresent) {
262         srcActivity.startActivityForResult(factory.newIntent(srcActivity, this,
263                 isAssetIdPresent), requestCode);
264     }
265 
266     @Override
getCollectionId(Context unused)267     public String getCollectionId(Context unused) {
268         return mCollectionId;
269     }
270 
271     @Override
getWallpaperId()272     public String getWallpaperId() {
273         return mWallpaperId;
274     }
275 
getResName()276     public String getResName() {
277         return mWallpaperId;
278     }
279 
getActionType(Context context)280     private int getActionType(Context context) {
281         if (mActionType == 0 && mActionTypeResId != 0) {
282             mActionType = getPackageResources(context).getInteger(mActionTypeResId);
283         }
284         return mActionType;
285     }
286 
287     /**
288      * Returns the {@link Resources} instance for the Nexus static wallpapers stub APK.
289      */
getPackageResources(Context context)290     private Resources getPackageResources(Context context) {
291         if (mResources != null) {
292             return mResources;
293         }
294 
295         try {
296             mResources = context.getPackageManager().getResourcesForApplication(mPackageName);
297         } catch (PackageManager.NameNotFoundException e) {
298             Log.e(TAG, "Could not get app resources");
299         }
300         return mResources;
301     }
302 
303     @Override
writeToParcel(Parcel dest, int flags)304     public void writeToParcel(Parcel dest, int flags) {
305         super.writeToParcel(dest, flags);
306         dest.writeString(mPackageName);
307         dest.writeString(mWallpaperId);
308         dest.writeString(mCollectionId);
309         dest.writeInt(mDrawableResId);
310         dest.writeInt(mTitleResId);
311         dest.writeInt(mSubtitle1ResId);
312         dest.writeInt(mSubtitle2ResId);
313         dest.writeInt(mActionTypeResId);
314         dest.writeInt(mActionUrlResId);
315         dest.writeInt(mThumbnailResId);
316     }
317 }
318