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