1 /* 2 * Copyright (C) 2016 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 17 package com.android.launcher3.graphics; 18 19 import static com.android.launcher3.graphics.IconShape.getShapePath; 20 import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; 21 22 import android.content.Context; 23 import android.content.pm.ActivityInfo; 24 import android.content.res.Resources; 25 import android.graphics.Bitmap; 26 import android.graphics.Canvas; 27 import android.graphics.Color; 28 import android.graphics.Rect; 29 import android.graphics.drawable.BitmapDrawable; 30 import android.graphics.drawable.Drawable; 31 import android.os.Process; 32 import android.os.UserHandle; 33 import android.util.ArrayMap; 34 35 import androidx.annotation.UiThread; 36 37 import com.android.launcher3.FastBitmapDrawable; 38 import com.android.launcher3.ItemInfoWithIcon; 39 import com.android.launcher3.R; 40 import com.android.launcher3.icons.BitmapInfo; 41 import com.android.launcher3.util.MainThreadInitializedObject; 42 import com.android.launcher3.util.ResourceBasedOverride; 43 44 /** 45 * Factory for creating new drawables. 46 */ 47 public class DrawableFactory implements ResourceBasedOverride { 48 49 public static final MainThreadInitializedObject<DrawableFactory> INSTANCE = 50 forOverride(DrawableFactory.class, R.string.drawable_factory_class); 51 52 protected final UserHandle mMyUser = Process.myUserHandle(); 53 protected final ArrayMap<UserHandle, Bitmap> mUserBadges = new ArrayMap<>(); 54 55 /** 56 * Returns a FastBitmapDrawable with the icon. 57 */ newIcon(Context context, ItemInfoWithIcon info)58 public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) { 59 FastBitmapDrawable drawable = info.usingLowResIcon() 60 ? new PlaceHolderIconDrawable(info, getShapePath(), context) 61 : new FastBitmapDrawable(info); 62 drawable.setIsDisabled(info.isDisabled()); 63 return drawable; 64 } 65 newIcon(Context context, BitmapInfo info, ActivityInfo target)66 public FastBitmapDrawable newIcon(Context context, BitmapInfo info, ActivityInfo target) { 67 return info.isLowRes() 68 ? new PlaceHolderIconDrawable(info, getShapePath(), context) 69 : new FastBitmapDrawable(info); 70 } 71 72 /** 73 * Returns a FastBitmapDrawable with the icon. 74 */ newPendingIcon(Context context, ItemInfoWithIcon info)75 public PreloadIconDrawable newPendingIcon(Context context, ItemInfoWithIcon info) { 76 return new PreloadIconDrawable(info, getShapePath(), context); 77 } 78 79 /** 80 * Returns a drawable that can be used as a badge for the user or null. 81 */ 82 @UiThread getBadgeForUser(UserHandle user, Context context, int badgeSize)83 public Drawable getBadgeForUser(UserHandle user, Context context, int badgeSize) { 84 if (mMyUser.equals(user)) { 85 return null; 86 } 87 88 Bitmap badgeBitmap = getUserBadge(user, context, badgeSize); 89 FastBitmapDrawable d = new FastBitmapDrawable(badgeBitmap); 90 d.setFilterBitmap(true); 91 d.setBounds(0, 0, badgeBitmap.getWidth(), badgeBitmap.getHeight()); 92 return d; 93 } 94 getUserBadge(UserHandle user, Context context, int badgeSize)95 protected synchronized Bitmap getUserBadge(UserHandle user, Context context, int badgeSize) { 96 Bitmap badgeBitmap = mUserBadges.get(user); 97 if (badgeBitmap != null) { 98 return badgeBitmap; 99 } 100 101 final Resources res = context.getApplicationContext().getResources(); 102 badgeBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888); 103 104 Drawable drawable = context.getPackageManager().getUserBadgedDrawableForDensity( 105 new BitmapDrawable(res, badgeBitmap), user, new Rect(0, 0, badgeSize, badgeSize), 106 0); 107 if (drawable instanceof BitmapDrawable) { 108 badgeBitmap = ((BitmapDrawable) drawable).getBitmap(); 109 } else { 110 badgeBitmap.eraseColor(Color.TRANSPARENT); 111 Canvas c = new Canvas(badgeBitmap); 112 drawable.setBounds(0, 0, badgeSize, badgeSize); 113 drawable.draw(c); 114 c.setBitmap(null); 115 } 116 117 mUserBadges.put(user, badgeBitmap); 118 return badgeBitmap; 119 } 120 } 121