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.Context;
21 import android.content.Intent;
22 import android.os.Build;
23 import android.text.TextUtils;
24 
25 import com.android.launcher3.LauncherSettings.Favorites;
26 import com.android.launcher3.compat.UserManagerCompat;
27 import com.android.launcher3.shortcuts.ShortcutInfoCompat;
28 import com.android.launcher3.util.ContentWriter;
29 
30 /**
31  * Represents a launchable icon on the workspaces and in folders.
32  */
33 public class ShortcutInfo extends ItemInfoWithIcon {
34 
35     public static final int DEFAULT = 0;
36 
37     /**
38      * The shortcut was restored from a backup and it not ready to be used. This is automatically
39      * set during backup/restore
40      */
41     public static final int FLAG_RESTORED_ICON = 1;
42 
43     /**
44      * The icon was added as an auto-install app, and is not ready to be used. This flag can't
45      * be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout
46      * parsing.
47      */
48     public static final int FLAG_AUTOINTALL_ICON = 2; //0B10;
49 
50     /**
51      * The icon is being installed. If {@link #FLAG_RESTORED_ICON} or {@link #FLAG_AUTOINTALL_ICON}
52      * is set, then the icon is either being installed or is in a broken state.
53      */
54     public static final int FLAG_INSTALL_SESSION_ACTIVE = 4; // 0B100;
55 
56     /**
57      * Indicates that the widget restore has started.
58      */
59     public static final int FLAG_RESTORE_STARTED = 8; //0B1000;
60 
61     /**
62      * Indicates if it represents a common type mentioned in {@link CommonAppTypeParser}.
63      * Upto 15 different types supported.
64      */
65     @Deprecated
66     public static final int FLAG_RESTORED_APP_TYPE = 0B0011110000;
67 
68     /**
69      * The intent used to start the application.
70      */
71     public Intent intent;
72 
73     /**
74      * If isShortcut=true and customIcon=false, this contains a reference to the
75      * shortcut icon as an application's resource.
76      */
77     public Intent.ShortcutIconResource iconResource;
78 
79     /**
80      * Indicates that the icon is disabled due to safe mode restrictions.
81      */
82     public static final int FLAG_DISABLED_SAFEMODE = 1 << 0;
83 
84     /**
85      * Indicates that the icon is disabled as the app is not available.
86      */
87     public static final int FLAG_DISABLED_NOT_AVAILABLE = 1 << 1;
88 
89     /**
90      * Indicates that the icon is disabled as the app is suspended
91      */
92     public static final int FLAG_DISABLED_SUSPENDED = 1 << 2;
93 
94     /**
95      * Indicates that the icon is disabled as the user is in quiet mode.
96      */
97     public static final int FLAG_DISABLED_QUIET_USER = 1 << 3;
98 
99     /**
100      * Indicates that the icon is disabled as the publisher has disabled the actual shortcut.
101      */
102     public static final int FLAG_DISABLED_BY_PUBLISHER = 1 << 4;
103 
104     /**
105      * Indicates that the icon is disabled as the user partition is currently locked.
106      */
107     public static final int FLAG_DISABLED_LOCKED_USER = 1 << 5;
108 
109     /**
110      * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when
111      * sd-card is not available).
112      */
113     public int isDisabled = DEFAULT;
114 
115     /**
116      * A message to display when the user tries to start a disabled shortcut.
117      * This is currently only used for deep shortcuts.
118      */
119     CharSequence disabledMessage;
120 
121     public int status;
122 
123     /**
124      * The installation progress [0-100] of the package that this shortcut represents.
125      */
126     private int mInstallProgress;
127 
ShortcutInfo()128     public ShortcutInfo() {
129         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
130     }
131 
ShortcutInfo(ShortcutInfo info)132     public ShortcutInfo(ShortcutInfo info) {
133         super(info);
134         title = info.title;
135         intent = new Intent(info.intent);
136         iconResource = info.iconResource;
137         status = info.status;
138         mInstallProgress = info.mInstallProgress;
139         isDisabled = info.isDisabled;
140     }
141 
142     /** TODO: Remove this.  It's only called by ApplicationInfo.makeShortcut. */
ShortcutInfo(AppInfo info)143     public ShortcutInfo(AppInfo info) {
144         super(info);
145         title = Utilities.trim(info.title);
146         intent = new Intent(info.intent);
147         isDisabled = info.isDisabled;
148     }
149 
150     /**
151      * Creates a {@link ShortcutInfo} from a {@link ShortcutInfoCompat}.
152      */
153     @TargetApi(Build.VERSION_CODES.N)
ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context)154     public ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) {
155         user = shortcutInfo.getUserHandle();
156         itemType = LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
157         updateFromDeepShortcutInfo(shortcutInfo, context);
158     }
159 
160     @Override
onAddToDatabase(ContentWriter writer)161     public void onAddToDatabase(ContentWriter writer) {
162         super.onAddToDatabase(writer);
163         writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title)
164                 .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent())
165                 .put(LauncherSettings.Favorites.RESTORED, status);
166 
167         if (!usingLowResIcon) {
168             writer.putIcon(iconBitmap, user);
169         }
170         if (iconResource != null) {
171             writer.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, iconResource.packageName)
172                     .put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
173                             iconResource.resourceName);
174         }
175     }
176 
177     @Override
getIntent()178     public Intent getIntent() {
179         return intent;
180     }
181 
hasStatusFlag(int flag)182     public boolean hasStatusFlag(int flag) {
183         return (status & flag) != 0;
184     }
185 
186 
isPromise()187     public final boolean isPromise() {
188         return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON);
189     }
190 
getInstallProgress()191     public int getInstallProgress() {
192         return mInstallProgress;
193     }
194 
setInstallProgress(int progress)195     public void setInstallProgress(int progress) {
196         mInstallProgress = progress;
197         status |= FLAG_INSTALL_SESSION_ACTIVE;
198     }
199 
updateFromDeepShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context)200     public void updateFromDeepShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) {
201         // {@link ShortcutInfoCompat#getActivity} can change during an update. Recreate the intent
202         intent = shortcutInfo.makeIntent();
203         title = shortcutInfo.getShortLabel();
204 
205         CharSequence label = shortcutInfo.getLongLabel();
206         if (TextUtils.isEmpty(label)) {
207             label = shortcutInfo.getShortLabel();
208         }
209         contentDescription = UserManagerCompat.getInstance(context)
210                 .getBadgedLabelForUser(label, user);
211         if (shortcutInfo.isEnabled()) {
212             isDisabled &= ~FLAG_DISABLED_BY_PUBLISHER;
213         } else {
214             isDisabled |= FLAG_DISABLED_BY_PUBLISHER;
215         }
216         disabledMessage = shortcutInfo.getDisabledMessage();
217     }
218 
219     /** Returns the ShortcutInfo id associated with the deep shortcut. */
getDeepShortcutId()220     public String getDeepShortcutId() {
221         return itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT ?
222                 getIntent().getStringExtra(ShortcutInfoCompat.EXTRA_SHORTCUT_ID) : null;
223     }
224 
225     @Override
isDisabled()226     public boolean isDisabled() {
227         return isDisabled != 0;
228     }
229 }
230