• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 android.appwidget;
18 
19 import static android.appwidget.flags.Flags.FLAG_GENERATED_PREVIEWS;
20 import static android.appwidget.flags.Flags.generatedPreviews;
21 
22 import android.annotation.FlaggedApi;
23 import android.annotation.IdRes;
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.SuppressLint;
28 import android.app.PendingIntent;
29 import android.compat.annotation.UnsupportedAppUsage;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.pm.ActivityInfo;
33 import android.content.pm.PackageManager;
34 import android.content.res.ResourceId;
35 import android.content.res.Resources;
36 import android.graphics.drawable.Drawable;
37 import android.os.Bundle;
38 import android.os.Parcel;
39 import android.os.Parcelable;
40 import android.os.UserHandle;
41 import android.util.DisplayMetrics;
42 import android.util.TypedValue;
43 
44 import java.lang.annotation.Retention;
45 import java.lang.annotation.RetentionPolicy;
46 
47 /**
48  * Describes the meta data for an installed AppWidget provider.  The fields in this class
49  * correspond to the fields in the <code>&lt;appwidget-provider&gt;</code> xml tag.
50  */
51 public class AppWidgetProviderInfo implements Parcelable {
52 
53     /**
54      * Widget is not resizable.
55      */
56     public static final int RESIZE_NONE             = 0;
57     /**
58      * Widget is resizable in the horizontal axis only.
59      */
60     public static final int RESIZE_HORIZONTAL       = 1;
61     /**
62      * Widget is resizable in the vertical axis only.
63      */
64     public static final int RESIZE_VERTICAL         = 2;
65     /**
66      * Widget is resizable in both the horizontal and vertical axes.
67      */
68     public static final int RESIZE_BOTH = RESIZE_HORIZONTAL | RESIZE_VERTICAL;
69 
70     /** @hide */
71     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
72             RESIZE_HORIZONTAL,
73             RESIZE_VERTICAL,
74     })
75     @Retention(RetentionPolicy.SOURCE)
76     public @interface ResizeModeFlags {}
77 
78     /** {@hide} */
79     public static final int WIDGET_CATEGORY_UNKNOWN = -1;
80 
81     /**
82      * Indicates that the widget can be displayed on the home screen. This is the default value.
83      */
84     public static final int WIDGET_CATEGORY_HOME_SCREEN = 1;
85 
86     /**
87      * Indicates that the widget can be displayed on the keyguard.
88      */
89     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
90 
91     /**
92      * Indicates that the widget can be displayed within a space reserved for the search box.
93      */
94     public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
95 
96     /**
97      * Indicates that the widget should never be shown on the keyguard.
98      *
99      * <p>Some keyguard style features may decide that {@link #WIDGET_CATEGORY_KEYGUARD} isn't
100      * required to be added by an app to show on the feature when chosen by a user.
101      * This category allows for a stronger statement about placement of the widget that, even in the
102      * above case, this widget should not be offered on the keyguard.
103      *
104      * <p>Setting this category doesn't change the behavior of AppWidgetManager queries, it is the
105      * responsibility of the widget surface to respect this value.
106      */
107     @FlaggedApi(android.appwidget.flags.Flags.FLAG_NOT_KEYGUARD_CATEGORY)
108     public static final int WIDGET_CATEGORY_NOT_KEYGUARD = 8;
109 
110     /** @hide */
111     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
112             WIDGET_CATEGORY_HOME_SCREEN,
113             WIDGET_CATEGORY_KEYGUARD,
114             WIDGET_CATEGORY_SEARCHBOX,
115             WIDGET_CATEGORY_NOT_KEYGUARD,
116     })
117     @Retention(RetentionPolicy.SOURCE)
118     public @interface CategoryFlags {}
119 
120     /**
121      * The widget can be reconfigured anytime after it is bound by starting the
122      * {@link #configure} activity.
123      *
124      * @see #widgetFeatures
125      */
126     public static final int WIDGET_FEATURE_RECONFIGURABLE = 1;
127 
128     /**
129      * The widget is added directly by the app, and the host may hide this widget when providing
130      * the user with the list of available widgets to choose from.
131      *
132      * @see AppWidgetManager#requestPinAppWidget(ComponentName, Bundle, PendingIntent)
133      * @see #widgetFeatures
134      */
135     public static final int WIDGET_FEATURE_HIDE_FROM_PICKER = 2;
136 
137     /**
138      * The widget provides a default configuration. The host may choose not to launch the provided
139      * configuration activity.
140      *
141      * @see #widgetFeatures
142      */
143     public static final int WIDGET_FEATURE_CONFIGURATION_OPTIONAL = 4;
144 
145     /** @hide */
146     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
147             WIDGET_FEATURE_RECONFIGURABLE,
148             WIDGET_FEATURE_HIDE_FROM_PICKER,
149             WIDGET_FEATURE_CONFIGURATION_OPTIONAL
150     })
151     @Retention(RetentionPolicy.SOURCE)
152     public @interface FeatureFlags {}
153 
154     /**
155      * Identity of this AppWidget component.  This component should be a {@link
156      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
157      * {@link android.appwidget as described in the AppWidget package documentation}.
158      *
159      * <p>This field corresponds to the <code>android:name</code> attribute in
160      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
161      */
162     public ComponentName provider;
163 
164     /**
165      * The default width of the widget when added to a host, in px. The widget will get
166      * at least this width, and will often be given more, depending on the host.
167      *
168      * <p>This field corresponds to the <code>android:minWidth</code> attribute in
169      * the AppWidget meta-data file.
170      */
171     public int minWidth;
172 
173     /**
174      * The default height of the widget when added to a host, in px. The widget will get
175      * at least this height, and will often be given more, depending on the host.
176      *
177      * <p>This field corresponds to the <code>android:minHeight</code> attribute in
178      * the AppWidget meta-data file.
179      */
180     public int minHeight;
181 
182     /**
183      * Minimum width (in px) which the widget can be resized to. This field has no effect if it
184      * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
185      *
186      * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in
187      * the AppWidget meta-data file.
188      */
189     public int minResizeWidth;
190 
191     /**
192      * Minimum height (in px) which the widget can be resized to. This field has no effect if it
193      * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
194      *
195      * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in
196      * the AppWidget meta-data file.
197      */
198     public int minResizeHeight;
199 
200     /**
201      * Maximum width (in px) which the widget can be resized to. This field has no effect if it is
202      * smaller than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
203      *
204      * <p>This field corresponds to the <code>android:maxResizeWidth</code> attribute in the
205      * AppWidget meta-data file.
206      */
207     @SuppressLint("MutableBareField")
208     public int maxResizeWidth;
209 
210     /**
211      * Maximum height (in px) which the widget can be resized to. This field has no effect if it is
212      * smaller than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
213      *
214      * <p>This field corresponds to the <code>android:maxResizeHeight</code> attribute in the
215      * AppWidget meta-data file.
216      */
217     @SuppressLint("MutableBareField")
218     public int maxResizeHeight;
219 
220     /**
221      * The default width of a widget when added to a host, in units of launcher grid cells.
222      *
223      * <p>This field corresponds to the <code>android:targetCellWidth</code> attribute in the
224      * AppWidget meta-data file.
225      */
226     @SuppressLint("MutableBareField")
227     public int targetCellWidth;
228 
229     /**
230      * The default height of a widget when added to a host, in units of launcher grid cells.
231      *
232      * <p>This field corresponds to the <code>android:targetCellHeight</code> attribute in the
233      * AppWidget meta-data file.
234      */
235     @SuppressLint("MutableBareField")
236     public int targetCellHeight;
237 
238     /**
239      * How often, in milliseconds, that this AppWidget wants to be updated.
240      * The AppWidget manager may place a limit on how often a AppWidget is updated.
241      *
242      * <p>This field corresponds to the <code>android:updatePeriodMillis</code> attribute in
243      * the AppWidget meta-data file.
244      *
245      * <p class="note"><b>Note:</b> Updates requested with <code>updatePeriodMillis</code>
246      * will not be delivered more than once every 30 minutes.</p>
247      */
248     public int updatePeriodMillis;
249 
250     /**
251      * The resource id of the initial layout for this AppWidget.  This should be
252      * displayed until the RemoteViews for the AppWidget is available.
253      *
254      * <p>This field corresponds to the <code>android:initialLayout</code> attribute in
255      * the AppWidget meta-data file.
256      */
257     public int initialLayout;
258 
259     /**
260      * The resource id of the initial layout for this AppWidget when it is displayed on keyguard.
261      * This parameter only needs to be provided if the widget can be displayed on the keyguard,
262      * see {@link #widgetCategory}.
263      *
264      * <p>This field corresponds to the <code>android:initialKeyguardLayout</code> attribute in
265      * the AppWidget meta-data file.
266      */
267     public int initialKeyguardLayout;
268 
269     /**
270      * The activity to launch that will configure the AppWidget.
271      *
272      * <p>This class name of field corresponds to the <code>android:configure</code> attribute in
273      * the AppWidget meta-data file.  The package name always corresponds to the package containing
274      * the AppWidget provider.
275      */
276     public ComponentName configure;
277 
278     /**
279      * The label to display to the user in the AppWidget picker.
280      *
281      * @deprecated Use {@link #loadLabel(android.content.pm.PackageManager)}.
282      */
283     @Deprecated
284     public String label;
285 
286     /**
287      * The icon to display for this AppWidget in the AppWidget picker. If not supplied in the
288      * xml, the application icon will be used.
289      *
290      * <p>This field corresponds to the <code>android:icon</code> attribute in
291      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
292      */
293     public int icon;
294 
295     /**
296      * The view id of the AppWidget subview which should be auto-advanced by the widget's host.
297      *
298      * <p>This field corresponds to the <code>android:autoAdvanceViewId</code> attribute in
299      * the AppWidget meta-data file.
300      */
301     public int autoAdvanceViewId;
302 
303     /**
304      * A preview of what the AppWidget will look like after it's configured.
305      * If not supplied, the AppWidget's icon will be used.
306      *
307      * <p>This field corresponds to the <code>android:previewImage</code> attribute in the AppWidget
308      * meta-data file.
309      */
310     public int previewImage;
311 
312     /**
313      * The layout resource id of a preview of what the AppWidget will look like after it's
314      * configured.
315      *
316      * <p>Unlike previewImage, previewLayout can better showcase AppWidget in different locales,
317      * system themes, display sizes & density etc.
318      *
319      * <p>If supplied, this will take precedence over the previewImage on supported widget hosts.
320      * Otherwise, previewImage will be used.
321      *
322      * <p>This field corresponds to the <code>android:previewLayout</code> attribute in the
323      * AppWidget meta-data file.
324      */
325     @SuppressLint("MutableBareField")
326     @IdRes
327     public int previewLayout;
328 
329     /**
330      * The rules by which a widget can be resized. See {@link #RESIZE_NONE},
331      * {@link #RESIZE_NONE}, {@link #RESIZE_HORIZONTAL},
332      * {@link #RESIZE_VERTICAL}, {@link #RESIZE_BOTH}.
333      *
334      * <p>This field corresponds to the <code>android:resizeMode</code> attribute in
335      * the AppWidget meta-data file.
336      */
337     @ResizeModeFlags
338     public int resizeMode;
339 
340     /**
341      * Determines whether this widget can be displayed on the home screen, the keyguard, or both.
342      * A widget which is displayed on both needs to ensure that it follows the design guidelines
343      * for both widget classes. This can be achieved by querying the AppWidget options in its
344      * widget provider's update method.
345      *
346      * <p>This field corresponds to the <code>widgetCategory</code> attribute in
347      * the AppWidget meta-data file.
348      */
349     @CategoryFlags
350     public int widgetCategory;
351 
352     /**
353      * Resource id for the description of the AppWidget.
354      *
355      * <p>This field corresponds to the <code>android:description</code> attribute in the AppWidget
356      * meta-data file.
357      */
358     @SuppressLint("MutableBareField")
359     @IdRes
360     public int descriptionRes;
361 
362     /**
363      * Flags indicating various features supported by the widget. These are hints to the widget
364      * host, and do not actually change the behavior of the widget.
365      *
366      * @see #WIDGET_FEATURE_RECONFIGURABLE
367      * @see #WIDGET_FEATURE_HIDE_FROM_PICKER
368      * @see #WIDGET_FEATURE_CONFIGURATION_OPTIONAL
369      */
370     @FeatureFlags
371     public int widgetFeatures;
372 
373     /** @hide */
374     @UnsupportedAppUsage
375     public ActivityInfo providerInfo;
376 
377     /** @hide */
378     public boolean isExtendedFromAppWidgetProvider;
379 
380     /**
381      * Flags indicating the widget categories for which generated previews are available.
382      * These correspond to the previews set by this provider with
383      * {@link AppWidgetManager#setWidgetPreview}.
384      *
385      * @see #WIDGET_CATEGORY_HOME_SCREEN
386      * @see #WIDGET_CATEGORY_KEYGUARD
387      * @see #WIDGET_CATEGORY_SEARCHBOX
388      * @see AppWidgetManager#getWidgetPreview
389      */
390     @FlaggedApi(FLAG_GENERATED_PREVIEWS)
391     @SuppressLint("MutableBareField")
392     public int generatedPreviewCategories;
393 
AppWidgetProviderInfo()394     public AppWidgetProviderInfo() {
395 
396     }
397 
398     /**
399      * Unflatten the AppWidgetProviderInfo from a parcel.
400      */
401     @SuppressWarnings("deprecation")
AppWidgetProviderInfo(Parcel in)402     public AppWidgetProviderInfo(Parcel in) {
403         this.provider = in.readTypedObject(ComponentName.CREATOR);
404         this.minWidth = in.readInt();
405         this.minHeight = in.readInt();
406         this.minResizeWidth = in.readInt();
407         this.minResizeHeight = in.readInt();
408         this.maxResizeWidth = in.readInt();
409         this.maxResizeHeight = in.readInt();
410         this.targetCellWidth = in.readInt();
411         this.targetCellHeight = in.readInt();
412         this.updatePeriodMillis = in.readInt();
413         this.initialLayout = in.readInt();
414         this.initialKeyguardLayout = in.readInt();
415         this.configure = in.readTypedObject(ComponentName.CREATOR);
416         this.label = in.readString();
417         this.icon = in.readInt();
418         this.previewImage = in.readInt();
419         this.previewLayout = in.readInt();
420         this.autoAdvanceViewId = in.readInt();
421         this.resizeMode = in.readInt();
422         this.widgetCategory = in.readInt();
423         this.providerInfo = in.readTypedObject(ActivityInfo.CREATOR);
424         this.widgetFeatures = in.readInt();
425         this.descriptionRes = in.readInt();
426         this.isExtendedFromAppWidgetProvider = in.readBoolean();
427         if (generatedPreviews()) {
428             generatedPreviewCategories = in.readInt();
429         }
430     }
431 
432     /**
433      * Loads the localized label to display to the user in the AppWidget picker.
434      *
435      * @param packageManager Package manager instance for loading resources.
436      * @return The label for the current locale.
437      */
loadLabel(PackageManager packageManager)438     public final String loadLabel(PackageManager packageManager) {
439         CharSequence label = providerInfo.loadLabel(packageManager);
440         if (label != null) {
441             return label.toString().trim();
442         }
443         return null;
444     }
445 
446     /**
447      * Loads the icon to display for this AppWidget in the AppWidget picker. If not
448      * supplied in the xml, the application icon will be used. A client can optionally
449      * provide a desired density such as {@link android.util.DisplayMetrics#DENSITY_LOW}
450      * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is
451      * provided, the density of the current display will be used.
452      * <p>
453      * The loaded icon corresponds to the <code>android:icon</code> attribute in
454      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
455      * </p>
456      *
457      * @param context Context for accessing resources.
458      * @param density The optional desired density as per
459      *         {@link android.util.DisplayMetrics#densityDpi}.
460      * @return The provider icon.
461      */
loadIcon(@onNull Context context, int density)462     public final Drawable loadIcon(@NonNull Context context, int density) {
463         return loadDrawable(context, density, providerInfo.getIconResource(), true);
464     }
465 
466     /**
467      * Loads a preview of what the AppWidget will look like after it's configured.
468      * A client can optionally provide a desired density such as
469      * {@link android.util.DisplayMetrics#DENSITY_LOW}
470      * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is
471      * provided, the density of the current display will be used.
472      * <p>
473      * The loaded image corresponds to the <code>android:previewImage</code> attribute
474      * in the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
475      * </p>
476      *
477      * @param context Context for accessing resources.
478      * @param density The optional desired density as per
479      *         {@link android.util.DisplayMetrics#densityDpi}.
480      * @return The widget preview image or null if preview image is not available.
481      */
loadPreviewImage(@onNull Context context, int density)482     public final Drawable loadPreviewImage(@NonNull Context context, int density) {
483         return loadDrawable(context, density, previewImage, false);
484     }
485 
486     /**
487      * Loads localized description for the app widget.
488      *
489      * <p>Description is intended to be displayed in the UI of the widget picker.
490      *
491      * @param context Context for accessing resources.
492      *
493      * @return CharSequence for app widget description for the current locale.
494      */
495     @Nullable
loadDescription(@onNull Context context)496     public final CharSequence loadDescription(@NonNull Context context) {
497         if (ResourceId.isValid(descriptionRes)) {
498             CharSequence description =
499                     context.getPackageManager().getText(
500                             providerInfo.packageName,
501                             descriptionRes,
502                             providerInfo.applicationInfo);
503             if (description != null) {
504                 return description.toString().trim();
505             }
506         }
507         return null;
508     }
509 
510     /**
511      * Gets the user profile in which the provider resides.
512      *
513      * @return The hosting user profile.
514      */
getProfile()515     public final UserHandle getProfile() {
516         return new UserHandle(UserHandle.getUserId(providerInfo.applicationInfo.uid));
517     }
518 
519     /**
520      * Returns the broadcast receiver that is providing this widget.
521      */
522     @NonNull
getActivityInfo()523     public ActivityInfo getActivityInfo() {
524         return providerInfo;
525     }
526 
527     @Override
528     @SuppressWarnings("deprecation")
writeToParcel(Parcel out, int flags)529     public void writeToParcel(Parcel out, int flags) {
530         out.writeTypedObject(this.provider, flags);
531         out.writeInt(this.minWidth);
532         out.writeInt(this.minHeight);
533         out.writeInt(this.minResizeWidth);
534         out.writeInt(this.minResizeHeight);
535         out.writeInt(this.maxResizeWidth);
536         out.writeInt(this.maxResizeHeight);
537         out.writeInt(this.targetCellWidth);
538         out.writeInt(this.targetCellHeight);
539         out.writeInt(this.updatePeriodMillis);
540         out.writeInt(this.initialLayout);
541         out.writeInt(this.initialKeyguardLayout);
542         out.writeTypedObject(this.configure, flags);
543         out.writeString(this.label);
544         out.writeInt(this.icon);
545         out.writeInt(this.previewImage);
546         out.writeInt(this.previewLayout);
547         out.writeInt(this.autoAdvanceViewId);
548         out.writeInt(this.resizeMode);
549         out.writeInt(this.widgetCategory);
550         out.writeTypedObject(this.providerInfo, flags);
551         out.writeInt(this.widgetFeatures);
552         out.writeInt(this.descriptionRes);
553         out.writeBoolean(this.isExtendedFromAppWidgetProvider);
554         if (generatedPreviews()) {
555             out.writeInt(this.generatedPreviewCategories);
556         }
557     }
558 
559     @Override
560     @SuppressWarnings("deprecation")
clone()561     public AppWidgetProviderInfo clone() {
562         AppWidgetProviderInfo that = new AppWidgetProviderInfo();
563         that.provider = this.provider == null ? null : this.provider.clone();
564         that.minWidth = this.minWidth;
565         that.minHeight = this.minHeight;
566         that.minResizeWidth = this.minResizeWidth;
567         that.minResizeHeight = this.minResizeHeight;
568         that.maxResizeWidth = this.maxResizeWidth;
569         that.maxResizeHeight = this.maxResizeHeight;
570         that.targetCellWidth = this.targetCellWidth;
571         that.targetCellHeight = this.targetCellHeight;
572         that.updatePeriodMillis = this.updatePeriodMillis;
573         that.initialLayout = this.initialLayout;
574         that.initialKeyguardLayout = this.initialKeyguardLayout;
575         that.configure = this.configure == null ? null : this.configure.clone();
576         that.label = this.label;
577         that.icon = this.icon;
578         that.previewImage = this.previewImage;
579         that.previewLayout = this.previewLayout;
580         that.autoAdvanceViewId = this.autoAdvanceViewId;
581         that.resizeMode = this.resizeMode;
582         that.widgetCategory = this.widgetCategory;
583         that.providerInfo = this.providerInfo;
584         that.widgetFeatures = this.widgetFeatures;
585         that.descriptionRes = this.descriptionRes;
586         that.isExtendedFromAppWidgetProvider = this.isExtendedFromAppWidgetProvider;
587         if (generatedPreviews()) {
588             that.generatedPreviewCategories = this.generatedPreviewCategories;
589         }
590         return that;
591     }
592 
describeContents()593     public int describeContents() {
594         return 0;
595     }
596 
loadDrawable(Context context, int density, int resourceId, boolean loadDefaultIcon)597     private Drawable loadDrawable(Context context, int density, int resourceId,
598             boolean loadDefaultIcon) {
599         try {
600             Resources resources = context.getPackageManager().getResourcesForApplication(
601                     providerInfo.applicationInfo);
602             if (ResourceId.isValid(resourceId)) {
603                 if (density < 0) {
604                     density = 0;
605                 }
606                 return resources.getDrawableForDensity(resourceId, density, null);
607             }
608         } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
609             /* ignore */
610         }
611         return loadDefaultIcon ? providerInfo.loadIcon(context.getPackageManager()) : null;
612     }
613 
614     /**
615      * @hide
616      */
updateDimensions(DisplayMetrics displayMetrics)617     public void updateDimensions(DisplayMetrics displayMetrics) {
618         // Converting complex to dp.
619         minWidth = TypedValue.complexToDimensionPixelSize(minWidth, displayMetrics);
620         minHeight = TypedValue.complexToDimensionPixelSize(minHeight, displayMetrics);
621         minResizeWidth = TypedValue.complexToDimensionPixelSize(minResizeWidth, displayMetrics);
622         minResizeHeight = TypedValue.complexToDimensionPixelSize(minResizeHeight, displayMetrics);
623         maxResizeWidth = TypedValue.complexToDimensionPixelSize(maxResizeWidth, displayMetrics);
624         maxResizeHeight = TypedValue.complexToDimensionPixelSize(maxResizeHeight, displayMetrics);
625     }
626 
627     /**
628      * Parcelable.Creator that instantiates AppWidgetProviderInfo objects
629      */
630     public static final @android.annotation.NonNull Parcelable.Creator<AppWidgetProviderInfo> CREATOR
631             = new Parcelable.Creator<AppWidgetProviderInfo>()
632     {
633         public AppWidgetProviderInfo createFromParcel(Parcel parcel)
634         {
635             return new AppWidgetProviderInfo(parcel);
636         }
637 
638         public AppWidgetProviderInfo[] newArray(int size)
639         {
640             return new AppWidgetProviderInfo[size];
641         }
642     };
643 
toString()644     public String toString() {
645         return "AppWidgetProviderInfo(" + getProfile() + '/' + provider + ')';
646     }
647 }
648