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