1 /* 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 */ 16 package com.android.wallpaper.asset; 17 18 import android.app.Activity; 19 import android.app.WallpaperManager; 20 import android.content.Context; 21 import android.graphics.Bitmap; 22 import android.graphics.Point; 23 import android.graphics.Rect; 24 import android.graphics.drawable.BitmapDrawable; 25 import android.graphics.drawable.Drawable; 26 import android.os.AsyncTask; 27 28 /** 29 * Asset implementation which represents the currently-set wallpaper on API 16 through 23 devices. 30 */ 31 public class CurrentWallpaperAssetV16 extends Asset { 32 33 private static final boolean FILTER_SCALED_BITMAP = true; 34 35 private Context mApplicationContext; 36 CurrentWallpaperAssetV16(Context context)37 public CurrentWallpaperAssetV16(Context context) { 38 mApplicationContext = context.getApplicationContext(); 39 } 40 41 @Override decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight, BitmapReceiver receiver)42 public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight, 43 BitmapReceiver receiver) { 44 receiver.onBitmapDecoded(null); 45 } 46 47 @Override decodeBitmap(int targetWidth, int targetHeight, BitmapReceiver receiver)48 public void decodeBitmap(int targetWidth, int targetHeight, 49 BitmapReceiver receiver) { 50 DecodeBitmapAsyncTask task = new DecodeBitmapAsyncTask(receiver, targetWidth, targetHeight); 51 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 52 } 53 54 @Override supportsTiling()55 public boolean supportsTiling() { 56 return false; 57 } 58 59 @Override decodeRawDimensions(Activity unused, DimensionsReceiver receiver)60 public void decodeRawDimensions(Activity unused, DimensionsReceiver receiver) { 61 DecodeDimensionsAsyncTask task = new DecodeDimensionsAsyncTask(receiver); 62 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 63 } 64 getCurrentWallpaperDrawable()65 private Drawable getCurrentWallpaperDrawable() { 66 WallpaperManager wallpaperManager = WallpaperManager.getInstance(mApplicationContext); 67 Drawable drawable; 68 try { 69 drawable = wallpaperManager.getDrawable(); 70 } catch (java.lang.SecurityException e) { 71 // Work around Samsung bug where SecurityException is thrown if device is still using its 72 // default wallpaper. 73 drawable = wallpaperManager.getBuiltInDrawable(); 74 } 75 return drawable; 76 } 77 78 /** 79 * Decodes and then post-decode scales down the currently-set wallpaper bitmap. 80 */ 81 private class DecodeBitmapAsyncTask extends AsyncTask<Void, Void, Bitmap> { 82 83 private BitmapReceiver mReceiver; 84 private int mTargetWidth; 85 private int mTargetHeight; 86 DecodeBitmapAsyncTask(BitmapReceiver receiver, int width, int height)87 public DecodeBitmapAsyncTask(BitmapReceiver receiver, int width, int height) { 88 mReceiver = receiver; 89 mTargetWidth = width; 90 mTargetHeight = height; 91 } 92 93 @Override doInBackground(Void... unused)94 protected Bitmap doInBackground(Void... unused) { 95 Drawable wallpaperDrawable = getCurrentWallpaperDrawable(); 96 Bitmap bitmap = ((BitmapDrawable) wallpaperDrawable).getBitmap(); 97 98 // The final bitmap may be constrained by only one of height and width, so find the maximum 99 // downscaling factor without having the final result bitmap's height or width dip below the 100 // provided target height or width. 101 float maxDownscaleFactor = Math.min((float) bitmap.getWidth() / mTargetWidth, 102 (float) bitmap.getHeight() / mTargetHeight); 103 104 // Scale down full bitmap to save memory consumption post-decoding, while maintaining the 105 // source bitmap's aspect ratio. 106 int resultWidth = Math.round(bitmap.getWidth() / maxDownscaleFactor); 107 int resultHeight = Math.round(bitmap.getHeight() / maxDownscaleFactor); 108 return Bitmap.createScaledBitmap(bitmap, resultWidth, resultHeight, FILTER_SCALED_BITMAP); 109 } 110 111 @Override onPostExecute(Bitmap bitmap)112 protected void onPostExecute(Bitmap bitmap) { 113 mReceiver.onBitmapDecoded(bitmap); 114 } 115 } 116 117 /** 118 * Decodes the raw dimensions of the currently-set wallpaper. 119 */ 120 private class DecodeDimensionsAsyncTask extends AsyncTask<Void, Void, Point> { 121 122 private DimensionsReceiver mReceiver; 123 DecodeDimensionsAsyncTask(DimensionsReceiver receiver)124 public DecodeDimensionsAsyncTask(DimensionsReceiver receiver) { 125 mReceiver = receiver; 126 } 127 128 @Override doInBackground(Void... unused)129 protected Point doInBackground(Void... unused) { 130 Drawable wallpaperDrawable = getCurrentWallpaperDrawable(); 131 return new Point( 132 wallpaperDrawable.getIntrinsicWidth(), wallpaperDrawable.getIntrinsicHeight()); 133 } 134 135 @Override onPostExecute(Point dimensions)136 protected void onPostExecute(Point dimensions) { 137 mReceiver.onDimensionsDecoded(dimensions); 138 } 139 } 140 } 141