1 /* 2 * Copyright (C) 2008 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; 18 19 import android.content.ComponentName; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.graphics.Bitmap; 24 import android.util.Log; 25 26 import com.android.launcher3.LauncherSettings.Favorites; 27 import com.android.launcher3.compat.LauncherActivityInfoCompat; 28 import com.android.launcher3.compat.UserHandleCompat; 29 import com.android.launcher3.compat.UserManagerCompat; 30 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 34 /** 35 * Represents a launchable icon on the workspaces and in folders. 36 */ 37 public class ShortcutInfo extends ItemInfo { 38 39 public static final int DEFAULT = 0; 40 41 /** 42 * The shortcut was restored from a backup and it not ready to be used. This is automatically 43 * set during backup/restore 44 */ 45 public static final int FLAG_RESTORED_ICON = 1; 46 47 /** 48 * The icon was added as an auto-install app, and is not ready to be used. This flag can't 49 * be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout 50 * parsing. 51 */ 52 public static final int FLAG_AUTOINTALL_ICON = 2; //0B10; 53 54 /** 55 * The icon is being installed. If {@link #FLAG_RESTORED_ICON} or {@link #FLAG_AUTOINTALL_ICON} 56 * is set, then the icon is either being installed or is in a broken state. 57 */ 58 public static final int FLAG_INSTALL_SESSION_ACTIVE = 4; // 0B100; 59 60 /** 61 * Indicates that the widget restore has started. 62 */ 63 public static final int FLAG_RESTORE_STARTED = 8; //0B1000; 64 65 /** 66 * Indicates if it represents a common type mentioned in {@link CommonAppTypeParser}. 67 * Upto 15 different types supported. 68 */ 69 public static final int FLAG_RESTORED_APP_TYPE = 0B0011110000; 70 71 /** 72 * The intent used to start the application. 73 */ 74 Intent intent; 75 76 /** 77 * Indicates whether the icon comes from an application's resource (if false) 78 * or from a custom Bitmap (if true.) 79 * TODO: remove this flag 80 */ 81 public boolean customIcon; 82 83 /** 84 * Indicates whether we're using the default fallback icon instead of something from the 85 * app. 86 */ 87 boolean usingFallbackIcon; 88 89 /** 90 * Indicates whether we're using a low res icon 91 */ 92 boolean usingLowResIcon; 93 94 /** 95 * If isShortcut=true and customIcon=false, this contains a reference to the 96 * shortcut icon as an application's resource. 97 */ 98 public Intent.ShortcutIconResource iconResource; 99 100 /** 101 * The application icon. 102 */ 103 private Bitmap mIcon; 104 105 /** 106 * Indicates that the icon is disabled due to safe mode restrictions. 107 */ 108 public static final int FLAG_DISABLED_SAFEMODE = 1; 109 110 /** 111 * Indicates that the icon is disabled as the app is not available. 112 */ 113 public static final int FLAG_DISABLED_NOT_AVAILABLE = 2; 114 115 /** 116 * Indicates that the icon is disabled as the app is suspended 117 */ 118 public static final int FLAG_DISABLED_SUSPENDED = 4; 119 120 /** 121 * Indicates that the icon is disabled as the user is in quiet mode. 122 */ 123 public static final int FLAG_DISABLED_QUIET_USER = 8; 124 125 /** 126 * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when 127 * sd-card is not available). 128 */ 129 int isDisabled = DEFAULT; 130 131 int status; 132 133 /** 134 * The installation progress [0-100] of the package that this shortcut represents. 135 */ 136 private int mInstallProgress; 137 138 /** 139 * TODO move this to {@link #status} 140 */ 141 int flags = 0; 142 143 /** 144 * If this shortcut is a placeholder, then intent will be a market intent for the package, and 145 * this will hold the original intent from the database. Otherwise, null. 146 * Refer {@link #FLAG_RESTORED_ICON}, {@link #FLAG_AUTOINTALL_ICON} 147 */ 148 Intent promisedIntent; 149 ShortcutInfo()150 ShortcutInfo() { 151 itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; 152 } 153 getIntent()154 public Intent getIntent() { 155 return intent; 156 } 157 ShortcutInfo(Intent intent, CharSequence title, CharSequence contentDescription, Bitmap icon, UserHandleCompat user)158 ShortcutInfo(Intent intent, CharSequence title, CharSequence contentDescription, 159 Bitmap icon, UserHandleCompat user) { 160 this(); 161 this.intent = intent; 162 this.title = Utilities.trim(title); 163 this.contentDescription = contentDescription; 164 mIcon = icon; 165 this.user = user; 166 } 167 ShortcutInfo(Context context, ShortcutInfo info)168 public ShortcutInfo(Context context, ShortcutInfo info) { 169 super(info); 170 title = Utilities.trim(info.title); 171 intent = new Intent(info.intent); 172 if (info.iconResource != null) { 173 iconResource = new Intent.ShortcutIconResource(); 174 iconResource.packageName = info.iconResource.packageName; 175 iconResource.resourceName = info.iconResource.resourceName; 176 } 177 mIcon = info.mIcon; // TODO: should make a copy here. maybe we don't need this ctor at all 178 customIcon = info.customIcon; 179 flags = info.flags; 180 user = info.user; 181 status = info.status; 182 } 183 184 /** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */ ShortcutInfo(AppInfo info)185 public ShortcutInfo(AppInfo info) { 186 super(info); 187 title = Utilities.trim(info.title); 188 intent = new Intent(info.intent); 189 customIcon = false; 190 flags = info.flags; 191 isDisabled = info.isDisabled; 192 } 193 setIcon(Bitmap b)194 public void setIcon(Bitmap b) { 195 mIcon = b; 196 } 197 getIcon(IconCache iconCache)198 public Bitmap getIcon(IconCache iconCache) { 199 if (mIcon == null) { 200 updateIcon(iconCache); 201 } 202 return mIcon; 203 } 204 updateIcon(IconCache iconCache, boolean useLowRes)205 public void updateIcon(IconCache iconCache, boolean useLowRes) { 206 if (itemType == Favorites.ITEM_TYPE_APPLICATION) { 207 iconCache.getTitleAndIcon(this, promisedIntent != null ? promisedIntent : intent, user, 208 useLowRes); 209 } 210 } 211 updateIcon(IconCache iconCache)212 public void updateIcon(IconCache iconCache) { 213 updateIcon(iconCache, shouldUseLowResIcon()); 214 } 215 216 @Override onAddToDatabase(Context context, ContentValues values)217 void onAddToDatabase(Context context, ContentValues values) { 218 super.onAddToDatabase(context, values); 219 220 String titleStr = title != null ? title.toString() : null; 221 values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr); 222 223 String uri = promisedIntent != null ? promisedIntent.toUri(0) 224 : (intent != null ? intent.toUri(0) : null); 225 values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri); 226 values.put(LauncherSettings.Favorites.RESTORED, status); 227 228 if (customIcon) { 229 values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE, 230 LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP); 231 writeBitmap(values, mIcon); 232 } else { 233 if (!usingFallbackIcon) { 234 writeBitmap(values, mIcon); 235 } 236 if (iconResource != null) { 237 values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE, 238 LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE); 239 values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, 240 iconResource.packageName); 241 values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE, 242 iconResource.resourceName); 243 } 244 } 245 } 246 247 @Override toString()248 public String toString() { 249 return "ShortcutInfo(title=" + title + "intent=" + intent + "id=" + this.id 250 + " type=" + this.itemType + " container=" + this.container + " screen=" + screenId 251 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY 252 + " dropPos=" + Arrays.toString(dropPos) + " user=" + user + ")"; 253 } 254 dumpShortcutInfoList(String tag, String label, ArrayList<ShortcutInfo> list)255 public static void dumpShortcutInfoList(String tag, String label, 256 ArrayList<ShortcutInfo> list) { 257 Log.d(tag, label + " size=" + list.size()); 258 for (ShortcutInfo info: list) { 259 Log.d(tag, " title=\"" + info.title + " icon=" + info.mIcon 260 + " customIcon=" + info.customIcon); 261 } 262 } 263 getTargetComponent()264 public ComponentName getTargetComponent() { 265 return promisedIntent != null ? promisedIntent.getComponent() : intent.getComponent(); 266 } 267 hasStatusFlag(int flag)268 public boolean hasStatusFlag(int flag) { 269 return (status & flag) != 0; 270 } 271 272 isPromise()273 public final boolean isPromise() { 274 return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON); 275 } 276 getInstallProgress()277 public int getInstallProgress() { 278 return mInstallProgress; 279 } 280 setInstallProgress(int progress)281 public void setInstallProgress(int progress) { 282 mInstallProgress = progress; 283 status |= FLAG_INSTALL_SESSION_ACTIVE; 284 } 285 shouldUseLowResIcon()286 public boolean shouldUseLowResIcon() { 287 return usingLowResIcon && container >= 0 && rank >= FolderIcon.NUM_ITEMS_IN_PREVIEW; 288 } 289 fromActivityInfo(LauncherActivityInfoCompat info, Context context)290 public static ShortcutInfo fromActivityInfo(LauncherActivityInfoCompat info, Context context) { 291 final ShortcutInfo shortcut = new ShortcutInfo(); 292 shortcut.user = info.getUser(); 293 shortcut.title = Utilities.trim(info.getLabel()); 294 shortcut.contentDescription = UserManagerCompat.getInstance(context) 295 .getBadgedLabelForUser(info.getLabel(), info.getUser()); 296 shortcut.customIcon = false; 297 shortcut.intent = AppInfo.makeLaunchIntent(context, info, info.getUser()); 298 shortcut.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; 299 shortcut.flags = AppInfo.initFlags(info); 300 return shortcut; 301 } 302 303 @Override isDisabled()304 public boolean isDisabled() { 305 return isDisabled != 0; 306 } 307 } 308 309