blob: dc8746756bef0387ea4f6d19cc7c0c81ed876f0b [file] [log] [blame]
Jon Miranda16ea1b12017-12-12 14:52:48 -08001/*
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 */
16package com.android.wallpaper.module;
17
18import android.annotation.SuppressLint;
19import android.app.Activity;
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -070020import android.app.WallpaperColors;
Jon Miranda16ea1b12017-12-12 14:52:48 -080021import android.app.WallpaperManager;
22import android.content.Context;
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -070023import android.content.res.Resources;
Jon Miranda16ea1b12017-12-12 14:52:48 -080024import android.graphics.Bitmap;
25import android.graphics.Bitmap.CompressFormat;
26import android.graphics.BitmapFactory;
27import android.graphics.Point;
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -070028import android.graphics.PointF;
Jon Miranda16ea1b12017-12-12 14:52:48 -080029import android.graphics.Rect;
30import android.graphics.drawable.BitmapDrawable;
31import android.os.AsyncTask;
32import android.os.ParcelFileDescriptor;
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -070033import android.text.TextUtils;
Jon Miranda16ea1b12017-12-12 14:52:48 -080034import android.util.Log;
35import android.view.Display;
36import android.view.WindowManager;
37
Samuel Fufa03bc6ac2019-09-19 12:01:50 -070038import androidx.annotation.Nullable;
39
Jon Miranda16ea1b12017-12-12 14:52:48 -080040import com.android.wallpaper.asset.Asset;
41import com.android.wallpaper.asset.Asset.BitmapReceiver;
42import com.android.wallpaper.asset.Asset.DimensionsReceiver;
43import com.android.wallpaper.asset.BitmapUtils;
44import com.android.wallpaper.asset.StreamableAsset;
45import com.android.wallpaper.asset.StreamableAsset.StreamReceiver;
46import com.android.wallpaper.compat.BuildCompat;
47import com.android.wallpaper.compat.WallpaperManagerCompat;
48import com.android.wallpaper.model.WallpaperInfo;
49import com.android.wallpaper.module.BitmapCropper.Callback;
Jon Miranda16ea1b12017-12-12 14:52:48 -080050import com.android.wallpaper.util.BitmapTransformer;
Santiago Etchebeherec105e102021-09-20 16:11:33 -070051import com.android.wallpaper.util.DisplayUtils;
Jon Miranda16ea1b12017-12-12 14:52:48 -080052import com.android.wallpaper.util.ScreenSizeCalculator;
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -070053import com.android.wallpaper.util.WallpaperCropUtils;
Jon Miranda16ea1b12017-12-12 14:52:48 -080054
55import java.io.ByteArrayInputStream;
56import java.io.ByteArrayOutputStream;
Jon Miranda16ea1b12017-12-12 14:52:48 -080057import java.io.FileInputStream;
Jon Miranda16ea1b12017-12-12 14:52:48 -080058import java.io.IOException;
59import java.io.InputStream;
60import java.util.List;
61
62/**
63 * Concrete implementation of WallpaperPersister which actually sets wallpapers to the system via
64 * the WallpaperManager.
65 */
66public class DefaultWallpaperPersister implements WallpaperPersister {
67
68 private static final int DEFAULT_COMPRESS_QUALITY = 100;
69 private static final String TAG = "WallpaperPersister";
70
71 private final Context mAppContext; // The application's context.
Santiago Etchebehere5a7f1dd2018-04-03 15:01:29 -070072 // Context that accesses files in device protected storage
Jon Miranda16ea1b12017-12-12 14:52:48 -080073 private final WallpaperManager mWallpaperManager;
74 private final WallpaperManagerCompat mWallpaperManagerCompat;
75 private final WallpaperPreferences mWallpaperPreferences;
Jon Miranda16ea1b12017-12-12 14:52:48 -080076 private final WallpaperChangedNotifier mWallpaperChangedNotifier;
Santiago Etchebeherec105e102021-09-20 16:11:33 -070077 private final DisplayUtils mDisplayUtils;
Jon Miranda16ea1b12017-12-12 14:52:48 -080078
79 private WallpaperInfo mWallpaperInfoInPreview;
80
81 @SuppressLint("ServiceCast")
82 public DefaultWallpaperPersister(Context context) {
83 mAppContext = context.getApplicationContext();
84 // Retrieve WallpaperManager using Context#getSystemService instead of
85 // WallpaperManager#getInstance so it can be mocked out in test.
86 Injector injector = InjectorProvider.getInjector();
87 mWallpaperManager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
88 mWallpaperManagerCompat = injector.getWallpaperManagerCompat(context);
89 mWallpaperPreferences = injector.getPreferences(context);
Jon Miranda16ea1b12017-12-12 14:52:48 -080090 mWallpaperChangedNotifier = WallpaperChangedNotifier.getInstance();
Santiago Etchebeherec105e102021-09-20 16:11:33 -070091 mDisplayUtils = injector.getDisplayUtils(context);
Jon Miranda16ea1b12017-12-12 14:52:48 -080092 }
93
94 @Override
95 public void setIndividualWallpaper(final WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -070096 @Nullable Rect cropRect, float scale, @Destination final int destination,
97 final SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -080098 // Set wallpaper without downscaling directly from an input stream if there's no crop rect
99 // specified by the caller and the asset is streamable.
100 if (cropRect == null && asset instanceof StreamableAsset) {
101 ((StreamableAsset) asset).fetchInputStream(new StreamReceiver() {
102 @Override
103 public void onInputStreamOpened(@Nullable InputStream inputStream) {
104 if (inputStream == null) {
105 callback.onError(null /* throwable */);
106 return;
107 }
108 setIndividualWallpaper(wallpaper, inputStream, destination, callback);
109 }
110 });
111 return;
112 }
113
114 // If no crop rect is specified but the wallpaper asset is not streamable, then fall back to
115 // using the device's display size.
116 if (cropRect == null) {
117 Display display = ((WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE))
118 .getDefaultDisplay();
119 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display);
120 asset.decodeBitmap(screenSize.x, screenSize.y, new BitmapReceiver() {
121 @Override
122 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
123 if (bitmap == null) {
124 callback.onError(null /* throwable */);
125 return;
126 }
127 setIndividualWallpaper(wallpaper, bitmap, destination, callback);
128 }
129 });
130 return;
131 }
132
133 BitmapCropper bitmapCropper = InjectorProvider.getInjector().getBitmapCropper();
Santiago Etchebehere16cf0602020-12-11 17:04:18 -0800134 bitmapCropper.cropAndScaleBitmap(asset, scale, cropRect, false, new Callback() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800135 @Override
136 public void onBitmapCropped(Bitmap croppedBitmap) {
137 setIndividualWallpaper(wallpaper, croppedBitmap, destination, callback);
138 }
139
140 @Override
141 public void onError(@Nullable Throwable e) {
142 callback.onError(e);
143 }
144 });
145 }
146
147 @Override
148 public void setIndividualWallpaperWithPosition(Activity activity, WallpaperInfo wallpaper,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700149 @WallpaperPosition int wallpaperPosition, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800150 Display display = ((WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE))
151 .getDefaultDisplay();
152 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display);
153
154 Asset asset = wallpaper.getAsset(activity);
155 asset.decodeRawDimensions(activity, new DimensionsReceiver() {
156 @Override
157 public void onDimensionsDecoded(@Nullable Point dimensions) {
158 if (dimensions == null) {
159 callback.onError(null);
160 return;
161 }
162
163 switch (wallpaperPosition) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700164 // Crop out screen-sized center portion of the source image if it's larger
165 // than the screen
166 // in both dimensions. Otherwise, decode the entire bitmap and fill the space
167 // around it to fill a new screen-sized bitmap with plain black pixels.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800168 case WALLPAPER_POSITION_CENTER:
169 setIndividualWallpaperWithCenterPosition(
170 wallpaper, asset, dimensions, screenSize, callback);
171 break;
172
173 // Crop out a screen-size portion of the source image and set the bitmap region.
174 case WALLPAPER_POSITION_CENTER_CROP:
175 setIndividualWallpaperWithCenterCropPosition(
176 wallpaper, asset, dimensions, screenSize, callback);
177 break;
178
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700179 // Decode full bitmap sized for screen and stretch it to fill the screen
180 // dimensions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800181 case WALLPAPER_POSITION_STRETCH:
182 asset.decodeBitmap(screenSize.x, screenSize.y, new BitmapReceiver() {
183 @Override
184 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700185 setIndividualWallpaperStretch(wallpaper, bitmap,
186 screenSize /* stretchSize */,
Jon Miranda16ea1b12017-12-12 14:52:48 -0800187 WallpaperPersister.DEST_BOTH, callback);
188 }
189 });
190 break;
191
192 default:
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700193 Log.e(TAG, "Unsupported wallpaper position option specified: "
194 + wallpaperPosition);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800195 callback.onError(null);
196 }
197 }
198 });
199 }
200
201 /**
202 * Sets an individual wallpaper to both home + lock static wallpaper destinations with a center
203 * wallpaper position.
204 *
205 * @param wallpaper The wallpaper model object representing the wallpaper to be set.
206 * @param asset The wallpaper asset that should be used to set a wallpaper.
207 * @param dimensions Raw dimensions of the wallpaper asset.
208 * @param screenSize Dimensions of the device screen.
209 * @param callback Callback used to notify original caller of wallpaper set operation result.
210 */
211 private void setIndividualWallpaperWithCenterPosition(WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700212 Point dimensions, Point screenSize, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800213 if (dimensions.x >= screenSize.x && dimensions.y >= screenSize.y) {
214 Rect cropRect = new Rect(
215 (dimensions.x - screenSize.x) / 2,
216 (dimensions.y - screenSize.y) / 2,
217 dimensions.x - ((dimensions.x - screenSize.x) / 2),
218 dimensions.y - ((dimensions.y - screenSize.y) / 2));
Santiago Etchebehere16cf0602020-12-11 17:04:18 -0800219 asset.decodeBitmapRegion(cropRect, screenSize.x, screenSize.y, false,
220 bitmap -> setIndividualWallpaper(wallpaper, bitmap,
221 WallpaperPersister.DEST_BOTH, callback));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800222 } else {
223 // Decode the full bitmap and pass with the screen size as a fill rect.
224 asset.decodeBitmap(dimensions.x, dimensions.y, new BitmapReceiver() {
225 @Override
226 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
227 if (bitmap == null) {
228 callback.onError(null);
229 return;
230 }
231
232 setIndividualWallpaperFill(wallpaper, bitmap, screenSize /* fillSize */,
233 WallpaperPersister.DEST_BOTH, callback);
234 }
235 });
236 }
237 }
238
239 /**
240 * Sets an individual wallpaper to both home + lock static wallpaper destinations with a center
241 * cropped wallpaper position.
242 *
243 * @param wallpaper The wallpaper model object representing the wallpaper to be set.
244 * @param asset The wallpaper asset that should be used to set a wallpaper.
245 * @param dimensions Raw dimensions of the wallpaper asset.
246 * @param screenSize Dimensions of the device screen.
247 * @param callback Callback used to notify original caller of wallpaper set operation result.
248 */
249 private void setIndividualWallpaperWithCenterCropPosition(WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700250 Point dimensions, Point screenSize, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800251 float scale = Math.max((float) screenSize.x / dimensions.x,
252 (float) screenSize.y / dimensions.y);
253
254 int scaledImageWidth = (int) (dimensions.x * scale);
255 int scaledImageHeight = (int) (dimensions.y * scale);
256
257 // Crop rect is in post-scale units.
258 Rect cropRect = new Rect(
259 (scaledImageWidth - screenSize.x) / 2,
260 (scaledImageHeight - screenSize.y) / 2,
261 scaledImageWidth - ((scaledImageWidth - screenSize.x) / 2),
262 scaledImageHeight - (((scaledImageHeight - screenSize.y) / 2)));
263
264 setIndividualWallpaper(
265 wallpaper, asset, cropRect, scale, WallpaperPersister.DEST_BOTH, callback);
266 }
267
268 /**
269 * Sets a static individual wallpaper to the system via the WallpaperManager.
270 *
271 * @param wallpaper Wallpaper model object.
272 * @param croppedBitmap Bitmap representing the individual wallpaper image.
273 * @param destination The destination - where to set the wallpaper to.
274 * @param callback Called once the wallpaper was set or if an error occurred.
275 */
276 private void setIndividualWallpaper(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700277 @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800278 SetWallpaperTask setWallpaperTask =
279 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
280 setWallpaperTask.execute();
281 }
282
283 /**
284 * Sets a static individual wallpaper to the system via the WallpaperManager with a fill option.
285 *
286 * @param wallpaper Wallpaper model object.
287 * @param croppedBitmap Bitmap representing the individual wallpaper image.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700288 * @param fillSize Specifies the final bitmap size that should be set to WallpaperManager.
289 * This final bitmap will show the visible area of the provided bitmap
290 * after applying a mask with black background the source bitmap and
291 * centering. There may be black borders around the original bitmap if
292 * it's smaller than the fillSize in one or both dimensions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800293 * @param destination The destination - where to set the wallpaper to.
294 * @param callback Called once the wallpaper was set or if an error occurred.
295 */
296 private void setIndividualWallpaperFill(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700297 Point fillSize, @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800298 SetWallpaperTask setWallpaperTask =
299 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
300 setWallpaperTask.setFillSize(fillSize);
301 setWallpaperTask.execute();
302 }
303
304 /**
305 * Sets a static individual wallpaper to the system via the WallpaperManager with a stretch
306 * option.
307 *
308 * @param wallpaper Wallpaper model object.
309 * @param croppedBitmap Bitmap representing the individual wallpaper image.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700310 * @param stretchSize Specifies the final size to which the bitmap should be stretched
311 * prior
Jon Miranda16ea1b12017-12-12 14:52:48 -0800312 * to being set to the device.
313 * @param destination The destination - where to set the wallpaper to.
314 * @param callback Called once the wallpaper was set or if an error occurred.
315 */
316 private void setIndividualWallpaperStretch(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700317 Point stretchSize, @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800318 SetWallpaperTask setWallpaperTask =
319 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
320 setWallpaperTask.setStretchSize(stretchSize);
321 setWallpaperTask.execute();
322 }
323
324 /**
325 * Sets a static individual wallpaper stream to the system via the WallpaperManager.
326 *
327 * @param wallpaper Wallpaper model object.
328 * @param inputStream JPEG or PNG stream of wallpaper image's bytes.
329 * @param destination The destination - where to set the wallpaper to.
330 * @param callback Called once the wallpaper was set or if an error occurred.
331 */
332 private void setIndividualWallpaper(WallpaperInfo wallpaper, InputStream inputStream,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700333 @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800334 SetWallpaperTask setWallpaperTask =
335 new SetWallpaperTask(wallpaper, inputStream, destination, callback);
336 setWallpaperTask.execute();
337 }
338
339 @Override
340 public boolean setWallpaperInRotation(Bitmap wallpaperBitmap, List<String> attributions,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700341 int actionLabelRes, int actionIconRes, String actionUrl, String collectionId) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800342
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700343 return setWallpaperInRotationStatic(wallpaperBitmap, attributions, actionUrl,
344 actionLabelRes, actionIconRes, collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800345 }
346
347 @Override
348 public int setWallpaperBitmapInNextRotation(Bitmap wallpaperBitmap) {
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700349 return cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800350 }
351
352 @Override
353 public boolean finalizeWallpaperForNextRotation(List<String> attributions, String actionUrl,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700354 int actionLabelRes, int actionIconRes, String collectionId, int wallpaperId) {
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700355 return saveStaticWallpaperMetadata(attributions, actionUrl, actionLabelRes,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700356 actionIconRes, collectionId, wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800357 }
358
359 /**
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700360 * Sets wallpaper image and attributions when a static wallpaper is responsible for presenting
361 * the
Jon Miranda16ea1b12017-12-12 14:52:48 -0800362 * current "daily wallpaper".
363 */
364 private boolean setWallpaperInRotationStatic(Bitmap wallpaperBitmap, List<String> attributions,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700365 String actionUrl, int actionLabelRes, int actionIconRes, String collectionId) {
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700366 final int wallpaperId = cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800367
368 if (wallpaperId == 0) {
369 return false;
370 }
371
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700372 return saveStaticWallpaperMetadata(attributions, actionUrl, actionLabelRes,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700373 actionIconRes, collectionId, wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800374 }
375
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700376 @Override
377 public boolean saveStaticWallpaperMetadata(List<String> attributions,
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700378 String actionUrl,
379 int actionLabelRes,
380 int actionIconRes,
381 String collectionId,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700382 int wallpaperId) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800383 mWallpaperPreferences.clearHomeWallpaperMetadata();
384
385 boolean isLockWallpaperSet = isSeparateLockScreenWallpaperSet();
386
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700387 // Persist wallpaper IDs if the rotating wallpaper component
388 mWallpaperPreferences.setHomeWallpaperManagerId(wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800389
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700390 // Only copy over wallpaper ID to lock wallpaper if no explicit lock wallpaper is set
391 // (so metadata isn't lost if a user explicitly sets a home-only wallpaper).
392 if (!isLockWallpaperSet) {
393 mWallpaperPreferences.setLockWallpaperId(wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800394 }
395
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700396
Jon Miranda16ea1b12017-12-12 14:52:48 -0800397 mWallpaperPreferences.setHomeWallpaperAttributions(attributions);
398 mWallpaperPreferences.setHomeWallpaperActionUrl(actionUrl);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700399 mWallpaperPreferences.setHomeWallpaperActionLabelRes(actionLabelRes);
400 mWallpaperPreferences.setHomeWallpaperActionIconRes(actionIconRes);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800401 // Only set base image URL for static Backdrop images, not for rotation.
402 mWallpaperPreferences.setHomeWallpaperBaseImageUrl(null);
403 mWallpaperPreferences.setHomeWallpaperCollectionId(collectionId);
404
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700405 // Set metadata to lock screen also when the rotating wallpaper so if user sets a home
406 // screen-only wallpaper later, these attributions will still be available.
407 if (!isLockWallpaperSet) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800408 mWallpaperPreferences.setLockWallpaperAttributions(attributions);
409 mWallpaperPreferences.setLockWallpaperActionUrl(actionUrl);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700410 mWallpaperPreferences.setLockWallpaperActionLabelRes(actionLabelRes);
411 mWallpaperPreferences.setLockWallpaperActionIconRes(actionIconRes);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800412 mWallpaperPreferences.setLockWallpaperCollectionId(collectionId);
413 }
414
415 return true;
416 }
417
418 /**
Jon Miranda16ea1b12017-12-12 14:52:48 -0800419 * Sets a wallpaper in rotation as a static wallpaper to the {@link WallpaperManager} with the
420 * option allowBackup=false to save user data.
421 *
422 * @return wallpaper ID for the wallpaper bitmap.
423 */
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700424 private int cropAndSetWallpaperBitmapInRotationStatic(Bitmap wallpaperBitmap) {
425 // Calculate crop and scale of the wallpaper to match the default one used in preview
426 Point wallpaperSize = new Point(wallpaperBitmap.getWidth(), wallpaperBitmap.getHeight());
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700427 Resources resources = mAppContext.getResources();
Santiago Etchebeherec105e102021-09-20 16:11:33 -0700428 Display croppingDisplay = mDisplayUtils.getWallpaperDisplay();
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700429 Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
Santiago Etchebeherec105e102021-09-20 16:11:33 -0700430 resources, croppingDisplay);
431 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(croppingDisplay);
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700432
433 // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
434 float minWallpaperZoom =
435 WallpaperCropUtils.calculateMinZoom(wallpaperSize, screenSize);
436
437 PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(mAppContext,
438 wallpaperSize, WallpaperCropUtils.calculateVisibleRect(wallpaperSize, screenSize));
439
440 Point scaledCenter = new Point((int) (minWallpaperZoom * centerPosition.x),
441 (int) (minWallpaperZoom * centerPosition.y));
442
443 int offsetX = Math.max(0, -(screenSize.x / 2 - scaledCenter.x));
444 int offsetY = Math.max(0, -(screenSize.y / 2 - scaledCenter.y));
445
446 Rect cropRect = WallpaperCropUtils.calculateCropRect(mAppContext, minWallpaperZoom,
447 wallpaperSize, defaultCropSurfaceSize, screenSize, offsetX, offsetY);
448
449 Rect scaledCropRect = new Rect(
450 Math.round((float) cropRect.left / minWallpaperZoom),
451 Math.round((float) cropRect.top / minWallpaperZoom),
452 Math.round((float) cropRect.right / minWallpaperZoom),
453 Math.round((float) cropRect.bottom / minWallpaperZoom));
454
455 // Scale and crop the bitmap
456 wallpaperBitmap = Bitmap.createBitmap(wallpaperBitmap,
457 scaledCropRect.left,
458 scaledCropRect.top,
459 scaledCropRect.width(),
460 scaledCropRect.height());
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700461 int whichWallpaper = getDefaultWhichWallpaper();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800462
463 return setBitmapToWallpaperManagerCompat(wallpaperBitmap, false /* allowBackup */,
464 whichWallpaper);
465 }
466
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700467 /*
468 * Note: this method will return use home-only (FLAG_SYSTEM) instead of both home and lock
469 * if there's a distinct lock-only static wallpaper set so we don't override the lock wallpaper.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800470 */
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700471 @Override
472 public int getDefaultWhichWallpaper() {
473 return isSeparateLockScreenWallpaperSet()
474 ? WallpaperManagerCompat.FLAG_SYSTEM
475 : WallpaperManagerCompat.FLAG_SYSTEM | WallpaperManagerCompat.FLAG_LOCK;
476 }
477
478 @Override
479 public int setBitmapToWallpaperManagerCompat(Bitmap wallpaperBitmap, boolean allowBackup,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700480 int whichWallpaper) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800481 ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
James O'Leary03375d72021-06-02 10:05:57 -0400482 if (wallpaperBitmap.compress(CompressFormat.PNG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800483 try {
484 byte[] outByteArray = tmpOut.toByteArray();
485 return mWallpaperManagerCompat.setStream(
486 new ByteArrayInputStream(outByteArray),
487 null /* visibleCropHint */,
488 allowBackup,
489 whichWallpaper);
490 } catch (IOException e) {
491 Log.e(TAG, "unable to write stream to wallpaper manager");
492 return 0;
493 }
494 } else {
495 Log.e(TAG, "unable to compress wallpaper");
496 try {
497 return mWallpaperManagerCompat.setBitmap(
498 wallpaperBitmap,
499 null /* visibleCropHint */,
500 allowBackup,
501 whichWallpaper);
502 } catch (IOException e) {
503 Log.e(TAG, "unable to set wallpaper");
504 return 0;
505 }
506 }
507 }
508
509 private int setStreamToWallpaperManagerCompat(InputStream inputStream, boolean allowBackup,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700510 int whichWallpaper) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800511 try {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700512 return mWallpaperManagerCompat.setStream(inputStream, null, allowBackup,
513 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800514 } catch (IOException e) {
515 return 0;
516 }
517 }
518
519 @Override
520 public void setWallpaperInfoInPreview(WallpaperInfo wallpaper) {
521 mWallpaperInfoInPreview = wallpaper;
522 }
523
524 @Override
525 public void onLiveWallpaperSet() {
526 android.app.WallpaperInfo currentWallpaperComponent = mWallpaperManager.getWallpaperInfo();
chihhangchuang210c9602020-06-02 12:38:14 +0800527 android.app.WallpaperInfo previewedWallpaperComponent = mWallpaperInfoInPreview != null
528 ? mWallpaperInfoInPreview.getWallpaperComponent() : null;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800529
530 // If there is no live wallpaper set on the WallpaperManager or it doesn't match the
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700531 // WallpaperInfo which was last previewed, then do nothing and nullify last previewed
532 // wallpaper.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800533 if (currentWallpaperComponent == null || previewedWallpaperComponent == null
534 || !currentWallpaperComponent.getPackageName()
535 .equals(previewedWallpaperComponent.getPackageName())) {
536 mWallpaperInfoInPreview = null;
537 return;
538 }
539
540 setLiveWallpaperMetadata();
541 }
542
543 /**
544 * Returns whether a separate lock-screen (static) wallpaper is set to the WallpaperManager.
545 */
546 private boolean isSeparateLockScreenWallpaperSet() {
547 ParcelFileDescriptor lockWallpaperFile =
548 mWallpaperManagerCompat.getWallpaperFile(WallpaperManagerCompat.FLAG_LOCK);
549
550 boolean isLockWallpaperSet = false;
551
552 if (lockWallpaperFile != null) {
553 isLockWallpaperSet = true;
554
555 try {
556 lockWallpaperFile.close();
557 } catch (IOException e) {
558 Log.e(TAG, "Unable to close PFD for lock wallpaper", e);
559 }
560 }
561
562 return isLockWallpaperSet;
563 }
564
565 /**
566 * Sets the live wallpaper's metadata on SharedPreferences.
567 */
568 private void setLiveWallpaperMetadata() {
569 android.app.WallpaperInfo previewedWallpaperComponent =
570 mWallpaperInfoInPreview.getWallpaperComponent();
571
572 mWallpaperPreferences.clearHomeWallpaperMetadata();
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700573 // NOTE: We explicitly do not also clear the lock wallpaper metadata. Since the user may
574 // have set the live wallpaper on the home screen only, we leave the lock wallpaper metadata
575 // intact. If the user has set the live wallpaper for both home and lock screens, then the
Jon Miranda16ea1b12017-12-12 14:52:48 -0800576 // WallpaperRefresher will pick up on that and update the preferences later.
577 mWallpaperPreferences
578 .setHomeWallpaperAttributions(mWallpaperInfoInPreview.getAttributions(mAppContext));
579 mWallpaperPreferences.setHomeWallpaperPackageName(
580 previewedWallpaperComponent.getPackageName());
Kunhung Li3e50fd22020-05-12 20:46:18 +0800581 mWallpaperPreferences.setHomeWallpaperServiceName(
582 previewedWallpaperComponent.getServiceName());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800583 mWallpaperPreferences.setHomeWallpaperCollectionId(
584 mWallpaperInfoInPreview.getCollectionId(mAppContext));
585 mWallpaperPreferences.setWallpaperPresentationMode(
586 WallpaperPreferences.PRESENTATION_MODE_STATIC);
587 mWallpaperPreferences.clearDailyRotations();
588 }
589
Jon Miranda16ea1b12017-12-12 14:52:48 -0800590 private class SetWallpaperTask extends AsyncTask<Void, Void, Boolean> {
591
592 private final WallpaperInfo mWallpaper;
593 @Destination
594 private final int mDestination;
595 private final WallpaperPersister.SetWallpaperCallback mCallback;
596
597 private Bitmap mBitmap;
598 private InputStream mInputStream;
599
600 /**
601 * Optional parameters for applying a post-decoding fill or stretch transformation.
602 */
603 @Nullable
604 private Point mFillSize;
605 @Nullable
606 private Point mStretchSize;
607
608 SetWallpaperTask(WallpaperInfo wallpaper, Bitmap bitmap, @Destination int destination,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700609 WallpaperPersister.SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800610 super();
611 mWallpaper = wallpaper;
612 mBitmap = bitmap;
613 mDestination = destination;
614 mCallback = callback;
615 }
616
617 /**
618 * Constructor for SetWallpaperTask which takes an InputStream instead of a bitmap. The task
619 * will close the InputStream once it is done with it.
620 */
621 SetWallpaperTask(WallpaperInfo wallpaper, InputStream stream,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700622 @Destination int destination, WallpaperPersister.SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800623 mWallpaper = wallpaper;
624 mInputStream = stream;
625 mDestination = destination;
626 mCallback = callback;
627 }
628
629 void setFillSize(Point fillSize) {
630 if (mStretchSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700631 throw new IllegalArgumentException(
632 "Can't pass a fill size option if a stretch size is "
633 + "already set.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800634 }
635 mFillSize = fillSize;
636 }
637
638 void setStretchSize(Point stretchSize) {
639 if (mFillSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700640 throw new IllegalArgumentException(
641 "Can't pass a stretch size option if a fill size is "
642 + "already set.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800643 }
644 mStretchSize = stretchSize;
645 }
646
647 @Override
648 protected Boolean doInBackground(Void... unused) {
649 int whichWallpaper;
650 if (mDestination == DEST_HOME_SCREEN) {
651 whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM;
652 } else if (mDestination == DEST_LOCK_SCREEN) {
653 whichWallpaper = WallpaperManagerCompat.FLAG_LOCK;
654 } else { // DEST_BOTH
655 whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM
656 | WallpaperManagerCompat.FLAG_LOCK;
657 }
658
Jon Miranda16ea1b12017-12-12 14:52:48 -0800659
Chuck Liao0fe6f612021-09-10 00:59:57 +0800660 boolean wasLockWallpaperSet =
661 InjectorProvider.getInjector().getWallpaperStatusChecker().isLockWallpaperSet(
662 mAppContext);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800663
664 boolean allowBackup = mWallpaper.getBackupPermission() == WallpaperInfo.BACKUP_ALLOWED;
665 final int wallpaperId;
666 if (mBitmap != null) {
667 // Apply fill or stretch transformations on mBitmap if necessary.
668 if (mFillSize != null) {
669 mBitmap = BitmapTransformer.applyFillTransformation(mBitmap, mFillSize);
670 }
671 if (mStretchSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700672 mBitmap = Bitmap.createScaledBitmap(mBitmap, mStretchSize.x, mStretchSize.y,
673 true);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800674 }
675
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700676 wallpaperId = setBitmapToWallpaperManagerCompat(mBitmap, allowBackup,
677 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800678 } else if (mInputStream != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700679 wallpaperId = setStreamToWallpaperManagerCompat(mInputStream, allowBackup,
680 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800681 } else {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700682 Log.e(TAG,
683 "Both the wallpaper bitmap and input stream are null so we're unable to "
684 + "set any "
685 + "kind of wallpaper here.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800686 wallpaperId = 0;
687 }
688
689 if (wallpaperId > 0) {
690 if (mDestination == DEST_HOME_SCREEN
691 && mWallpaperPreferences.getWallpaperPresentationMode()
692 == WallpaperPreferences.PRESENTATION_MODE_ROTATING
693 && !wasLockWallpaperSet
694 && BuildCompat.isAtLeastN()) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700695 copyRotatingWallpaperToLock();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800696 }
697 setImageWallpaperMetadata(mDestination, wallpaperId);
698 return true;
699 } else {
700 return false;
701 }
702 }
703
704 @Override
705 protected void onPostExecute(Boolean isSuccess) {
706 if (mInputStream != null) {
707 try {
708 mInputStream.close();
709 } catch (IOException e) {
710 Log.e(TAG, "Failed to close input stream " + e);
711 mCallback.onError(e /* throwable */);
712 return;
713 }
714 }
715
716 if (isSuccess) {
“Chuckffd832c2020-03-22 02:15:58 +0800717 mCallback.onSuccess(mWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800718 mWallpaperChangedNotifier.notifyWallpaperChanged();
719 } else {
720 mCallback.onError(null /* throwable */);
721 }
722 }
723
724 /**
725 * Copies home wallpaper metadata to lock, and if rotation was enabled with a live wallpaper
726 * previously, then copies over the rotating wallpaper image to the WallpaperManager also.
727 * <p>
728 * Used to accommodate the case where a user had gone from a home+lock daily rotation to
729 * selecting a static wallpaper on home-only. The image and metadata that was previously
730 * rotating is now copied to the lock screen.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800731 */
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700732 private void copyRotatingWallpaperToLock() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800733
734 mWallpaperPreferences.setLockWallpaperAttributions(
735 mWallpaperPreferences.getHomeWallpaperAttributions());
736 mWallpaperPreferences.setLockWallpaperActionUrl(
737 mWallpaperPreferences.getHomeWallpaperActionUrl());
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700738 mWallpaperPreferences.setLockWallpaperActionLabelRes(
739 mWallpaperPreferences.getHomeWallpaperActionLabelRes());
740 mWallpaperPreferences.setLockWallpaperActionIconRes(
741 mWallpaperPreferences.getHomeWallpaperActionIconRes());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800742 mWallpaperPreferences.setLockWallpaperCollectionId(
743 mWallpaperPreferences.getHomeWallpaperCollectionId());
744
745 // Set the lock wallpaper ID to what Android set it to, following its having
746 // copied the system wallpaper over to the lock screen when we changed from
747 // "both" to distinct system and lock screen wallpapers.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700748 mWallpaperPreferences.setLockWallpaperId(
749 mWallpaperManagerCompat.getWallpaperId(WallpaperManagerCompat.FLAG_LOCK));
750
Jon Miranda16ea1b12017-12-12 14:52:48 -0800751 }
752
753 /**
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700754 * Sets the image wallpaper's metadata on SharedPreferences. This method is called after the
755 * set wallpaper operation is successful.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800756 *
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700757 * @param destination Which destination of wallpaper the metadata corresponds to (home
758 * screen, lock screen, or both).
759 * @param wallpaperId The ID of the static wallpaper returned by WallpaperManager, which
760 * on N and later versions of Android uniquely identifies a wallpaper
761 * image.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800762 */
763 private void setImageWallpaperMetadata(@Destination int destination, int wallpaperId) {
764 if (destination == DEST_HOME_SCREEN || destination == DEST_BOTH) {
765 mWallpaperPreferences.clearHomeWallpaperMetadata();
766 setImageWallpaperHomeMetadata(wallpaperId);
767
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700768 // Reset presentation mode to STATIC if an individual wallpaper is set to the
769 // home screen
Jon Miranda16ea1b12017-12-12 14:52:48 -0800770 // because rotation always affects at least the home screen.
771 mWallpaperPreferences.setWallpaperPresentationMode(
772 WallpaperPreferences.PRESENTATION_MODE_STATIC);
773 }
774
775 if (destination == DEST_LOCK_SCREEN || destination == DEST_BOTH) {
776 mWallpaperPreferences.clearLockWallpaperMetadata();
777 setImageWallpaperLockMetadata(wallpaperId);
778 }
779
780 mWallpaperPreferences.clearDailyRotations();
781 }
782
783 private void setImageWallpaperHomeMetadata(int homeWallpaperId) {
784 if (BuildCompat.isAtLeastN()) {
785 mWallpaperPreferences.setHomeWallpaperManagerId(homeWallpaperId);
786 }
787
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700788 // Compute bitmap hash code after setting the wallpaper because JPEG compression has
789 // likely changed many pixels' color values. Forget the previously loaded wallpaper
790 // bitmap so that WallpaperManager doesn't return the old wallpaper drawable. Do this
791 // on N+ devices in addition to saving the wallpaper ID for the purpose of backup &
792 // restore.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800793 mWallpaperManager.forgetLoadedWallpaper();
794 mBitmap = ((BitmapDrawable) mWallpaperManagerCompat.getDrawable()).getBitmap();
795 long bitmapHash = BitmapUtils.generateHashCode(mBitmap);
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -0700796 WallpaperColors colors = WallpaperColors.fromBitmap(mBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800797
798 mWallpaperPreferences.setHomeWallpaperHashCode(bitmapHash);
799
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700800 mWallpaperPreferences.setHomeWallpaperAttributions(
801 mWallpaper.getAttributions(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800802 mWallpaperPreferences.setHomeWallpaperBaseImageUrl(mWallpaper.getBaseImageUrl());
803 mWallpaperPreferences.setHomeWallpaperActionUrl(mWallpaper.getActionUrl(mAppContext));
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700804 mWallpaperPreferences.setHomeWallpaperActionLabelRes(
805 mWallpaper.getActionLabelRes(mAppContext));
806 mWallpaperPreferences.setHomeWallpaperActionIconRes(
807 mWallpaper.getActionIconRes(mAppContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700808 mWallpaperPreferences.setHomeWallpaperCollectionId(
809 mWallpaper.getCollectionId(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800810 mWallpaperPreferences.setHomeWallpaperRemoteId(mWallpaper.getWallpaperId());
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -0700811 mWallpaperPreferences.storeLatestHomeWallpaper(
812 TextUtils.isEmpty(mWallpaper.getWallpaperId()) ? String.valueOf(bitmapHash)
813 : mWallpaper.getWallpaperId(),
814 mWallpaper, mBitmap, colors);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800815 }
816
817 private void setImageWallpaperLockMetadata(int lockWallpaperId) {
818 mWallpaperPreferences.setLockWallpaperId(lockWallpaperId);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700819 mWallpaperPreferences.setLockWallpaperAttributions(
820 mWallpaper.getAttributions(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800821 mWallpaperPreferences.setLockWallpaperActionUrl(mWallpaper.getActionUrl(mAppContext));
Santiago Etchebehere1ab75482018-06-15 15:05:25 -0700822 mWallpaperPreferences.setLockWallpaperActionLabelRes(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700823 mWallpaper.getActionLabelRes(mAppContext));
Santiago Etchebehere1ab75482018-06-15 15:05:25 -0700824 mWallpaperPreferences.setLockWallpaperActionIconRes(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700825 mWallpaper.getActionIconRes(mAppContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700826 mWallpaperPreferences.setLockWallpaperCollectionId(
827 mWallpaper.getCollectionId(mAppContext));
“Chuck2c8626f2020-03-22 03:47:59 +0800828 mWallpaperPreferences.setLockWallpaperRemoteId(mWallpaper.getWallpaperId());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800829
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700830 // Save the lock wallpaper image's hash code as well for the sake of backup & restore
831 // because WallpaperManager-generated IDs are specific to a physical device and
832 // cannot be used to identify a wallpaper image on another device after restore is
833 // complete.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800834 saveLockWallpaperHashCode();
835 }
836
837 private void saveLockWallpaperHashCode() {
838 Bitmap lockBitmap = null;
839
840 ParcelFileDescriptor parcelFd = mWallpaperManagerCompat.getWallpaperFile(
841 WallpaperManagerCompat.FLAG_LOCK);
842
843 if (parcelFd == null) {
844 return;
845 }
846
847 InputStream fileStream = null;
848 try {
849 fileStream = new FileInputStream(parcelFd.getFileDescriptor());
850 lockBitmap = BitmapFactory.decodeStream(fileStream);
851 parcelFd.close();
852 } catch (IOException e) {
853 Log.e(TAG, "IO exception when closing the file descriptor.");
854 } finally {
855 if (fileStream != null) {
856 try {
857 fileStream.close();
858 } catch (IOException e) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700859 Log.e(TAG,
860 "IO exception when closing the input stream for the lock screen "
861 + "WP.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800862 }
863 }
864 }
865
866 if (lockBitmap != null) {
867 long bitmapHash = BitmapUtils.generateHashCode(lockBitmap);
868 mWallpaperPreferences.setLockWallpaperHashCode(bitmapHash);
869 }
870 }
871 }
872}