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