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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 21b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Color; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 2709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.os.Parcelable; 2809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.os.Parcel; 29b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.util.AttributeSet; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 3109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.util.SparseArray; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.FrameLayout; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.TextView; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 40c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Provides the glue to show AppWidget views. This class offers automatic animation 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * between updates, and will try recycling old views for each incoming 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link RemoteViews}. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 44c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpublic class AppWidgetHostView extends FrameLayout { 45c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project static final String TAG = "AppWidgetHostView"; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final boolean LOGD = false; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final boolean CROSSFADE = false; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato static final int UPDATE_FLAGS_RESET = 0x00000001; 50f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_NOINIT = 0; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_CONTENT = 1; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_ERROR = 2; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int VIEW_MODE_DEFAULT = 3; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int FADE_DURATION = 1000; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 58c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // When we're inflating the initialLayout for a AppWidget, we only allow 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // views that are allowed in RemoteViews. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onLoadClass(Class clazz) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return clazz.isAnnotationPresent(RemoteViews.RemoteView.class); 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context mContext; 67b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey Context mRemoteContext; 68b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 69c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mAppWidgetId; 70c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AppWidgetProviderInfo mInfo; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View mView; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mViewMode = VIEW_MODE_NOINIT; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mLayoutId = -1; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mFadeStartTime = -1; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bitmap mOld; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint mOldPaint = new Paint(); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a host view. Uses default fade animations. 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 81c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetHostView(Context context) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, android.R.anim.fade_in, android.R.anim.fade_out); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a host view. Uses specified animations when pushing 87c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * {@link #updateAppWidget(RemoteViews)}. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param animationIn Resource ID of in animation to use 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param animationOut Resource ID of out animation to use 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 92a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy @SuppressWarnings({"UnusedDeclaration"}) 93c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetHostView(Context context, int animationIn, int animationOut) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 99c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Set the AppWidget that will be displayed by this view. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 101c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) { 102c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mAppWidgetId = appWidgetId; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInfo = info; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 106c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public int getAppWidgetId() { 107c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return mAppWidgetId; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 110c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetProviderInfo getAppWidgetInfo() { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mInfo; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy @Override 11509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 11609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ParcelableSparseArray jail = new ParcelableSparseArray(); 11709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy super.dispatchSaveInstanceState(jail); 11809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy container.put(generateId(), jail); 11909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 12009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 12109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy private int generateId() { 12209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int id = getId(); 12309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return id == View.NO_ID ? mAppWidgetId : id; 12409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 12509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 12609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy @Override 12709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 128ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy final Parcelable parcelable = container.get(generateId()); 129ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 130ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy ParcelableSparseArray jail = null; 131ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy if (parcelable != null && parcelable instanceof ParcelableSparseArray) { 132ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy jail = (ParcelableSparseArray) parcelable; 133ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy } 134ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 135a8a720d8cd208d7d265de28ab69f7e68eb10140aRomain Guy if (jail == null) jail = new ParcelableSparseArray(); 136ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy 13709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy super.dispatchRestoreInstanceState(jail); 13809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 13909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 140b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey /** {@inheritDoc} */ 141b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey @Override 142b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey public LayoutParams generateLayoutParams(AttributeSet attrs) { 143b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // We're being asked to inflate parameters, probably by a LayoutInflater 144b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // in a remote Context. To help resolve any remote references, we 145b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // inflate through our last mRemoteContext when it exists. 146b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey final Context context = mRemoteContext != null ? mRemoteContext : mContext; 147b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey return new FrameLayout.LayoutParams(context, attrs); 148b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 149b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Process a set of {@link RemoteViews} coming in as an update from the 152ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy * AppWidget provider. Will animate into these new views as needed 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 154c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void updateAppWidget(RemoteViews remoteViews) { 155f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato updateAppWidget(remoteViews, 0); 156f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 157f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato 158f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato void updateAppWidget(RemoteViews remoteViews, int flags) { 159f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld + " flags=0x" 160f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato + Integer.toHexString(flags)); 161f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato 162f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato if ((flags & UPDATE_FLAGS_RESET) != 0) { 163f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato mViewMode = VIEW_MODE_NOINIT; 164f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean recycled = false; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View content = null; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Exception exception = null; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Capture the old view into a bitmap so we can do the crossfade. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime < 0) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mView != null) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int width = mView.getWidth(); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int height = mView.getHeight(); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (OutOfMemoryError e) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we just won't do the fade 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = null; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOld != null) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //mView.drawIntoBitmap(mOld); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (remoteViews == null) { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mViewMode == VIEW_MODE_DEFAULT) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've already done this -- nothing to do. 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = getDefaultView(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutId = -1; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_DEFAULT; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 198b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Prepare a local reference to the remote Context so we're ready to 199b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // inflate any requested LayoutParams. 200b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey mRemoteContext = getRemoteContext(remoteViews); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int layoutId = remoteViews.getLayoutId(); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If our stale view has been prepared to match active, and the new 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // layout matches, try recycling it 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null && layoutId == mLayoutId) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remoteViews.reapply(mContext, mView); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = mView; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycled = true; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "was able to recycled existing layout"); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try normal RemoteView inflation 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = remoteViews.apply(mContext, this); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "had to inflate new layout"); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutId = layoutId; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_CONTENT; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (content == null) { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mViewMode == VIEW_MODE_ERROR) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've already done this -- nothing to do. 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 235c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content = getErrorView(); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mViewMode = VIEW_MODE_ERROR; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!recycled) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prepareView(content); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addView(content); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mView != content) { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeView(mView); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mView = content; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime < 0) { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if there is already an animation in progress, don't do anything -- 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the new view will pop in on top of the old one during the cross fade, 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and that looks okay. 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeStartTime = SystemClock.uptimeMillis(); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 261b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey /** 262b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey * Build a {@link Context} cloned into another package name, usually for the 263b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey * purposes of reading remote resources. 264b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey */ 265b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey private Context getRemoteContext(RemoteViews views) { 266b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Bail if missing package name 267b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey final String packageName = views.getPackage(); 268b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey if (packageName == null) return mContext; 269b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 270b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey try { 271b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Return if cloned successfully, otherwise default 272b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey return mContext.createPackageContext(packageName, Context.CONTEXT_RESTRICTED); 273b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } catch (NameNotFoundException e) { 274b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey Log.e(TAG, "Package name " + packageName + " not found"); 275b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey return mContext; 276b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 277b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey } 278b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (CROSSFADE) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int l = child.getLeft(); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int t = child.getTop(); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFadeStartTime > 0) { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = (int)(((drawingTime-mFadeStartTime)*255)/FADE_DURATION); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha > 255) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 255; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "drawChild alpha=" + alpha + " l=" + l + " t=" + t 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " w=" + child.getWidth()); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha != 255 && mOld != null) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldPaint.setAlpha(255-alpha); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //canvas.drawBitmap(mOld, l, t, mOldPaint); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 255; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int restoreTo = canvas.saveLayerAlpha(l, t, child.getWidth(), child.getHeight(), alpha, 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean rv = super.drawChild(canvas, child, drawingTime); 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restoreToCount(restoreTo); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha < 255) { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeStartTime = -1; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOld != null) { 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld.recycle(); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOld = null; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rv; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.drawChild(canvas, child, drawingTime); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prepare the given view to be shown. This might include adjusting 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link FrameLayout.LayoutParams} before inserting. 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void prepareView(View view) { 322b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey // Take requested dimensions from child, but apply default gravity. 323b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams(); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (requested == null) { 325980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy requested = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 326980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy LayoutParams.MATCH_PARENT); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 328b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey 329b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey requested.gravity = Gravity.CENTER; 330b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey view.setLayoutParams(requested); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 334c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Inflate and return the default layout requested by AppWidget provider. 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View getDefaultView() { 337f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato if (LOGD) { 338f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato Log.d(TAG, "getDefaultView"); 339f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View defaultView = null; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Exception exception = null; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInfo != null) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context theirContext = mContext.createPackageContext( 346870e09fcd2dfdc12ac318962efd28b0420c562bbRomain Guy mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED); 347220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey mRemoteContext = theirContext; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutInflater inflater = (LayoutInflater) 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater = inflater.cloneInContext(theirContext); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater.setFilter(sInflaterFilter); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultView = inflater.inflate(mInfo.initialLayout, this, false); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "can't inflate defaultView because mInfo is missing"); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PackageManager.NameNotFoundException e) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exception = e; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 362220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey if (exception != null) { 363220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString()); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (defaultView == null) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error"); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultView = getErrorView(); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return defaultView; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate and return a view that represents an error state. 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View getErrorView() { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextView tv = new TextView(mContext); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.setText(com.android.internal.R.string.gadget_host_error_inflating); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: get this color from somewhere. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.setBackgroundColor(Color.argb(127, 0, 0, 0)); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tv; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 38509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable { 38609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public int describeContents() { 38709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return 0; 38809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 38909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 39009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public void writeToParcel(Parcel dest, int flags) { 39109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int count = size(); 39209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeInt(count); 39309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy for (int i = 0; i < count; i++) { 39409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeInt(keyAt(i)); 39509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy dest.writeParcelable(valueAt(i), 0); 39609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 39709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 39809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 39909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public static final Parcelable.Creator<ParcelableSparseArray> CREATOR = 40009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy new Parcelable.Creator<ParcelableSparseArray>() { 40109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public ParcelableSparseArray createFromParcel(Parcel source) { 40209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ParcelableSparseArray array = new ParcelableSparseArray(); 40309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final ClassLoader loader = array.getClass().getClassLoader(); 40409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy final int count = source.readInt(); 40509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy for (int i = 0; i < count; i++) { 40609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy array.put(source.readInt(), source.readParcelable(loader)); 40709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 40809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return array; 40909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 41009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy 41109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy public ParcelableSparseArray[] newArray(int size) { 41209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy return new ParcelableSparseArray[size]; 41309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 41409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy }; 41509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 417