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.annotation.TargetApi; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Build; 24 import android.text.TextUtils; 25 26 import com.android.launcher3.LauncherSettings.Favorites; 27 import com.android.launcher3.compat.UserManagerCompat; 28 import com.android.launcher3.shortcuts.ShortcutInfoCompat; 29 import com.android.launcher3.util.ContentWriter; 30 31 /** 32 * Represents a launchable icon on the workspaces and in folders. 33 */ 34 public 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 * The intent used to start the application. 69 */ 70 public Intent intent; 71 72 /** 73 * If isShortcut=true and customIcon=false, this contains a reference to the 74 * shortcut icon as an application's resource. 75 */ 76 public Intent.ShortcutIconResource iconResource; 77 78 /** 79 * A message to display when the user tries to start a disabled shortcut. 80 * This is currently only used for deep shortcuts. 81 */ 82 public CharSequence disabledMessage; 83 84 public int status; 85 86 /** 87 * The installation progress [0-100] of the package that this shortcut represents. 88 */ 89 private int mInstallProgress; 90 91 public ShortcutInfo() { 92 itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; 93 } 94 95 public ShortcutInfo(ShortcutInfo info) { 96 super(info); 97 title = info.title; 98 intent = new Intent(info.intent); 99 iconResource = info.iconResource; 100 status = info.status; 101 mInstallProgress = info.mInstallProgress; 102 } 103 104 /** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */ 105 public ShortcutInfo(AppInfo info) { 106 super(info); 107 title = Utilities.trim(info.title); 108 intent = new Intent(info.intent); 109 } 110 111 /** 112 * Creates a {@link ShortcutInfo} from a {@link ShortcutInfoCompat}. 113 */ 114 @TargetApi(Build.VERSION_CODES.N) 115 public ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) { 116 user = shortcutInfo.getUserHandle(); 117 itemType = LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; 118 updateFromDeepShortcutInfo(shortcutInfo, context); 119 } 120 121 @Override 122 public void onAddToDatabase(ContentWriter writer) { 123 super.onAddToDatabase(writer); 124 writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title) 125 .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent()) 126 .put(LauncherSettings.Favorites.RESTORED, status); 127 128 if (!usingLowResIcon) { 129 writer.putIcon(iconBitmap, user); 130 } 131 if (iconResource != null) { 132 writer.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, iconResource.packageName) 133 .put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE, 134 iconResource.resourceName); 135 } 136 } 137 138 @Override 139 public Intent getIntent() { 140 return intent; 141 } 142 143 public boolean hasStatusFlag(int flag) { 144 return (status & flag) != 0; 145 } 146 147 148 public final boolean isPromise() { 149 return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON); 150 } 151 152 public boolean hasPromiseIconUi() { 153 return isPromise() && !hasStatusFlag(FLAG_SUPPORTS_WEB_UI); 154 } 155 156 public int getInstallProgress() { 157 return mInstallProgress; 158 } 159 160 public void setInstallProgress(int progress) { 161 mInstallProgress = progress; 162 status |= FLAG_INSTALL_SESSION_ACTIVE; 163 } 164 165 public void updateFromDeepShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) { 166 // {@link ShortcutInfoCompat#getActivity} can change during an update. Recreate the intent 167 intent = shortcutInfo.makeIntent(); 168 title = shortcutInfo.getShortLabel(); 169 170 CharSequence label = shortcutInfo.getLongLabel(); 171 if (TextUtils.isEmpty(label)) { 172 label = shortcutInfo.getShortLabel(); 173 } 174 contentDescription = UserManagerCompat.getInstance(context) 175 .getBadgedLabelForUser(label, user); 176 if (shortcutInfo.isEnabled()) { 177 runtimeStatusFlags &= ~FLAG_DISABLED_BY_PUBLISHER; 178 } else { 179 runtimeStatusFlags |= FLAG_DISABLED_BY_PUBLISHER; 180 } 181 disabledMessage = shortcutInfo.getDisabledMessage(); 182 } 183 184 /** Returns the ShortcutInfo id associated with the deep shortcut. */ 185 public String getDeepShortcutId() { 186 return itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT ? 187 getIntent().getStringExtra(ShortcutInfoCompat.EXTRA_SHORTCUT_ID) : null; 188 } 189 190 @Override 191 public ComponentName getTargetComponent() { 192 ComponentName cn = super.getTargetComponent(); 193 if (cn == null && (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT 194 || hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) { 195 // Legacy shortcuts and promise icons with web UI may not have a componentName but just 196 // a packageName. In that case create a dummy componentName instead of adding additional 197 // check everywhere. 198 String pkg = intent.getPackage(); 199 return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME); 200 } 201 return cn; 202 } 203 } 204