blob: b6341f9dc47699355580501f8487a908bea5a107 [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.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 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 ExecutorService sExecutorService = Executors.newCachedThreadPool();
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,
boolean shouldAdjustForRtl, BitmapReceiver receiver) {
sExecutorService.execute(() -> {
Point dimensions = calculateRawDimensions();
float horizontalCenter = BitmapUtils.calculateHorizontalAlignment(dimensions, rect);
float verticalCenter = BitmapUtils.calculateVerticalAlignment(dimensions, rect);
Drawable drawable = WallpaperManager.getInstance(mContext).getBuiltInDrawable(
rect.width(),
rect.height(),
CROP_TO_FIT,
horizontalCenter,
verticalCenter);
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
decodeBitmapCompleted(receiver, bitmap);
});
}
@Override
public void decodeRawDimensions(Activity unused, DimensionsReceiver receiver) {
sExecutorService.execute(() -> {
Point dimensions = calculateRawDimensions();
new Handler(Looper.getMainLooper()).post(
() -> receiver.onDimensionsDecoded(dimensions));
});
}
@Override
public void decodeBitmap(int targetWidth, int targetHeight, boolean useHardwareBitmapIfPossible,
BitmapReceiver receiver) {
sExecutorService.execute(() -> {
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
Drawable drawable = (targetWidth <= 0 || targetHeight <= 0)
? wallpaperManager.getBuiltInDrawable()
: wallpaperManager.getBuiltInDrawable(
targetWidth,
targetHeight,
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();
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
decodeBitmapCompleted(receiver, bitmap);
});
}
@Override
public void decodeBitmap(BitmapReceiver receiver) {
decodeBitmap(0, 0, receiver);
}
@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);
}
}