blob: 1c73511e3a915f43faa8cd3da22cd6f40b688c0a [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wallpaper.asset;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
/**
* Asset representing the system's built-in wallpaper.
* NOTE: This is only used for KitKat and newer devices. On older versions of Android, the
* built-in wallpaper is accessed via the system Resources object, and is thus be represented
* by a {@code ResourceAsset} instead.
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public final class BuiltInWallpaperAsset extends Asset {
private static final boolean SCALE_TO_FIT = true;
private static final boolean CROP_TO_FIT = false;
private static final float HORIZONTAL_CENTER_ALIGNED = 0.5f;
private static final float VERTICAL_CENTER_ALIGNED = 0.5f;
private final Context mContext;
private Point mDimensions;
private WallpaperModel mBuiltInWallpaperModel;
/**
* @param context The application's context.
*/
public BuiltInWallpaperAsset(Context context) {
if (VERSION.SDK_INT < VERSION_CODES.KITKAT) {
throw new AssertionError("BuiltInWallpaperAsset should not be instantiated on a pre-KitKat"
+ " build");
}
mContext = context.getApplicationContext();
}
@Override
public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
BitmapReceiver receiver) {
DecodeBitmapRegionAsyncTask task = new DecodeBitmapRegionAsyncTask(rect, receiver);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public void decodeRawDimensions(Activity unused, DimensionsReceiver receiver) {
DecodeDimensionsAsyncTask task = new DecodeDimensionsAsyncTask(receiver);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public void decodeBitmap(int targetWidth, int targetHeight,
BitmapReceiver receiver) {
DecodeBitmapAsyncTask task = new DecodeBitmapAsyncTask(targetWidth, targetHeight, receiver);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public boolean supportsTiling() {
return false;
}
/**
* Calculates the raw dimensions of the built-in drawable. This method should not be called from
* the main UI thread.
*
* @return Raw dimensions of the built-in wallpaper drawable.
*/
private Point calculateRawDimensions() {
if (mDimensions != null) {
return mDimensions;
}
Drawable builtInDrawable = WallpaperManager.getInstance(mContext).getBuiltInDrawable();
Bitmap builtInBitmap = ((BitmapDrawable) builtInDrawable).getBitmap();
mDimensions = new Point(builtInBitmap.getWidth(), builtInBitmap.getHeight());
return mDimensions;
}
@Override
public void loadDrawable(Context context, ImageView imageView, int placeholderColor) {
if (mBuiltInWallpaperModel == null) {
mBuiltInWallpaperModel =
new WallpaperModel(context.getApplicationContext(), WallpaperModel.SOURCE_BUILT_IN);
}
Glide.with(context)
.asDrawable()
.load(mBuiltInWallpaperModel)
.apply(RequestOptions.centerCropTransform()
.placeholder(new ColorDrawable(placeholderColor)))
.transition(DrawableTransitionOptions.withCrossFade())
.into(imageView);
}
/**
* AsyncTask subclass which decodes the full built-in wallpaper bitmap off the UI thread.
*/
private class DecodeBitmapAsyncTask extends AsyncTask<Void, Void, Bitmap> {
private int mWidth;
private int mHeight;
private BitmapReceiver mReceiver;
public DecodeBitmapAsyncTask(int width, int height, BitmapReceiver receiver) {
mWidth = width;
mHeight = height;
mReceiver = receiver;
}
@Override
protected Bitmap doInBackground(Void... unused) {
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
Drawable drawable = wallpaperManager.getBuiltInDrawable(
mWidth,
mHeight,
SCALE_TO_FIT,
HORIZONTAL_CENTER_ALIGNED,
VERTICAL_CENTER_ALIGNED);
// Manually request that WallpaperManager loses its reference to the built-in wallpaper
// bitmap, which can occupy a large memory allocation for the lifetime of the app.
wallpaperManager.forgetLoadedWallpaper();
return ((BitmapDrawable) drawable).getBitmap();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
mReceiver.onBitmapDecoded(bitmap);
}
}
/**
* AsyncTask subclass which decodes a bitmap region off the UI thread.
*/
private class DecodeBitmapRegionAsyncTask extends AsyncTask<Void, Void, Bitmap> {
private Rect mRect;
private BitmapReceiver mReceiver;
public DecodeBitmapRegionAsyncTask(Rect rect, BitmapReceiver receiver) {
mRect = rect;
mReceiver = receiver;
}
@Override
protected Bitmap doInBackground(Void... unused) {
Point dimensions = calculateRawDimensions();
float horizontalCenter = BitmapUtils.calculateHorizontalAlignment(dimensions, mRect);
float verticalCenter = BitmapUtils.calculateVerticalAlignment(dimensions, mRect);
Drawable drawable = WallpaperManager.getInstance(mContext).getBuiltInDrawable(
mRect.width(),
mRect.height(),
CROP_TO_FIT,
horizontalCenter,
verticalCenter);
return ((BitmapDrawable) drawable).getBitmap();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
mReceiver.onBitmapDecoded(bitmap);
}
}
/**
* AsyncTask subclass which decodes the raw dimensions of the built-in wallpaper drawable off the
* main UI thread.
*/
private class DecodeDimensionsAsyncTask extends AsyncTask<Void, Void, Point> {
private DimensionsReceiver mReceiver;
public DecodeDimensionsAsyncTask(DimensionsReceiver receiver) {
mReceiver = receiver;
}
@Override
protected Point doInBackground(Void... unused) {
return calculateRawDimensions();
}
@Override
protected void onPostExecute(Point dimensions) {
mReceiver.onDimensionsDecoded(dimensions);
}
}
}