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