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