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