AppWidgetManager.java revision 311c79c3e93589c6fc720fe6c58ed522af591376
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.util.DisplayMetrics;
27import android.util.TypedValue;
28import android.widget.RemoteViews;
29
30import com.android.internal.appwidget.IAppWidgetService;
31
32import java.lang.ref.WeakReference;
33import java.util.List;
34import java.util.WeakHashMap;
35
36/**
37 * Updates AppWidget state; gets information about installed AppWidget providers and other
38 * AppWidget related state.
39 *
40 * <div class="special reference">
41 * <h3>Developer Guides</h3>
42 * <p>For more information about creating app widgets, read the
43 * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
44 * </div>
45 */
46public class AppWidgetManager {
47    static final String TAG = "AppWidgetManager";
48
49    /**
50     * Send this from your {@link AppWidgetHost} activity when you want to pick an AppWidget to display.
51     * The AppWidget picker activity will be launched.
52     * <p>
53     * You must supply the following extras:
54     * <table>
55     *   <tr>
56     *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
57     *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
58     *         once the user has selected one.</td>
59     *  </tr>
60     * </table>
61     *
62     * <p>
63     * The system will respond with an onActivityResult call with the following extras in
64     * the intent:
65     * <table>
66     *   <tr>
67     *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
68     *     <td>The appWidgetId that you supplied in the original intent.</td>
69     *  </tr>
70     * </table>
71     * <p>
72     * When you receive the result from the AppWidget pick activity, if the resultCode is
73     * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected.  You should then
74     * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its configuration
75     * activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete
76     * the appWidgetId.
77     *
78     * @see #ACTION_APPWIDGET_CONFIGURE
79     */
80    public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
81
82    /**
83     * Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to
84     * display and bindAppWidgetIdIfAllowed returns false.
85     * <p>
86     * You must supply the following extras:
87     * <table>
88     *   <tr>
89     *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
90     *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
91     *         you provide.</td>
92     *  </tr>
93     *  <tr>
94     *     <td>{@link #EXTRA_APPWIDGET_PROVIDER}</td>
95     *     <td>The BroadcastReceiver that will be the AppWidget provider for this AppWidget.
96     *     </td>
97     *  </tr>
98     * </table>
99     *
100     * <p>
101     * The system will respond with an onActivityResult call with the following extras in
102     * the intent:
103     * <table>
104     *   <tr>
105     *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
106     *     <td>The appWidgetId that you supplied in the original intent.</td>
107     *  </tr>
108     * </table>
109     * <p>
110     * When you receive the result from the AppWidget bind activity, if the resultCode is
111     * {@link android.app.Activity#RESULT_OK}, the AppWidget has been bound.  You should then
112     * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
113     * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
114     * should delete
115     * the appWidgetId.
116     *
117     * @see #ACTION_APPWIDGET_CONFIGURE
118     *
119     */
120    public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
121
122    /**
123     * Sent when it is time to configure your AppWidget while it is being added to a host.
124     * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity
125     * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo meta-data}.
126     *
127     * <p>
128     * The intent will contain the following extras:
129     * <table>
130     *   <tr>
131     *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
132     *     <td>The appWidgetId to configure.</td>
133     *  </tr>
134     * </table>
135     *
136     * <p>If you return {@link android.app.Activity#RESULT_OK} using
137     * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added,
138     * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget.
139     * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
140     * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} broadcast.
141     */
142    public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
143
144    /**
145     * An intent extra that contains one appWidgetId.
146     * <p>
147     * The value will be an int that can be retrieved like this:
148     * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java getExtra_EXTRA_APPWIDGET_ID}
149     */
150    public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
151
152    /**
153     * An bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
154     */
155    public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
156
157    /**
158     * An bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
159     */
160    public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
161
162    /**
163     * An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
164     */
165    public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
166
167    /**
168     * An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
169     */
170    public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
171
172    /**
173     * An intent extra which points to a bundle of extra information for a particular widget id.
174     * In particular this bundle can contain EXTRA_APPWIDGET_WIDTH and EXTRA_APPWIDGET_HEIGHT.
175     */
176    public static final String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
177
178    /**
179     * An intent extra that contains multiple appWidgetIds.
180     * <p>
181     * The value will be an int array that can be retrieved like this:
182     * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
183     */
184    public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
185
186    /**
187     * An intent extra that contains the component name of a AppWidget provider.
188     * <p>
189     * The value will be an ComponentName.
190     */
191    public static final String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
192
193    /**
194     * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
195     * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are
196     * installed.  (This is how the launcher shows the search widget).
197     */
198    public static final String EXTRA_CUSTOM_INFO = "customInfo";
199
200    /**
201     * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
202     * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are
203     * installed.  It will be added to the extras object on the {@link android.content.Intent}
204     * that is returned from the picker activity.
205     *
206     * {@more}
207     */
208    public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
209
210    /**
211     * A sentiel value that the AppWidget manager will never return as a appWidgetId.
212     */
213    public static final int INVALID_APPWIDGET_ID = 0;
214
215    /**
216     * Sent when it is time to update your AppWidget.
217     *
218     * <p>This may be sent in response to a new instance for this AppWidget provider having
219     * been instantiated, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval}
220     * having lapsed, or the system booting.
221     *
222     * <p>
223     * The intent will contain the following extras:
224     * <table>
225     *   <tr>
226     *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
227     *     <td>The appWidgetIds to update.  This may be all of the AppWidgets created for this
228     *     provider, or just a subset.  The system tries to send updates for as few AppWidget
229     *     instances as possible.</td>
230     *  </tr>
231     * </table>
232     *
233     * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
234     */
235    public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
236
237    /**
238     * Sent when the custom extras for an AppWidget change.
239     *
240     * @see AppWidgetProvider#onAppWidgetExtrasChanged AppWidgetProvider#onAppWidgetExtrasChanged(
241     *      Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
242     */
243    public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
244
245    /**
246     * Sent when an instance of an AppWidget is deleted from its host.
247     *
248     * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
249     */
250    public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
251
252    /**
253     * Sent when an instance of an AppWidget is removed from the last host.
254     *
255     * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
256     */
257    public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
258
259    /**
260     * Sent when an instance of an AppWidget is added to a host for the first time.
261     * This broadcast is sent at boot time if there is a AppWidgetHost installed with
262     * an instance for this provider.
263     *
264     * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
265     */
266    public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
267
268    /**
269     * Field for the manifest meta-data tag.
270     *
271     * @see AppWidgetProviderInfo
272     */
273    public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
274
275    static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache =
276        new WeakHashMap<Context, WeakReference<AppWidgetManager>>();
277    static IAppWidgetService sService;
278
279    Context mContext;
280
281    private DisplayMetrics mDisplayMetrics;
282
283    /**
284     * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
285     * Context} object.
286     */
287    public static AppWidgetManager getInstance(Context context) {
288        synchronized (sManagerCache) {
289            if (sService == null) {
290                IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
291                sService = IAppWidgetService.Stub.asInterface(b);
292            }
293
294            WeakReference<AppWidgetManager> ref = sManagerCache.get(context);
295            AppWidgetManager result = null;
296            if (ref != null) {
297                result = ref.get();
298            }
299            if (result == null) {
300                result = new AppWidgetManager(context);
301                sManagerCache.put(context, new WeakReference<AppWidgetManager>(result));
302            }
303            return result;
304        }
305    }
306
307    private AppWidgetManager(Context context) {
308        mContext = context;
309        mDisplayMetrics = context.getResources().getDisplayMetrics();
310    }
311
312    /**
313     * Set the RemoteViews to use for the specified appWidgetIds.
314     *
315     * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
316     * contain a complete representation of the widget. For performing partial widget updates, see
317     * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}.
318     *
319     * <p>
320     * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
321     * and outside of the handler.
322     * This method will only work when called from the uid that owns the AppWidget provider.
323     *
324     * <p>
325     * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
326     * fill the screen once, ie. (screen width x screen height x 4) bytes.
327     *
328     * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
329     * @param views         The RemoteViews object to show.
330     */
331    public void updateAppWidget(int[] appWidgetIds, RemoteViews views) {
332        try {
333            sService.updateAppWidgetIds(appWidgetIds, views);
334        }
335        catch (RemoteException e) {
336            throw new RuntimeException("system server dead?", e);
337        }
338    }
339
340    /**
341     * Update the extras for a given widget instance.
342     *
343     * The extras can be used to embed additional information about this widget to be accessed
344     * by the associated widget's AppWidgetProvider.
345     *
346     * @see #getAppWidgetOptions(int)
347     *
348     * @param appWidgetId    The AppWidget instances for which to set the RemoteViews.
349     * @param options         The options to associate with this widget
350     */
351    public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
352        try {
353            sService.updateAppWidgetOptions(appWidgetId, options);
354        }
355        catch (RemoteException e) {
356            throw new RuntimeException("system server dead?", e);
357        }
358    }
359
360    /**
361     * Get the extras associated with a given widget instance.
362     *
363     * The extras can be used to embed additional information about this widget to be accessed
364     * by the associated widget's AppWidgetProvider.
365     *
366     * @see #updateAppWidgetOptions(int, Bundle)
367     *
368     * @param appWidgetId     The AppWidget instances for which to set the RemoteViews.
369     * @return                The options associated with the given widget instance.
370     */
371    public Bundle getAppWidgetOptions(int appWidgetId) {
372        try {
373            return sService.getAppWidgetOptions(appWidgetId);
374        }
375        catch (RemoteException e) {
376            throw new RuntimeException("system server dead?", e);
377        }
378    }
379
380    /**
381     * Set the RemoteViews to use for the specified appWidgetId.
382     *
383     * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
384     * contain a complete representation of the widget. For performing partial widget updates, see
385     * {@link #partiallyUpdateAppWidget(int, RemoteViews)}.
386     *
387     * <p>
388     * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
389     * and outside of the handler.
390     * This method will only work when called from the uid that owns the AppWidget provider.
391     *
392     * <p>
393     * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
394     * fill the screen once, ie. (screen width x screen height x 4) bytes.
395     *
396     * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
397     * @param views         The RemoteViews object to show.
398     */
399    public void updateAppWidget(int appWidgetId, RemoteViews views) {
400        updateAppWidget(new int[] { appWidgetId }, views);
401    }
402
403    /**
404     * Perform an incremental update or command on the widget(s) specified by appWidgetIds.
405     *
406     * This update  differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
407     * RemoteViews object which is passed is understood to be an incomplete representation of the
408     * widget, and hence is not cached by the AppWidgetService. Note that because these updates are
409     * not cached, any state that they modify that is not restored by restoreInstanceState will not
410     * persist in the case that the widgets are restored using the cached version in
411     * AppWidgetService.
412     *
413     * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
414     * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
415     *
416     * <p>
417     * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
418     * and outside of the handler.
419     * This method will only work when called from the uid that owns the AppWidget provider.
420     *
421     * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
422     * @param views            The RemoteViews object containing the incremental update / command.
423     */
424    public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) {
425        try {
426            sService.partiallyUpdateAppWidgetIds(appWidgetIds, views);
427        } catch (RemoteException e) {
428            throw new RuntimeException("system server dead?", e);
429        }
430    }
431
432    /**
433     * Perform an incremental update or command on the widget specified by appWidgetId.
434     *
435     * This update  differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews
436     * object which is passed is understood to be an incomplete representation of the widget, and
437     * hence is not cached by the AppWidgetService. Note that because these updates are not cached,
438     * any state that they modify that is not restored by restoreInstanceState will not persist in
439     * the case that the widgets are restored using the cached version in AppWidgetService.
440     *
441     * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
442     * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
443     *
444     * <p>
445     * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
446     * and outside of the handler.
447     * This method will only work when called from the uid that owns the AppWidget provider.
448     *
449     * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
450     * @param views            The RemoteViews object containing the incremental update / command.
451     */
452    public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) {
453        partiallyUpdateAppWidget(new int[] { appWidgetId }, views);
454    }
455
456    /**
457     * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider.
458     *
459     * <p>
460     * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
461     * and outside of the handler.
462     * This method will only work when called from the uid that owns the AppWidget provider.
463     *
464     * @param provider      The {@link ComponentName} for the {@link
465     * android.content.BroadcastReceiver BroadcastReceiver} provider
466     *                      for your AppWidget.
467     * @param views         The RemoteViews object to show.
468     */
469    public void updateAppWidget(ComponentName provider, RemoteViews views) {
470        try {
471            sService.updateAppWidgetProvider(provider, views);
472        }
473        catch (RemoteException e) {
474            throw new RuntimeException("system server dead?", e);
475        }
476    }
477
478    /**
479     * Notifies the specified collection view in all the specified AppWidget instances
480     * to invalidate their currently data.
481     *
482     * @param appWidgetIds  The AppWidget instances for which to notify of view data changes.
483     * @param viewId        The collection view id.
484     */
485    public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
486        try {
487            sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
488        }
489        catch (RemoteException e) {
490            throw new RuntimeException("system server dead?", e);
491        }
492    }
493
494    /**
495     * Notifies the specified collection view in all the specified AppWidget instance
496     * to invalidate it's currently data.
497     *
498     * @param appWidgetId  The AppWidget instance for which to notify of view data changes.
499     * @param viewId        The collection view id.
500     */
501    public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
502        notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
503    }
504
505    /**
506     * Return a list of the AppWidget providers that are currently installed.
507     */
508    public List<AppWidgetProviderInfo> getInstalledProviders() {
509        try {
510            List<AppWidgetProviderInfo> providers = sService.getInstalledProviders();
511            for (AppWidgetProviderInfo info : providers) {
512                // Converting complex to dp.
513                info.minWidth =
514                        TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
515                info.minHeight =
516                        TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
517                info.minResizeWidth =
518                    TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
519                info.minResizeHeight =
520                    TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
521            }
522            return providers;
523        }
524        catch (RemoteException e) {
525            throw new RuntimeException("system server dead?", e);
526        }
527    }
528
529    /**
530     * Get the available info about the AppWidget.
531     *
532     * @return A appWidgetId.  If the appWidgetId has not been bound to a provider yet, or
533     * you don't have access to that appWidgetId, null is returned.
534     */
535    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
536        try {
537            AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId);
538            if (info != null) {
539                // Converting complex to dp.
540                info.minWidth =
541                        TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
542                info.minHeight =
543                        TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
544                info.minResizeWidth =
545                    TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
546                info.minResizeHeight =
547                    TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
548            }
549            return info;
550        }
551        catch (RemoteException e) {
552            throw new RuntimeException("system server dead?", e);
553        }
554    }
555
556    /**
557     * Set the component for a given appWidgetId.
558     *
559     * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
560     *         widgets always for your component. This method is used by the AppWidget picker and
561     *         should not be used by other apps.
562     *
563     * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
564     * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
565     *                      provider for this AppWidget.
566     * @hide
567     */
568    public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
569        try {
570            sService.bindAppWidgetId(appWidgetId, provider);
571        }
572        catch (RemoteException e) {
573            throw new RuntimeException("system server dead?", e);
574        }
575    }
576
577    /**
578     * Set the component for a given appWidgetId.
579     *
580     * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
581     *         widgets always for your component. Should be used by apps that host widgets; if this
582     *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
583     *         bind
584     *
585     * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
586     * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
587     *                      provider for this AppWidget.
588     * @return true if this component has permission to bind the AppWidget
589     */
590    public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider) {
591        if (mContext == null) {
592            return false;
593        }
594        try {
595            return sService.bindAppWidgetIdIfAllowed(
596                    mContext.getPackageName(), appWidgetId, provider);
597        }
598        catch (RemoteException e) {
599            throw new RuntimeException("system server dead?", e);
600        }
601    }
602
603    /**
604     * Query if a given package was granted permission by the user to bind app widgets
605     *
606     * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
607     *
608     * @param packageName        The package for which the permission is being queried
609     * @return true if the package was granted permission by the user to bind app widgets
610     * @hide
611     */
612    public boolean hasBindAppWidgetPermission(String packageName) {
613        try {
614            return sService.hasBindAppWidgetPermission(packageName);
615        }
616        catch (RemoteException e) {
617            throw new RuntimeException("system server dead?", e);
618        }
619    }
620
621    /**
622     * Changes any user-granted permission for the given package to bind app widgets
623     *
624     * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
625     *
626     * @param provider        The package whose permission is being changed
627     * @param permission      Whether to give the package permission to bind widgets
628     * @hide
629     */
630    public void setBindAppWidgetPermission(String packageName, boolean permission) {
631        try {
632            sService.setBindAppWidgetPermission(packageName, permission);
633        }
634        catch (RemoteException e) {
635            throw new RuntimeException("system server dead?", e);
636        }
637    }
638
639    /**
640     * Binds the RemoteViewsService for a given appWidgetId and intent.
641     *
642     * The appWidgetId specified must already be bound to the calling AppWidgetHost via
643     * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
644     *
645     * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
646     * @param intent        The intent of the service which will be providing the data to the
647     *                      RemoteViewsAdapter.
648     * @param connection    The callback interface to be notified when a connection is made or lost.
649     * @hide
650     */
651    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
652        try {
653            sService.bindRemoteViewsService(appWidgetId, intent, connection);
654        }
655        catch (RemoteException e) {
656            throw new RuntimeException("system server dead?", e);
657        }
658    }
659
660    /**
661     * Unbinds the RemoteViewsService for a given appWidgetId and intent.
662     *
663     * The appWidgetId specified muse already be bound to the calling AppWidgetHost via
664     * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
665     *
666     * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
667     * @param intent        The intent of the service which will be providing the data to the
668     *                      RemoteViewsAdapter.
669     * @hide
670     */
671    public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
672        try {
673            sService.unbindRemoteViewsService(appWidgetId, intent);
674        }
675        catch (RemoteException e) {
676            throw new RuntimeException("system server dead?", e);
677        }
678    }
679
680    /**
681     * Get the list of appWidgetIds that have been bound to the given AppWidget
682     * provider.
683     *
684     * @param provider The {@link android.content.BroadcastReceiver} that is the
685     *            AppWidget provider to find appWidgetIds for.
686     */
687    public int[] getAppWidgetIds(ComponentName provider) {
688        try {
689            return sService.getAppWidgetIds(provider);
690        }
691        catch (RemoteException e) {
692            throw new RuntimeException("system server dead?", e);
693        }
694    }
695}
696
697