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 android.util;
17 
18 import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
19 import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON_BADGE;
20 import static android.app.admin.DevicePolicyResources.UNDEFINED;
21 
22 import android.annotation.UserIdInt;
23 import android.app.admin.DevicePolicyManager;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.content.Context;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageItemInfo;
28 import android.content.pm.PackageManager;
29 import android.content.res.Resources;
30 import android.graphics.drawable.Drawable;
31 import android.os.Build;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 
35 /**
36  * Utility class to load app drawables with appropriate badging.
37  *
38  * @hide
39  */
40 public class IconDrawableFactory {
41 
42     protected final Context mContext;
43     protected final PackageManager mPm;
44     protected final UserManager mUm;
45     protected final DevicePolicyManager mDpm;
46     protected final LauncherIcons mLauncherIcons;
47     protected final boolean mEmbedShadow;
48 
IconDrawableFactory(Context context, boolean embedShadow)49     private IconDrawableFactory(Context context, boolean embedShadow) {
50         mContext = context;
51         mPm = context.getPackageManager();
52         mUm = context.getSystemService(UserManager.class);
53         mDpm = context.getSystemService(DevicePolicyManager.class);
54         mLauncherIcons = new LauncherIcons(context);
55         mEmbedShadow = embedShadow;
56     }
57 
needsBadging(ApplicationInfo appInfo, @UserIdInt int userId)58     protected boolean needsBadging(ApplicationInfo appInfo, @UserIdInt int userId) {
59         return appInfo.isInstantApp() || mUm.hasBadge(userId);
60     }
61 
62     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getBadgedIcon(ApplicationInfo appInfo)63     public Drawable getBadgedIcon(ApplicationInfo appInfo) {
64         return getBadgedIcon(appInfo, UserHandle.getUserId(appInfo.uid));
65     }
66 
getBadgedIcon(ApplicationInfo appInfo, @UserIdInt int userId)67     public Drawable getBadgedIcon(ApplicationInfo appInfo, @UserIdInt int userId) {
68         return getBadgedIcon(appInfo, appInfo, userId);
69     }
70 
71     @UnsupportedAppUsage
getBadgedIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo, @UserIdInt int userId)72     public Drawable getBadgedIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo,
73             @UserIdInt int userId) {
74         Drawable icon = mPm.loadUnbadgedItemIcon(itemInfo, appInfo);
75         if (!mEmbedShadow && !needsBadging(appInfo, userId)) {
76             return icon;
77         }
78 
79         icon = getShadowedIcon(icon);
80         if (appInfo.isInstantApp()) {
81             int badgeColor = Resources.getSystem().getColor(
82                     com.android.internal.R.color.instant_app_badge, null);
83             Drawable badge = mContext.getDrawable(
84                     com.android.internal.R.drawable.ic_instant_icon_badge_bolt);
85             icon = mLauncherIcons.getBadgedDrawable(icon,
86                     badge,
87                     badgeColor);
88         }
89         if (mUm.hasBadge(userId)) {
90 
91             Drawable badge = mDpm.getResources().getDrawable(
92                     getUpdatableUserIconBadgeId(userId),
93                     SOLID_COLORED,
94                     () -> getDefaultUserIconBadge(userId));
95 
96             icon = mLauncherIcons.getBadgedDrawable(icon, badge, mUm.getUserBadgeColor(userId));
97         }
98         return icon;
99     }
100 
getUpdatableUserIconBadgeId(int userId)101     private String getUpdatableUserIconBadgeId(int userId) {
102         return mUm.isManagedProfile(userId) ? WORK_PROFILE_ICON_BADGE : UNDEFINED;
103     }
104 
getDefaultUserIconBadge(int userId)105     private Drawable getDefaultUserIconBadge(int userId) {
106         return mContext.getResources().getDrawable(mUm.getUserIconBadgeResId(userId));
107     }
108 
109     /**
110      * Add shadow to the icon if {@link AdaptiveIconDrawable}
111      */
getShadowedIcon(Drawable icon)112     public Drawable getShadowedIcon(Drawable icon) {
113         return mLauncherIcons.wrapIconDrawableWithShadow(icon);
114     }
115 
116     @UnsupportedAppUsage
newInstance(Context context)117     public static IconDrawableFactory newInstance(Context context) {
118         return new IconDrawableFactory(context, true);
119     }
120 
newInstance(Context context, boolean embedShadow)121     public static IconDrawableFactory newInstance(Context context, boolean embedShadow) {
122         return new IconDrawableFactory(context, embedShadow);
123     }
124 }
125