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 * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when 92 * sd-card is not available). 93 */ 94 boolean isDisabled = false; 95 96 int status; 97 98 /** 99 * The installation progress [0-100] of the package that this shortcut represents. 100 */ 101 private int mInstallProgress; 102 103 /** 104 * Refer {@link AppInfo#firstInstallTime}. 105 */ 106 long firstInstallTime; 107 108 /** 109 * TODO move this to {@link status} 110 */ 111 int flags = 0; 112 113 /** 114 * If this shortcut is a placeholder, then intent will be a market intent for the package, and 115 * this will hold the original intent from the database. Otherwise, null. 116 * Refer {@link #FLAG_RESTORE_PENDING}, {@link #FLAG_INSTALL_PENDING} 117 */ 118 Intent promisedIntent; 119 120 ShortcutInfo() { 121 itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; 122 } 123 124 public Intent getIntent() { 125 return intent; 126 } 127 128 ShortcutInfo(Intent intent, CharSequence title, CharSequence contentDescription, 129 Bitmap icon, UserHandleCompat user) { 130 this(); 131 this.intent = intent; 132 this.title = title; 133 this.contentDescription = contentDescription; 134 mIcon = icon; 135 this.user = user; 136 } 137 138 public ShortcutInfo(Context context, ShortcutInfo info) { 139 super(info); 140 title = info.title.toString(); 141 intent = new Intent(info.intent); 142 if (info.iconResource != null) { 143 iconResource = new Intent.ShortcutIconResource(); 144 iconResource.packageName = info.iconResource.packageName; 145 iconResource.resourceName = info.iconResource.resourceName; 146 } 147 mIcon = info.mIcon; // TODO: should make a copy here. maybe we don't need this ctor at all 148 customIcon = info.customIcon; 149 flags = info.flags; 150 firstInstallTime = info.firstInstallTime; 151 user = info.user; 152 status = info.status; 153 } 154 155 /** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */ 156 public ShortcutInfo(AppInfo info) { 157 super(info); 158 title = info.title.toString(); 159 intent = new Intent(info.intent); 160 customIcon = false; 161 flags = info.flags; 162 firstInstallTime = info.firstInstallTime; 163 } 164 165 public void setIcon(Bitmap b) { 166 mIcon = b; 167 } 168 169 public Bitmap getIcon(IconCache iconCache) { 170 if (mIcon == null) { 171 updateIcon(iconCache); 172 } 173 return mIcon; 174 } 175 176 public void updateIcon(IconCache iconCache) { 177 mIcon = iconCache.getIcon(promisedIntent != null ? promisedIntent : intent, user); 178 usingFallbackIcon = iconCache.isDefaultIcon(mIcon, user); 179 } 180 181 @Override 182 void onAddToDatabase(Context context, ContentValues values) { 183 super.onAddToDatabase(context, values); 184 185 String titleStr = title != null ? title.toString() : null; 186 values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr); 187 188 String uri = promisedIntent != null ? promisedIntent.toUri(0) 189 : (intent != null ? intent.toUri(0) : null); 190 values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri); 191 192 if (customIcon) { 193 values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE, 194 LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP); 195 writeBitmap(values, mIcon); 196 } else { 197 if (!usingFallbackIcon) { 198 writeBitmap(values, mIcon); 199 } 200 values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE, 201 LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE); 202 if (iconResource != null) { 203 values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, 204 iconResource.packageName); 205 values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE, 206 iconResource.resourceName); 207 } 208 } 209 } 210 211 @Override 212 public String toString() { 213 return "ShortcutInfo(title=" + title + "intent=" + intent + "id=" + this.id 214 + " type=" + this.itemType + " container=" + this.container + " screen=" + screenId 215 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY 216 + " dropPos=" + Arrays.toString(dropPos) + " user=" + user + ")"; 217 } 218 219 public static void dumpShortcutInfoList(String tag, String label, 220 ArrayList<ShortcutInfo> list) { 221 Log.d(tag, label + " size=" + list.size()); 222 for (ShortcutInfo info: list) { 223 Log.d(tag, " title=\"" + info.title + " icon=" + info.mIcon 224 + " customIcon=" + info.customIcon); 225 } 226 } 227 228 public ComponentName getTargetComponent() { 229 return promisedIntent != null ? promisedIntent.getComponent() : intent.getComponent(); 230 } 231 232 public boolean hasStatusFlag(int flag) { 233 return (status & flag) != 0; 234 } 235 236 237 public final boolean isPromise() { 238 return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON); 239 } 240 241 public int getInstallProgress() { 242 return mInstallProgress; 243 } 244 245 public void setInstallProgress(int progress) { 246 mInstallProgress = progress; 247 status |= FLAG_INSTALL_SESSION_ACTIVE; 248 } 249 } 250 251