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;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
23b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
245d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.content.res.Resources;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Color;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint;
294c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohenimport android.graphics.Rect;
305d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohenimport android.os.Build;
31e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohenimport android.os.Bundle;
3209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.os.Parcel;
333030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport android.os.Parcelable;
343030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport android.os.SystemClock;
35b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkeyimport android.util.AttributeSet;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
3709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guyimport android.util.SparseArray;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
411affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhuimport android.view.accessibility.AccessibilityNodeInfo;
42499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.Adapter;
43499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.AdapterView;
44499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.BaseAdapter;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.FrameLayout;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews;
472148d43eb23c702e834c93ae427f822f32d280a2Adam Cohenimport android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
484c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohenimport android.widget.TextView;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
51c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Provides the glue to show AppWidget views. This class offers automatic animation
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * between updates, and will try recycling old views for each incoming
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link RemoteViews}.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
55c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpublic class AppWidgetHostView extends FrameLayout {
56c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    static final String TAG = "AppWidgetHostView";
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean LOGD = false;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean CROSSFADE = false;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int VIEW_MODE_NOINIT = 0;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int VIEW_MODE_CONTENT = 1;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int VIEW_MODE_ERROR = 2;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int VIEW_MODE_DEFAULT = 3;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int FADE_DURATION = 1000;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    // When we're inflating the initialLayout for a AppWidget, we only allow
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // views that are allowed in RemoteViews.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() {
70e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        public boolean onLoadClass(Class clazz) {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Context mContext;
76b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    Context mRemoteContext;
77b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey
78c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    int mAppWidgetId;
79c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    AppWidgetProviderInfo mInfo;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mView;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mViewMode = VIEW_MODE_NOINIT;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLayoutId = -1;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mFadeStartTime = -1;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Bitmap mOld;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Paint mOldPaint = new Paint();
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a host view.  Uses default fade animations.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
90c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public AppWidgetHostView(Context context) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a host view. Uses specified animations when pushing
96c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * {@link #updateAppWidget(RemoteViews)}.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param animationIn Resource ID of in animation to use
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param animationOut Resource ID of out animation to use
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
101a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
102c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public AppWidgetHostView(Context context, int animationIn, int animationOut) {
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
105d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen
106d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen        // We want to segregate the view ids within AppWidgets to prevent
107d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen        // problems when those ids collide with view ids in the AppWidgetHost.
108d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen        setIsRootNamespace(true);
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
110d110889cbca4d40f8cdeddfe6eb2f498f470ae4bAdam Cohen
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1124c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * Set the AppWidget that will be displayed by this view. This method also adds default padding
1134c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
1144c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * and can be overridden in order to add custom padding.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
116c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) {
117c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        mAppWidgetId = appWidgetId;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInfo = info;
1195d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen
1205d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        // Sometimes the AppWidgetManager returns a null AppWidgetProviderInfo object for
1215d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        // a widget, eg. for some widgets in safe mode.
1225d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        if (info != null) {
1235d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen            // We add padding to the AppWidgetHostView if necessary
1244c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null);
1255d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen            setPadding(padding.left, padding.top, padding.right, padding.bottom);
1265d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        }
1275d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen    }
1285d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen
1295d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen    /**
1305d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen     * As of ICE_CREAM_SANDWICH we are automatically adding padding to widgets targeting
1315d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen     * ICE_CREAM_SANDWICH and higher. The new widget design guidelines strongly recommend
1325d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen     * that widget developers do not add extra padding to their widgets. This will help
1335d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen     * achieve consistency among widgets.
1344c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     *
1354c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * Note: this method is only needed by developers of AppWidgetHosts. The method is provided in
1364c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * order for the AppWidgetHost to account for the automatic padding when computing the number
1374c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * of cells to allocate to a particular widget.
1384c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     *
1394c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * @param context the current context
1404c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * @param component the component name of the widget
1414c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * @param padding Rect in which to place the output, if null, a new Rect will be allocated and
1424c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     *                returned
1434c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen     * @return default padding for this widget
1445d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen     */
1454c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen    public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
1464c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            Rect padding) {
1474c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        PackageManager packageManager = context.getPackageManager();
1485d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        ApplicationInfo appInfo;
1495d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen
1504c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        if (padding == null) {
1514c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding = new Rect(0, 0, 0, 0);
1524c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        } else {
1534c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding.set(0, 0, 0, 0);
1544c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        }
1554c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen
1565d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        try {
1575d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen            appInfo = packageManager.getApplicationInfo(component.getPackageName(), 0);
1584c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        } catch (NameNotFoundException e) {
1595d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen            // if we can't find the package, return 0 padding
1604c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            return padding;
1615d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        }
1625d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen
1635d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        if (appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1644c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            Resources r = context.getResources();
1654c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding.left = r.getDimensionPixelSize(com.android.internal.
1665d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen                    R.dimen.default_app_widget_padding_left);
1674c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding.right = r.getDimensionPixelSize(com.android.internal.
1685d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen                    R.dimen.default_app_widget_padding_right);
1694c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding.top = r.getDimensionPixelSize(com.android.internal.
1705d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen                    R.dimen.default_app_widget_padding_top);
1714c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen            padding.bottom = r.getDimensionPixelSize(com.android.internal.
1725d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen                    R.dimen.default_app_widget_padding_bottom);
1735d5f3405204ecb5045edc756fde71c97d10bcda4Adam Cohen        }
1744c96a59b4354c4a593a07a3273c186b51597bcc1Adam Cohen        return padding;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
176c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato
177c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public int getAppWidgetId() {
178c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        return mAppWidgetId;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
181c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public AppWidgetProviderInfo getAppWidgetInfo() {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInfo;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    @Override
18609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
18709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        final ParcelableSparseArray jail = new ParcelableSparseArray();
18809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        super.dispatchSaveInstanceState(jail);
18909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        container.put(generateId(), jail);
19009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    }
19109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
19209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    private int generateId() {
19309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        final int id = getId();
19409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        return id == View.NO_ID ? mAppWidgetId : id;
19509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    }
19609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
19709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    @Override
19809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
199ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy        final Parcelable parcelable = container.get(generateId());
200ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy
201ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy        ParcelableSparseArray jail = null;
202ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy        if (parcelable != null && parcelable instanceof ParcelableSparseArray) {
203ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy            jail = (ParcelableSparseArray) parcelable;
204ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy        }
205ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy
206a8a720d8cd208d7d265de28ab69f7e68eb10140aRomain Guy        if (jail == null) jail = new ParcelableSparseArray();
207ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy
20809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        super.dispatchRestoreInstanceState(jail);
20909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    }
21009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
211e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen    /**
21288f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen     * Provide guidance about the size of this widget to the AppWidgetManager. The widths and
21388f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen     * heights should correspond to the full area the AppWidgetHostView is given. Padding added by
21488f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen     * the framework will be accounted for automatically. This information gets embedded into the
21588f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen     * AppWidget options and causes a callback to the AppWidgetProvider.
216d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
217c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     *
218d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @param options The bundle of options, in addition to the size information,
219c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     *          can be null.
220c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     * @param minWidth The minimum width that the widget will be displayed at.
221c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     * @param minHeight The maximum height that the widget will be displayed at.
222d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @param maxWidth The maximum width that the widget will be displayed at.
223d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @param maxHeight The maximum height that the widget will be displayed at.
224e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen     *
225e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen     */
226d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen    public void updateAppWidgetSize(Bundle options, int minWidth, int minHeight, int maxWidth,
227c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen            int maxHeight) {
228d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen        if (options == null) {
229d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen            options = new Bundle();
230e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen        }
23188f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen
23288f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen        Rect padding = new Rect();
23388f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen        if (mInfo != null) {
23488f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen            padding = getDefaultPaddingForWidget(mContext, mInfo.provider, padding);
23588f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen        }
236f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        float density = getResources().getDisplayMetrics().density;
23788f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen
238f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        int xPaddingDips = (int) ((padding.left + padding.right) / density);
239f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
24088f041ed312299f1d2746e570b989c336bfd97c8Adam Cohen
241f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, minWidth - xPaddingDips);
242f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, minHeight - yPaddingDips);
243f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, maxWidth - xPaddingDips);
244f065c9663172094d2d79eb5f77c59d89e812437aAdam Cohen        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, maxHeight - yPaddingDips);
245d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen        updateAppWidgetOptions(options);
246e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen    }
247e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
248c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen    /**
249c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     * Specify some extra information for the widget provider. Causes a callback to the
250c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     * AppWidgetProvider.
251d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
252c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     *
253d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen     * @param options The bundle of options information.
254c88d11f9493e65d318dcd3b094ef446e1905ebfdAdam Cohen     */
255d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen    public void updateAppWidgetOptions(Bundle options) {
256d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen        AppWidgetManager.getInstance(mContext).updateAppWidgetOptions(mAppWidgetId, options);
257e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen    }
258e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
259b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    /** {@inheritDoc} */
260b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    @Override
261b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    public LayoutParams generateLayoutParams(AttributeSet attrs) {
262b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        // We're being asked to inflate parameters, probably by a LayoutInflater
263b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        // in a remote Context. To help resolve any remote references, we
264b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        // inflate through our last mRemoteContext when it exists.
265b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        final Context context = mRemoteContext != null ? mRemoteContext : mContext;
266b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        return new FrameLayout.LayoutParams(context, attrs);
267b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    }
268b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
270c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato     * Update the AppWidgetProviderInfo for this view, and reset it to the
271c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato     * initial layout.
272c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato     */
273c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato    void resetAppWidget(AppWidgetProviderInfo info) {
274c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato        mInfo = info;
275c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato        mViewMode = VIEW_MODE_NOINIT;
276c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato        updateAppWidget(null);
277c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato    }
278c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato
279c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato    /**
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Process a set of {@link RemoteViews} coming in as an update from the
281ae8dd29c035fffa6e302bd485d0552f97db39127Romain Guy     * AppWidget provider. Will animate into these new views as needed
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
283c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void updateAppWidget(RemoteViews remoteViews) {
284c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato        if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
285f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean recycled = false;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View content = null;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Exception exception = null;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Capture the old view into a bitmap so we can do the crossfade.
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (CROSSFADE) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mFadeStartTime < 0) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mView != null) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int width = mView.getWidth();
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int height = mView.getHeight();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mOld = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (OutOfMemoryError e) {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we just won't do the fade
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mOld = null;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mOld != null) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        //mView.drawIntoBitmap(mOld);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (remoteViews == null) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mViewMode == VIEW_MODE_DEFAULT) {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We've already done this -- nothing to do.
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            content = getDefaultView();
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayoutId = -1;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mViewMode = VIEW_MODE_DEFAULT;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
318b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            // Prepare a local reference to the remote Context so we're ready to
319b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            // inflate any requested LayoutParams.
320b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            mRemoteContext = getRemoteContext(remoteViews);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int layoutId = remoteViews.getLayoutId();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If our stale view has been prepared to match active, and the new
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // layout matches, try recycling it
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (content == null && layoutId == mLayoutId) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    remoteViews.reapply(mContext, mView);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    content = mView;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    recycled = true;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (LOGD) Log.d(TAG, "was able to recycled existing layout");
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RuntimeException e) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    exception = e;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Try normal RemoteView inflation
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (content == null) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    content = remoteViews.apply(mContext, this);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (LOGD) Log.d(TAG, "had to inflate new layout");
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RuntimeException e) {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    exception = e;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayoutId = layoutId;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mViewMode = VIEW_MODE_CONTENT;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (content == null) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mViewMode == VIEW_MODE_ERROR) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We've already done this -- nothing to do.
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
355c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            content = getErrorView();
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mViewMode = VIEW_MODE_ERROR;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!recycled) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            prepareView(content);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addView(content);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mView != content) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            removeView(mView);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mView = content;
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (CROSSFADE) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mFadeStartTime < 0) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // if there is already an animation in progress, don't do anything --
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the new view will pop in on top of the old one during the cross fade,
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // and that looks okay.
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFadeStartTime = SystemClock.uptimeMillis();
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invalidate();
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
381b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    /**
382499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * Process data-changed notifications for the specified view in the specified
383499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * set of {@link RemoteViews} views.
384499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     */
3856394c0e52cf641d93f678fd052499aa952e3595dWinson Chung    void viewDataChanged(int viewId) {
386499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        View v = findViewById(viewId);
387499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        if ((v != null) && (v instanceof AdapterView<?>)) {
388499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            AdapterView<?> adapterView = (AdapterView<?>) v;
389499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            Adapter adapter = adapterView.getAdapter();
390499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            if (adapter instanceof BaseAdapter) {
391499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                BaseAdapter baseAdapter = (BaseAdapter) adapter;
392499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                baseAdapter.notifyDataSetChanged();
3932148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen            }  else if (adapter == null && adapterView instanceof RemoteAdapterConnectionCallback) {
3942148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                // If the adapter is null, it may mean that the RemoteViewsAapter has not yet
3952148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                // connected to its associated service, and hence the adapter hasn't been set.
3962148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                // In this case, we need to defer the notify call until it has been set.
3972148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                ((RemoteAdapterConnectionCallback) adapterView).deferNotifyDataSetChanged();
398499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            }
399499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
400499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
401499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
402499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    /**
403b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey     * Build a {@link Context} cloned into another package name, usually for the
404b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey     * purposes of reading remote resources.
405b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey     */
406b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    private Context getRemoteContext(RemoteViews views) {
407b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        // Bail if missing package name
408b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        final String packageName = views.getPackage();
409b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        if (packageName == null) return mContext;
410b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey
411b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        try {
412b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            // Return if cloned successfully, otherwise default
413b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            return mContext.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
414b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        } catch (NameNotFoundException e) {
415b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            Log.e(TAG, "Package name " + packageName + " not found");
416b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey            return mContext;
417b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        }
418b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey    }
419b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey
4203030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne    @Override
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (CROSSFADE) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int alpha;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int l = child.getLeft();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int t = child.getTop();
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mFadeStartTime > 0) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                alpha = (int)(((drawingTime-mFadeStartTime)*255)/FADE_DURATION);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (alpha > 255) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    alpha = 255;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.d(TAG, "drawChild alpha=" + alpha + " l=" + l + " t=" + t
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " w=" + child.getWidth());
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (alpha != 255 && mOld != null) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mOldPaint.setAlpha(255-alpha);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    //canvas.drawBitmap(mOld, l, t, mOldPaint);
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                alpha = 255;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int restoreTo = canvas.saveLayerAlpha(l, t, child.getWidth(), child.getHeight(), alpha,
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean rv = super.drawChild(canvas, child, drawingTime);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.restoreToCount(restoreTo);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (alpha < 255) {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invalidate();
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFadeStartTime = -1;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mOld != null) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mOld.recycle();
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mOld = null;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return rv;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.drawChild(canvas, child, drawingTime);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prepare the given view to be shown. This might include adjusting
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link FrameLayout.LayoutParams} before inserting.
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void prepareView(View view) {
464b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        // Take requested dimensions from child, but apply default gravity.
465b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams();
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (requested == null) {
467980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy            requested = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
468980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                    LayoutParams.MATCH_PARENT);
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
470b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey
471b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        requested.gravity = Gravity.CENTER;
472b8560b66fd2bdf465a8c7fad983f2236778e8106Jeff Sharkey        view.setLayoutParams(requested);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
476c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Inflate and return the default layout requested by AppWidget provider.
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View getDefaultView() {
479f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        if (LOGD) {
480f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato            Log.d(TAG, "getDefaultView");
481f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View defaultView = null;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Exception exception = null;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInfo != null) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context theirContext = mContext.createPackageContext(
488870e09fcd2dfdc12ac318962efd28b0420c562bbRomain Guy                        mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED);
489220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey                mRemoteContext = theirContext;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LayoutInflater inflater = (LayoutInflater)
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inflater = inflater.cloneInContext(theirContext);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inflater.setFilter(sInflaterFilter);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                defaultView = inflater.inflate(mInfo.initialLayout, this, false);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w(TAG, "can't inflate defaultView because mInfo is missing");
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (PackageManager.NameNotFoundException e) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            exception = e;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            exception = e;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
504220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey        if (exception != null) {
505220dec2897d739ecb627e46b4cafbd664f4ff762Jeff Sharkey            Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (defaultView == null) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            defaultView = getErrorView();
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return defaultView;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate and return a view that represents an error state.
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View getErrorView() {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TextView tv = new TextView(mContext);
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tv.setText(com.android.internal.R.string.gadget_host_error_inflating);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: get this color from somewhere.
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tv.setBackgroundColor(Color.argb(127, 0, 0, 0));
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return tv;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
52609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
5271affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu    @Override
5281affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5291affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu        super.onInitializeAccessibilityNodeInfo(info);
5301affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu        info.setClassName(AppWidgetHostView.class.getName());
5311affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu    }
5321affb937641fd42c3b94f0c2427b1b68336a572fGuang Zhu
53309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
53409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        public int describeContents() {
53509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy            return 0;
53609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        }
53709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
53809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        public void writeToParcel(Parcel dest, int flags) {
53909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy            final int count = size();
54009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy            dest.writeInt(count);
54109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy            for (int i = 0; i < count; i++) {
54209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                dest.writeInt(keyAt(i));
54309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                dest.writeParcelable(valueAt(i), 0);
54409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy            }
54509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        }
54609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
54709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy        public static final Parcelable.Creator<ParcelableSparseArray> CREATOR =
54809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                new Parcelable.Creator<ParcelableSparseArray>() {
54909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                    public ParcelableSparseArray createFromParcel(Parcel source) {
55009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        final ParcelableSparseArray array = new ParcelableSparseArray();
55109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        final ClassLoader loader = array.getClass().getClassLoader();
55209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        final int count = source.readInt();
55309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        for (int i = 0; i < count; i++) {
55409ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                            array.put(source.readInt(), source.readParcelable(loader));
55509ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        }
55609ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        return array;
55709ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                    }
55809ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy
55909ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                    public ParcelableSparseArray[] newArray(int size) {
56009ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                        return new ParcelableSparseArray[size];
56109ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                    }
56209ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy                };
56309ddc08b0d9c849e22f778666f383b7ceefbd9c8Romain Guy    }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
565