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