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 android.annotation.BroadcastBehavior;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresFeature;
23 import android.annotation.SdkConstant;
24 import android.annotation.SdkConstant.SdkConstantType;
25 import android.annotation.SystemService;
26 import android.app.IServiceConnection;
27 import android.app.PendingIntent;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.IntentSender;
33 import android.content.ServiceConnection;
34 import android.content.pm.PackageManager;
35 import android.content.pm.ParceledListSlice;
36 import android.content.pm.ShortcutInfo;
37 import android.os.Bundle;
38 import android.os.Handler;
39 import android.os.RemoteException;
40 import android.os.UserHandle;
41 import android.util.DisplayMetrics;
42 import android.widget.RemoteViews;
43 
44 import com.android.internal.appwidget.IAppWidgetService;
45 
46 import java.util.Collections;
47 import java.util.List;
48 
49 /**
50  * Updates AppWidget state; gets information about installed AppWidget providers and other
51  * AppWidget related state.
52  *
53  * <div class="special reference">
54  * <h3>Developer Guides</h3>
55  * <p>For more information about creating app widgets, read the
56  * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
57  * </div>
58  */
59 @SystemService(Context.APPWIDGET_SERVICE)
60 @RequiresFeature(PackageManager.FEATURE_APP_WIDGETS)
61 public class AppWidgetManager {
62 
63     /**
64      * Activity action to launch from your {@link AppWidgetHost} activity when you want to
65      * pick an AppWidget to display.  The AppWidget picker activity will be launched.
66      * <p>
67      * You must supply the following extras:
68      * <table>
69      *   <tr>
70      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
71      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
72      *         once the user has selected one.</td>
73      *  </tr>
74      * </table>
75      *
76      * <p>
77      * The system will respond with an onActivityResult call with the following extras in
78      * the intent:
79      * <table>
80      *   <tr>
81      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
82      *     <td>The appWidgetId that you supplied in the original intent.</td>
83      *  </tr>
84      * </table>
85      * <p>
86      * When you receive the result from the AppWidget pick activity, if the resultCode is
87      * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected.  You should then
88      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
89      * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
90      * should delete the appWidgetId.
91      *
92      * @see #ACTION_APPWIDGET_CONFIGURE
93      */
94     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
95     public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
96 
97     /**
98      * Similar to ACTION_APPWIDGET_PICK, but used from keyguard
99      * @hide
100      */
101     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
102     public static final String
103             ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
104 
105     /**
106      * Activity action to launch from your {@link AppWidgetHost} activity when you want to bind
107      * an AppWidget to display and bindAppWidgetIdIfAllowed returns false.
108      * <p>
109      * You must supply the following extras:
110      * <table>
111      *   <tr>
112      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
113      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
114      *         you provide.</td>
115      *  </tr>
116      *  <tr>
117      *     <td>{@link #EXTRA_APPWIDGET_PROVIDER}</td>
118      *     <td>The BroadcastReceiver that will be the AppWidget provider for this AppWidget.
119      *     </td>
120      *  </tr>
121      *  <tr>
122      *     <td>{@link #EXTRA_APPWIDGET_PROVIDER_PROFILE}</td>
123      *     <td>An optional handle to a user profile under which runs the provider
124      *     for this AppWidget.
125      *     </td>
126      *  </tr>
127      * </table>
128      *
129      * <p>
130      * The system will respond with an onActivityResult call with the following extras in
131      * the intent:
132      * <table>
133      *   <tr>
134      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
135      *     <td>The appWidgetId that you supplied in the original intent.</td>
136      *  </tr>
137      * </table>
138      * <p>
139      * When you receive the result from the AppWidget bind activity, if the resultCode is
140      * {@link android.app.Activity#RESULT_OK}, the AppWidget has been bound.  You should then
141      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
142      * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
143      * should delete the appWidgetId.
144      *
145      * @see #ACTION_APPWIDGET_CONFIGURE
146      *
147      */
148     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
149     public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
150 
151     /**
152      * Sent when it is time to configure your AppWidget while it is being added to a host.
153      * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity
154      * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo
155      * meta-data}.
156      *
157      * <p>
158      * The intent will contain the following extras:
159      * <table>
160      *   <tr>
161      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
162      *     <td>The appWidgetId to configure.</td>
163      *  </tr>
164      * </table>
165      *
166      * <p>If you return {@link android.app.Activity#RESULT_OK} using
167      * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added,
168      * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget.
169      * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
170      * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED}
171      * broadcast.
172      */
173     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
174     public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
175 
176     /**
177      * An intent extra that contains one appWidgetId.
178      * <p>
179      * The value will be an int that can be retrieved like this:
180      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java getExtra_EXTRA_APPWIDGET_ID}
181      */
182     public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
183 
184     /**
185      * A bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
186      */
187     public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
188 
189     /**
190      * A bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
191      */
192     public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
193 
194     /**
195      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
196      */
197     public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
198 
199     /**
200      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
201      */
202     public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
203 
204     /**
205      * A bundle extra that hints to the AppWidgetProvider the category of host that owns this
206      * this widget. Can have the value {@link
207      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
208      * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
209      * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
210      */
211     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
212 
213     /**
214      * An intent extra which points to a bundle of extra information for a particular widget id.
215      * In particular this bundle can contain {@link #OPTION_APPWIDGET_MIN_WIDTH},
216      * {@link #OPTION_APPWIDGET_MIN_HEIGHT}, {@link #OPTION_APPWIDGET_MAX_WIDTH},
217      * {@link #OPTION_APPWIDGET_MAX_HEIGHT}.
218      */
219     public static final String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
220 
221     /**
222      * An intent extra that contains multiple appWidgetIds.
223      * <p>
224      * The value will be an int array that can be retrieved like this:
225      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
226      */
227     public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
228 
229     /**
230      * An intent extra that contains the component name of a AppWidget provider.
231      * <p>
232      * The value will be an {@link android.content.ComponentName}.
233      */
234     public static final String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
235 
236     /**
237      * An intent extra that contains the user handle of the profile under
238      * which an AppWidget provider is registered.
239      * <p>
240      * The value will be a {@link android.os.UserHandle}.
241      */
242     public static final String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
243 
244     /**
245      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
246      * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are
247      * installed.  (This is how the launcher shows the search widget).
248      */
249     public static final String EXTRA_CUSTOM_INFO = "customInfo";
250 
251     /**
252      * An intent extra attached to the {@link #ACTION_APPWIDGET_HOST_RESTORED} broadcast,
253      * indicating the integer ID of the host whose widgets have just been restored.
254      */
255     public static final String EXTRA_HOST_ID = "hostId";
256 
257     /**
258      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
259      * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are
260      * installed.  It will be added to the extras object on the {@link android.content.Intent}
261      * that is returned from the picker activity.
262      *
263      * {@more}
264      */
265     public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
266 
267     /**
268      * An intent extra to pass to the AppWidget picker which allows the picker to filter
269      * the list based on the {@link AppWidgetProviderInfo#widgetCategory}.
270      *
271      * @hide
272      */
273     public static final String EXTRA_CATEGORY_FILTER = "categoryFilter";
274 
275     /**
276      * An intent extra to pass to the AppWidget picker to specify whether or not to sort
277      * the list of caller-specified extra AppWidgets along with the rest of the AppWidgets
278      * @hide
279      */
280     public static final String EXTRA_CUSTOM_SORT = "customSort";
281 
282     /**
283      * A sentinel value that the AppWidget manager will never return as a appWidgetId.
284      */
285     public static final int INVALID_APPWIDGET_ID = 0;
286 
287     /**
288      * Sent when it is time to update your AppWidget.
289      *
290      * <p>This may be sent in response to a new instance for this AppWidget provider having
291      * been instantiated, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval}
292      * having lapsed, or the system booting.
293      *
294      * <p>
295      * The intent will contain the following extras:
296      * <table>
297      *   <tr>
298      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
299      *     <td>The appWidgetIds to update.  This may be all of the AppWidgets created for this
300      *     provider, or just a subset.  The system tries to send updates for as few AppWidget
301      *     instances as possible.</td>
302      *  </tr>
303      * </table>
304      *
305      * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
306      */
307     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
308     @BroadcastBehavior(explicitOnly = true)
309     public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
310 
311     /**
312      * Sent when the custom extras for an AppWidget change.
313      *
314      * <p class="note">This is a protected intent that can only be sent
315      * by the system.
316      *
317      * @see AppWidgetProvider#onAppWidgetOptionsChanged
318      *      AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
319      *      AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
320      */
321     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
322     @BroadcastBehavior(explicitOnly = true)
323     public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
324 
325     /**
326      * Sent when an instance of an AppWidget is deleted from its host.
327      *
328      * <p class="note">This is a protected intent that can only be sent
329      * by the system.
330      *
331      * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
332      */
333     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
334     @BroadcastBehavior(explicitOnly = true)
335     public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
336 
337     /**
338      * Sent when the last AppWidget of this provider is removed from the last host.
339      *
340      * <p class="note">This is a protected intent that can only be sent
341      * by the system.
342      *
343      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context)
344      */
345     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
346     @BroadcastBehavior(explicitOnly = true)
347     public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
348 
349     /**
350      * Sent when an instance of an AppWidget is added to a host for the first time.
351      * This broadcast is sent at boot time if there is a AppWidgetHost installed with
352      * an instance for this provider.
353      *
354      * <p class="note">This is a protected intent that can only be sent
355      * by the system.
356      *
357      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
358      */
359     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
360     @BroadcastBehavior(explicitOnly = true)
361     public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
362 
363     /**
364      * Sent to an {@link AppWidgetProvider} after AppWidget state related to that provider has
365      * been restored from backup. The intent contains information about how to translate AppWidget
366      * ids from the restored data to their new equivalents.
367      *
368      * <p>The intent will contain the following extras:
369      *
370      * <table>
371      *   <tr>
372      *     <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td>
373      *     <td>The set of appWidgetIds represented in a restored backup that have been successfully
374      *     incorporated into the current environment.  This may be all of the AppWidgets known
375      *     to this application, or just a subset.  Each entry in this array of appWidgetIds has
376      *     a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td>
377      *  </tr>
378      *   <tr>
379      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
380      *     <td>The set of appWidgetIds now valid for this application.  The app should look at
381      *     its restored widget configuration and translate each appWidgetId in the
382      *     {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding
383      *     index within this array.</td>
384      *  </tr>
385      * </table>
386      *
387      * <p class="note">This is a protected intent that can only be sent
388      * by the system.
389      *
390      * @see #ACTION_APPWIDGET_HOST_RESTORED
391      */
392     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
393     @BroadcastBehavior(explicitOnly = true)
394     public static final String ACTION_APPWIDGET_RESTORED
395             = "android.appwidget.action.APPWIDGET_RESTORED";
396 
397     /**
398      * Sent to widget hosts after AppWidget state related to the host has been restored from
399      * backup. The intent contains information about how to translate AppWidget ids from the
400      * restored data to their new equivalents.  If an application maintains multiple separate
401      * widget host instances, it will receive this broadcast separately for each one.
402      *
403      * <p>The intent will contain the following extras:
404      *
405      * <table>
406      *   <tr>
407      *     <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td>
408      *     <td>The set of appWidgetIds represented in a restored backup that have been successfully
409      *     incorporated into the current environment.  This may be all of the AppWidgets known
410      *     to this application, or just a subset.  Each entry in this array of appWidgetIds has
411      *     a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td>
412      *  </tr>
413      *   <tr>
414      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
415      *     <td>The set of appWidgetIds now valid for this application.  The app should look at
416      *     its restored widget configuration and translate each appWidgetId in the
417      *     {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding
418      *     index within this array.</td>
419      *  </tr>
420      *  <tr>
421      *     <td>{@link #EXTRA_HOST_ID}</td>
422      *     <td>The integer ID of the widget host instance whose state has just been restored.</td>
423      *  </tr>
424      * </table>
425      *
426      * <p class="note">This is a protected intent that can only be sent
427      * by the system.
428      *
429      * @see #ACTION_APPWIDGET_RESTORED
430      */
431     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
432     @BroadcastBehavior(explicitOnly = true)
433     public static final String ACTION_APPWIDGET_HOST_RESTORED
434             = "android.appwidget.action.APPWIDGET_HOST_RESTORED";
435 
436     /**
437      * An intent extra that contains multiple appWidgetIds.  These are id values as
438      * they were provided to the application during a recent restore from backup.  It is
439      * attached to the {@link #ACTION_APPWIDGET_RESTORED} broadcast intent.
440      *
441      * <p>
442      * The value will be an int array that can be retrieved like this:
443      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
444      */
445     public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
446 
447     /**
448      * An extra that can be passed to
449      * {@link #requestPinAppWidget(ComponentName, Bundle, PendingIntent)}. This would allow the
450      * launcher app to present a custom preview to the user.
451      *
452      * <p>
453      * The value should be a {@link RemoteViews} similar to what is used with
454      * {@link #updateAppWidget} calls.
455      */
456     public static final String EXTRA_APPWIDGET_PREVIEW = "appWidgetPreview";
457 
458     /**
459      * Field for the manifest meta-data tag.
460      *
461      * @see AppWidgetProviderInfo
462      */
463     public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
464 
465     private final Context mContext;
466     private final String mPackageName;
467     @UnsupportedAppUsage
468     private final IAppWidgetService mService;
469     private final DisplayMetrics mDisplayMetrics;
470 
471     /**
472      * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
473      * Context} object.
474      */
getInstance(Context context)475     public static AppWidgetManager getInstance(Context context) {
476         return (AppWidgetManager) context.getSystemService(Context.APPWIDGET_SERVICE);
477     }
478 
479     /**
480      * Creates a new instance.
481      *
482      * @param context The current context in which to operate.
483      * @param service The backing system service.
484      * @hide
485      */
AppWidgetManager(Context context, IAppWidgetService service)486     public AppWidgetManager(Context context, IAppWidgetService service) {
487         mContext = context;
488         mPackageName = context.getOpPackageName();
489         mService = service;
490         mDisplayMetrics = context.getResources().getDisplayMetrics();
491     }
492 
493     /**
494      * Set the RemoteViews to use for the specified appWidgetIds.
495      * <p>
496      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
497      * contain a complete representation of the widget. For performing partial widget updates, see
498      * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}.
499      *
500      * <p>
501      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
502      * and outside of the handler.
503      * This method will only work when called from the uid that owns the AppWidget provider.
504      *
505      * <p>
506      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
507      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
508      *
509      * @param appWidgetIds The AppWidget instances for which to set the RemoteViews.
510      * @param views The RemoteViews object to show.
511      */
updateAppWidget(int[] appWidgetIds, RemoteViews views)512     public void updateAppWidget(int[] appWidgetIds, RemoteViews views) {
513         if (mService == null) {
514             return;
515         }
516         try {
517             mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
518         } catch (RemoteException e) {
519             throw e.rethrowFromSystemServer();
520         }
521     }
522 
523     /**
524      * Update the extras for a given widget instance.
525      * <p>
526      * The extras can be used to embed additional information about this widget to be accessed
527      * by the associated widget's AppWidgetProvider.
528      *
529      * @see #getAppWidgetOptions(int)
530      *
531      * @param appWidgetId The AppWidget instances for which to set the RemoteViews.
532      * @param options The options to associate with this widget
533      */
updateAppWidgetOptions(int appWidgetId, Bundle options)534     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
535         if (mService == null) {
536             return;
537         }
538         try {
539             mService.updateAppWidgetOptions(mPackageName, appWidgetId, options);
540         } catch (RemoteException e) {
541             throw e.rethrowFromSystemServer();
542         }
543     }
544 
545     /**
546      * Get the extras associated with a given widget instance.
547      * <p>
548      * The extras can be used to embed additional information about this widget to be accessed
549      * by the associated widget's AppWidgetProvider.
550      *
551      * @see #updateAppWidgetOptions(int, Bundle)
552      *
553      * @param appWidgetId The AppWidget instances for which to set the RemoteViews.
554      * @return The options associated with the given widget instance.
555      */
getAppWidgetOptions(int appWidgetId)556     public Bundle getAppWidgetOptions(int appWidgetId) {
557         if (mService == null) {
558             return Bundle.EMPTY;
559         }
560         try {
561             return mService.getAppWidgetOptions(mPackageName, appWidgetId);
562         } catch (RemoteException e) {
563             throw e.rethrowFromSystemServer();
564         }
565     }
566 
567     /**
568      * Set the RemoteViews to use for the specified appWidgetId.
569      * <p>
570      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
571      * contain a complete representation of the widget. For performing partial widget updates, see
572      * {@link #partiallyUpdateAppWidget(int, RemoteViews)}.
573      *
574      * <p>
575      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
576      * and outside of the handler.
577      * This method will only work when called from the uid that owns the AppWidget provider.
578      *
579      * <p>
580      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
581      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
582      *
583      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
584      * @param views         The RemoteViews object to show.
585      */
updateAppWidget(int appWidgetId, RemoteViews views)586     public void updateAppWidget(int appWidgetId, RemoteViews views) {
587         if (mService == null) {
588             return;
589         }
590         updateAppWidget(new int[] { appWidgetId }, views);
591     }
592 
593     /**
594      * Perform an incremental update or command on the widget(s) specified by appWidgetIds.
595      * <p>
596      * This update  differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
597      * RemoteViews object which is passed is understood to be an incomplete representation of the
598      * widget, and hence does not replace the cached representation of the widget. As of API
599      * level 17, the new properties set within the views objects will be appended to the cached
600      * representation of the widget, and hence will persist.
601      *
602      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
603      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
604      *
605      * <p>
606      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
607      * and outside of the handler.
608      * This method will only work when called from the uid that owns the AppWidget provider.
609      *
610      * <p>
611      * This method will be ignored if a widget has not received a full update via
612      * {@link #updateAppWidget(int[], RemoteViews)}.
613      *
614      * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
615      * @param views            The RemoteViews object containing the incremental update / command.
616      */
partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views)617     public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) {
618         if (mService == null) {
619             return;
620         }
621         try {
622             mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
623         } catch (RemoteException e) {
624             throw e.rethrowFromSystemServer();
625         }
626     }
627 
628     /**
629      * Perform an incremental update or command on the widget specified by appWidgetId.
630      * <p>
631      * This update  differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews
632      * object which is passed is understood to be an incomplete representation of the widget, and
633      * hence is not cached by the AppWidgetService. Note that because these updates are not cached,
634      * any state that they modify that is not restored by restoreInstanceState will not persist in
635      * the case that the widgets are restored using the cached version in AppWidgetService.
636      *
637      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
638      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
639      *
640      * <p>
641      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
642      * and outside of the handler.
643      * This method will only work when called from the uid that owns the AppWidget provider.
644      *
645      * <p>
646      * This method will be ignored if a widget has not received a full update via
647      * {@link #updateAppWidget(int[], RemoteViews)}.
648      *
649      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
650      * @param views            The RemoteViews object containing the incremental update / command.
651      */
partiallyUpdateAppWidget(int appWidgetId, RemoteViews views)652     public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) {
653         if (mService == null) {
654             return;
655         }
656         partiallyUpdateAppWidget(new int[] { appWidgetId }, views);
657     }
658 
659     /**
660      * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider.
661      *
662      * <p>
663      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
664      * and outside of the handler.
665      * This method will only work when called from the uid that owns the AppWidget provider.
666      *
667      * @param provider      The {@link ComponentName} for the {@link
668      * android.content.BroadcastReceiver BroadcastReceiver} provider
669      *                      for your AppWidget.
670      * @param views         The RemoteViews object to show.
671      */
updateAppWidget(ComponentName provider, RemoteViews views)672     public void updateAppWidget(ComponentName provider, RemoteViews views) {
673         if (mService == null) {
674             return;
675         }
676         try {
677             mService.updateAppWidgetProvider(provider, views);
678         } catch (RemoteException e) {
679             throw e.rethrowFromSystemServer();
680         }
681     }
682 
683     /**
684      * Updates the info for the supplied AppWidget provider. Apps can use this to change the default
685      * behavior of the widget based on the state of the app (for e.g., if the user is logged in
686      * or not). Calling this API completely replaces the previous definition.
687      *
688      * <p>
689      * The manifest entry of the provider should contain an additional meta-data tag similar to
690      * {@link #META_DATA_APPWIDGET_PROVIDER} which should point to any alternative definitions for
691      * the provider.
692      *
693      * <p>
694      * This is persisted across device reboots and app updates. If this meta-data key is not
695      * present in the manifest entry, the info reverts to default.
696      *
697      * @param provider {@link ComponentName} for the {@link
698      *    android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget.
699      * @param metaDataKey key for the meta-data tag pointing to the new provider info. Use null
700      *    to reset any previously set info.
701      */
updateAppWidgetProviderInfo(ComponentName provider, @Nullable String metaDataKey)702     public void updateAppWidgetProviderInfo(ComponentName provider, @Nullable String metaDataKey) {
703         if (mService == null) {
704             return;
705         }
706         try {
707             mService.updateAppWidgetProviderInfo(provider, metaDataKey);
708         } catch (RemoteException e) {
709             throw e.rethrowFromSystemServer();
710         }
711     }
712 
713     /**
714      * Notifies the specified collection view in all the specified AppWidget instances
715      * to invalidate their data.
716      *
717      * @param appWidgetIds  The AppWidget instances to notify of view data changes.
718      * @param viewId        The collection view id.
719      */
notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)720     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
721         if (mService == null) {
722             return;
723         }
724         try {
725             mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
726         } catch (RemoteException e) {
727             throw e.rethrowFromSystemServer();
728         }
729     }
730 
731     /**
732      * Notifies the specified collection view in the specified AppWidget instance
733      * to invalidate its data.
734      *
735      * @param appWidgetId  The AppWidget instance to notify of view data changes.
736      * @param viewId       The collection view id.
737      */
notifyAppWidgetViewDataChanged(int appWidgetId, int viewId)738     public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
739         if (mService == null) {
740             return;
741         }
742         notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
743     }
744 
745     /**
746      * Gets the AppWidget providers for the given user profile. User profile can only
747      * be the current user or a profile of the current user. For example, the current
748      * user may have a corporate profile. In this case the parent user profile has a
749      * child profile, the corporate one.
750      *
751      * @param profile The profile for which to get providers. Passing null is equivalent
752      *        to querying for only the calling user.
753      * @return The installed providers, or an empty list if none are found for the given user.
754      *
755      * @see android.os.Process#myUserHandle()
756      * @see android.os.UserManager#getUserProfiles()
757      */
getInstalledProvidersForProfile( @ullable UserHandle profile)758     public @NonNull List<AppWidgetProviderInfo> getInstalledProvidersForProfile(
759             @Nullable UserHandle profile) {
760         if (mService == null) {
761             return Collections.emptyList();
762         }
763         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
764                 profile, null);
765     }
766 
767     /**
768      * Gets the AppWidget providers for the given package and user profile. User
769      * profile can only be the current user or a profile of the current user. For
770      * example, the current user may have a corporate profile. In this case the
771      * parent user profile has a child profile, the corporate one.
772      *
773      * @param packageName The package for which to get providers. If null, this method is
774      *        equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
775      * @param profile The profile for which to get providers. Passing null is equivalent
776      *        to querying for only the calling user.
777      * @return The installed providers, or an empty list if none are found for the given
778      *         package and user.
779      * @throws NullPointerException if the provided package name is null
780      *
781      * @see android.os.Process#myUserHandle()
782      * @see android.os.UserManager#getUserProfiles()
783      */
getInstalledProvidersForPackage( @onNull String packageName, @Nullable UserHandle profile)784     public @NonNull List<AppWidgetProviderInfo> getInstalledProvidersForPackage(
785             @NonNull String packageName, @Nullable UserHandle profile) {
786         if (packageName == null) {
787             throw new NullPointerException("A non-null package must be passed to this method. " +
788                     "If you want all widgets regardless of package, see " +
789                     "getInstalledProvidersForProfile(UserHandle)");
790         }
791         if (mService == null) {
792             return Collections.emptyList();
793         }
794         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
795                 profile, packageName);
796     }
797 
798     /**
799      * Return a list of the AppWidget providers that are currently installed.
800      */
getInstalledProviders()801     public List<AppWidgetProviderInfo> getInstalledProviders() {
802         if (mService == null) {
803             return Collections.emptyList();
804         }
805         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
806                 null, null);
807     }
808 
809     /**
810      * Gets the AppWidget providers for the current user.
811      *
812      * @param categoryFilter Will only return providers which register as any of the specified
813      *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
814      * @return The intalled providers.
815      *
816      * @see android.os.Process#myUserHandle()
817      * @see android.os.UserManager#getUserProfiles()
818      *
819      * @hide
820      */
821     @UnsupportedAppUsage
getInstalledProviders(int categoryFilter)822     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
823         if (mService == null) {
824             return Collections.emptyList();
825         }
826         return getInstalledProvidersForProfile(categoryFilter, null, null);
827     }
828 
829     /**
830      * Gets the AppWidget providers for the given user profile. User profile can only
831      * be the current user or a profile of the current user. For example, the current
832      * user may have a corporate profile. In this case the parent user profile has a
833      * child profile, the corporate one.
834      *
835      * @param categoryFilter Will only return providers which register as any of the specified
836      *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
837      * @param profile A profile of the current user which to be queried. The user
838      *        is itself also a profile. If null, the providers only for the current user
839      *        are returned.
840      * @param packageName If specified, will only return providers from the given package.
841      * @return The intalled providers.
842      *
843      * @see android.os.Process#myUserHandle()
844      * @see android.os.UserManager#getUserProfiles()
845      *
846      * @hide
847      */
848     @UnsupportedAppUsage
getInstalledProvidersForProfile(int categoryFilter, @Nullable UserHandle profile, @Nullable String packageName)849     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
850             @Nullable UserHandle profile, @Nullable String packageName) {
851         if (mService == null) {
852             return Collections.emptyList();
853         }
854 
855         if (profile == null) {
856             profile = mContext.getUser();
857         }
858 
859         try {
860             ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
861                     categoryFilter, profile.getIdentifier(), packageName);
862             if (providers == null) {
863                 return Collections.emptyList();
864             }
865             for (AppWidgetProviderInfo info : providers.getList()) {
866                 // Converting complex to dp.
867                 info.updateDimensions(mDisplayMetrics);
868             }
869             return providers.getList();
870         } catch (RemoteException e) {
871             throw e.rethrowFromSystemServer();
872         }
873     }
874 
875     /**
876      * Get the available info about the AppWidget.
877      *
878      * @return A appWidgetId.  If the appWidgetId has not been bound to a provider yet, or
879      * you don't have access to that appWidgetId, null is returned.
880      */
getAppWidgetInfo(int appWidgetId)881     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
882         if (mService == null) {
883             return null;
884         }
885         try {
886             AppWidgetProviderInfo info = mService.getAppWidgetInfo(mPackageName, appWidgetId);
887             if (info != null) {
888                 // Converting complex to dp.
889                 info.updateDimensions(mDisplayMetrics);
890             }
891             return info;
892         } catch (RemoteException e) {
893             throw e.rethrowFromSystemServer();
894         }
895     }
896 
897     /**
898      * Set the component for a given appWidgetId.
899      *
900      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
901      *         widgets always for your component. This method is used by the AppWidget picker and
902      *         should not be used by other apps.
903      *
904      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
905      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
906      *                      provider for this AppWidget.
907      * @hide
908      */
909     @UnsupportedAppUsage
bindAppWidgetId(int appWidgetId, ComponentName provider)910     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
911         if (mService == null) {
912             return;
913         }
914         bindAppWidgetId(appWidgetId, provider, null);
915     }
916 
917     /**
918      * Set the component for a given appWidgetId.
919      *
920      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
921      *         widgets always for your component. This method is used by the AppWidget picker and
922      *         should not be used by other apps.
923      *
924      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
925      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
926      *                      provider for this AppWidget.
927      * @param options       Bundle containing options for the AppWidget. See also
928      *                      {@link #updateAppWidgetOptions(int, Bundle)}
929      *
930      * @hide
931      */
932     @UnsupportedAppUsage
bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)933     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
934         if (mService == null) {
935             return;
936         }
937         bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUser(), provider, options);
938     }
939 
940     /**
941      * Set the component for a given appWidgetId.
942      *
943      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
944      *         widgets always for your component. Should be used by apps that host widgets; if this
945      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
946      *         bind
947      *
948      * @param appWidgetId   The AppWidget id under which to bind the provider.
949      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
950      *                      provider for this AppWidget.
951      * @return true if this component has permission to bind the AppWidget
952      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider)953     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider) {
954         if (mService == null) {
955             return false;
956         }
957         return bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUserId(), provider, null);
958     }
959 
960     /**
961      * Set the component for a given appWidgetId.
962      *
963      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
964      *         widgets always for your component. Should be used by apps that host widgets; if this
965      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
966      *         bind
967      *
968      * @param appWidgetId The AppWidget id under which to bind the provider.
969      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
970      *                      provider for this AppWidget.
971      * @param options       Bundle containing options for the AppWidget. See also
972      *                      {@link #updateAppWidgetOptions(int, Bundle)}
973      *
974      * @return true if this component has permission to bind the AppWidget
975      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider, Bundle options)976     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider,
977             Bundle options) {
978         if (mService == null) {
979             return false;
980         }
981         return bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUserId(), provider, options);
982     }
983 
984     /**
985      * Set the provider for a given appWidgetId if the caller has a permission.
986      * <p>
987      * <strong>Note:</strong> You need the {@link android.Manifest.permission#BIND_APPWIDGET}
988      * permission or the user must have enabled binding widgets always for your component.
989      * Should be used by apps that host widgets. If this method returns false, call {@link
990      * #ACTION_APPWIDGET_BIND} to request permission to bind.
991      * </p>
992      *
993      * @param appWidgetId The AppWidget id under which to bind the provider.
994      * @param user The user id in which the provider resides.
995      * @param provider The component name of the provider.
996      * @param options An optional Bundle containing options for the AppWidget.
997      *
998      * @return true if this component has permission to bind the AppWidget
999      */
bindAppWidgetIdIfAllowed(int appWidgetId, UserHandle user, ComponentName provider, Bundle options)1000     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, UserHandle user,
1001             ComponentName provider, Bundle options) {
1002         if (mService == null) {
1003             return false;
1004         }
1005         return bindAppWidgetIdIfAllowed(appWidgetId, user.getIdentifier(), provider, options);
1006     }
1007 
1008     /**
1009      * Query if a given package was granted permission by the user to bind app widgets
1010      *
1011      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
1012      *
1013      * @param packageName The package for which the permission is being queried
1014      * @param userId The user id of the user under which the package runs.
1015      * @return true if the package was granted permission by the user to bind app widgets
1016      * @hide
1017      */
hasBindAppWidgetPermission(String packageName, int userId)1018     public boolean hasBindAppWidgetPermission(String packageName, int userId) {
1019         if (mService == null) {
1020             return false;
1021         }
1022         try {
1023             return mService.hasBindAppWidgetPermission(packageName, userId);
1024         } catch (RemoteException e) {
1025             throw e.rethrowFromSystemServer();
1026         }
1027     }
1028 
1029     /**
1030      * Query if a given package was granted permission by the user to bind app widgets
1031      *
1032      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
1033      *
1034      * @param packageName        The package for which the permission is being queried
1035      * @return true if the package was granted permission by the user to bind app widgets
1036      * @hide
1037      */
hasBindAppWidgetPermission(String packageName)1038     public boolean hasBindAppWidgetPermission(String packageName) {
1039         if (mService == null) {
1040             return false;
1041         }
1042         try {
1043             return mService.hasBindAppWidgetPermission(packageName, mContext.getUserId());
1044         } catch (RemoteException e) {
1045             throw e.rethrowFromSystemServer();
1046         }
1047     }
1048 
1049     /**
1050      * Changes any user-granted permission for the given package to bind app widgets
1051      *
1052      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
1053      *
1054      * @param packageName The package whose permission is being changed
1055      * @param permission Whether to give the package permission to bind widgets
1056      *
1057      * @hide
1058      */
setBindAppWidgetPermission(String packageName, boolean permission)1059     public void setBindAppWidgetPermission(String packageName, boolean permission) {
1060         if (mService == null) {
1061             return;
1062         }
1063         setBindAppWidgetPermission(packageName, mContext.getUserId(), permission);
1064     }
1065 
1066     /**
1067      * Changes any user-granted permission for the given package to bind app widgets
1068      *
1069      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
1070      *
1071      * @param packageName The package whose permission is being changed
1072      * @param userId The user under which the package is running.
1073      * @param permission Whether to give the package permission to bind widgets
1074      *
1075      * @hide
1076      */
setBindAppWidgetPermission(String packageName, int userId, boolean permission)1077     public void setBindAppWidgetPermission(String packageName, int userId, boolean permission) {
1078         if (mService == null) {
1079             return;
1080         }
1081         try {
1082             mService.setBindAppWidgetPermission(packageName, userId, permission);
1083         } catch (RemoteException e) {
1084             throw e.rethrowFromSystemServer();
1085         }
1086     }
1087 
1088     /**
1089      * Binds the RemoteViewsService for a given appWidgetId and intent.
1090      *
1091      * The appWidgetId specified must already be bound to the calling AppWidgetHost via
1092      * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
1093      *
1094      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
1095      * @param intent        The intent of the service which will be providing the data to the
1096      *                      RemoteViewsAdapter.
1097      * @param connection    The callback interface to be notified when a connection is made or lost.
1098      * @param flags         Flags used for binding to the service
1099      *
1100      * @see Context#getServiceDispatcher(ServiceConnection, Handler, int)
1101      * @hide
1102      */
1103     @UnsupportedAppUsage
bindRemoteViewsService(Context context, int appWidgetId, Intent intent, IServiceConnection connection, @Context.BindServiceFlags int flags)1104     public boolean bindRemoteViewsService(Context context, int appWidgetId, Intent intent,
1105             IServiceConnection connection, @Context.BindServiceFlags int flags) {
1106         if (mService == null) {
1107             return false;
1108         }
1109         try {
1110             return mService.bindRemoteViewsService(context.getOpPackageName(), appWidgetId, intent,
1111                     context.getIApplicationThread(), context.getActivityToken(), connection, flags);
1112         } catch (RemoteException e) {
1113             throw e.rethrowFromSystemServer();
1114         }
1115     }
1116 
1117     /**
1118      * Get the list of appWidgetIds that have been bound to the given AppWidget
1119      * provider.
1120      *
1121      * @param provider The {@link android.content.BroadcastReceiver} that is the
1122      *            AppWidget provider to find appWidgetIds for.
1123      */
getAppWidgetIds(ComponentName provider)1124     public int[] getAppWidgetIds(ComponentName provider) {
1125         if (mService == null) {
1126             return new int[0];
1127         }
1128         try {
1129             return mService.getAppWidgetIds(provider);
1130         } catch (RemoteException e) {
1131             throw e.rethrowFromSystemServer();
1132         }
1133     }
1134 
1135     /**
1136      * @hide
1137      */
isBoundWidgetPackage(String packageName, int userId)1138     public boolean isBoundWidgetPackage(String packageName, int userId) {
1139         if (mService == null) {
1140             return false;
1141         }
1142         try {
1143             return mService.isBoundWidgetPackage(packageName, userId);
1144         } catch (RemoteException e) {
1145             throw e.rethrowFromSystemServer();
1146         }
1147     }
1148 
1149     @UnsupportedAppUsage
bindAppWidgetIdIfAllowed(int appWidgetId, int profileId, ComponentName provider, Bundle options)1150     private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
1151             ComponentName provider, Bundle options) {
1152         if (mService == null) {
1153             return false;
1154         }
1155         try {
1156             return mService.bindAppWidgetId(mPackageName, appWidgetId,
1157                     profileId, provider, options);
1158         } catch (RemoteException e) {
1159             throw e.rethrowFromSystemServer();
1160         }
1161     }
1162 
1163     /**
1164      * Return {@code TRUE} if the default launcher supports
1165      * {@link #requestPinAppWidget(ComponentName, Bundle, PendingIntent)}
1166      */
isRequestPinAppWidgetSupported()1167     public boolean isRequestPinAppWidgetSupported() {
1168         try {
1169             return mService.isRequestPinAppWidgetSupported();
1170         } catch (RemoteException e) {
1171             throw e.rethrowFromSystemServer();
1172         }
1173     }
1174 
1175     /**
1176      * Only used during development. Can be deleted before release.
1177      * @hide
1178      */
requestPinAppWidget(@onNull ComponentName provider, @Nullable PendingIntent successCallback)1179     public boolean requestPinAppWidget(@NonNull ComponentName provider,
1180             @Nullable PendingIntent successCallback) {
1181         return requestPinAppWidget(provider, null, successCallback);
1182     }
1183 
1184     /**
1185      * Request to pin an app widget on the current launcher. It's up to the launcher to accept this
1186      * request (optionally showing a user confirmation). If the request is accepted, the caller will
1187      * get a confirmation with extra {@link #EXTRA_APPWIDGET_ID}.
1188      *
1189      * <p>When a request is denied by the user, the caller app will not get any response.
1190      *
1191      * <p>Only apps with a foreground activity or a foreground service can call it.  Otherwise
1192      * it'll throw {@link IllegalStateException}.
1193      *
1194      * <p>It's up to the launcher how to handle previous pending requests when the same package
1195      * calls this API multiple times in a row.  It may ignore the previous requests,
1196      * for example.
1197      *
1198      * <p>Launcher will not show the configuration activity associated with the provider in this
1199      * case. The app could either show the configuration activity as a response to the callback,
1200      * or show if before calling the API (various configurations can be encapsulated in
1201      * {@code successCallback} to avoid persisting them before the widgetId is known).
1202      *
1203      * @param provider The {@link ComponentName} for the {@link
1204      *    android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget.
1205      * @param extras In not null, this is passed to the launcher app. For eg {@link
1206      *    #EXTRA_APPWIDGET_PREVIEW} can be used for a custom preview.
1207      * @param successCallback If not null, this intent will be sent when the widget is created.
1208      *
1209      * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
1210      *    waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
1211      *    the shortcut is pinned. {@code FALSE} if the launcher doesn't support this feature.
1212      *
1213      * @see android.content.pm.ShortcutManager#isRequestPinShortcutSupported()
1214      * @see android.content.pm.ShortcutManager#requestPinShortcut(ShortcutInfo, IntentSender)
1215      * @see #isRequestPinAppWidgetSupported()
1216      *
1217      * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
1218      * service or when the user is locked.
1219      */
requestPinAppWidget(@onNull ComponentName provider, @Nullable Bundle extras, @Nullable PendingIntent successCallback)1220     public boolean requestPinAppWidget(@NonNull ComponentName provider,
1221             @Nullable Bundle extras, @Nullable PendingIntent successCallback) {
1222         try {
1223             return mService.requestPinAppWidget(mPackageName, provider, extras,
1224                     successCallback == null ? null : successCallback.getIntentSender());
1225         } catch (RemoteException e) {
1226             throw e.rethrowFromSystemServer();
1227         }
1228     }
1229 }
1230