• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
20 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_BOTTOM_WIDGETS_TRAY;
21 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PIN_WIDGETS;
22 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
23 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
24 import static com.android.launcher3.Utilities.ATLEAST_S;
25 
26 import android.appwidget.AppWidgetHostView;
27 import android.content.ComponentName;
28 import android.content.Intent;
29 import android.content.res.Resources;
30 import android.os.Process;
31 
32 import androidx.annotation.Nullable;
33 
34 import com.android.launcher3.Launcher;
35 import com.android.launcher3.LauncherSettings;
36 import com.android.launcher3.logger.LauncherAtom;
37 import com.android.launcher3.util.ContentWriter;
38 import com.android.launcher3.widget.LauncherAppWidgetHostView;
39 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
40 import com.android.launcher3.widget.util.WidgetSizes;
41 
42 /**
43  * Represents a widget (either instantiated or about to be) in the Launcher.
44  */
45 public class LauncherAppWidgetInfo extends ItemInfo {
46 
47     public static final int OPTION_SEARCH_WIDGET = 1;
48 
49 
50     public static final int RESTORE_COMPLETED = 0;
51 
52     /**
53      * This is set during the package backup creation.
54      */
55     public static final int FLAG_ID_NOT_VALID = 1;
56 
57     /**
58      * Indicates that the provider is not available yet.
59      */
60     public static final int FLAG_PROVIDER_NOT_READY = 2;
61 
62     /**
63      * Indicates that the widget UI is not yet ready, and user needs to set it up again.
64      */
65     public static final int FLAG_UI_NOT_READY = 4;
66 
67     /**
68      * Indicates that the widget restore has started.
69      */
70     public static final int FLAG_RESTORE_STARTED = 8;
71 
72     /**
73      * Indicates that the widget has been allocated an Id. The id is still not valid, as it has
74      * not been bound yet.
75      */
76     public static final int FLAG_ID_ALLOCATED = 16;
77 
78     /**
79      * Indicates that the widget does not need to show config activity, even if it has a
80      * configuration screen. It can also optionally have some extras which are sent during bind.
81      */
82     public static final int FLAG_DIRECT_CONFIG = 32;
83 
84     /**
85      * Indicates that the widget hasn't been instantiated yet.
86      */
87     public static final int NO_ID = -1;
88 
89     /**
90      * Indicates that this is a locally defined widget and hence has no system allocated id.
91      */
92     public static final int CUSTOM_WIDGET_ID = -100;
93 
94     /**
95      * Flags for recording all the features that a widget has enabled.
96      * @see widgetFeatures
97      */
98     public static final int FEATURE_RECONFIGURABLE = 1;
99     public static final int FEATURE_OPTIONAL_CONFIGURATION = 1 << 1;
100     public static final int FEATURE_PREVIEW_LAYOUT = 1 << 2;
101     public static final int FEATURE_TARGET_CELL_SIZE = 1 << 3;
102     public static final int FEATURE_MIN_SIZE = 1 << 4;
103     public static final int FEATURE_MAX_SIZE = 1 << 5;
104     public static final int FEATURE_ROUNDED_CORNERS = 1 << 6;
105 
106     /**
107      * Identifier for this widget when talking with
108      * {@link android.appwidget.AppWidgetManager} for updates.
109      */
110     public int appWidgetId = NO_ID;
111 
112     public ComponentName providerName;
113 
114     /**
115      * Indicates the restore status of the widget.
116      */
117     public int restoreStatus;
118 
119     /**
120      * Indicates the installation progress of the widget provider
121      */
122     public int installProgress = -1;
123 
124     /**
125      * Optional extras sent during widget bind. See {@link #FLAG_DIRECT_CONFIG}.
126      */
127     public Intent bindOptions;
128 
129     /**
130      * Widget options
131      */
132     public int options;
133 
134     /**
135      * Nonnull for pending widgets. We use this to get the icon and title for the widget.
136      */
137     public PackageItemInfo pendingItemInfo;
138 
139     /**
140      * Contains a binary representation indicating which widget features are enabled. This value is
141      * -1 if widget features could not be identified.
142      */
143     private int widgetFeatures;
144 
145     private boolean mHasNotifiedInitialWidgetSizeChanged;
146 
147     /**
148      * The container from which this widget was added (e.g. widgets tray, pin widget, search)
149      */
150     public int sourceContainer = LauncherSettings.Favorites.CONTAINER_UNKNOWN;
151 
LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName)152     public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
153         this.appWidgetId = appWidgetId;
154         this.providerName = providerName;
155 
156         if (isCustomWidget()) {
157             itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
158         } else {
159             itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
160         }
161 
162         // Since the widget isn't instantiated yet, we don't know these values. Set them to -1
163         // to indicate that they should be calculated based on the layout and minWidth/minHeight
164         spanX = -1;
165         spanY = -1;
166         widgetFeatures = -1;
167         // We only support app widgets on current user.
168         user = Process.myUserHandle();
169         restoreStatus = RESTORE_COMPLETED;
170     }
171 
LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName, LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView)172     public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName,
173             LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
174         this(appWidgetId, providerName);
175         widgetFeatures = computeWidgetFeatures(providerInfo, hostView);
176     }
177 
178     /** Used for testing **/
LauncherAppWidgetInfo()179     public LauncherAppWidgetInfo() {
180         itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
181     }
182 
isCustomWidget()183     public boolean isCustomWidget() {
184         return appWidgetId <= CUSTOM_WIDGET_ID;
185     }
186 
187     @Nullable
188     @Override
getTargetComponent()189     public ComponentName getTargetComponent() {
190         return providerName;
191     }
192 
193     @Override
onAddToDatabase(ContentWriter writer)194     public void onAddToDatabase(ContentWriter writer) {
195         super.onAddToDatabase(writer);
196         writer.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId)
197                 .put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString())
198                 .put(LauncherSettings.Favorites.RESTORED, restoreStatus)
199                 .put(LauncherSettings.Favorites.OPTIONS, options)
200                 .put(LauncherSettings.Favorites.INTENT, bindOptions)
201                 .put(LauncherSettings.Favorites.APPWIDGET_SOURCE, sourceContainer);
202     }
203 
204     /**
205      * When we bind the widget, we should notify the widget that the size has changed if we have not
206      * done so already (only really for default workspace widgets).
207      */
onBindAppWidget(Launcher launcher, AppWidgetHostView hostView)208     public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) {
209         if (!mHasNotifiedInitialWidgetSizeChanged) {
210             WidgetSizes.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
211             mHasNotifiedInitialWidgetSizeChanged = true;
212         }
213     }
214 
215     @Override
dumpProperties()216     protected String dumpProperties() {
217         return super.dumpProperties()
218                 + " providerName=" + providerName
219                 + " appWidgetId=" + appWidgetId;
220     }
221 
isWidgetIdAllocated()222     public final boolean isWidgetIdAllocated() {
223         return (restoreStatus & FLAG_ID_NOT_VALID) == 0
224                 || (restoreStatus & FLAG_ID_ALLOCATED) == FLAG_ID_ALLOCATED;
225     }
226 
hasRestoreFlag(int flag)227     public final boolean hasRestoreFlag(int flag) {
228         return (restoreStatus & flag) == flag;
229     }
230 
231     /**
232      * returns if widget options include an option or not
233      * @param option
234      * @return
235      */
hasOptionFlag(int option)236     public final boolean hasOptionFlag(int option) {
237         return (options & option) != 0;
238     }
239 
240     @SuppressWarnings("NewApi")
computeWidgetFeatures( LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView)241     private static int computeWidgetFeatures(
242             LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
243         int widgetFeatures = 0;
244         if (providerInfo.isReconfigurable()) {
245             widgetFeatures |= FEATURE_RECONFIGURABLE;
246         }
247         if (providerInfo.isConfigurationOptional()) {
248             widgetFeatures |= FEATURE_OPTIONAL_CONFIGURATION;
249         }
250         if (ATLEAST_S && providerInfo.previewLayout != Resources.ID_NULL) {
251             widgetFeatures |= FEATURE_PREVIEW_LAYOUT;
252         }
253         if (ATLEAST_S && providerInfo.targetCellWidth > 0 || providerInfo.targetCellHeight > 0) {
254             widgetFeatures |= FEATURE_TARGET_CELL_SIZE;
255         }
256         if (providerInfo.minResizeWidth > 0 || providerInfo.minResizeHeight > 0) {
257             widgetFeatures |= FEATURE_MIN_SIZE;
258         }
259         if (ATLEAST_S && providerInfo.maxResizeWidth > 0 || providerInfo.maxResizeHeight > 0) {
260             widgetFeatures |= FEATURE_MAX_SIZE;
261         }
262         if (hostView instanceof LauncherAppWidgetHostView &&
263                 ((LauncherAppWidgetHostView) hostView).hasEnforcedCornerRadius()) {
264             widgetFeatures |= FEATURE_ROUNDED_CORNERS;
265         }
266         return widgetFeatures;
267     }
268 
getAttribute(int container)269     public static LauncherAtom.Attribute getAttribute(int container) {
270         switch (container) {
271             case CONTAINER_WIDGETS_TRAY:
272                 return LauncherAtom.Attribute.WIDGETS;
273             case CONTAINER_BOTTOM_WIDGETS_TRAY:
274                 return LauncherAtom.Attribute.WIDGETS_BOTTOM_TRAY;
275             case CONTAINER_PIN_WIDGETS:
276                 return LauncherAtom.Attribute.PINITEM;
277             case CONTAINER_WIDGETS_PREDICTION:
278                 return LauncherAtom.Attribute.WIDGETS_TRAY_PREDICTION;
279             case CONTAINER_ALL_APPS:
280                 return LauncherAtom.Attribute.ALL_APPS_SEARCH_RESULT_WIDGETS;
281             default:
282                 return LauncherAtom.Attribute.UNKNOWN;
283         }
284     }
285 
286     @Override
buildProto(FolderInfo folderInfo)287     public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
288         LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
289         return info.toBuilder()
290                 .setWidget(info.getWidget().toBuilder().setWidgetFeatures(widgetFeatures))
291                 .setAttribute(getAttribute(sourceContainer))
292                 .build();
293     }
294 }
295