19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpackage android.appwidget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 195d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.content.ComponentName; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 215d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.content.pm.ApplicationInfo; 22af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guyimport android.content.pm.LauncherApps; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 24b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException; 255d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.content.res.Resources; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Color; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 304c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohenimport android.graphics.Rect; 315d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.os.Build; 32e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohenimport android.os.Bundle; 33dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyalimport android.os.CancellationSignal; 3409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.os.Parcel; 353030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport android.os.Parcelable; 363030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport android.os.SystemClock; 37b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.util.AttributeSet; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 3909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.util.SparseArray; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 434d1bf093396982d6838af934ab46672773772200Hyunyoung Songimport android.view.ViewGroup; 441affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhuimport android.view.accessibility.AccessibilityNodeInfo; 45499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.Adapter; 46499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.AdapterView; 47499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.BaseAdapter; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.FrameLayout; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews; 50e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Millerimport android.widget.RemoteViews.OnClickHandler; 512148d43eb23c702e834c93ae427f822f32d280a2Adam Cohenimport android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback; 524c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohenimport android.widget.TextView; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 54dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyalimport java.util.concurrent.Executor; 55dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 57c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Provides the glue to show AppWidget views. This class offers automatic animation 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * between updates, and will try recycling old views for each incoming 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link RemoteViews}. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 61c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpublic class AppWidgetHostView extends FrameLayout { 62c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project static final String TAG = "AppWidgetHostView"; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final boolean LOGD = false; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final boolean CROSSFADE = false; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_NOINIT = 0; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_CONTENT = 1; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_ERROR = 2; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_DEFAULT = 3; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int FADE_DURATION = 1000; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 73c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // When we're inflating the initialLayout for a AppWidget, we only allow 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // views that are allowed in RemoteViews. 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() { 76e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne public boolean onLoadClass(Class clazz) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return clazz.isAnnotationPresent(RemoteViews.RemoteView.class); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context mContext; 82b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey Context mRemoteContext; 83b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 84c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mAppWidgetId; 85c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AppWidgetProviderInfo mInfo; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View mView; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mViewMode = VIEW_MODE_NOINIT; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mLayoutId = -1; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mFadeStartTime = -1; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bitmap mOld; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint mOldPaint = new Paint(); 92e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller private OnClickHandler mOnClickHandler; 93e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 94dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private Executor mAsyncExecutor; 95dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private CancellationSignal mLastExecutionSignal; 96dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a host view. Uses default fade animations. 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 100c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetHostView(Context context) { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, android.R.anim.fade_in, android.R.anim.fade_out); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 105e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * @hide 106e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller */ 107e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller public AppWidgetHostView(Context context, OnClickHandler handler) { 108e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller this(context, android.R.anim.fade_in, android.R.anim.fade_out); 109e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller mOnClickHandler = handler; 110e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller } 111e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 112e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a host view. Uses specified animations when pushing 114c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * {@link #updateAppWidget(RemoteViews)}. 115e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param animationIn Resource ID of in animation to use 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param animationOut Resource ID of out animation to use 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 119a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy @SuppressWarnings({"UnusedDeclaration"}) 120c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetHostView(Context context, int animationIn, int animationOut) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 123d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen // We want to segregate the view ids within AppWidgets to prevent 124d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen // problems when those ids collide with view ids in the AppWidgetHost. 125d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen setIsRootNamespace(true); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 127d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 129e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * Pass the given handler to RemoteViews when updating this widget. Unless this 130e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)} 131e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * should be made. 132e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * @param handler 133e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * @hide 134e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller */ 135e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller public void setOnClickHandler(OnClickHandler handler) { 136e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller mOnClickHandler = handler; 137e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller } 138e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 139e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller /** 1404c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * Set the AppWidget that will be displayed by this view. This method also adds default padding 1414c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)} 1424c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * and can be overridden in order to add custom padding. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) { 145c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mAppWidgetId = appWidgetId; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInfo = info; 1475d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen 1485d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen // Sometimes the AppWidgetManager returns a null AppWidgetProviderInfo object for 1495d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen // a widget, eg. for some widgets in safe mode. 1505d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen if (info != null) { 1515d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen // We add padding to the AppWidgetHostView if necessary 1524c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null); 1535d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen setPadding(padding.left, padding.top, padding.right, padding.bottom); 154af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy updateContentDescription(info); 1555d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen } 1565d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen } 1575d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen 1585d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen /** 1595d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen * As of ICE_CREAM_SANDWICH we are automatically adding padding to widgets targeting 1605d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen * ICE_CREAM_SANDWICH and higher. The new widget design guidelines strongly recommend 1615d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen * that widget developers do not add extra padding to their widgets. This will help 1625d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen * achieve consistency among widgets. 1634c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * 1644c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * Note: this method is only needed by developers of AppWidgetHosts. The method is provided in 1654c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * order for the AppWidgetHost to account for the automatic padding when computing the number 1664c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * of cells to allocate to a particular widget. 1674c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * 1684c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * @param context the current context 1694c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * @param component the component name of the widget 1704c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * @param padding Rect in which to place the output, if null, a new Rect will be allocated and 1714c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen * returned 172a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen * @return default padding for this widget, in pixels 1735d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen */ 1744c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen public static Rect getDefaultPaddingForWidget(Context context, ComponentName component, 1754c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen Rect padding) { 1764c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen PackageManager packageManager = context.getPackageManager(); 1775d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen ApplicationInfo appInfo; 1785d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen 1794c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen if (padding == null) { 1804c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding = new Rect(0, 0, 0, 0); 1814c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen } else { 1824c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding.set(0, 0, 0, 0); 1834c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen } 1844c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen 1855d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen try { 1865d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen appInfo = packageManager.getApplicationInfo(component.getPackageName(), 0); 1874c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen } catch (NameNotFoundException e) { 1885d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen // if we can't find the package, return 0 padding 1894c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen return padding; 1905d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen } 1915d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen 1925d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen if (appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 1934c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen Resources r = context.getResources(); 1944c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding.left = r.getDimensionPixelSize(com.android.internal. 1955d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen R.dimen.default_app_widget_padding_left); 1964c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding.right = r.getDimensionPixelSize(com.android.internal. 1975d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen R.dimen.default_app_widget_padding_right); 1984c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding.top = r.getDimensionPixelSize(com.android.internal. 1995d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen R.dimen.default_app_widget_padding_top); 2004c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen padding.bottom = r.getDimensionPixelSize(com.android.internal. 2015d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen R.dimen.default_app_widget_padding_bottom); 2025d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen } 2034c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen return padding; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 205c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato 206c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public int getAppWidgetId() { 207c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return mAppWidgetId; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 209e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 210c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetProviderInfo getAppWidgetInfo() { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mInfo; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy @Override 21509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 21609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ParcelableSparseArray jail = new ParcelableSparseArray(); 21709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy super.dispatchSaveInstanceState(jail); 21809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy container.put(generateId(), jail); 21909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 22009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 22109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy private int generateId() { 22209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int id = getId(); 22309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return id == View.NO_ID ? mAppWidgetId : id; 22409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 22509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 22609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy @Override 22709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 228ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy final Parcelable parcelable = container.get(generateId()); 229ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 230ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy ParcelableSparseArray jail = null; 231ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy if (parcelable != null && parcelable instanceof ParcelableSparseArray) { 232ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy jail = (ParcelableSparseArray) parcelable; 233ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy } 234ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 235a8a720d8cd208d7d265de28ab69f7e68eb10140aRomain Guy if (jail == null) jail = new ParcelableSparseArray(); 236ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 2376ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen try { 2386ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen super.dispatchRestoreInstanceState(jail); 2396ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen } catch (Exception e) { 2406ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen Log.e(TAG, "failed to restoreInstanceState for widget id: " + mAppWidgetId + ", " 2416ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen + (mInfo == null ? "null" : mInfo.provider), e); 2426ccf4e279170ef7f7602d1e2a63e9a2ef98cd57fAdam Cohen } 24309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 24409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 2454d1bf093396982d6838af934ab46672773772200Hyunyoung Song @Override 2464d1bf093396982d6838af934ab46672773772200Hyunyoung Song protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 2474d1bf093396982d6838af934ab46672773772200Hyunyoung Song try { 2484d1bf093396982d6838af934ab46672773772200Hyunyoung Song super.onLayout(changed, left, top, right, bottom); 2494d1bf093396982d6838af934ab46672773772200Hyunyoung Song } catch (final RuntimeException e) { 2504d1bf093396982d6838af934ab46672773772200Hyunyoung Song Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e); 2514d1bf093396982d6838af934ab46672773772200Hyunyoung Song removeViewInLayout(mView); 2524d1bf093396982d6838af934ab46672773772200Hyunyoung Song View child = getErrorView(); 2534d1bf093396982d6838af934ab46672773772200Hyunyoung Song prepareView(child); 2544d1bf093396982d6838af934ab46672773772200Hyunyoung Song addViewInLayout(child, 0, child.getLayoutParams()); 2554d1bf093396982d6838af934ab46672773772200Hyunyoung Song measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY), 2564d1bf093396982d6838af934ab46672773772200Hyunyoung Song MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); 2574d1bf093396982d6838af934ab46672773772200Hyunyoung Song child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight, 2584d1bf093396982d6838af934ab46672773772200Hyunyoung Song child.getMeasuredHeight() + mPaddingTop + mPaddingBottom); 2594d1bf093396982d6838af934ab46672773772200Hyunyoung Song mView = child; 2604d1bf093396982d6838af934ab46672773772200Hyunyoung Song mViewMode = VIEW_MODE_ERROR; 2614d1bf093396982d6838af934ab46672773772200Hyunyoung Song } 2624d1bf093396982d6838af934ab46672773772200Hyunyoung Song } 2634d1bf093396982d6838af934ab46672773772200Hyunyoung Song 264e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen /** 26588f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen * Provide guidance about the size of this widget to the AppWidgetManager. The widths and 26688f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen * heights should correspond to the full area the AppWidgetHostView is given. Padding added by 26788f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen * the framework will be accounted for automatically. This information gets embedded into the 26888f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen * AppWidget options and causes a callback to the AppWidgetProvider. 269d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle) 270c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen * 271a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen * @param newOptions The bundle of options, in addition to the size information, 272c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen * can be null. 2734ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen * @param minWidth The minimum width in dips that the widget will be displayed at. 2744ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen * @param minHeight The maximum height in dips that the widget will be displayed at. 2754ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen * @param maxWidth The maximum width in dips that the widget will be displayed at. 2764ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen * @param maxHeight The maximum height in dips that the widget will be displayed at. 277e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen * 278e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen */ 279a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth, 280c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen int maxHeight) { 2814ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight, false); 2824ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen } 2834ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen 2844ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen /** 2854ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen * @hide 2864ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen */ 2874ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth, 2884ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen int maxHeight, boolean ignorePadding) { 289a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen if (newOptions == null) { 290a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newOptions = new Bundle(); 291e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 29288f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen 29388f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen Rect padding = new Rect(); 29488f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen if (mInfo != null) { 29588f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen padding = getDefaultPaddingForWidget(mContext, mInfo.provider, padding); 29688f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen } 297f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen float density = getResources().getDisplayMetrics().density; 29888f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen 299f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen int xPaddingDips = (int) ((padding.left + padding.right) / density); 300f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen int yPaddingDips = (int) ((padding.top + padding.bottom) / density); 30188f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen 3024ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen int newMinWidth = minWidth - (ignorePadding ? 0 : xPaddingDips); 3034ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen int newMinHeight = minHeight - (ignorePadding ? 0 : yPaddingDips); 3044ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen int newMaxWidth = maxWidth - (ignorePadding ? 0 : xPaddingDips); 3054ddcd573dd06a96c32285e34469cae6e7f03109bAdam Cohen int newMaxHeight = maxHeight - (ignorePadding ? 0 : yPaddingDips); 306a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen 307a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext); 308a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen 309a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen // We get the old options to see if the sizes have changed 310a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen Bundle oldOptions = widgetManager.getAppWidgetOptions(mAppWidgetId); 311a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen boolean needsUpdate = false; 312a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen if (newMinWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) || 313a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newMinHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) || 314a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newMaxWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) || 315a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newMaxHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)) { 316a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen needsUpdate = true; 317a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen } 318a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen 319a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen if (needsUpdate) { 320a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, newMinWidth); 321a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, newMinHeight); 322a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, newMaxWidth); 323a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, newMaxHeight); 324a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen updateAppWidgetOptions(newOptions); 325a21bf0c6ea0205abced7bfdcaf552535f395f34fAdam Cohen } 326e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 327e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 328c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen /** 329c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen * Specify some extra information for the widget provider. Causes a callback to the 330c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen * AppWidgetProvider. 331d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle) 332c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen * 333d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen * @param options The bundle of options information. 334c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen */ 335d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen public void updateAppWidgetOptions(Bundle options) { 336d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen AppWidgetManager.getInstance(mContext).updateAppWidgetOptions(mAppWidgetId, options); 337e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 338e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 339b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey /** {@inheritDoc} */ 340b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey @Override 341b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey public LayoutParams generateLayoutParams(AttributeSet attrs) { 342b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // We're being asked to inflate parameters, probably by a LayoutInflater 343b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // in a remote Context. To help resolve any remote references, we 344b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // inflate through our last mRemoteContext when it exists. 345b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey final Context context = mRemoteContext != null ? mRemoteContext : mContext; 346b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey return new FrameLayout.LayoutParams(context, attrs); 347b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 348b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 350f960248951c1f71f54c02fa3867e8342b494ae70Sunny Goyal * Sets an executor which can be used for asynchronously inflating. CPU intensive tasks like 351f960248951c1f71f54c02fa3867e8342b494ae70Sunny Goyal * view inflation or loading images will be performed on the executor. The updates will still 352f960248951c1f71f54c02fa3867e8342b494ae70Sunny Goyal * be applied on the UI thread. 353dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal * 354dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal * @param executor the executor to use or null. 355dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal */ 3560ddf6aa0a4e5db30a19f27bb3372d8a86fba1660Sunny Goyal public void setExecutor(Executor executor) { 357dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal if (mLastExecutionSignal != null) { 358dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal.cancel(); 359dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal = null; 360dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 361dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 362dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mAsyncExecutor = executor; 363dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 364dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 365dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal /** 366c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato * Update the AppWidgetProviderInfo for this view, and reset it to the 367c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato * initial layout. 368c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato */ 369c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato void resetAppWidget(AppWidgetProviderInfo info) { 370c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato mInfo = info; 371c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato mViewMode = VIEW_MODE_NOINIT; 372c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato updateAppWidget(null); 373c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato } 374c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato 375c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato /** 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Process a set of {@link RemoteViews} coming in as an update from the 377ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy * AppWidget provider. Will animate into these new views as needed 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 379c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void updateAppWidget(RemoteViews remoteViews) { 3805c022639d7e1eebbeb190975980621a286bb2ff1Sunny Goyal applyRemoteViews(remoteViews, true); 381a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal } 382e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 383a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal /** 384a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal * @hide 385a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal */ 3865c022639d7e1eebbeb190975980621a286bb2ff1Sunny Goyal protected void applyRemoteViews(RemoteViews remoteViews, boolean useAsyncIfPossible) { 387c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld); 388f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean recycled = false; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View content = null; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Exception exception = null; 392e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Capture the old view into a bitmap so we can do the crossfade. 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime < 0) { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mView != null) { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int width = mView.getWidth(); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int height = mView.getHeight(); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (OutOfMemoryError e) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we just won't do the fade 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = null; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOld != null) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //mView.drawIntoBitmap(mOld); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 411e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 412dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal if (mLastExecutionSignal != null) { 413dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal.cancel(); 414dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal = null; 415dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 416dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (remoteViews == null) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mViewMode == VIEW_MODE_DEFAULT) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've already done this -- nothing to do. 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = getDefaultView(); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutId = -1; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_DEFAULT; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4265c022639d7e1eebbeb190975980621a286bb2ff1Sunny Goyal if (mAsyncExecutor != null && useAsyncIfPossible) { 427dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal inflateAsync(remoteViews); 428dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal return; 429dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 430b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Prepare a local reference to the remote Context so we're ready to 431b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // inflate any requested LayoutParams. 43239999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav mRemoteContext = getRemoteContext(); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int layoutId = remoteViews.getLayoutId(); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If our stale view has been prepared to match active, and the new 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // layout matches, try recycling it 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null && layoutId == mLayoutId) { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 439e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller remoteViews.reapply(mContext, mView, mOnClickHandler); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = mView; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycled = true; 4424d1bf093396982d6838af934ab46672773772200Hyunyoung Song if (LOGD) Log.d(TAG, "was able to recycle existing layout"); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 447e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try normal RemoteView inflation 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 451e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller content = remoteViews.apply(mContext, this, mOnClickHandler); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "had to inflate new layout"); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutId = layoutId; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_CONTENT; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 461e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 462dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal applyContent(content, recycled, exception); 463af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy updateContentDescription(mInfo); 464dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 465dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 466dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private void applyContent(View content, boolean recycled, Exception exception) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mViewMode == VIEW_MODE_ERROR) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've already done this -- nothing to do. 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 472c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = getErrorView(); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_ERROR; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 476e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!recycled) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prepareView(content); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addView(content); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mView != content) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeView(mView); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mView = content; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime < 0) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if there is already an animation in progress, don't do anything -- 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the new view will pop in on top of the old one during the cross fade, 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and that looks okay. 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeStartTime = SystemClock.uptimeMillis(); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 498af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy private void updateContentDescription(AppWidgetProviderInfo info) { 499af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy if (info != null) { 500af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy LauncherApps launcherApps = getContext().getSystemService(LauncherApps.class); 5017c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki ApplicationInfo appInfo = null; 5027c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki try { 5037c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki appInfo = launcherApps.getApplicationInfo( 5047c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki info.provider.getPackageName(), 0, info.getProfile()); 5057c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki } catch (NameNotFoundException e) { 5067c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki // ignore -- use null. 5077c7fbf6f45925b93833ab9d946b6704da0caf1fcMakoto Onuki } 508af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy if (appInfo != null && 509af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy (appInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0) { 510af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy setContentDescription( 511af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy Resources.getSystem().getString( 512af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy com.android.internal.R.string.suspended_widget_accessibility, info.label)); 513af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy } else { 514af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy setContentDescription(info.label); 515af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy } 516af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy } 517af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy } 518af6ef8f6f97e28e6f0bbb6947f70f4366116b09aKenny Guy 519dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private void inflateAsync(RemoteViews remoteViews) { 520dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // Prepare a local reference to the remote Context so we're ready to 521dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // inflate any requested LayoutParams. 522dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mRemoteContext = getRemoteContext(); 523dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal int layoutId = remoteViews.getLayoutId(); 524dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 525dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // If our stale view has been prepared to match active, and the new 526dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // layout matches, try recycling it 527dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal if (layoutId == mLayoutId && mView != null) { 528dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal try { 529dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal = remoteViews.reapplyAsync(mContext, 530dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mView, 531dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mAsyncExecutor, 532dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal new ViewApplyListener(remoteViews, layoutId, true), 533dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mOnClickHandler); 534dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } catch (Exception e) { 535dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // Reapply failed. Try apply 536dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 537dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 538dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal if (mLastExecutionSignal == null) { 539dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal = remoteViews.applyAsync(mContext, 540dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal this, 541dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mAsyncExecutor, 542dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal new ViewApplyListener(remoteViews, layoutId, false), 543dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mOnClickHandler); 544dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 545dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 546dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 547dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private class ViewApplyListener implements RemoteViews.OnViewAppliedListener { 548dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private final RemoteViews mViews; 549dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private final boolean mIsReapply; 550dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal private final int mLayoutId; 551dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 552dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal public ViewApplyListener(RemoteViews views, int layoutId, boolean isReapply) { 553dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mViews = views; 554dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLayoutId = layoutId; 555dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mIsReapply = isReapply; 556dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 557dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 558dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal @Override 559dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal public void onViewApplied(View v) { 560dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal AppWidgetHostView.this.mLayoutId = mLayoutId; 561dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mViewMode = VIEW_MODE_CONTENT; 562dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 563dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal applyContent(v, mIsReapply, null); 564dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 565dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 566dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal @Override 567dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal public void onError(Exception e) { 568dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal if (mIsReapply) { 569dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal // Try a fresh replay 570dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mLastExecutionSignal = mViews.applyAsync(mContext, 571dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal AppWidgetHostView.this, 572dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mAsyncExecutor, 573dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal new ViewApplyListener(mViews, mLayoutId, false), 574dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal mOnClickHandler); 575dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } else { 576dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal applyContent(null, false, e); 577dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 578dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 579dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal } 580dd292f4fab52f99d0b15fcf961864cd8186d662cSunny Goyal 581b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey /** 582499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Process data-changed notifications for the specified view in the specified 583499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * set of {@link RemoteViews} views. 584499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 5856394c0e52cf641d93f678fd052499aa952e3595dWinson Chung void viewDataChanged(int viewId) { 586499cb9f516062b654952d282f211bee44c31a3c2Winson Chung View v = findViewById(viewId); 587499cb9f516062b654952d282f211bee44c31a3c2Winson Chung if ((v != null) && (v instanceof AdapterView<?>)) { 588499cb9f516062b654952d282f211bee44c31a3c2Winson Chung AdapterView<?> adapterView = (AdapterView<?>) v; 589499cb9f516062b654952d282f211bee44c31a3c2Winson Chung Adapter adapter = adapterView.getAdapter(); 590499cb9f516062b654952d282f211bee44c31a3c2Winson Chung if (adapter instanceof BaseAdapter) { 591499cb9f516062b654952d282f211bee44c31a3c2Winson Chung BaseAdapter baseAdapter = (BaseAdapter) adapter; 592499cb9f516062b654952d282f211bee44c31a3c2Winson Chung baseAdapter.notifyDataSetChanged(); 5932148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen } else if (adapter == null && adapterView instanceof RemoteAdapterConnectionCallback) { 5942148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen // If the adapter is null, it may mean that the RemoteViewsAapter has not yet 5952148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen // connected to its associated service, and hence the adapter hasn't been set. 5962148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen // In this case, we need to defer the notify call until it has been set. 5972148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen ((RemoteAdapterConnectionCallback) adapterView).deferNotifyDataSetChanged(); 598499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 599499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 600499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 601499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 602499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 603b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey * Build a {@link Context} cloned into another package name, usually for the 604b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey * purposes of reading remote resources. 605a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal * @hide 606b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey */ 607a086f0436ad600915db1f8e0dc284d653d152e8dSunny Goyal protected Context getRemoteContext() { 608b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey try { 609b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Return if cloned successfully, otherwise default 61039999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav return mContext.createApplicationContext( 61139999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav mInfo.providerInfo.applicationInfo, 61239999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav Context.CONTEXT_RESTRICTED); 613b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } catch (NameNotFoundException e) { 61439999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found"); 615b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey return mContext; 616b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 617b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 618b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 6193030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne @Override 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha; 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int l = child.getLeft(); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int t = child.getTop(); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime > 0) { 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = (int)(((drawingTime-mFadeStartTime)*255)/FADE_DURATION); 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha > 255) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 255; 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "drawChild alpha=" + alpha + " l=" + l + " t=" + t 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " w=" + child.getWidth()); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha != 255 && mOld != null) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldPaint.setAlpha(255-alpha); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //canvas.drawBitmap(mOld, l, t, mOldPaint); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 255; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int restoreTo = canvas.saveLayerAlpha(l, t, child.getWidth(), child.getHeight(), alpha, 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean rv = super.drawChild(canvas, child, drawingTime); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restoreToCount(restoreTo); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha < 255) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeStartTime = -1; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOld != null) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld.recycle(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = null; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rv; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.drawChild(canvas, child, drawingTime); 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 657e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prepare the given view to be shown. This might include adjusting 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link FrameLayout.LayoutParams} before inserting. 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void prepareView(View view) { 663b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Take requested dimensions from child, but apply default gravity. 664b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams(); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (requested == null) { 666980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy requested = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 667980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy LayoutParams.MATCH_PARENT); 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 670b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey requested.gravity = Gravity.CENTER; 671b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey view.setLayoutParams(requested); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 673e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 675c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Inflate and return the default layout requested by AppWidget provider. 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View getDefaultView() { 678f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato if (LOGD) { 679f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato Log.d(TAG, "getDefaultView"); 680f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View defaultView = null; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Exception exception = null; 683e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInfo != null) { 68639999cf0263d0568337a87d0e586dcafd9e22ba1Svetoslav Context theirContext = getRemoteContext(); 687220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey mRemoteContext = theirContext; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutInflater inflater = (LayoutInflater) 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater = inflater.cloneInContext(theirContext); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater.setFilter(sInflaterFilter); 6920aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen AppWidgetManager manager = AppWidgetManager.getInstance(mContext); 6930aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Bundle options = manager.getAppWidgetOptions(mAppWidgetId); 6940aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 6950aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen int layoutId = mInfo.initialLayout; 6960aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen if (options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) { 6970aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY); 6980aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen if (category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) { 699180cfd5feb4fe415d04494bf00f2013896f93b77Adam Cohen int kgLayoutId = mInfo.initialKeyguardLayout; 700180cfd5feb4fe415d04494bf00f2013896f93b77Adam Cohen // If a default keyguard layout is not specified, use the standard 701180cfd5feb4fe415d04494bf00f2013896f93b77Adam Cohen // default layout. 702180cfd5feb4fe415d04494bf00f2013896f93b77Adam Cohen layoutId = kgLayoutId == 0 ? layoutId : kgLayoutId; 7030aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 7040aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 7050aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen defaultView = inflater.inflate(layoutId, this, false); 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "can't inflate defaultView because mInfo is missing"); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 712e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 713220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey if (exception != null) { 714220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString()); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 716e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (defaultView == null) { 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error"); 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultView = getErrorView(); 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 721e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return defaultView; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 724e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate and return a view that represents an error state. 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View getErrorView() { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextView tv = new TextView(mContext); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.setText(com.android.internal.R.string.gadget_host_error_inflating); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: get this color from somewhere. 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.setBackgroundColor(Color.argb(127, 0, 0, 0)); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tv; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 73509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 736a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 7371affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu @Override 738a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 739a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 7401affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu info.setClassName(AppWidgetHostView.class.getName()); 7411affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu } 7421affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu 74309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable { 74409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public int describeContents() { 74509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return 0; 74609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 74709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 74809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public void writeToParcel(Parcel dest, int flags) { 74909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int count = size(); 75009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeInt(count); 75109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy for (int i = 0; i < count; i++) { 75209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeInt(keyAt(i)); 75309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeParcelable(valueAt(i), 0); 75409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 75509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 75609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 75709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public static final Parcelable.Creator<ParcelableSparseArray> CREATOR = 75809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy new Parcelable.Creator<ParcelableSparseArray>() { 75909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public ParcelableSparseArray createFromParcel(Parcel source) { 76009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ParcelableSparseArray array = new ParcelableSparseArray(); 76109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ClassLoader loader = array.getClass().getClassLoader(); 76209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int count = source.readInt(); 76309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy for (int i = 0; i < count; i++) { 76409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy array.put(source.readInt(), source.readParcelable(loader)); 76509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 76609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return array; 76709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 76809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 76909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public ParcelableSparseArray[] newArray(int size) { 77009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return new ParcelableSparseArray[size]; 77109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 77209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy }; 77309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 775