1 package com.android.launcher3.model;
2 
3 import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN;
4 import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
5 import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX;
6 
7 import static com.android.launcher3.Utilities.ATLEAST_S;
8 
9 import android.annotation.SuppressLint;
10 import android.content.Context;
11 import android.content.pm.ActivityInfo;
12 import android.content.pm.PackageManager;
13 import android.content.res.Resources;
14 import android.util.SparseArray;
15 import android.widget.RemoteViews;
16 
17 import androidx.core.os.BuildCompat;
18 
19 import com.android.launcher3.Flags;
20 import com.android.launcher3.InvariantDeviceProfile;
21 import com.android.launcher3.Utilities;
22 import com.android.launcher3.icons.BitmapInfo;
23 import com.android.launcher3.icons.IconCache;
24 import com.android.launcher3.pm.ShortcutConfigActivityInfo;
25 import com.android.launcher3.util.ComponentKey;
26 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
27 import com.android.launcher3.widget.WidgetManagerHelper;
28 
29 /**
30  * An wrapper over various items displayed in a widget picker,
31  * {@link LauncherAppWidgetProviderInfo} & {@link ActivityInfo}. This provides easier access to
32  * common attributes like spanX and spanY.
33  */
34 public class WidgetItem extends ComponentKey {
35 
36     public final LauncherAppWidgetProviderInfo widgetInfo;
37     public final ShortcutConfigActivityInfo activityInfo;
38 
39     public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
40     public final String label;
41     public final CharSequence description;
42     public final int spanX, spanY;
43     public final SparseArray<RemoteViews> generatedPreviews;
44 
WidgetItem(LauncherAppWidgetProviderInfo info, InvariantDeviceProfile idp, IconCache iconCache, Context context, WidgetManagerHelper helper)45     public WidgetItem(LauncherAppWidgetProviderInfo info,
46             InvariantDeviceProfile idp, IconCache iconCache, Context context,
47             WidgetManagerHelper helper) {
48         super(info.provider, info.getProfile());
49 
50         label = iconCache.getTitleNoCache(info);
51         description = ATLEAST_S ? info.loadDescription(context) : null;
52         widgetInfo = info;
53         activityInfo = null;
54 
55         spanX = Math.min(info.spanX, idp.numColumns);
56         spanY = Math.min(info.spanY, idp.numRows);
57 
58         if (BuildCompat.isAtLeastV() && Flags.enableGeneratedPreviews()) {
59             generatedPreviews = new SparseArray<>(3);
60             for (int widgetCategory : new int[] {
61                     WIDGET_CATEGORY_HOME_SCREEN,
62                     WIDGET_CATEGORY_KEYGUARD,
63                     WIDGET_CATEGORY_SEARCHBOX,
64             }) {
65                 if ((widgetCategory & widgetInfo.generatedPreviewCategories) != 0) {
66                     generatedPreviews.put(widgetCategory,
67                             helper.loadGeneratedPreview(widgetInfo, widgetCategory));
68                 }
69             }
70         } else {
71             generatedPreviews = null;
72         }
73     }
74 
WidgetItem(LauncherAppWidgetProviderInfo info, InvariantDeviceProfile idp, IconCache iconCache, Context context)75     public WidgetItem(LauncherAppWidgetProviderInfo info,
76             InvariantDeviceProfile idp, IconCache iconCache, Context context) {
77         this(info, idp, iconCache, context, new WidgetManagerHelper(context));
78     }
79 
WidgetItem(ShortcutConfigActivityInfo info, IconCache iconCache, PackageManager pm)80     public WidgetItem(ShortcutConfigActivityInfo info, IconCache iconCache, PackageManager pm) {
81         super(info.getComponent(), info.getUser());
82         label = info.isPersistable() ? iconCache.getTitleNoCache(info) :
83                 Utilities.trim(info.getLabel(pm));
84         description = null;
85         widgetInfo = null;
86         activityInfo = info;
87         spanX = spanY = 1;
88         generatedPreviews = null;
89     }
90 
91     /**
92      * Returns {@code true} if this {@link WidgetItem} has the same type as the given
93      * {@code otherItem}.
94      *
95      * For example, both items are widgets or both items are shortcuts.
96      */
hasSameType(WidgetItem otherItem)97     public boolean hasSameType(WidgetItem otherItem) {
98         if (widgetInfo != null && otherItem.widgetInfo != null) {
99             return true;
100         }
101         if (activityInfo != null && otherItem.activityInfo != null) {
102             return true;
103         }
104         return false;
105     }
106 
107     /** Returns whether this {@link WidgetItem} has a preview layout that can be used. */
108     @SuppressLint("NewApi") // Already added API check.
hasPreviewLayout()109     public boolean hasPreviewLayout() {
110         return ATLEAST_S && widgetInfo != null && widgetInfo.previewLayout != Resources.ID_NULL;
111     }
112 
113     /** Returns whether this {@link WidgetItem} is for a shortcut rather than an app widget. */
isShortcut()114     public boolean isShortcut() {
115         return activityInfo != null;
116     }
117 
118     /**
119      * Returns whether this {@link WidgetItem} has a generated preview for the given widget
120      * category.
121      */
hasGeneratedPreview(int widgetCategory)122     public boolean hasGeneratedPreview(int widgetCategory) {
123         if (!Flags.enableGeneratedPreviews() || generatedPreviews == null) {
124             return false;
125         }
126         return generatedPreviews.contains(widgetCategory)
127                 && generatedPreviews.get(widgetCategory) != null;
128     }
129 }
130