• 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.launcher3.icons;
17 
18 import static com.android.launcher3.icons.GraphicsUtils.getExpectedBitmapSize;
19 
20 import android.content.Context;
21 import android.graphics.Bitmap;
22 import android.graphics.Bitmap.Config;
23 import android.graphics.BitmapFactory;
24 import android.graphics.Canvas;
25 import android.graphics.drawable.Drawable;
26 import android.os.Build;
27 import android.os.UserHandle;
28 import android.util.Log;
29 
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 
33 import com.android.launcher3.icons.ThemedIconDrawable.ThemedBitmapInfo;
34 import com.android.launcher3.icons.cache.BaseIconCache;
35 
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 
39 public class BitmapInfo {
40 
41     public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
42     public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON);
43 
44     public static final String TAG = "BitmapInfo";
45 
46     protected static final byte TYPE_DEFAULT = 1;
47     protected static final byte TYPE_THEMED = 2;
48 
49     public final Bitmap icon;
50     public final int color;
51 
BitmapInfo(Bitmap icon, int color)52     public BitmapInfo(Bitmap icon, int color) {
53         this.icon = icon;
54         this.color = color;
55     }
56 
57     /**
58      * Ideally icon should not be null, except in cases when generating hardware bitmap failed
59      */
isNullOrLowRes()60     public final boolean isNullOrLowRes() {
61         return icon == null || icon == LOW_RES_ICON;
62     }
63 
isLowRes()64     public final boolean isLowRes() {
65         return LOW_RES_ICON == icon;
66     }
67 
68     /**
69      * Returns a serialized version of BitmapInfo
70      */
71     @Nullable
toByteArray()72     public byte[] toByteArray() {
73         if (isNullOrLowRes()) {
74             return null;
75         }
76         ByteArrayOutputStream out = new ByteArrayOutputStream(getExpectedBitmapSize(icon) + 1);
77         try {
78             out.write(TYPE_DEFAULT);
79             icon.compress(Bitmap.CompressFormat.PNG, 100, out);
80             out.flush();
81             out.close();
82             return out.toByteArray();
83         } catch (IOException e) {
84             Log.w(TAG, "Could not write bitmap");
85             return null;
86         }
87     }
88 
89     /**
90      * Returns a new icon based on the theme of the context
91      */
newThemedIcon(Context context)92     public FastBitmapDrawable newThemedIcon(Context context) {
93         return newIcon(context);
94     }
95 
96     /**
97      * Creates a drawable for the provided BitmapInfo
98      */
newIcon(Context context)99     public FastBitmapDrawable newIcon(Context context) {
100         FastBitmapDrawable drawable = isLowRes()
101                 ? new PlaceHolderIconDrawable(this, context)
102                 : new FastBitmapDrawable(this);
103         drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f);
104         return drawable;
105     }
106 
107     /**
108      * Returns a BitmapInfo previously serialized using {@link #toByteArray()};
109      */
110     @NonNull
fromByteArray(byte[] data, int color, UserHandle user, BaseIconCache iconCache, Context context)111     public static BitmapInfo fromByteArray(byte[] data, int color, UserHandle user,
112             BaseIconCache iconCache, Context context) {
113         if (data == null) {
114             return null;
115         }
116         BitmapFactory.Options decodeOptions;
117         if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
118             decodeOptions = new BitmapFactory.Options();
119             decodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
120         } else {
121             decodeOptions = null;
122         }
123         if (data[0] == TYPE_DEFAULT) {
124             return BitmapInfo.of(
125                     BitmapFactory.decodeByteArray(data, 1, data.length - 1, decodeOptions),
126                     color);
127         } else if (data[0] == TYPE_THEMED) {
128             return ThemedBitmapInfo.decode(data, color, decodeOptions, user, iconCache, context);
129         } else {
130             return null;
131         }
132     }
133 
fromBitmap(@onNull Bitmap bitmap)134     public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
135         return of(bitmap, 0);
136     }
137 
of(@onNull Bitmap bitmap, int color)138     public static BitmapInfo of(@NonNull Bitmap bitmap, int color) {
139         return new BitmapInfo(bitmap, color);
140     }
141 
142     /**
143      * Interface to be implemented by drawables to provide a custom BitmapInfo
144      */
145     public interface Extender {
146 
147         /**
148          * Called for creating a custom BitmapInfo
149          */
getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user)150         BitmapInfo getExtendedInfo(Bitmap bitmap, int color,
151                 BaseIconFactory iconFactory, float normalizationScale, UserHandle user);
152 
153         /**
154          * Called to draw the UI independent of any runtime configurations like time or theme
155          */
drawForPersistence(Canvas canvas)156         void drawForPersistence(Canvas canvas);
157 
158         /**
159          * Returns a new icon with theme applied
160          */
getThemedDrawable(Context context)161         Drawable getThemedDrawable(Context context);
162     }
163 }
164