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