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