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