• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.TargetApi;
19 import android.app.Activity;
20 import android.app.WallpaperManager;
21 import android.content.Context;
22 import android.graphics.Bitmap;
23 import android.graphics.Point;
24 import android.graphics.Rect;
25 import android.graphics.drawable.BitmapDrawable;
26 import android.graphics.drawable.ColorDrawable;
27 import android.graphics.drawable.Drawable;
28 import android.os.Build;
29 import android.os.Build.VERSION;
30 import android.os.Build.VERSION_CODES;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.widget.ImageView;
34 
35 import com.bumptech.glide.Glide;
36 import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
37 import com.bumptech.glide.request.RequestOptions;
38 
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.Executors;
41 
42 /**
43  * Asset representing the system's built-in wallpaper.
44  * NOTE: This is only used for KitKat and newer devices. On older versions of Android, the
45  * built-in wallpaper is accessed via the system Resources object, and is thus be represented
46  * by a {@code ResourceAsset} instead.
47  */
48 @TargetApi(Build.VERSION_CODES.KITKAT)
49 public final class BuiltInWallpaperAsset extends Asset {
50     private static final ExecutorService sExecutorService = Executors.newCachedThreadPool();
51     private static final boolean SCALE_TO_FIT = true;
52     private static final boolean CROP_TO_FIT = false;
53     private static final float HORIZONTAL_CENTER_ALIGNED = 0.5f;
54     private static final float VERTICAL_CENTER_ALIGNED = 0.5f;
55 
56     private final Context mContext;
57 
58     private Point mDimensions;
59     private WallpaperModel mBuiltInWallpaperModel;
60 
61     /**
62      * @param context The application's context.
63      */
BuiltInWallpaperAsset(Context context)64     public BuiltInWallpaperAsset(Context context) {
65         if (VERSION.SDK_INT < VERSION_CODES.KITKAT) {
66             throw new AssertionError("BuiltInWallpaperAsset should not be instantiated on a pre-KitKat"
67                     + " build");
68         }
69 
70         mContext = context.getApplicationContext();
71     }
72 
73     @Override
decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight, boolean shouldAdjustForRtl, BitmapReceiver receiver)74     public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
75             boolean shouldAdjustForRtl, BitmapReceiver receiver) {
76         sExecutorService.execute(() -> {
77             Point dimensions = calculateRawDimensions();
78 
79             float horizontalCenter = BitmapUtils.calculateHorizontalAlignment(dimensions, rect);
80             float verticalCenter = BitmapUtils.calculateVerticalAlignment(dimensions, rect);
81 
82             Drawable drawable = WallpaperManager.getInstance(mContext).getBuiltInDrawable(
83                     rect.width(),
84                     rect.height(),
85                     CROP_TO_FIT,
86                     horizontalCenter,
87                     verticalCenter);
88             Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
89             decodeBitmapCompleted(receiver, bitmap);
90         });
91     }
92 
93     @Override
decodeRawDimensions(Activity unused, DimensionsReceiver receiver)94     public void decodeRawDimensions(Activity unused, DimensionsReceiver receiver) {
95         sExecutorService.execute(() -> {
96             Point dimensions = calculateRawDimensions();
97             new Handler(Looper.getMainLooper()).post(
98                     () -> receiver.onDimensionsDecoded(dimensions));
99         });
100     }
101 
102     @Override
decodeBitmap(int targetWidth, int targetHeight, boolean useHardwareBitmapIfPossible, BitmapReceiver receiver)103     public void decodeBitmap(int targetWidth, int targetHeight, boolean useHardwareBitmapIfPossible,
104                              BitmapReceiver receiver) {
105         sExecutorService.execute(() -> {
106             final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
107 
108             Drawable drawable = (targetWidth <= 0 || targetHeight <= 0)
109                     ? wallpaperManager.getBuiltInDrawable()
110                     : wallpaperManager.getBuiltInDrawable(
111                         targetWidth,
112                         targetHeight,
113                         SCALE_TO_FIT,
114                         HORIZONTAL_CENTER_ALIGNED,
115                         VERTICAL_CENTER_ALIGNED);
116 
117             // Manually request that WallpaperManager loses its reference to the built-in wallpaper
118             // bitmap, which can occupy a large memory allocation for the lifetime of the app.
119             wallpaperManager.forgetLoadedWallpaper();
120 
121             Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
122             decodeBitmapCompleted(receiver, bitmap);
123         });
124     }
125 
126     @Override
decodeBitmap(BitmapReceiver receiver)127     public void decodeBitmap(BitmapReceiver receiver) {
128         decodeBitmap(0, 0, receiver);
129     }
130 
131     @Override
supportsTiling()132     public boolean supportsTiling() {
133         return false;
134     }
135 
136     /**
137      * Calculates the raw dimensions of the built-in drawable. This method should not be called from
138      * the main UI thread.
139      *
140      * @return Raw dimensions of the built-in wallpaper drawable.
141      */
calculateRawDimensions()142     private Point calculateRawDimensions() {
143         if (mDimensions != null) {
144             return mDimensions;
145         }
146 
147         Drawable builtInDrawable = WallpaperManager.getInstance(mContext).getBuiltInDrawable();
148         Bitmap builtInBitmap = ((BitmapDrawable) builtInDrawable).getBitmap();
149         mDimensions = new Point(builtInBitmap.getWidth(), builtInBitmap.getHeight());
150         return mDimensions;
151     }
152 
153     @Override
loadDrawable(Context context, ImageView imageView, int placeholderColor)154     public void loadDrawable(Context context, ImageView imageView, int placeholderColor) {
155         if (mBuiltInWallpaperModel == null) {
156             mBuiltInWallpaperModel =
157                     new WallpaperModel(context.getApplicationContext(), WallpaperModel.SOURCE_BUILT_IN);
158         }
159 
160         Glide.with(context)
161                 .asDrawable()
162                 .load(mBuiltInWallpaperModel)
163                 .apply(RequestOptions.centerCropTransform()
164                         .placeholder(new ColorDrawable(placeholderColor)))
165                 .transition(DrawableTransitionOptions.withCrossFade())
166                 .into(imageView);
167     }
168 }
169