• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.model.data;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 
23 import androidx.annotation.Nullable;
24 
25 import com.android.launcher3.icons.BitmapInfo;
26 import com.android.launcher3.icons.FastBitmapDrawable;
27 import com.android.launcher3.pm.PackageInstallInfo;
28 import com.android.launcher3.util.PackageManagerHelper;
29 
30 /**
31  * Represents an ItemInfo which also holds an icon.
32  */
33 public abstract class ItemInfoWithIcon extends ItemInfo {
34 
35     public static final String TAG = "ItemInfoDebug";
36 
37     /**
38      * The bitmap for the application icon
39      */
40     public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
41 
42     /**
43      * Indicates that the icon is disabled due to safe mode restrictions.
44      */
45     public static final int FLAG_DISABLED_SAFEMODE = 1 << 0;
46 
47     /**
48      * Indicates that the icon is disabled as the app is not available.
49      */
50     public static final int FLAG_DISABLED_NOT_AVAILABLE = 1 << 1;
51 
52     /**
53      * Indicates that the icon is disabled as the app is suspended
54      */
55     public static final int FLAG_DISABLED_SUSPENDED = 1 << 2;
56 
57     /**
58      * Indicates that the icon is disabled as the user is in quiet mode.
59      */
60     public static final int FLAG_DISABLED_QUIET_USER = 1 << 3;
61 
62     /**
63      * Indicates that the icon is disabled as the publisher has disabled the actual shortcut.
64      */
65     public static final int FLAG_DISABLED_BY_PUBLISHER = 1 << 4;
66 
67     /**
68      * Indicates that the icon is disabled as the user partition is currently locked.
69      */
70     public static final int FLAG_DISABLED_LOCKED_USER = 1 << 5;
71 
72     public static final int FLAG_DISABLED_MASK = FLAG_DISABLED_SAFEMODE
73             | FLAG_DISABLED_NOT_AVAILABLE | FLAG_DISABLED_SUSPENDED
74             | FLAG_DISABLED_QUIET_USER | FLAG_DISABLED_BY_PUBLISHER | FLAG_DISABLED_LOCKED_USER;
75 
76     /**
77      * The item points to a system app.
78      */
79     public static final int FLAG_SYSTEM_YES = 1 << 6;
80 
81     /**
82      * The item points to a non system app.
83      */
84     public static final int FLAG_SYSTEM_NO = 1 << 7;
85 
86     public static final int FLAG_SYSTEM_MASK = FLAG_SYSTEM_YES | FLAG_SYSTEM_NO;
87 
88     /**
89      * Flag indicating that the icon is an {@link android.graphics.drawable.AdaptiveIconDrawable}
90      * that can be optimized in various way.
91      */
92     public static final int FLAG_ADAPTIVE_ICON = 1 << 8;
93 
94     /**
95      * Flag indicating that the icon is badged.
96      */
97     public static final int FLAG_ICON_BADGED = 1 << 9;
98 
99     /**
100      * The icon is being installed. If {@link WorkspaceItemInfo#FLAG_RESTORED_ICON} or
101      * {@link WorkspaceItemInfo#FLAG_AUTOINSTALL_ICON} is set, then the icon is either being
102      * installed or is in a broken state.
103      */
104     public static final int FLAG_INSTALL_SESSION_ACTIVE = 1 << 10;
105 
106     /**
107      * This icon is still being downloaded.
108      */
109     public static final int FLAG_INCREMENTAL_DOWNLOAD_ACTIVE = 1 << 11;
110 
111     public static final int FLAG_SHOW_DOWNLOAD_PROGRESS_MASK = FLAG_INSTALL_SESSION_ACTIVE
112             | FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
113 
114     /**
115      * Status associated with the system state of the underlying item. This is calculated every
116      * time a new info is created and not persisted on the disk.
117      */
118     public int runtimeStatusFlags = 0;
119 
120     /**
121      * The download progress of the package that this shortcut represents. For legacy apps, this
122      * will always be the installation progress. For apps that support incremental downloads, this
123      * will only match be the installation progress until the app is installed, then this will the
124      * total download progress.
125      */
126     private int mProgressLevel = 100;
127 
ItemInfoWithIcon()128     protected ItemInfoWithIcon() { }
129 
ItemInfoWithIcon(ItemInfoWithIcon info)130     protected ItemInfoWithIcon(ItemInfoWithIcon info) {
131         super(info);
132         bitmap = info.bitmap;
133         mProgressLevel = info.mProgressLevel;
134         runtimeStatusFlags = info.runtimeStatusFlags;
135         user = info.user;
136     }
137 
138     @Override
isDisabled()139     public boolean isDisabled() {
140         return (runtimeStatusFlags & FLAG_DISABLED_MASK) != 0;
141     }
142 
143     /**
144      * Indicates whether we're using a low res icon
145      */
usingLowResIcon()146     public boolean usingLowResIcon() {
147         return bitmap.isLowRes();
148     }
149 
150     /**
151      * Returns whether the app this shortcut represents is able to be started. For legacy apps,
152      * this returns whether it is fully installed. For apps that support incremental downloads,
153      * this returns whether the app is either fully downloaded or has installed and is downloading
154      * incrementally.
155      */
isAppStartable()156     public boolean isAppStartable() {
157         return ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) == 0)
158                 && (((runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0)
159                     || mProgressLevel == 100);
160     }
161 
162     /**
163      * Returns the download progress for the app this shortcut represents. If this app is not yet
164      * installed or does not support incremental downloads, this will return the installation
165      * progress.
166      */
getProgressLevel()167     public int getProgressLevel() {
168         if ((runtimeStatusFlags & FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
169             return mProgressLevel;
170         }
171         return 100;
172     }
173 
174     /**
175      * Sets the download progress for the app this shortcut represents. If this app is not yet
176      * installed or does not support incremental downloads, this will set
177      * {@code FLAG_INSTALL_SESSION_ACTIVE}. If this app is downloading incrementally, this will
178      * set {@code FLAG_INCREMENTAL_DOWNLOAD_ACTIVE}. Otherwise, this will remove both flags.
179      */
setProgressLevel(PackageInstallInfo installInfo)180     public void setProgressLevel(PackageInstallInfo installInfo) {
181         setProgressLevel(installInfo.progress, installInfo.state);
182     }
183 
184     /**
185      * Sets the download progress for the app this shortcut represents.
186      */
setProgressLevel(int progress, int status)187     public void setProgressLevel(int progress, int status) {
188         if (status == PackageInstallInfo.STATUS_INSTALLING) {
189             mProgressLevel = progress;
190             runtimeStatusFlags = progress < 100
191                     ? runtimeStatusFlags | FLAG_INSTALL_SESSION_ACTIVE
192                     : runtimeStatusFlags & ~FLAG_INSTALL_SESSION_ACTIVE;
193         } else if (status == PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING) {
194             mProgressLevel = progress;
195             runtimeStatusFlags = runtimeStatusFlags & ~FLAG_INSTALL_SESSION_ACTIVE;
196             runtimeStatusFlags = progress < 100
197                     ? runtimeStatusFlags | FLAG_INCREMENTAL_DOWNLOAD_ACTIVE
198                     : runtimeStatusFlags & ~FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
199         } else {
200             mProgressLevel = status == PackageInstallInfo.STATUS_INSTALLED ? 100 : 0;
201             runtimeStatusFlags &= ~FLAG_INSTALL_SESSION_ACTIVE;
202             runtimeStatusFlags &= ~FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
203         }
204     }
205 
206     /** Creates an intent to that launches the app store at this app's page. */
207     @Nullable
208     public Intent getMarketIntent(Context context) {
209         ComponentName componentName = getTargetComponent();
210 
211         return componentName != null
212                 ? new PackageManagerHelper(context).getMarketIntent(componentName.getPackageName())
213                 : null;
214     }
215 
216     /**
217      * @return a copy of this
218      */
219     public abstract ItemInfoWithIcon clone();
220 
221 
222     /**
223      * Returns a FastBitmapDrawable with the icon.
224      */
225     public FastBitmapDrawable newIcon(Context context) {
226         return newIcon(context, false);
227     }
228 
229     /**
230      * Returns a FastBitmapDrawable with the icon and context theme applied
231      */
232     public FastBitmapDrawable newIcon(Context context, boolean applyTheme) {
233         FastBitmapDrawable drawable = applyTheme
234                 ? bitmap.newThemedIcon(context) : bitmap.newIcon(context);
235         drawable.setIsDisabled(isDisabled());
236         return drawable;
237     }
238 }
239