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