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