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