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 21 import android.content.Context; 22 import android.content.pm.ActivityInfo; 23 import android.content.res.Resources; 24 import android.graphics.Bitmap; 25 import android.graphics.Canvas; 26 import android.graphics.Color; 27 import android.graphics.Rect; 28 import android.graphics.drawable.BitmapDrawable; 29 import android.graphics.drawable.Drawable; 30 import android.os.Process; 31 import android.os.UserHandle; 32 import android.util.ArrayMap; 33 34 import com.android.launcher3.FastBitmapDrawable; 35 import com.android.launcher3.ItemInfoWithIcon; 36 import com.android.launcher3.R; 37 import com.android.launcher3.icons.BitmapInfo; 38 import com.android.launcher3.util.MainThreadInitializedObject; 39 import com.android.launcher3.util.ResourceBasedOverride; 40 41 import androidx.annotation.UiThread; 42 43 /** 44 * Factory for creating new drawables. 45 */ 46 public class DrawableFactory implements ResourceBasedOverride { 47 48 public static final MainThreadInitializedObject<DrawableFactory> INSTANCE = 49 new MainThreadInitializedObject<>(c -> Overrides.getObject(DrawableFactory.class, 50 c.getApplicationContext(), 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)83 public Drawable getBadgeForUser(UserHandle user, Context context) { 84 if (mMyUser.equals(user)) { 85 return null; 86 } 87 88 Bitmap badgeBitmap = getUserBadge(user, context); 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)95 protected synchronized Bitmap getUserBadge(UserHandle user, Context context) { 96 Bitmap badgeBitmap = mUserBadges.get(user); 97 if (badgeBitmap != null) { 98 return badgeBitmap; 99 } 100 101 final Resources res = context.getApplicationContext().getResources(); 102 int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size); 103 badgeBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888); 104 105 Drawable drawable = context.getPackageManager().getUserBadgedDrawableForDensity( 106 new BitmapDrawable(res, badgeBitmap), user, new Rect(0, 0, badgeSize, badgeSize), 107 0); 108 if (drawable instanceof BitmapDrawable) { 109 badgeBitmap = ((BitmapDrawable) drawable).getBitmap(); 110 } else { 111 badgeBitmap.eraseColor(Color.TRANSPARENT); 112 Canvas c = new Canvas(badgeBitmap); 113 drawable.setBounds(0, 0, badgeSize, badgeSize); 114 drawable.draw(c); 115 c.setBitmap(null); 116 } 117 118 mUserBadges.put(user, badgeBitmap); 119 return badgeBitmap; 120 } 121 } 122