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