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 17package com.android.launcher3; 18 19import android.annotation.TargetApi; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.Intent; 23import android.os.Build; 24import android.text.TextUtils; 25 26import com.android.launcher3.LauncherSettings.Favorites; 27import com.android.launcher3.compat.UserManagerCompat; 28import com.android.launcher3.shortcuts.ShortcutInfoCompat; 29import com.android.launcher3.util.ContentWriter; 30 31/** 32 * Represents a launchable icon on the workspaces and in folders. 33 */ 34public class ShortcutInfo extends ItemInfoWithIcon { 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_AUTOINSTALL_ICON = 2; //0B10; 50 51 /** 52 * The icon is being installed. If {@link #FLAG_RESTORED_ICON} or {@link #FLAG_AUTOINSTALL_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; // 0B100; 56 57 /** 58 * Indicates that the widget restore has started. 59 */ 60 public static final int FLAG_RESTORE_STARTED = 8; //0B1000; 61 62 /** 63 * Web UI supported. 64 */ 65 public static final int FLAG_SUPPORTS_WEB_UI = 16; //0B10000; 66 67 /** 68 * Indicates if it represents a common type mentioned in {@link CommonAppTypeParser}. 69 * Upto 15 different types supported. 70 */ 71 @Deprecated 72 public static final int FLAG_RESTORED_APP_TYPE = 0B0011110000; 73 74 /** 75 * The intent used to start the application. 76 */ 77 public Intent intent; 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 public Intent.ShortcutIconResource iconResource; 84 85 /** 86 * Indicates that the icon is disabled due to safe mode restrictions. 87 */ 88 public static final int FLAG_DISABLED_SAFEMODE = 1 << 0; 89 90 /** 91 * Indicates that the icon is disabled as the app is not available. 92 */ 93 public static final int FLAG_DISABLED_NOT_AVAILABLE = 1 << 1; 94 95 /** 96 * Indicates that the icon is disabled as the app is suspended 97 */ 98 public static final int FLAG_DISABLED_SUSPENDED = 1 << 2; 99 100 /** 101 * Indicates that the icon is disabled as the user is in quiet mode. 102 */ 103 public static final int FLAG_DISABLED_QUIET_USER = 1 << 3; 104 105 /** 106 * Indicates that the icon is disabled as the publisher has disabled the actual shortcut. 107 */ 108 public static final int FLAG_DISABLED_BY_PUBLISHER = 1 << 4; 109 110 /** 111 * Indicates that the icon is disabled as the user partition is currently locked. 112 */ 113 public static final int FLAG_DISABLED_LOCKED_USER = 1 << 5; 114 115 /** 116 * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when 117 * sd-card is not available). 118 */ 119 public int isDisabled = DEFAULT; 120 121 /** 122 * A message to display when the user tries to start a disabled shortcut. 123 * This is currently only used for deep shortcuts. 124 */ 125 CharSequence disabledMessage; 126 127 public int status; 128 129 /** 130 * The installation progress [0-100] of the package that this shortcut represents. 131 */ 132 private int mInstallProgress; 133 134 public ShortcutInfo() { 135 itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; 136 } 137 138 public ShortcutInfo(ShortcutInfo info) { 139 super(info); 140 title = info.title; 141 intent = new Intent(info.intent); 142 iconResource = info.iconResource; 143 status = info.status; 144 mInstallProgress = info.mInstallProgress; 145 isDisabled = info.isDisabled; 146 } 147 148 /** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */ 149 public ShortcutInfo(AppInfo info) { 150 super(info); 151 title = Utilities.trim(info.title); 152 intent = new Intent(info.intent); 153 isDisabled = info.isDisabled; 154 } 155 156 /** 157 * Creates a {@link ShortcutInfo} from a {@link ShortcutInfoCompat}. 158 */ 159 @TargetApi(Build.VERSION_CODES.N) 160 public ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) { 161 user = shortcutInfo.getUserHandle(); 162 itemType = LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; 163 updateFromDeepShortcutInfo(shortcutInfo, context); 164 } 165 166 @Override 167 public void onAddToDatabase(ContentWriter writer) { 168 super.onAddToDatabase(writer); 169 writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title) 170 .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent()) 171 .put(LauncherSettings.Favorites.RESTORED, status); 172 173 if (!usingLowResIcon) { 174 writer.putIcon(iconBitmap, user); 175 } 176 if (iconResource != null) { 177 writer.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, iconResource.packageName) 178 .put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE, 179 iconResource.resourceName); 180 } 181 } 182 183 @Override 184 public Intent getIntent() { 185 return intent; 186 } 187 188 public boolean hasStatusFlag(int flag) { 189 return (status & flag) != 0; 190 } 191 192 193 public final boolean isPromise() { 194 return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON); 195 } 196 197 public boolean hasPromiseIconUi() { 198 return isPromise() && !hasStatusFlag(FLAG_SUPPORTS_WEB_UI); 199 } 200 201 public int getInstallProgress() { 202 return mInstallProgress; 203 } 204 205 public void setInstallProgress(int progress) { 206 mInstallProgress = progress; 207 status |= FLAG_INSTALL_SESSION_ACTIVE; 208 } 209 210 public void updateFromDeepShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) { 211 // {@link ShortcutInfoCompat#getActivity} can change during an update. Recreate the intent 212 intent = shortcutInfo.makeIntent(); 213 title = shortcutInfo.getShortLabel(); 214 215 CharSequence label = shortcutInfo.getLongLabel(); 216 if (TextUtils.isEmpty(label)) { 217 label = shortcutInfo.getShortLabel(); 218 } 219 contentDescription = UserManagerCompat.getInstance(context) 220 .getBadgedLabelForUser(label, user); 221 if (shortcutInfo.isEnabled()) { 222 isDisabled &= ~FLAG_DISABLED_BY_PUBLISHER; 223 } else { 224 isDisabled |= FLAG_DISABLED_BY_PUBLISHER; 225 } 226 disabledMessage = shortcutInfo.getDisabledMessage(); 227 } 228 229 /** Returns the ShortcutInfo id associated with the deep shortcut. */ 230 public String getDeepShortcutId() { 231 return itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT ? 232 getIntent().getStringExtra(ShortcutInfoCompat.EXTRA_SHORTCUT_ID) : null; 233 } 234 235 @Override 236 public boolean isDisabled() { 237 return isDisabled != 0; 238 } 239 240 @Override 241 public ComponentName getTargetComponent() { 242 ComponentName cn = super.getTargetComponent(); 243 if (cn == null && (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT 244 || hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) { 245 // Legacy shortcuts and promise icons with web UI may not have a componentName but just 246 // a packageName. In that case create a dummy componentName instead of adding additional 247 // check everywhere. 248 String pkg = intent.getPackage(); 249 return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME); 250 } 251 return cn; 252 } 253} 254