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