1package com.android.wallpaperpicker.tileinfo;
2
3import android.annotation.TargetApi;
4import android.app.Activity;
5import android.app.WallpaperManager;
6import android.content.Context;
7import android.content.res.Resources;
8import android.graphics.Bitmap;
9import android.graphics.BitmapFactory;
10import android.graphics.Canvas;
11import android.graphics.Point;
12import android.graphics.RectF;
13import android.graphics.drawable.BitmapDrawable;
14import android.graphics.drawable.Drawable;
15import android.os.Build;
16import android.util.Log;
17
18import com.android.wallpaperpicker.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
19import com.android.wallpaperpicker.WallpaperFiles;
20import com.android.wallpaperpicker.WallpaperPickerActivity;
21import com.android.wallpaperpicker.common.CropAndSetWallpaperTask;
22import com.android.wallpaperpicker.common.DialogUtils;
23import com.android.wallpaperpicker.common.InputStreamProvider;
24import com.android.wallpaperpicker.common.WallpaperManagerCompat;
25
26import java.io.ByteArrayInputStream;
27import java.io.ByteArrayOutputStream;
28import java.io.File;
29import java.io.FileOutputStream;
30import java.io.IOException;
31
32public class DefaultWallpaperInfo extends DrawableThumbWallpaperInfo {
33
34    private static final String TAG = "DefaultWallpaperInfo";
35
36    public DefaultWallpaperInfo(Drawable thumb) {
37        super(thumb);
38    }
39
40    @Override
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
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)
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
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
124    public boolean isSelectable() {
125        return true;
126    }
127
128    @Override
129    public boolean isNamelessWallpaper() {
130        return true;
131    }
132
133    /**
134     * @return the system default wallpaper tile or null
135     */
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)
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
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
199    private static File getDefaultThumbFile(Context context) {
200        return new File(context.getFilesDir(), Build.VERSION.SDK_INT
201                + "_" + WallpaperFiles.DEFAULT_WALLPAPER_THUMBNAIL);
202    }
203
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}