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