1 package com.android.wallpaperpicker.tileinfo;
2 
3 import android.annotation.TargetApi;
4 import android.app.Activity;
5 import android.app.WallpaperManager;
6 import android.content.Context;
7 import android.content.res.Resources;
8 import android.graphics.Bitmap;
9 import android.graphics.BitmapFactory;
10 import android.graphics.Canvas;
11 import android.graphics.Point;
12 import android.graphics.RectF;
13 import android.graphics.drawable.BitmapDrawable;
14 import android.graphics.drawable.Drawable;
15 import android.os.Build;
16 import android.util.Log;
17 
18 import com.android.wallpaperpicker.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
19 import com.android.wallpaperpicker.WallpaperFiles;
20 import com.android.wallpaperpicker.WallpaperPickerActivity;
21 import com.android.wallpaperpicker.common.CropAndSetWallpaperTask;
22 import com.android.wallpaperpicker.common.DialogUtils;
23 import com.android.wallpaperpicker.common.InputStreamProvider;
24 import com.android.wallpaperpicker.common.WallpaperManagerCompat;
25 
26 import java.io.ByteArrayInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.File;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 
32 public class DefaultWallpaperInfo extends DrawableThumbWallpaperInfo {
33 
34     private static final String TAG = "DefaultWallpaperInfo";
35 
DefaultWallpaperInfo(Drawable thumb)36     public DefaultWallpaperInfo(Drawable thumb) {
37         super(thumb);
38     }
39 
40     @Override
onClick(WallpaperPickerActivity a)41     public void onClick(WallpaperPickerActivity a) {
42         a.setCropViewTileSource(null, false, false, new CropViewScaleAndOffsetProvider() {
43 
44             @Override
45             public float getScale(Point wallpaperSize, RectF crop) {
46                 return 1f;
47             }
48 
49             @Override
50             public float getParallaxOffset() {
51                 return 0.5f;
52             }
53         }, null);
54     }
55 
56     @Override
onSave(final WallpaperPickerActivity a)57     public void onSave(final WallpaperPickerActivity a) {
58         CropAndSetWallpaperTask.OnEndCropHandler onEndCropHandler
59                 = new CropAndSetWallpaperTask.OnEndCropHandler() {
60             @Override
61             public void run(boolean cropSucceeded) {
62                 if (cropSucceeded) {
63                     a.setResult(Activity.RESULT_OK);
64                 }
65                 a.finish();
66             }
67         };
68         CropAndSetWallpaperTask setWallpaperTask = new CropAndSetWallpaperTask(
69                 null, a, null, -1, -1, -1, onEndCropHandler) {
70             @Override
71             protected Boolean doInBackground(Integer... params) {
72                 int whichWallpaper = params[0];
73                 boolean succeeded;
74                 if (whichWallpaper == WallpaperManagerCompat.FLAG_SET_LOCK) {
75                     succeeded = setDefaultOnLock(a);
76                 } else {
77                     succeeded = clearWallpaper(a, whichWallpaper);
78                 }
79                 return succeeded;
80             }
81         };
82 
83         DialogUtils.executeCropTaskAfterPrompt(a, setWallpaperTask, a.getOnDialogCancelListener());
84     }
85 
86     //TODO: @TargetApi(Build.VERSION_CODES.N)
setDefaultOnLock(WallpaperPickerActivity a)87     private boolean setDefaultOnLock(WallpaperPickerActivity a) {
88         boolean succeeded = true;
89         try {
90             Bitmap defaultWallpaper = ((BitmapDrawable) WallpaperManager.getInstance(
91                     a.getApplicationContext()).getBuiltInDrawable()).getBitmap();
92             ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
93             if (defaultWallpaper.compress(Bitmap.CompressFormat.PNG, 100, tmpOut)) {
94                 byte[] outByteArray = tmpOut.toByteArray();
95                 WallpaperManagerCompat.getInstance(a.getApplicationContext())
96                         .setStream(new ByteArrayInputStream(outByteArray), null,
97                                 true, WallpaperManagerCompat.FLAG_SET_LOCK);
98             }
99         } catch (IOException e) {
100             Log.w(TAG, "Setting wallpaper to default threw exception", e);
101             succeeded = false;
102         }
103         return succeeded;
104     }
105 
clearWallpaper(WallpaperPickerActivity a, int whichWallpaper)106     private boolean clearWallpaper(WallpaperPickerActivity a, int whichWallpaper) {
107         boolean succeeded = true;
108         try {
109             WallpaperManagerCompat.getInstance(a.getApplicationContext()).clear(whichWallpaper);
110         } catch (IOException e) {
111             Log.w(TAG, "Setting wallpaper to default threw exception", e);
112             succeeded = false;
113         } catch (SecurityException e) {
114             // Happens on Samsung S6, for instance:
115             // "Permission denial: writing to settings requires android.permission.WRITE_SETTINGS"
116             Log.w(TAG, "Setting wallpaper to default threw exception", e);
117             // In this case, clearing worked even though the exception was thrown afterwards.
118             succeeded = true;
119         }
120         return succeeded;
121     }
122 
123     @Override
isSelectable()124     public boolean isSelectable() {
125         return true;
126     }
127 
128     @Override
isNamelessWallpaper()129     public boolean isNamelessWallpaper() {
130         return true;
131     }
132 
133     /**
134      * @return the system default wallpaper tile or null
135      */
get(Context context)136     public static WallpaperTileInfo get(Context context) {
137         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
138                 ? getDefaultWallpaper(context) : getPreKKDefaultWallpaperInfo(context);
139     }
140 
141     @TargetApi(Build.VERSION_CODES.KITKAT)
getDefaultWallpaper(Context context)142     private static DefaultWallpaperInfo getDefaultWallpaper(Context context) {
143         File defaultThumbFile = getDefaultThumbFile(context);
144         Bitmap thumb = null;
145         boolean defaultWallpaperExists = false;
146         Resources res = context.getResources();
147 
148         if (defaultThumbFile.exists()) {
149             thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
150             defaultWallpaperExists = true;
151         } else {
152             Point defaultThumbSize = getDefaultThumbSize(res);
153             Drawable wallpaperDrawable = WallpaperManager.getInstance(context).getBuiltInDrawable(
154                     defaultThumbSize.x, defaultThumbSize.y, true, 0.5f, 0.5f);
155             if (wallpaperDrawable != null) {
156                 thumb = Bitmap.createBitmap(
157                         defaultThumbSize.x, defaultThumbSize.y, Bitmap.Config.ARGB_8888);
158                 Canvas c = new Canvas(thumb);
159                 wallpaperDrawable.setBounds(0, 0, defaultThumbSize.x, defaultThumbSize.y);
160                 wallpaperDrawable.draw(c);
161                 c.setBitmap(null);
162             }
163             if (thumb != null) {
164                 defaultWallpaperExists = saveDefaultWallpaperThumb(context, thumb);
165             }
166         }
167         if (defaultWallpaperExists) {
168             return new DefaultWallpaperInfo(new BitmapDrawable(res, thumb));
169         }
170         return null;
171     }
172 
getPreKKDefaultWallpaperInfo(Context context)173     private static ResourceWallpaperInfo getPreKKDefaultWallpaperInfo(Context context) {
174         Resources sysRes = Resources.getSystem();
175         Resources res = context.getResources();
176 
177         int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android");
178 
179         File defaultThumbFile = getDefaultThumbFile(context);
180         Bitmap thumb = null;
181         boolean defaultWallpaperExists = false;
182         if (defaultThumbFile.exists()) {
183             thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
184             defaultWallpaperExists = true;
185         } else {
186             InputStreamProvider streamProvider = InputStreamProvider.fromResource(res, resId);
187             thumb = createThumbnail(
188                     streamProvider, context, streamProvider.getRotationFromExif(context), false);
189             if (thumb != null) {
190                 defaultWallpaperExists = saveDefaultWallpaperThumb(context, thumb);
191             }
192         }
193         if (defaultWallpaperExists) {
194             return new ResourceWallpaperInfo(sysRes, resId, new BitmapDrawable(res, thumb));
195         }
196         return null;
197     }
198 
getDefaultThumbFile(Context context)199     private static File getDefaultThumbFile(Context context) {
200         return new File(context.getFilesDir(), Build.VERSION.SDK_INT
201                 + "_" + WallpaperFiles.DEFAULT_WALLPAPER_THUMBNAIL);
202     }
203 
saveDefaultWallpaperThumb(Context c, Bitmap b)204     private static boolean saveDefaultWallpaperThumb(Context c, Bitmap b) {
205         // Delete old thumbnails.
206         new File(c.getFilesDir(), WallpaperFiles.DEFAULT_WALLPAPER_THUMBNAIL_OLD).delete();
207         new File(c.getFilesDir(), WallpaperFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
208 
209         for (int i = Build.VERSION_CODES.JELLY_BEAN; i < Build.VERSION.SDK_INT; i++) {
210             new File(c.getFilesDir(), i + "_" + WallpaperFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
211         }
212         File f = getDefaultThumbFile(c);
213         try {
214             f.createNewFile();
215             FileOutputStream thumbFileStream = c.openFileOutput(f.getName(), Context.MODE_PRIVATE);
216             b.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
217             thumbFileStream.close();
218             return true;
219         } catch (IOException e) {
220             Log.e(TAG, "Error while writing bitmap to file " + e);
221             f.delete();
222             return false;
223         }
224     }
225 }