blob: abe1728e546e0470b331491ede256c0e88918e77 [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;
Jon Miranda16ea1b12017-12-12 14:52:48 -080051import com.android.wallpaper.util.ScreenSizeCalculator;
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -070052import com.android.wallpaper.util.WallpaperCropUtils;
Jon Miranda16ea1b12017-12-12 14:52:48 -080053
54import java.io.ByteArrayInputStream;
55import java.io.ByteArrayOutputStream;
Jon Miranda16ea1b12017-12-12 14:52:48 -080056import java.io.FileInputStream;
Jon Miranda16ea1b12017-12-12 14:52:48 -080057import java.io.IOException;
58import java.io.InputStream;
59import java.util.List;
60
61/**
62 * Concrete implementation of WallpaperPersister which actually sets wallpapers to the system via
63 * the WallpaperManager.
64 */
65public class DefaultWallpaperPersister implements WallpaperPersister {
66
67 private static final int DEFAULT_COMPRESS_QUALITY = 100;
68 private static final String TAG = "WallpaperPersister";
69
70 private final Context mAppContext; // The application's context.
Santiago Etchebehere5a7f1dd2018-04-03 15:01:29 -070071 // Context that accesses files in device protected storage
Jon Miranda16ea1b12017-12-12 14:52:48 -080072 private final WallpaperManager mWallpaperManager;
73 private final WallpaperManagerCompat mWallpaperManagerCompat;
74 private final WallpaperPreferences mWallpaperPreferences;
Jon Miranda16ea1b12017-12-12 14:52:48 -080075 private final WallpaperChangedNotifier mWallpaperChangedNotifier;
76
77 private WallpaperInfo mWallpaperInfoInPreview;
78
79 @SuppressLint("ServiceCast")
80 public DefaultWallpaperPersister(Context context) {
81 mAppContext = context.getApplicationContext();
82 // Retrieve WallpaperManager using Context#getSystemService instead of
83 // WallpaperManager#getInstance so it can be mocked out in test.
84 Injector injector = InjectorProvider.getInjector();
85 mWallpaperManager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
86 mWallpaperManagerCompat = injector.getWallpaperManagerCompat(context);
87 mWallpaperPreferences = injector.getPreferences(context);
Jon Miranda16ea1b12017-12-12 14:52:48 -080088 mWallpaperChangedNotifier = WallpaperChangedNotifier.getInstance();
89 }
90
91 @Override
92 public void setIndividualWallpaper(final WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -070093 @Nullable Rect cropRect, float scale, @Destination final int destination,
94 final SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -080095 // Set wallpaper without downscaling directly from an input stream if there's no crop rect
96 // specified by the caller and the asset is streamable.
97 if (cropRect == null && asset instanceof StreamableAsset) {
98 ((StreamableAsset) asset).fetchInputStream(new StreamReceiver() {
99 @Override
100 public void onInputStreamOpened(@Nullable InputStream inputStream) {
101 if (inputStream == null) {
102 callback.onError(null /* throwable */);
103 return;
104 }
105 setIndividualWallpaper(wallpaper, inputStream, destination, callback);
106 }
107 });
108 return;
109 }
110
111 // If no crop rect is specified but the wallpaper asset is not streamable, then fall back to
112 // using the device's display size.
113 if (cropRect == null) {
114 Display display = ((WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE))
115 .getDefaultDisplay();
116 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display);
117 asset.decodeBitmap(screenSize.x, screenSize.y, new BitmapReceiver() {
118 @Override
119 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
120 if (bitmap == null) {
121 callback.onError(null /* throwable */);
122 return;
123 }
124 setIndividualWallpaper(wallpaper, bitmap, destination, callback);
125 }
126 });
127 return;
128 }
129
130 BitmapCropper bitmapCropper = InjectorProvider.getInjector().getBitmapCropper();
Santiago Etchebehere16cf0602020-12-11 17:04:18 -0800131 bitmapCropper.cropAndScaleBitmap(asset, scale, cropRect, false, new Callback() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800132 @Override
133 public void onBitmapCropped(Bitmap croppedBitmap) {
134 setIndividualWallpaper(wallpaper, croppedBitmap, destination, callback);
135 }
136
137 @Override
138 public void onError(@Nullable Throwable e) {
139 callback.onError(e);
140 }
141 });
142 }
143
144 @Override
145 public void setIndividualWallpaperWithPosition(Activity activity, WallpaperInfo wallpaper,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700146 @WallpaperPosition int wallpaperPosition, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800147 Display display = ((WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE))
148 .getDefaultDisplay();
149 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display);
150
151 Asset asset = wallpaper.getAsset(activity);
152 asset.decodeRawDimensions(activity, new DimensionsReceiver() {
153 @Override
154 public void onDimensionsDecoded(@Nullable Point dimensions) {
155 if (dimensions == null) {
156 callback.onError(null);
157 return;
158 }
159
160 switch (wallpaperPosition) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700161 // Crop out screen-sized center portion of the source image if it's larger
162 // than the screen
163 // in both dimensions. Otherwise, decode the entire bitmap and fill the space
164 // around it to fill a new screen-sized bitmap with plain black pixels.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800165 case WALLPAPER_POSITION_CENTER:
166 setIndividualWallpaperWithCenterPosition(
167 wallpaper, asset, dimensions, screenSize, callback);
168 break;
169
170 // Crop out a screen-size portion of the source image and set the bitmap region.
171 case WALLPAPER_POSITION_CENTER_CROP:
172 setIndividualWallpaperWithCenterCropPosition(
173 wallpaper, asset, dimensions, screenSize, callback);
174 break;
175
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700176 // Decode full bitmap sized for screen and stretch it to fill the screen
177 // dimensions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800178 case WALLPAPER_POSITION_STRETCH:
179 asset.decodeBitmap(screenSize.x, screenSize.y, new BitmapReceiver() {
180 @Override
181 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700182 setIndividualWallpaperStretch(wallpaper, bitmap,
183 screenSize /* stretchSize */,
Jon Miranda16ea1b12017-12-12 14:52:48 -0800184 WallpaperPersister.DEST_BOTH, callback);
185 }
186 });
187 break;
188
189 default:
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700190 Log.e(TAG, "Unsupported wallpaper position option specified: "
191 + wallpaperPosition);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800192 callback.onError(null);
193 }
194 }
195 });
196 }
197
198 /**
199 * Sets an individual wallpaper to both home + lock static wallpaper destinations with a center
200 * wallpaper position.
201 *
202 * @param wallpaper The wallpaper model object representing the wallpaper to be set.
203 * @param asset The wallpaper asset that should be used to set a wallpaper.
204 * @param dimensions Raw dimensions of the wallpaper asset.
205 * @param screenSize Dimensions of the device screen.
206 * @param callback Callback used to notify original caller of wallpaper set operation result.
207 */
208 private void setIndividualWallpaperWithCenterPosition(WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700209 Point dimensions, Point screenSize, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800210 if (dimensions.x >= screenSize.x && dimensions.y >= screenSize.y) {
211 Rect cropRect = new Rect(
212 (dimensions.x - screenSize.x) / 2,
213 (dimensions.y - screenSize.y) / 2,
214 dimensions.x - ((dimensions.x - screenSize.x) / 2),
215 dimensions.y - ((dimensions.y - screenSize.y) / 2));
Santiago Etchebehere16cf0602020-12-11 17:04:18 -0800216 asset.decodeBitmapRegion(cropRect, screenSize.x, screenSize.y, false,
217 bitmap -> setIndividualWallpaper(wallpaper, bitmap,
218 WallpaperPersister.DEST_BOTH, callback));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800219 } else {
220 // Decode the full bitmap and pass with the screen size as a fill rect.
221 asset.decodeBitmap(dimensions.x, dimensions.y, new BitmapReceiver() {
222 @Override
223 public void onBitmapDecoded(@Nullable Bitmap bitmap) {
224 if (bitmap == null) {
225 callback.onError(null);
226 return;
227 }
228
229 setIndividualWallpaperFill(wallpaper, bitmap, screenSize /* fillSize */,
230 WallpaperPersister.DEST_BOTH, callback);
231 }
232 });
233 }
234 }
235
236 /**
237 * Sets an individual wallpaper to both home + lock static wallpaper destinations with a center
238 * cropped wallpaper position.
239 *
240 * @param wallpaper The wallpaper model object representing the wallpaper to be set.
241 * @param asset The wallpaper asset that should be used to set a wallpaper.
242 * @param dimensions Raw dimensions of the wallpaper asset.
243 * @param screenSize Dimensions of the device screen.
244 * @param callback Callback used to notify original caller of wallpaper set operation result.
245 */
246 private void setIndividualWallpaperWithCenterCropPosition(WallpaperInfo wallpaper, Asset asset,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700247 Point dimensions, Point screenSize, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800248 float scale = Math.max((float) screenSize.x / dimensions.x,
249 (float) screenSize.y / dimensions.y);
250
251 int scaledImageWidth = (int) (dimensions.x * scale);
252 int scaledImageHeight = (int) (dimensions.y * scale);
253
254 // Crop rect is in post-scale units.
255 Rect cropRect = new Rect(
256 (scaledImageWidth - screenSize.x) / 2,
257 (scaledImageHeight - screenSize.y) / 2,
258 scaledImageWidth - ((scaledImageWidth - screenSize.x) / 2),
259 scaledImageHeight - (((scaledImageHeight - screenSize.y) / 2)));
260
261 setIndividualWallpaper(
262 wallpaper, asset, cropRect, scale, WallpaperPersister.DEST_BOTH, callback);
263 }
264
265 /**
266 * Sets a static individual wallpaper to the system via the WallpaperManager.
267 *
268 * @param wallpaper Wallpaper model object.
269 * @param croppedBitmap Bitmap representing the individual wallpaper image.
270 * @param destination The destination - where to set the wallpaper to.
271 * @param callback Called once the wallpaper was set or if an error occurred.
272 */
273 private void setIndividualWallpaper(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700274 @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800275 SetWallpaperTask setWallpaperTask =
276 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
277 setWallpaperTask.execute();
278 }
279
280 /**
281 * Sets a static individual wallpaper to the system via the WallpaperManager with a fill option.
282 *
283 * @param wallpaper Wallpaper model object.
284 * @param croppedBitmap Bitmap representing the individual wallpaper image.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700285 * @param fillSize Specifies the final bitmap size that should be set to WallpaperManager.
286 * This final bitmap will show the visible area of the provided bitmap
287 * after applying a mask with black background the source bitmap and
288 * centering. There may be black borders around the original bitmap if
289 * it's smaller than the fillSize in one or both dimensions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800290 * @param destination The destination - where to set the wallpaper to.
291 * @param callback Called once the wallpaper was set or if an error occurred.
292 */
293 private void setIndividualWallpaperFill(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700294 Point fillSize, @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800295 SetWallpaperTask setWallpaperTask =
296 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
297 setWallpaperTask.setFillSize(fillSize);
298 setWallpaperTask.execute();
299 }
300
301 /**
302 * Sets a static individual wallpaper to the system via the WallpaperManager with a stretch
303 * option.
304 *
305 * @param wallpaper Wallpaper model object.
306 * @param croppedBitmap Bitmap representing the individual wallpaper image.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700307 * @param stretchSize Specifies the final size to which the bitmap should be stretched
308 * prior
Jon Miranda16ea1b12017-12-12 14:52:48 -0800309 * to being set to the device.
310 * @param destination The destination - where to set the wallpaper to.
311 * @param callback Called once the wallpaper was set or if an error occurred.
312 */
313 private void setIndividualWallpaperStretch(WallpaperInfo wallpaper, Bitmap croppedBitmap,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700314 Point stretchSize, @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800315 SetWallpaperTask setWallpaperTask =
316 new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
317 setWallpaperTask.setStretchSize(stretchSize);
318 setWallpaperTask.execute();
319 }
320
321 /**
322 * Sets a static individual wallpaper stream to the system via the WallpaperManager.
323 *
324 * @param wallpaper Wallpaper model object.
325 * @param inputStream JPEG or PNG stream of wallpaper image's bytes.
326 * @param destination The destination - where to set the wallpaper to.
327 * @param callback Called once the wallpaper was set or if an error occurred.
328 */
329 private void setIndividualWallpaper(WallpaperInfo wallpaper, InputStream inputStream,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700330 @Destination int destination, SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800331 SetWallpaperTask setWallpaperTask =
332 new SetWallpaperTask(wallpaper, inputStream, destination, callback);
333 setWallpaperTask.execute();
334 }
335
336 @Override
337 public boolean setWallpaperInRotation(Bitmap wallpaperBitmap, List<String> attributions,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700338 int actionLabelRes, int actionIconRes, String actionUrl, String collectionId) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800339
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700340 return setWallpaperInRotationStatic(wallpaperBitmap, attributions, actionUrl,
341 actionLabelRes, actionIconRes, collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800342 }
343
344 @Override
345 public int setWallpaperBitmapInNextRotation(Bitmap wallpaperBitmap) {
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700346 return cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800347 }
348
349 @Override
350 public boolean finalizeWallpaperForNextRotation(List<String> attributions, String actionUrl,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700351 int actionLabelRes, int actionIconRes, String collectionId, int wallpaperId) {
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700352 return saveStaticWallpaperMetadata(attributions, actionUrl, actionLabelRes,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700353 actionIconRes, collectionId, wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800354 }
355
356 /**
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700357 * Sets wallpaper image and attributions when a static wallpaper is responsible for presenting
358 * the
Jon Miranda16ea1b12017-12-12 14:52:48 -0800359 * current "daily wallpaper".
360 */
361 private boolean setWallpaperInRotationStatic(Bitmap wallpaperBitmap, List<String> attributions,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700362 String actionUrl, int actionLabelRes, int actionIconRes, String collectionId) {
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700363 final int wallpaperId = cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800364
365 if (wallpaperId == 0) {
366 return false;
367 }
368
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700369 return saveStaticWallpaperMetadata(attributions, actionUrl, actionLabelRes,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700370 actionIconRes, collectionId, wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800371 }
372
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700373 @Override
374 public boolean saveStaticWallpaperMetadata(List<String> attributions,
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700375 String actionUrl,
376 int actionLabelRes,
377 int actionIconRes,
378 String collectionId,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700379 int wallpaperId) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800380 mWallpaperPreferences.clearHomeWallpaperMetadata();
381
382 boolean isLockWallpaperSet = isSeparateLockScreenWallpaperSet();
383
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700384 // Persist wallpaper IDs if the rotating wallpaper component
385 mWallpaperPreferences.setHomeWallpaperManagerId(wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800386
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700387 // Only copy over wallpaper ID to lock wallpaper if no explicit lock wallpaper is set
388 // (so metadata isn't lost if a user explicitly sets a home-only wallpaper).
389 if (!isLockWallpaperSet) {
390 mWallpaperPreferences.setLockWallpaperId(wallpaperId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800391 }
392
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700393
Jon Miranda16ea1b12017-12-12 14:52:48 -0800394 mWallpaperPreferences.setHomeWallpaperAttributions(attributions);
395 mWallpaperPreferences.setHomeWallpaperActionUrl(actionUrl);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700396 mWallpaperPreferences.setHomeWallpaperActionLabelRes(actionLabelRes);
397 mWallpaperPreferences.setHomeWallpaperActionIconRes(actionIconRes);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800398 // Only set base image URL for static Backdrop images, not for rotation.
399 mWallpaperPreferences.setHomeWallpaperBaseImageUrl(null);
400 mWallpaperPreferences.setHomeWallpaperCollectionId(collectionId);
401
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700402 // Set metadata to lock screen also when the rotating wallpaper so if user sets a home
403 // screen-only wallpaper later, these attributions will still be available.
404 if (!isLockWallpaperSet) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800405 mWallpaperPreferences.setLockWallpaperAttributions(attributions);
406 mWallpaperPreferences.setLockWallpaperActionUrl(actionUrl);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700407 mWallpaperPreferences.setLockWallpaperActionLabelRes(actionLabelRes);
408 mWallpaperPreferences.setLockWallpaperActionIconRes(actionIconRes);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800409 mWallpaperPreferences.setLockWallpaperCollectionId(collectionId);
410 }
411
412 return true;
413 }
414
415 /**
Jon Miranda16ea1b12017-12-12 14:52:48 -0800416 * Sets a wallpaper in rotation as a static wallpaper to the {@link WallpaperManager} with the
417 * option allowBackup=false to save user data.
418 *
419 * @return wallpaper ID for the wallpaper bitmap.
420 */
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700421 private int cropAndSetWallpaperBitmapInRotationStatic(Bitmap wallpaperBitmap) {
422 // Calculate crop and scale of the wallpaper to match the default one used in preview
423 Point wallpaperSize = new Point(wallpaperBitmap.getWidth(), wallpaperBitmap.getHeight());
424 WindowManager windowManager =
425 (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE);
426 Resources resources = mAppContext.getResources();
427 Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
428 resources, windowManager.getDefaultDisplay());
429 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(
430 windowManager.getDefaultDisplay());
431
432 // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
433 float minWallpaperZoom =
434 WallpaperCropUtils.calculateMinZoom(wallpaperSize, screenSize);
435
436 PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(mAppContext,
437 wallpaperSize, WallpaperCropUtils.calculateVisibleRect(wallpaperSize, screenSize));
438
439 Point scaledCenter = new Point((int) (minWallpaperZoom * centerPosition.x),
440 (int) (minWallpaperZoom * centerPosition.y));
441
442 int offsetX = Math.max(0, -(screenSize.x / 2 - scaledCenter.x));
443 int offsetY = Math.max(0, -(screenSize.y / 2 - scaledCenter.y));
444
445 Rect cropRect = WallpaperCropUtils.calculateCropRect(mAppContext, minWallpaperZoom,
446 wallpaperSize, defaultCropSurfaceSize, screenSize, offsetX, offsetY);
447
448 Rect scaledCropRect = new Rect(
449 Math.round((float) cropRect.left / minWallpaperZoom),
450 Math.round((float) cropRect.top / minWallpaperZoom),
451 Math.round((float) cropRect.right / minWallpaperZoom),
452 Math.round((float) cropRect.bottom / minWallpaperZoom));
453
454 // Scale and crop the bitmap
455 wallpaperBitmap = Bitmap.createBitmap(wallpaperBitmap,
456 scaledCropRect.left,
457 scaledCropRect.top,
458 scaledCropRect.width(),
459 scaledCropRect.height());
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700460 int whichWallpaper = getDefaultWhichWallpaper();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800461
462 return setBitmapToWallpaperManagerCompat(wallpaperBitmap, false /* allowBackup */,
463 whichWallpaper);
464 }
465
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700466 /*
467 * Note: this method will return use home-only (FLAG_SYSTEM) instead of both home and lock
468 * 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 -0800469 */
Santiago Etchebehere763b1bb2021-05-14 22:01:16 -0700470 @Override
471 public int getDefaultWhichWallpaper() {
472 return isSeparateLockScreenWallpaperSet()
473 ? WallpaperManagerCompat.FLAG_SYSTEM
474 : WallpaperManagerCompat.FLAG_SYSTEM | WallpaperManagerCompat.FLAG_LOCK;
475 }
476
477 @Override
478 public int setBitmapToWallpaperManagerCompat(Bitmap wallpaperBitmap, boolean allowBackup,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700479 int whichWallpaper) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800480 ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
James O'Leary03375d72021-06-02 10:05:57 -0400481 if (wallpaperBitmap.compress(CompressFormat.PNG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800482 try {
483 byte[] outByteArray = tmpOut.toByteArray();
484 return mWallpaperManagerCompat.setStream(
485 new ByteArrayInputStream(outByteArray),
486 null /* visibleCropHint */,
487 allowBackup,
488 whichWallpaper);
489 } catch (IOException e) {
490 Log.e(TAG, "unable to write stream to wallpaper manager");
491 return 0;
492 }
493 } else {
494 Log.e(TAG, "unable to compress wallpaper");
495 try {
496 return mWallpaperManagerCompat.setBitmap(
497 wallpaperBitmap,
498 null /* visibleCropHint */,
499 allowBackup,
500 whichWallpaper);
501 } catch (IOException e) {
502 Log.e(TAG, "unable to set wallpaper");
503 return 0;
504 }
505 }
506 }
507
508 private int setStreamToWallpaperManagerCompat(InputStream inputStream, boolean allowBackup,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700509 int whichWallpaper) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800510 try {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700511 return mWallpaperManagerCompat.setStream(inputStream, null, allowBackup,
512 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800513 } catch (IOException e) {
514 return 0;
515 }
516 }
517
518 @Override
519 public void setWallpaperInfoInPreview(WallpaperInfo wallpaper) {
520 mWallpaperInfoInPreview = wallpaper;
521 }
522
523 @Override
524 public void onLiveWallpaperSet() {
525 android.app.WallpaperInfo currentWallpaperComponent = mWallpaperManager.getWallpaperInfo();
chihhangchuang210c9602020-06-02 12:38:14 +0800526 android.app.WallpaperInfo previewedWallpaperComponent = mWallpaperInfoInPreview != null
527 ? mWallpaperInfoInPreview.getWallpaperComponent() : null;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800528
529 // If there is no live wallpaper set on the WallpaperManager or it doesn't match the
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700530 // WallpaperInfo which was last previewed, then do nothing and nullify last previewed
531 // wallpaper.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800532 if (currentWallpaperComponent == null || previewedWallpaperComponent == null
533 || !currentWallpaperComponent.getPackageName()
534 .equals(previewedWallpaperComponent.getPackageName())) {
535 mWallpaperInfoInPreview = null;
536 return;
537 }
538
539 setLiveWallpaperMetadata();
540 }
541
542 /**
543 * Returns whether a separate lock-screen (static) wallpaper is set to the WallpaperManager.
544 */
545 private boolean isSeparateLockScreenWallpaperSet() {
546 ParcelFileDescriptor lockWallpaperFile =
547 mWallpaperManagerCompat.getWallpaperFile(WallpaperManagerCompat.FLAG_LOCK);
548
549 boolean isLockWallpaperSet = false;
550
551 if (lockWallpaperFile != null) {
552 isLockWallpaperSet = true;
553
554 try {
555 lockWallpaperFile.close();
556 } catch (IOException e) {
557 Log.e(TAG, "Unable to close PFD for lock wallpaper", e);
558 }
559 }
560
561 return isLockWallpaperSet;
562 }
563
564 /**
565 * Sets the live wallpaper's metadata on SharedPreferences.
566 */
567 private void setLiveWallpaperMetadata() {
568 android.app.WallpaperInfo previewedWallpaperComponent =
569 mWallpaperInfoInPreview.getWallpaperComponent();
570
571 mWallpaperPreferences.clearHomeWallpaperMetadata();
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700572 // NOTE: We explicitly do not also clear the lock wallpaper metadata. Since the user may
573 // have set the live wallpaper on the home screen only, we leave the lock wallpaper metadata
574 // intact. If the user has set the live wallpaper for both home and lock screens, then the
Jon Miranda16ea1b12017-12-12 14:52:48 -0800575 // WallpaperRefresher will pick up on that and update the preferences later.
576 mWallpaperPreferences
577 .setHomeWallpaperAttributions(mWallpaperInfoInPreview.getAttributions(mAppContext));
578 mWallpaperPreferences.setHomeWallpaperPackageName(
579 previewedWallpaperComponent.getPackageName());
Kunhung Li3e50fd22020-05-12 20:46:18 +0800580 mWallpaperPreferences.setHomeWallpaperServiceName(
581 previewedWallpaperComponent.getServiceName());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800582 mWallpaperPreferences.setHomeWallpaperCollectionId(
583 mWallpaperInfoInPreview.getCollectionId(mAppContext));
584 mWallpaperPreferences.setWallpaperPresentationMode(
585 WallpaperPreferences.PRESENTATION_MODE_STATIC);
586 mWallpaperPreferences.clearDailyRotations();
587 }
588
Jon Miranda16ea1b12017-12-12 14:52:48 -0800589 private class SetWallpaperTask extends AsyncTask<Void, Void, Boolean> {
590
591 private final WallpaperInfo mWallpaper;
592 @Destination
593 private final int mDestination;
594 private final WallpaperPersister.SetWallpaperCallback mCallback;
595
596 private Bitmap mBitmap;
597 private InputStream mInputStream;
598
599 /**
600 * Optional parameters for applying a post-decoding fill or stretch transformation.
601 */
602 @Nullable
603 private Point mFillSize;
604 @Nullable
605 private Point mStretchSize;
606
607 SetWallpaperTask(WallpaperInfo wallpaper, Bitmap bitmap, @Destination int destination,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700608 WallpaperPersister.SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800609 super();
610 mWallpaper = wallpaper;
611 mBitmap = bitmap;
612 mDestination = destination;
613 mCallback = callback;
614 }
615
616 /**
617 * Constructor for SetWallpaperTask which takes an InputStream instead of a bitmap. The task
618 * will close the InputStream once it is done with it.
619 */
620 SetWallpaperTask(WallpaperInfo wallpaper, InputStream stream,
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700621 @Destination int destination, WallpaperPersister.SetWallpaperCallback callback) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800622 mWallpaper = wallpaper;
623 mInputStream = stream;
624 mDestination = destination;
625 mCallback = callback;
626 }
627
628 void setFillSize(Point fillSize) {
629 if (mStretchSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700630 throw new IllegalArgumentException(
631 "Can't pass a fill size option if a stretch size is "
632 + "already set.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800633 }
634 mFillSize = fillSize;
635 }
636
637 void setStretchSize(Point stretchSize) {
638 if (mFillSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700639 throw new IllegalArgumentException(
640 "Can't pass a stretch size option if a fill size is "
641 + "already set.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800642 }
643 mStretchSize = stretchSize;
644 }
645
646 @Override
647 protected Boolean doInBackground(Void... unused) {
648 int whichWallpaper;
649 if (mDestination == DEST_HOME_SCREEN) {
650 whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM;
651 } else if (mDestination == DEST_LOCK_SCREEN) {
652 whichWallpaper = WallpaperManagerCompat.FLAG_LOCK;
653 } else { // DEST_BOTH
654 whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM
655 | WallpaperManagerCompat.FLAG_LOCK;
656 }
657
Jon Miranda16ea1b12017-12-12 14:52:48 -0800658
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700659 boolean wasLockWallpaperSet = LockWallpaperStatusChecker.isLockWallpaperSet(
660 mAppContext);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800661
662 boolean allowBackup = mWallpaper.getBackupPermission() == WallpaperInfo.BACKUP_ALLOWED;
663 final int wallpaperId;
664 if (mBitmap != null) {
665 // Apply fill or stretch transformations on mBitmap if necessary.
666 if (mFillSize != null) {
667 mBitmap = BitmapTransformer.applyFillTransformation(mBitmap, mFillSize);
668 }
669 if (mStretchSize != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700670 mBitmap = Bitmap.createScaledBitmap(mBitmap, mStretchSize.x, mStretchSize.y,
671 true);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800672 }
673
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700674 wallpaperId = setBitmapToWallpaperManagerCompat(mBitmap, allowBackup,
675 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800676 } else if (mInputStream != null) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700677 wallpaperId = setStreamToWallpaperManagerCompat(mInputStream, allowBackup,
678 whichWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800679 } else {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700680 Log.e(TAG,
681 "Both the wallpaper bitmap and input stream are null so we're unable to "
682 + "set any "
683 + "kind of wallpaper here.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800684 wallpaperId = 0;
685 }
686
687 if (wallpaperId > 0) {
688 if (mDestination == DEST_HOME_SCREEN
689 && mWallpaperPreferences.getWallpaperPresentationMode()
690 == WallpaperPreferences.PRESENTATION_MODE_ROTATING
691 && !wasLockWallpaperSet
692 && BuildCompat.isAtLeastN()) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700693 copyRotatingWallpaperToLock();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800694 }
695 setImageWallpaperMetadata(mDestination, wallpaperId);
696 return true;
697 } else {
698 return false;
699 }
700 }
701
702 @Override
703 protected void onPostExecute(Boolean isSuccess) {
704 if (mInputStream != null) {
705 try {
706 mInputStream.close();
707 } catch (IOException e) {
708 Log.e(TAG, "Failed to close input stream " + e);
709 mCallback.onError(e /* throwable */);
710 return;
711 }
712 }
713
714 if (isSuccess) {
“Chuckffd832c2020-03-22 02:15:58 +0800715 mCallback.onSuccess(mWallpaper);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800716 mWallpaperChangedNotifier.notifyWallpaperChanged();
717 } else {
718 mCallback.onError(null /* throwable */);
719 }
720 }
721
722 /**
723 * Copies home wallpaper metadata to lock, and if rotation was enabled with a live wallpaper
724 * previously, then copies over the rotating wallpaper image to the WallpaperManager also.
725 * <p>
726 * Used to accommodate the case where a user had gone from a home+lock daily rotation to
727 * selecting a static wallpaper on home-only. The image and metadata that was previously
728 * rotating is now copied to the lock screen.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800729 */
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700730 private void copyRotatingWallpaperToLock() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800731
732 mWallpaperPreferences.setLockWallpaperAttributions(
733 mWallpaperPreferences.getHomeWallpaperAttributions());
734 mWallpaperPreferences.setLockWallpaperActionUrl(
735 mWallpaperPreferences.getHomeWallpaperActionUrl());
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700736 mWallpaperPreferences.setLockWallpaperActionLabelRes(
737 mWallpaperPreferences.getHomeWallpaperActionLabelRes());
738 mWallpaperPreferences.setLockWallpaperActionIconRes(
739 mWallpaperPreferences.getHomeWallpaperActionIconRes());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800740 mWallpaperPreferences.setLockWallpaperCollectionId(
741 mWallpaperPreferences.getHomeWallpaperCollectionId());
742
743 // Set the lock wallpaper ID to what Android set it to, following its having
744 // copied the system wallpaper over to the lock screen when we changed from
745 // "both" to distinct system and lock screen wallpapers.
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700746 mWallpaperPreferences.setLockWallpaperId(
747 mWallpaperManagerCompat.getWallpaperId(WallpaperManagerCompat.FLAG_LOCK));
748
Jon Miranda16ea1b12017-12-12 14:52:48 -0800749 }
750
751 /**
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700752 * Sets the image wallpaper's metadata on SharedPreferences. This method is called after the
753 * set wallpaper operation is successful.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800754 *
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700755 * @param destination Which destination of wallpaper the metadata corresponds to (home
756 * screen, lock screen, or both).
757 * @param wallpaperId The ID of the static wallpaper returned by WallpaperManager, which
758 * on N and later versions of Android uniquely identifies a wallpaper
759 * image.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800760 */
761 private void setImageWallpaperMetadata(@Destination int destination, int wallpaperId) {
762 if (destination == DEST_HOME_SCREEN || destination == DEST_BOTH) {
763 mWallpaperPreferences.clearHomeWallpaperMetadata();
764 setImageWallpaperHomeMetadata(wallpaperId);
765
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700766 // Reset presentation mode to STATIC if an individual wallpaper is set to the
767 // home screen
Jon Miranda16ea1b12017-12-12 14:52:48 -0800768 // because rotation always affects at least the home screen.
769 mWallpaperPreferences.setWallpaperPresentationMode(
770 WallpaperPreferences.PRESENTATION_MODE_STATIC);
771 }
772
773 if (destination == DEST_LOCK_SCREEN || destination == DEST_BOTH) {
774 mWallpaperPreferences.clearLockWallpaperMetadata();
775 setImageWallpaperLockMetadata(wallpaperId);
776 }
777
778 mWallpaperPreferences.clearDailyRotations();
779 }
780
781 private void setImageWallpaperHomeMetadata(int homeWallpaperId) {
782 if (BuildCompat.isAtLeastN()) {
783 mWallpaperPreferences.setHomeWallpaperManagerId(homeWallpaperId);
784 }
785
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700786 // Compute bitmap hash code after setting the wallpaper because JPEG compression has
787 // likely changed many pixels' color values. Forget the previously loaded wallpaper
788 // bitmap so that WallpaperManager doesn't return the old wallpaper drawable. Do this
789 // on N+ devices in addition to saving the wallpaper ID for the purpose of backup &
790 // restore.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800791 mWallpaperManager.forgetLoadedWallpaper();
792 mBitmap = ((BitmapDrawable) mWallpaperManagerCompat.getDrawable()).getBitmap();
793 long bitmapHash = BitmapUtils.generateHashCode(mBitmap);
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -0700794 WallpaperColors colors = WallpaperColors.fromBitmap(mBitmap);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800795
796 mWallpaperPreferences.setHomeWallpaperHashCode(bitmapHash);
797
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700798 mWallpaperPreferences.setHomeWallpaperAttributions(
799 mWallpaper.getAttributions(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800800 mWallpaperPreferences.setHomeWallpaperBaseImageUrl(mWallpaper.getBaseImageUrl());
801 mWallpaperPreferences.setHomeWallpaperActionUrl(mWallpaper.getActionUrl(mAppContext));
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700802 mWallpaperPreferences.setHomeWallpaperActionLabelRes(
803 mWallpaper.getActionLabelRes(mAppContext));
804 mWallpaperPreferences.setHomeWallpaperActionIconRes(
805 mWallpaper.getActionIconRes(mAppContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700806 mWallpaperPreferences.setHomeWallpaperCollectionId(
807 mWallpaper.getCollectionId(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800808 mWallpaperPreferences.setHomeWallpaperRemoteId(mWallpaper.getWallpaperId());
Santiago Etchebeherec320c5f2021-05-14 17:35:57 -0700809 mWallpaperPreferences.storeLatestHomeWallpaper(
810 TextUtils.isEmpty(mWallpaper.getWallpaperId()) ? String.valueOf(bitmapHash)
811 : mWallpaper.getWallpaperId(),
812 mWallpaper, mBitmap, colors);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800813 }
814
815 private void setImageWallpaperLockMetadata(int lockWallpaperId) {
816 mWallpaperPreferences.setLockWallpaperId(lockWallpaperId);
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700817 mWallpaperPreferences.setLockWallpaperAttributions(
818 mWallpaper.getAttributions(mAppContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800819 mWallpaperPreferences.setLockWallpaperActionUrl(mWallpaper.getActionUrl(mAppContext));
Santiago Etchebehere1ab75482018-06-15 15:05:25 -0700820 mWallpaperPreferences.setLockWallpaperActionLabelRes(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700821 mWallpaper.getActionLabelRes(mAppContext));
Santiago Etchebehere1ab75482018-06-15 15:05:25 -0700822 mWallpaperPreferences.setLockWallpaperActionIconRes(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700823 mWallpaper.getActionIconRes(mAppContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700824 mWallpaperPreferences.setLockWallpaperCollectionId(
825 mWallpaper.getCollectionId(mAppContext));
“Chuck2c8626f2020-03-22 03:47:59 +0800826 mWallpaperPreferences.setLockWallpaperRemoteId(mWallpaper.getWallpaperId());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800827
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700828 // Save the lock wallpaper image's hash code as well for the sake of backup & restore
829 // because WallpaperManager-generated IDs are specific to a physical device and
830 // cannot be used to identify a wallpaper image on another device after restore is
831 // complete.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800832 saveLockWallpaperHashCode();
833 }
834
835 private void saveLockWallpaperHashCode() {
836 Bitmap lockBitmap = null;
837
838 ParcelFileDescriptor parcelFd = mWallpaperManagerCompat.getWallpaperFile(
839 WallpaperManagerCompat.FLAG_LOCK);
840
841 if (parcelFd == null) {
842 return;
843 }
844
845 InputStream fileStream = null;
846 try {
847 fileStream = new FileInputStream(parcelFd.getFileDescriptor());
848 lockBitmap = BitmapFactory.decodeStream(fileStream);
849 parcelFd.close();
850 } catch (IOException e) {
851 Log.e(TAG, "IO exception when closing the file descriptor.");
852 } finally {
853 if (fileStream != null) {
854 try {
855 fileStream.close();
856 } catch (IOException e) {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700857 Log.e(TAG,
858 "IO exception when closing the input stream for the lock screen "
859 + "WP.");
Jon Miranda16ea1b12017-12-12 14:52:48 -0800860 }
861 }
862 }
863
864 if (lockBitmap != null) {
865 long bitmapHash = BitmapUtils.generateHashCode(lockBitmap);
866 mWallpaperPreferences.setLockWallpaperHashCode(bitmapHash);
867 }
868 }
869 }
870}