19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 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
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlarmManager;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
21c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.appwidget.AppWidgetManager;
22c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.appwidget.AppWidgetProviderInfo;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
27c3f581b0474a216938810885f4f606e0db1f21ffWinson Chungimport android.content.Intent.FilterComparison;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
2981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport android.content.ServiceConnection;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ActivityInfo;
31331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onoratoimport android.content.pm.ApplicationInfo;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageInfo;
3381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport android.content.pm.PackageManager;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
3581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport android.content.pm.ServiceInfo;
3620cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackbornimport android.content.res.Resources;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
42c3f581b0474a216938810885f4f606e0db1f21ffWinson Chungimport android.os.Handler;
43c3f581b0474a216938810885f4f606e0db1f21ffWinson Chungimport android.os.HandlerThread;
4481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport android.os.IBinder;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
4816c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chungimport android.util.Log;
4981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport android.util.Pair;
508a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
518f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshimaimport android.util.TypedValue;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport com.android.internal.appwidget.IAppWidgetHost;
5681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport com.android.internal.appwidget.IAppWidgetService;
579730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport com.android.internal.os.AtomicFile;
582269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
5981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chungimport com.android.internal.widget.IRemoteViewsAdapterConnection;
6084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chungimport com.android.internal.widget.IRemoteViewsFactory;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport org.xmlpull.v1.XmlPullParser;
639730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport org.xmlpull.v1.XmlPullParserException;
649730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport org.xmlpull.v1.XmlSerializer;
659730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen
669730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.File;
679730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.FileDescriptor;
689730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.FileInputStream;
699730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.FileNotFoundException;
709730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.FileOutputStream;
719730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.IOException;
729730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.io.PrintWriter;
739730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.ArrayList;
749730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.HashMap;
759730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.HashSet;
769730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.Iterator;
779730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.List;
789730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohenimport java.util.Locale;
79c3f581b0474a216938810885f4f606e0db1f21ffWinson Chungimport java.util.Set;
809730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen
81c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectclass AppWidgetService extends IAppWidgetService.Stub
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
83c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    private static final String TAG = "AppWidgetService";
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
85c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    private static final String SETTINGS_FILENAME = "appwidgets.xml";
86be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato    private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * When identifying a Host or Provider based on the calling process, use the uid field.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * When identifying a Host or Provider based on a package manager broadcast, use the
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * package given.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class Provider {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int uid;
96c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        AppWidgetProviderInfo info;
97a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent broadcast;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int tag;    // for use while saving state (the index)
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class Host {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int uid;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int hostId;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String packageName;
108a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
109c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        IAppWidgetHost callbacks;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int tag;    // for use while saving state (the index)
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
115c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    static class AppWidgetId {
116c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        int appWidgetId;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Provider provider;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RemoteViews views;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Host host;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    /**
12381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung     * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection.
12481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung     * This needs to be a static inner class since a reference to the ServiceConnection is held
12581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung     * globally and may lead us to leak AppWidgetService instances (if there were more than one).
12681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung     */
12781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    static class ServiceConnectionProxy implements ServiceConnection {
12881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        private final Pair<Integer, Intent.FilterComparison> mKey;
12981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        private final IBinder mConnectionCb;
13081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
13116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
13281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            mKey = key;
13381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            mConnectionCb = connectionCb;
13481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
13581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        public void onServiceConnected(ComponentName name, IBinder service) {
13616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            final IRemoteViewsAdapterConnection cb =
13781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
13881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            try {
13981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                cb.onServiceConnected(service);
140c2be22cf209b675e36893d31ebe3166b6321ba6bAdam Cohen            } catch (Exception e) {
14181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                e.printStackTrace();
14281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
14381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
14481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        public void onServiceDisconnected(ComponentName name) {
14516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            disconnect();
14616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        }
14716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        public void disconnect() {
14816c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            final IRemoteViewsAdapterConnection cb =
14981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
15081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            try {
15181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                cb.onServiceDisconnected();
152c2be22cf209b675e36893d31ebe3166b6321ba6bAdam Cohen            } catch (Exception e) {
15381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                e.printStackTrace();
15481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
15581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
15681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    }
15781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
15884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Manages active connections to RemoteViewsServices
15981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection>
16081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        mBoundRemoteViewsServices = new HashMap<Pair<Integer,FilterComparison>,ServiceConnection>();
16184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Manages persistent references to RemoteViewsServices from different App Widgets
16284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    private final HashMap<FilterComparison, HashSet<Integer>>
16384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        mRemoteViewsServicesAppWidgets = new HashMap<FilterComparison, HashSet<Integer>>();
16481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Context mContext;
16663c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer    Locale mLocale;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PackageManager mPackageManager;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AlarmManager mAlarmManager;
169a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy    ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
170c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
171a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy    final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
172a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy    ArrayList<Host> mHosts = new ArrayList<Host>();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mSafeMode;
17415d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey    boolean mStateLoaded;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1767bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    // These are for debugging only -- widgets are going missing in some rare instances
1777bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>();
1787bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    ArrayList<Host> mDeletedHosts = new ArrayList<Host>();
1797bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
180c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    AppWidgetService(Context context) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPackageManager = context.getPackageManager();
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void systemReady(boolean safeMode) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSafeMode = safeMode;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18915d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey        synchronized (mAppWidgetIds) {
19015d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
19115d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey        }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for the boot completed broadcast, so we can send the
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // ENABLE broacasts.  If we try to send them now, they time out,
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // because the system isn't ready to handle them yet.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.registerReceiver(mBroadcastReceiver,
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19963c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer        // Register for configuration changes so we can update the names
20063c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer        // of the widgets when the locale changes.
20163c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer        mContext.registerReceiver(mBroadcastReceiver,
20263c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null);
20363c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for broadcasts about package install, etc., so we can
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // update the provider list.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
208d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addDataScheme("package");
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.registerReceiver(mBroadcastReceiver, filter);
21208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        // Register for events related to sdcard installation.
21308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        IntentFilter sdFilter = new IntentFilter();
214b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
215b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
21608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21915d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey    private void ensureStateLoadedLocked() {
22015d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey        if (!mStateLoaded) {
22115d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            loadAppWidgetList();
22215d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            loadStateLocked();
22315d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            mStateLoaded = true;
22415d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey        }
22515d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey    }
22615d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey
2277bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    private void dumpProvider(Provider p, int index, PrintWriter pw) {
2287bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        AppWidgetProviderInfo info = p.info;
2297bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("  ["); pw.print(index); pw.print("] provider ");
2307bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(info.provider.flattenToShortString());
2317bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.println(':');
2327bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("    min=("); pw.print(info.minWidth);
2337bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print("x"); pw.print(info.minHeight);
2347bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print(")   minResize=("); pw.print(info.minResizeWidth);
2357bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print("x"); pw.print(info.minResizeHeight);
2367bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(") updatePeriodMillis=");
2377bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(info.updatePeriodMillis);
2387bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(" resizeMode=");
2397bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(info.resizeMode);
2407bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(" autoAdvanceViewId=");
2417bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(info.autoAdvanceViewId);
2427bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(" initialLayout=#");
2437bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(Integer.toHexString(info.initialLayout));
2447bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(" zombie="); pw.println(p.zombie);
2457bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    }
2467bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
2477bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    private void dumpHost(Host host, int index, PrintWriter pw) {
2487bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("  ["); pw.print(index); pw.print("] hostId=");
2497bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(host.hostId); pw.print(' ');
2507bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(host.packageName); pw.print('/');
2517bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print(host.uid); pw.println(':');
2527bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("    callbacks="); pw.println(host.callbacks);
2537bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("    instances.size="); pw.print(host.instances.size());
2547bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(" zombie="); pw.println(host.zombie);
2557bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    }
2567bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
2577bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    private void dumpAppWidgetId(AppWidgetId id, int index, PrintWriter pw) {
2587bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("  ["); pw.print(index); pw.print("] id=");
2597bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.println(id.appWidgetId);
2607bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        pw.print("    hostId=");
2617bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(id.host.hostId); pw.print(' ');
2627bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.print(id.host.packageName); pw.print('/');
2637bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                pw.println(id.host.uid);
2647bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        if (id.provider != null) {
2657bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.print("    provider=");
2667bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                    pw.println(id.provider.info.provider.flattenToShortString());
2677bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        }
2687bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        if (id.host != null) {
2697bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.print("    host.callbacks="); pw.println(id.host.callbacks);
2707bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        }
2717bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        if (id.views != null) {
2727bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.print("    views="); pw.println(id.views);
2737bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        }
2747bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen    }
2757bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump from from pid="
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
286c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mInstalledProviders.size();
2881d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            pw.println("Providers:");
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
2907bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                dumpProvider(mInstalledProviders.get(i), i, pw);
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
293c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            N = mAppWidgetIds.size();
2941d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            pw.println(" ");
2951d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            pw.println("AppWidgetIds:");
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
2977bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                dumpAppWidgetId(mAppWidgetIds.get(i), i, pw);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            N = mHosts.size();
3011d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            pw.println(" ");
3021d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            pw.println("Hosts:");
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
3047bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                dumpHost(mHosts.get(i), i, pw);
3057bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            }
3067bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
3077bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            N = mDeletedProviders.size();
3087bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.println(" ");
3097bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.println("Deleted Providers:");
3107bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            for (int i=0; i<N; i++) {
3117bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                dumpProvider(mDeletedProviders.get(i), i, pw);
3127bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            }
3137bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen
3147bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            N = mDeletedHosts.size();
3157bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.println(" ");
3167bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            pw.println("Deleted Hosts:");
3177bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen            for (int i=0; i<N; i++) {
3187bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen                dumpHost(mDeletedHosts.get(i), i, pw);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
323c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public int allocateAppWidgetId(String packageName, int hostId) {
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int callingUid = enforceCallingUid(packageName);
325c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
32615d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
327c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            int appWidgetId = mNextAppWidgetId++;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
331c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = new AppWidgetId();
332c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            id.appWidgetId = appWidgetId;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id.host = host;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            host.instances.add(id);
336c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            mAppWidgetIds.add(id);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            saveStateLocked();
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
340c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            return appWidgetId;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
344c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void deleteAppWidgetId(int appWidgetId) {
345c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
34615d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
347c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id != null) {
349c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                deleteAppWidgetLocked(id);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                saveStateLocked();
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deleteHost(int hostId) {
356c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
35715d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int callingUid = getCallingUid();
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host host = lookupHostLocked(callingUid, hostId);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (host != null) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                deleteHostLocked(host);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                saveStateLocked();
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deleteAllHosts() {
368c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
36915d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int callingUid = getCallingUid();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = mHosts.size();
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean changed = false;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=N-1; i>=0; i--) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Host host = mHosts.get(i);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (host.uid == callingUid) {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    deleteHostLocked(host);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    changed = true;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (changed) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                saveStateLocked();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void deleteHostLocked(Host host) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = host.instances.size();
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=N-1; i>=0; i--) {
389c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = host.instances.get(i);
390c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            deleteAppWidgetLocked(id);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.instances.clear();
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHosts.remove(host);
3947bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        mDeletedHosts.add(host);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // it's gone or going away, abruptly drop the callback connection
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.callbacks = null;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    void deleteAppWidgetLocked(AppWidgetId id) {
40081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        // We first unbind all services that are bound to this id
40181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        unbindAppWidgetRemoteViewsServicesLocked(id);
40281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Host host = id.host;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.instances.remove(id);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pruneHostLocked(host);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
407c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        mAppWidgetIds.remove(id);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Provider p = id.provider;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p != null) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.instances.remove(id);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!p.zombie) {
413c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                // send the broacast saying that this appWidgetId has been deleted
414c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.setComponent(p.info.provider);
416c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mContext.sendBroadcast(intent);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p.instances.size() == 0) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // cancel the future updates
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cancelBroadcasts(p);
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // send the broacast saying that the provider is not in use any more
423c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.setComponent(p.info.provider);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mContext.sendBroadcast(intent);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void cancelBroadcasts(Provider p) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.broadcast != null) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAlarmManager.cancel(p.broadcast);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long token = Binder.clearCallingIdentity();
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.broadcast.cancel();
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(token);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.broadcast = null;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
444c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
445c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET,
446c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                "bindGagetId appWidgetId=" + appWidgetId + " provider=" + provider);
4474912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn
4484912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
4494912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn        try {
4504912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn            synchronized (mAppWidgetIds) {
45115d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey                ensureStateLoadedLocked();
4524912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
4534912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                if (id == null) {
4544912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    throw new IllegalArgumentException("bad appWidgetId");
4554912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                }
4564912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                if (id.provider != null) {
4574912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    throw new IllegalArgumentException("appWidgetId " + appWidgetId + " already bound to "
4584912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                            + id.provider.info.provider);
4594912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                }
4604912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                Provider p = lookupProviderLocked(provider);
4614912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                if (p == null) {
4624912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    throw new IllegalArgumentException("not a appwidget provider: " + provider);
4634912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                }
4644912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                if (p.zombie) {
4654912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    throw new IllegalArgumentException("can't bind to a 3rd party provider in"
4664912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                            + " safe mode: " + provider);
4674912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                }
4684912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn
4694912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                id.provider = p;
4704912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                p.instances.add(id);
4714912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                int instancesSize = p.instances.size();
4724912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                if (instancesSize == 1) {
4734912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    // tell the provider that it's ready
4744912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                    sendEnableIntentLocked(p);
4754912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                }
4764912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn
4774912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                // send an update now -- We need this update now, and just for this appWidgetId.
4784912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                // It's less critical when the next one happens, so when we schdule the next one,
4794912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                // we add updatePeriodMillis to its start time.  That time will have some slop,
4804912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                // but that's okay.
4814912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                sendUpdateIntentLocked(p, new int[] { appWidgetId });
4824912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn
4834912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                // schedule the future updates
4844912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                registerForBroadcastsLocked(p, getAppWidgetIds(p));
4854912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn                saveStateLocked();
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4874912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn        } finally {
4884912f160875441927d012fc17b04fe7cc6567ef8Dianne Hackborn            Binder.restoreCallingIdentity(ident);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Binds to a specific RemoteViewsService
49381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
49481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        synchronized (mAppWidgetIds) {
49515d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
49681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
49781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            if (id == null) {
49881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                throw new IllegalArgumentException("bad appWidgetId");
49981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
50081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            final ComponentName componentName = intent.getComponent();
50181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            try {
50281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                final ServiceInfo si = mContext.getPackageManager().getServiceInfo(componentName,
50381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                        PackageManager.GET_PERMISSIONS);
50481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(si.permission)) {
50581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                    throw new SecurityException("Selected service does not require "
50681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                            + android.Manifest.permission.BIND_REMOTEVIEWS
50781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                            + ": " + componentName);
50881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                }
50981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            } catch (PackageManager.NameNotFoundException e) {
51081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                throw new IllegalArgumentException("Unknown component " + componentName);
51181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
51281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
51316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // If there is already a connection made for this service intent, then disconnect from
51416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // that first.  (This does not allow multiple connections to the same service under
51516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // the same key)
51616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            ServiceConnectionProxy conn = null;
51784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            FilterComparison fc = new FilterComparison(intent);
51884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
51916c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            if (mBoundRemoteViewsServices.containsKey(key)) {
52016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                conn = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
52116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                conn.disconnect();
52216c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                mContext.unbindService(conn);
52316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                mBoundRemoteViewsServices.remove(key);
52416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            }
52516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung
52616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // Bind to the RemoteViewsService (which will trigger a callback to the
52716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // RemoteViewsAdapter.onServiceConnected())
52881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            final long token = Binder.clearCallingIdentity();
52981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            try {
53016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                conn = new ServiceConnectionProxy(key, connection);
53181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
53281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                mBoundRemoteViewsServices.put(key, conn);
53381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            } finally {
53481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                Binder.restoreCallingIdentity(token);
53581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
53684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
53784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            // Add it to the mapping of RemoteViewsService to appWidgetIds so that we can determine
53884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            // when we can call back to the RemoteViewsService later to destroy associated
53984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            // factories.
54022bc69de50ebd9e6437eb3775ce6b06b8c6052dcWinson Chung            incrementAppWidgetServiceRefCount(appWidgetId, fc);
54181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
54281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    }
54381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
54484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Unbinds from a specific RemoteViewsService
54581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
54681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        synchronized (mAppWidgetIds) {
54715d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
54881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            // Unbind from the RemoteViewsService (which will trigger a callback to the bound
54981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            // RemoteViewsAdapter)
55081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId,
55181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                    new FilterComparison(intent));
55281f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            if (mBoundRemoteViewsServices.containsKey(key)) {
55316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                // We don't need to use the appWidgetId until after we are sure there is something
55416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                // to unbind.  Note that this may mask certain issues with apps calling unbind()
55516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                // more than necessary.
55616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
55716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                if (id == null) {
55816c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                    throw new IllegalArgumentException("bad appWidgetId");
55916c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                }
56016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung
56116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                ServiceConnectionProxy conn =
56216c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                    (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
56316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                conn.disconnect();
56481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                mContext.unbindService(conn);
56516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                mBoundRemoteViewsServices.remove(key);
56616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            } else {
56716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                Log.e("AppWidgetService", "Error (unbindRemoteViewsService): Connection not bound");
56881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
56981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
57081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    }
57181f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
57284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Unbinds from a RemoteViewsService when we delete an app widget
57381f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    private void unbindAppWidgetRemoteViewsServicesLocked(AppWidgetId id) {
57416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        int appWidgetId = id.appWidgetId;
57516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        // Unbind all connections to Services bound to this AppWidgetId
57681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        Iterator<Pair<Integer, Intent.FilterComparison>> it =
57781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            mBoundRemoteViewsServices.keySet().iterator();
57881f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        while (it.hasNext()) {
57981f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            final Pair<Integer, Intent.FilterComparison> key = it.next();
58081f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            if (key.first.intValue() == appWidgetId) {
58116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                final ServiceConnectionProxy conn = (ServiceConnectionProxy)
58216c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                        mBoundRemoteViewsServices.get(key);
58316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                conn.disconnect();
58481f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung                mContext.unbindService(conn);
58516c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                it.remove();
58681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung            }
58781f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung        }
58884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
58984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        // Check if we need to destroy any services (if no other app widgets are
59084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        // referencing the same service)
59184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        decrementAppWidgetServiceRefCount(appWidgetId);
59284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    }
59384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
59484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Destroys the cached factory on the RemoteViewsService's side related to the specified intent
59584bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    private void destroyRemoteViewsService(final Intent intent) {
59684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        final ServiceConnection conn = new ServiceConnection() {
59784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            @Override
59884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            public void onServiceConnected(ComponentName name, IBinder service) {
59984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                final IRemoteViewsFactory cb =
60084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                    IRemoteViewsFactory.Stub.asInterface(service);
60184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                try {
60284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                    cb.onDestroy(intent);
6032625feae79ab418355c2a4dafe8b162bba3cc1cfAdam Cohen                } catch (RemoteException e) {
6042625feae79ab418355c2a4dafe8b162bba3cc1cfAdam Cohen                    e.printStackTrace();
6052625feae79ab418355c2a4dafe8b162bba3cc1cfAdam Cohen                } catch (RuntimeException e) {
60684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                    e.printStackTrace();
60784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                }
60884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                mContext.unbindService(this);
60984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            }
61084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            @Override
61184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            public void onServiceDisconnected(android.content.ComponentName name) {
61284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                // Do nothing
61384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            }
61484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        };
61584bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
61684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        // Bind to the service and remove the static intent->factory mapping in the
61784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        // RemoteViewsService.
61884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        final long token = Binder.clearCallingIdentity();
61984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        try {
62084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
62184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        } finally {
62284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            Binder.restoreCallingIdentity(token);
62384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        }
62484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    }
62584bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
62684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Adds to the ref-count for a given RemoteViewsService intent
62784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    private void incrementAppWidgetServiceRefCount(int appWidgetId, FilterComparison fc) {
62884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        HashSet<Integer> appWidgetIds = null;
62984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        if (mRemoteViewsServicesAppWidgets.containsKey(fc)) {
63084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            appWidgetIds = mRemoteViewsServicesAppWidgets.get(fc);
63184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        } else {
63284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            appWidgetIds = new HashSet<Integer>();
63384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            mRemoteViewsServicesAppWidgets.put(fc, appWidgetIds);
63484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        }
63584bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        appWidgetIds.add(appWidgetId);
63684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    }
63784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung
63884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if
63984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    // the ref-count reaches zero.
64084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung    private void decrementAppWidgetServiceRefCount(int appWidgetId) {
64184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        Iterator<FilterComparison> it =
64284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            mRemoteViewsServicesAppWidgets.keySet().iterator();
64384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        while (it.hasNext()) {
64484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            final FilterComparison key = it.next();
64584bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
64684bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            if (ids.remove(appWidgetId)) {
64784bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                // If we have removed the last app widget referencing this service, then we
64884bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                // should destroy it and remove it from this set
64984bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                if (ids.isEmpty()) {
65084bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                    destroyRemoteViewsService(key.getIntent());
65184bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                    it.remove();
65284bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung                }
65384bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung            }
65484bbb020217adcdfe0694c44ccab57e208ffde16Winson Chung        }
65581f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung    }
65681f39eb6e76d0be1dd341af835e8002a0f80524eWinson Chung
657c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
658c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
65915d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
660c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id != null && id.provider != null && !id.provider.zombie) {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return id.provider.info;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
668c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public RemoteViews getAppWidgetViews(int appWidgetId) {
669c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
67015d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
671c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id != null) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return id.views;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public List<AppWidgetProviderInfo> getInstalledProviders() {
680c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
68115d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = mInstalledProviders.size();
683a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy            ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>(N);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Provider p = mInstalledProviders.get(i);
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!p.zombie) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result.add(p.info);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
694c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
695c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (appWidgetIds == null) {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
698c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (appWidgetIds.length == 0) {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
701c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        final int N = appWidgetIds.length;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
703c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
70415d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
706c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
707c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                updateAppWidgetInstanceLocked(id, views);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7122dd2197805edb4d9547b143deef2226413218f4cAdam Cohen    public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
7132dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        if (appWidgetIds == null) {
7142dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            return;
7152dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        }
7162dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        if (appWidgetIds.length == 0) {
7172dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            return;
7182dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        }
7192dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        final int N = appWidgetIds.length;
7202dd2197805edb4d9547b143deef2226413218f4cAdam Cohen
7212dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        synchronized (mAppWidgetIds) {
72215d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
7232dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            for (int i=0; i<N; i++) {
7242dd2197805edb4d9547b143deef2226413218f4cAdam Cohen                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
7252dd2197805edb4d9547b143deef2226413218f4cAdam Cohen                updateAppWidgetInstanceLocked(id, views, true);
7262dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            }
7272dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        }
7282dd2197805edb4d9547b143deef2226413218f4cAdam Cohen    }
7292dd2197805edb4d9547b143deef2226413218f4cAdam Cohen
7306394c0e52cf641d93f678fd052499aa952e3595dWinson Chung    public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
731499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        if (appWidgetIds == null) {
732499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            return;
733499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
734499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        if (appWidgetIds.length == 0) {
735499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            return;
736499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
737499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        final int N = appWidgetIds.length;
738499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
739499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        synchronized (mAppWidgetIds) {
74015d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
741499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            for (int i=0; i<N; i++) {
742499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
7436394c0e52cf641d93f678fd052499aa952e3595dWinson Chung                notifyAppWidgetViewDataChangedInstanceLocked(id, viewId);
744499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            }
745499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
746499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
747499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
748c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) {
749c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
75015d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Provider p = lookupProviderLocked(provider);
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (p == null) {
7538a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "updateAppWidgetProvider: provider doesn't exist: " + provider);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
756c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            ArrayList<AppWidgetId> instances = p.instances;
757933decaa5e9402099b1bfbbe1012633908c84d11Jeff Sharkey            final int callingUid = getCallingUid();
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = instances.size();
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
760c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                AppWidgetId id = instances.get(i);
761933decaa5e9402099b1bfbbe1012633908c84d11Jeff Sharkey                if (canAccessAppWidgetId(id, callingUid)) {
762933decaa5e9402099b1bfbbe1012633908c84d11Jeff Sharkey                    updateAppWidgetInstanceLocked(id, views);
763933decaa5e9402099b1bfbbe1012633908c84d11Jeff Sharkey                }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
768c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views) {
7692dd2197805edb4d9547b143deef2226413218f4cAdam Cohen        updateAppWidgetInstanceLocked(id, views, false);
7702dd2197805edb4d9547b143deef2226413218f4cAdam Cohen    }
7712dd2197805edb4d9547b143deef2226413218f4cAdam Cohen
7722dd2197805edb4d9547b143deef2226413218f4cAdam Cohen    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views, boolean isPartialUpdate) {
773c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        // allow for stale appWidgetIds and other badness
774c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        // lookup also checks that the calling process can access the appWidgetId
775c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
7772dd2197805edb4d9547b143deef2226413218f4cAdam Cohen
7782dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            // We do not want to save this RemoteViews
7792dd2197805edb4d9547b143deef2226413218f4cAdam Cohen            if (!isPartialUpdate) id.views = views;
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // is anyone listening?
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id.host.callbacks != null) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the lock is held, but this is a oneway call
785c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    id.host.callbacks.updateAppWidget(id.appWidgetId, views);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // It failed; remove the callback. No need to prune because
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we know that this host is still referenced by this instance.
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    id.host.callbacks = null;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7956394c0e52cf641d93f678fd052499aa952e3595dWinson Chung    void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, int viewId) {
796499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        // allow for stale appWidgetIds and other badness
797499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        // lookup also checks that the calling process can access the appWidgetId
798499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
799499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
800499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            // is anyone listening?
801499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            if (id.host.callbacks != null) {
802499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                try {
803499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                    // the lock is held, but this is a oneway call
8046394c0e52cf641d93f678fd052499aa952e3595dWinson Chung                    id.host.callbacks.viewDataChanged(id.appWidgetId, viewId);
805499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                } catch (RemoteException e) {
806499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                    // It failed; remove the callback. No need to prune because
807499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                    // we know that this host is still referenced by this instance.
808499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                    id.host.callbacks = null;
809499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                }
810499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            }
811c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung
812c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung            // If the host is unavailable, then we call the associated
813c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung            // RemoteViewsFactory.onDataSetChanged() directly
814c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung            if (id.host.callbacks == null) {
815c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                Set<FilterComparison> keys = mRemoteViewsServicesAppWidgets.keySet();
816c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                for (FilterComparison key : keys) {
817c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                    if (mRemoteViewsServicesAppWidgets.get(key).contains(id.appWidgetId)) {
818c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        Intent intent = key.getIntent();
819c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung
820c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        final ServiceConnection conn = new ServiceConnection() {
821c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            @Override
822c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            public void onServiceConnected(ComponentName name, IBinder service) {
823c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                IRemoteViewsFactory cb =
824c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                    IRemoteViewsFactory.Stub.asInterface(service);
825c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                try {
826c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                    cb.onDataSetChangedAsync();
827c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                } catch (RemoteException e) {
828c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                    e.printStackTrace();
829c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                } catch (RuntimeException e) {
830c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                    e.printStackTrace();
831c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                }
832c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                mContext.unbindService(this);
833c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            }
834c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            @Override
835c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            public void onServiceDisconnected(android.content.ComponentName name) {
836c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                                // Do nothing
837c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            }
838c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        };
839c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung
840c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        // Bind to the service and call onDataSetChanged()
841c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        final long token = Binder.clearCallingIdentity();
842c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        try {
843c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
844c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        } finally {
845c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                            Binder.restoreCallingIdentity(token);
846c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                        }
847c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                    }
848c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung                }
849c3f581b0474a216938810885f4f606e0db1f21ffWinson Chung            }
850499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
851499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
852499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
853c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            List<RemoteViews> updatedViews) {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int callingUid = enforceCallingUid(packageName);
856c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
85715d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            host.callbacks = callbacks;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updatedViews.clear();
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
863c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            ArrayList<AppWidgetId> instances = host.instances;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = instances.size();
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] updatedIds = new int[N];
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
867c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                AppWidgetId id = instances.get(i);
868c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                updatedIds[i] = id.appWidgetId;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updatedViews.add(id.views);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return updatedIds;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopListening(int hostId) {
876c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
87715d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host host = lookupHostLocked(getCallingUid(), hostId);
879e21167a9e5978f167fa6e8d26bbb2986b6609372Ken Shirriff            if (host != null) {
880e21167a9e5978f167fa6e8d26bbb2986b6609372Ken Shirriff                host.callbacks = null;
881e21167a9e5978f167fa6e8d26bbb2986b6609372Ken Shirriff                pruneHostLocked(host);
882e21167a9e5978f167fa6e8d26bbb2986b6609372Ken Shirriff            }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
886c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    boolean canAccessAppWidgetId(AppWidgetId id, int callingUid) {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.host.uid == callingUid) {
888c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            // Apps hosting the AppWidget have access to it.
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.provider != null && id.provider.uid == callingUid) {
892c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            // Apps providing the AppWidget have access to it (if the appWidgetId has been bound)
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
895c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET)
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                == PackageManager.PERMISSION_GRANTED) {
897c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            // Apps that can bind have access to all appWidgetIds.
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Nobody else can access it.
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
904c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project   AppWidgetId lookupAppWidgetIdLocked(int appWidgetId) {
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int callingUid = getCallingUid();
906c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        final int N = mAppWidgetIds.size();
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
908c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = mAppWidgetIds.get(i);
909c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (id.appWidgetId == appWidgetId && canAccessAppWidgetId(id, callingUid)) {
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return id;
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Provider lookupProviderLocked(ComponentName provider) {
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mInstalledProviders.size();
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Provider p = mInstalledProviders.get(i);
920bac26a1205883ad30343f1d1f64a039dcdda9f63Adam Cohen            if (p.info.provider.equals(provider)) {
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return p;
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Host lookupHostLocked(int uid, int hostId) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mHosts.size();
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host h = mHosts.get(i);
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (h.uid == uid && h.hostId == hostId) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return h;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Host lookupOrAddHostLocked(int uid, String packageName, int hostId) {
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mHosts.size();
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host h = mHosts.get(i);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (h.hostId == hostId && h.packageName.equals(packageName)) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return h;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Host host = new Host();
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.packageName = packageName;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.uid = uid;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        host.hostId = hostId;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHosts.add(host);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return host;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void pruneHostLocked(Host host) {
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (host.instances.size() == 0 && host.callbacks == null) {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHosts.remove(host);
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
960c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    void loadAppWidgetList() {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageManager pm = mPackageManager;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
963c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.GET_META_DATA);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9675f85780db058d3babb435466b33834c3cc70f5c1Bjorn Bringert        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = broadcastReceivers.get(i);
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addProviderLocked(ri);
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean addProviderLocked(ResolveInfo ri) {
975d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato        if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
976d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato            return false;
977d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato        }
978d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato        if (!ri.activityInfo.isEnabled()) {
979d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato            return false;
980d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato        }
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.name), ri);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p != null) {
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInstalledProviders.add(p);
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeProviderLocked(int index, Provider p) {
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int N = p.instances.size();
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
994c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetId id = p.instances.get(i);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Call back with empty RemoteViews
996c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            updateAppWidgetInstanceLocked(id, null);
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Stop telling the host about updates for this from now on
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cancelBroadcasts(p);
999c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            // clear out references to this appWidgetId
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id.host.instances.remove(id);
1001c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            mAppWidgetIds.remove(id);
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id.provider = null;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pruneHostLocked(id.host);
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id.host = null;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.instances.clear();
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInstalledProviders.remove(index);
10087bb9883d0564e1d3f7303d4934418998d540c1b8Adam Cohen        mDeletedProviders.add(p);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // no need to send the DISABLE broadcast, since the receiver is gone anyway
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cancelBroadcasts(p);
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void sendEnableIntentLocked(Provider p) {
1014c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.setComponent(p.info.provider);
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) {
1020c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (appWidgetIds != null && appWidgetIds.length > 0) {
1021c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1022c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.setComponent(p.info.provider);
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1028c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    void registerForBroadcastsLocked(Provider p, int[] appWidgetIds) {
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.info.updatePeriodMillis > 0) {
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if this is the first instance, set the alarm.  otherwise,
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // rely on the fact that we've already set it and that
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // PendingIntent.getBroadcast will update the extras.
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean alreadyRegistered = p.broadcast != null;
1034c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1035c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.setComponent(p.info.provider);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long token = Binder.clearCallingIdentity();
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.broadcast = PendingIntent.getBroadcast(mContext, 1, intent,
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        PendingIntent.FLAG_UPDATE_CURRENT);
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(token);
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!alreadyRegistered) {
1045be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato                long period = p.info.updatePeriodMillis;
1046be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato                if (period < MIN_UPDATE_PERIOD) {
1047be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato                    period = MIN_UPDATE_PERIOD;
1048be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato                }
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1050be96b3a2aa7ec6d57ac038d4a5326fc168585ad6Joe Onorato                        SystemClock.elapsedRealtime() + period, period, p.broadcast);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1055c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    static int[] getAppWidgetIds(Provider p) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int instancesSize = p.instances.size();
1057c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        int appWidgetIds[] = new int[instancesSize];
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<instancesSize; i++) {
1059c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            appWidgetIds[i] = p.instances.get(i).appWidgetId;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1061c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        return appWidgetIds;
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1064c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public int[] getAppWidgetIds(ComponentName provider) {
1065c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
106615d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Provider p = lookupProviderLocked(provider);
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (p != null && getCallingUid() == p.uid) {
1069c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                return getAppWidgetIds(p);
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return new int[0];
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Provider p = null;
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ActivityInfo activityInfo = ri.activityInfo;
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        XmlResourceParser parser = null;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser = activityInfo.loadXmlMetaData(mPackageManager,
1083c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (parser == null) {
10858a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER + " meta-data for "
1086c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        + "AppWidget provider '" + component + '\'');
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1089d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AttributeSet attrs = Xml.asAttributeSet(parser);
1091d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int type;
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && type != XmlPullParser.START_TAG) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // drain whitespace, comments, etc.
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1097d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String nodeName = parser.getName();
1099c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (!"appwidget-provider".equals(nodeName)) {
11008a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for"
1101c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        + " AppWidget provider '" + component + '\'');
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p = new Provider();
1106c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetProviderInfo info = p.info = new AppWidgetProviderInfo();
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.provider = component;
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.uid = activityInfo.applicationInfo.uid;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
111020cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn            Resources res = mPackageManager.getResourcesForApplication(
111120cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                    activityInfo.applicationInfo);
1112d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
111320cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn            TypedArray sa = res.obtainAttributes(attrs,
1114c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    com.android.internal.R.styleable.AppWidgetProviderInfo);
1115d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
11168f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            // These dimensions has to be resolved in the application's context.
11178f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            // We simply send back the raw complex data, which will be
11188f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
11198f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            TypedValue value = sa.peekValue(
11208f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima                    com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
11218f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            info.minWidth = value != null ? value.data : 0;
11228f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
11238f25c426b118c35f558cbf27bd413e1eb6d59823Mitsuru Oshima            info.minHeight = value != null ? value.data : 0;
11241bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            value = sa.peekValue(
11251bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
11261bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            info.minResizeWidth = value != null ? value.data : info.minWidth;
11271bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            value = sa.peekValue(
11281bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
11291bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            info.minResizeHeight = value != null ? value.data : info.minHeight;
1130d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.updatePeriodMillis = sa.getInt(
1132c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.initialLayout = sa.getResourceId(
1134c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String className = sa.getString(
1136c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (className != null) {
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.configure = new ComponentName(component.getPackageName(), className);
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.label = activityInfo.loadLabel(mPackageManager).toString();
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.icon = ri.getIconResource();
1142d2db2a579440608453994b64eb5b425840f5307aPatrick Dubroy            info.previewImage = sa.getResourceId(
1143d2db2a579440608453994b64eb5b425840f5307aPatrick Dubroy            		com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
1144a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen            info.autoAdvanceViewId = sa.getResourceId(
1145a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
11469611f2ea6c962c7eb05a2841d06656745f524097Adam Cohen            info.resizeMode = sa.getInt(
1147d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen                    com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
1148d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen                    AppWidgetProviderInfo.RESIZE_NONE);
1149d2db2a579440608453994b64eb5b425840f5307aPatrick Dubroy
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sa.recycle();
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Ok to catch Exception here, because anything going wrong because
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of what a client process passes to us should not be fatal for the
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // system process.
11558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "XML parsing failed for AppWidget provider '" + component + '\'', e);
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (parser != null) parser.close();
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return p;
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageInfo pkgInfo = mPackageManager.getPackageInfo(packageName, 0);
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pkgInfo == null || pkgInfo.applicationInfo == null) {
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new PackageManager.NameNotFoundException();
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return pkgInfo.applicationInfo.uid;
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int enforceCallingUid(String packageName) throws IllegalArgumentException {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int callingUid = getCallingUid();
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int packageUid;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            packageUid = getUidForPackage(packageName);
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (PackageManager.NameNotFoundException ex) {
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("packageName and uid don't match packageName="
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + packageName);
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
118010e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown        if (callingUid != packageUid) {
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("packageName and uid don't match packageName="
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + packageName);
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return callingUid;
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void sendInitialBroadcasts() {
1188c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        synchronized (mAppWidgetIds) {
118915d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey            ensureStateLoadedLocked();
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = mInstalledProviders.size();
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Provider p = mInstalledProviders.get(i);
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p.instances.size() > 0) {
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sendEnableIntentLocked(p);
1195c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    int[] appWidgetIds = getAppWidgetIds(p);
1196c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    sendUpdateIntentLocked(p, appWidgetIds);
1197c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    registerForBroadcastsLocked(p, appWidgetIds);
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // only call from initialization -- it assumes that the data structures are all empty
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void loadStateLocked() {
12059730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        AtomicFile file = savedStateFile();
12069730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        try {
12079730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            FileInputStream stream = file.openRead();
12089730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            readStateFromFileLocked(stream);
12099730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen
12109730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            if (stream != null) {
12119730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                try {
12129730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                    stream.close();
12139730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                } catch (IOException e) {
12149730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                    Slog.w(TAG, "Failed to close state FileInputStream " + e);
12159730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12179730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        } catch (FileNotFoundException e) {
12189730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "Failed to read state: " + e);
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12219730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void saveStateLocked() {
12239730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        AtomicFile file = savedStateFile();
12249730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        FileOutputStream stream;
12259730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        try {
12269730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            stream = file.startWrite();
12279730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            if (writeStateToFileLocked(stream)) {
12289730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                file.finishWrite(stream);
12299730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            } else {
12309730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                file.failWrite(stream);
12319730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen                Slog.w(TAG, "Failed to save state, restoring backup.");
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12339730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        } catch (IOException e) {
12349730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "Failed open state file for write: " + e);
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12389730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen    boolean writeStateToFileLocked(FileOutputStream stream) {
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int N;
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            XmlSerializer out = new FastXmlSerializer();
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.setOutput(stream, "utf-8");
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.startDocument(null, true);
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.startTag(null, "gs");
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int providerIndex = 0;
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            N = mInstalledProviders.size();
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Provider p = mInstalledProviders.get(i);
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p.instances.size() > 0) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    out.startTag(null, "p");
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    out.attribute(null, "pkg", p.info.provider.getPackageName());
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    out.attribute(null, "cl", p.info.provider.getClassName());
1255bd742e4336a04ea1e8e9a15cf8f66ec6097b883fPatrick Tsai                    out.endTag(null, "p");
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    p.tag = providerIndex;
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    providerIndex++;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            N = mHosts.size();
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Host host = mHosts.get(i);
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.startTag(null, "h");
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.attribute(null, "pkg", host.packageName);
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.attribute(null, "id", Integer.toHexString(host.hostId));
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.endTag(null, "h");
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                host.tag = i;
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1271c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            N = mAppWidgetIds.size();
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
1273c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                AppWidgetId id = mAppWidgetIds.get(i);
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.startTag(null, "g");
1275c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                out.attribute(null, "id", Integer.toHexString(id.appWidgetId));
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.attribute(null, "h", Integer.toHexString(id.host.tag));
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (id.provider != null) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    out.attribute(null, "p", Integer.toHexString(id.provider.tag));
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.endTag(null, "g");
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.endTag(null, "gs");
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.endDocument();
12868550f255232eb4e4852466c5297fdc125887f5afSuchi Amalapurapu            return true;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
12889730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "Failed to write state: " + e);
12898550f255232eb4e4852466c5297fdc125887f5afSuchi Amalapurapu            return false;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12939730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen    void readStateFromFileLocked(FileInputStream stream) {
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean success = false;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            XmlPullParser parser = Xml.newPullParser();
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser.setInput(stream, null);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int type;
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int providerIndex = 0;
1302a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy            HashMap<Integer,Provider> loadedProviders = new HashMap<Integer, Provider>();
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            do {
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                type = parser.next();
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == XmlPullParser.START_TAG) {
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String tag = parser.getName();
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ("p".equals(tag)) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // TODO: do we need to check that this package has the same signature
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // as before?
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String pkg = parser.getAttributeValue(null, "pkg");
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String cl = parser.getAttributeValue(null, "cl");
1312ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy
1313ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                        final PackageManager packageManager = mContext.getPackageManager();
1314ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                        try {
1315ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                            packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0);
1316ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                        } catch (PackageManager.NameNotFoundException e) {
1317ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                            String[] pkgs = packageManager.currentToCanonicalPackageNames(
1318ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                                    new String[] { pkg });
1319ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                            pkg = pkgs[0];
1320ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy                        }
1321ff3e61c6d5de339300d26227b69bfd9ee0827103Romain Guy
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Provider p = lookupProviderLocked(new ComponentName(pkg, cl));
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (p == null && mSafeMode) {
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // if we're in safe mode, make a temporary one
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            p = new Provider();
1326c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            p.info = new AppWidgetProviderInfo();
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            p.info.provider = new ComponentName(pkg, cl);
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            p.zombie = true;
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mInstalledProviders.add(p);
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (p != null) {
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // if it wasn't uninstalled or something
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            loadedProviders.put(providerIndex, p);
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        providerIndex++;
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    else if ("h".equals(tag)) {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Host host = new Host();
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // TODO: do we need to check that this package has the same signature
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // as before?
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        host.packageName = parser.getAttributeValue(null, "pkg");
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            host.uid = getUidForPackage(host.packageName);
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PackageManager.NameNotFoundException ex) {
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            host.zombie = true;
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!host.zombie || mSafeMode) {
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // In safe mode, we don't discard the hosts we don't recognize
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // so that they're not pruned from our list.  Otherwise, we do.
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            host.hostId = Integer.parseInt(
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    parser.getAttributeValue(null, "id"), 16);
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mHosts.add(host);
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    else if ("g".equals(tag)) {
1357c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        AppWidgetId id = new AppWidgetId();
1358c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        id.appWidgetId = Integer.parseInt(parser.getAttributeValue(null, "id"), 16);
1359c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        if (id.appWidgetId >= mNextAppWidgetId) {
1360c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            mNextAppWidgetId = id.appWidgetId + 1;
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String providerString = parser.getAttributeValue(null, "p");
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (providerString != null) {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // there's no provider if it hasn't been bound yet.
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // maybe we don't have to save this, but it brings the system
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // to the state it was in.
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int pIndex = Integer.parseInt(providerString, 16);
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            id.provider = loadedProviders.get(pIndex);
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (false) {
13718a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.d(TAG, "bound appWidgetId=" + id.appWidgetId + " to provider "
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        + pIndex + " which is " + id.provider);
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (id.provider == null) {
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // This provider is gone.  We just let the host figure out
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // that this happened when it fails to load it.
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                continue;
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int hIndex = Integer.parseInt(parser.getAttributeValue(null, "h"), 16);
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        id.host = mHosts.get(hIndex);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id.host == null) {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // This host is gone.
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            continue;
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id.provider != null) {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            id.provider.instances.add(id);
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        id.host.instances.add(id);
1392c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        mAppWidgetIds.add(id);
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } while (type != XmlPullParser.END_DOCUMENT);
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            success = true;
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NullPointerException e) {
13989730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "failed parsing " + e);
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NumberFormatException e) {
14009730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "failed parsing " + e);
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (XmlPullParserException e) {
14029730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "failed parsing " + e);
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
14049730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "failed parsing " + e);
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IndexOutOfBoundsException e) {
14069730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "failed parsing " + e);
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (success) {
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // delete any hosts that didn't manage to get connected (should happen)
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if it matters, they'll be reconnected.
1412002716d49a27d72efff810418b08c1ec8620aa8cDianne Hackborn            for (int i=mHosts.size()-1; i>=0; i--) {
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pruneHostLocked(mHosts.get(i));
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // failed reading, clean up
14179730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen            Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
14189730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen
1419c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            mAppWidgetIds.clear();
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHosts.clear();
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = mInstalledProviders.size();
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInstalledProviders.get(i).instances.clear();
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14289730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen    AtomicFile savedStateFile() {
14299730031f8af9f20f3e85fbb2b8925461c3980233Adam Cohen        return new AtomicFile(new File("/data/system/" + SETTINGS_FILENAME));
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
14358a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            //Slog.d(TAG, "received " + action);
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sendInitialBroadcasts();
143863c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer            } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
143963c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                Locale revised = Locale.getDefault();
144063c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                if (revised == null || mLocale == null ||
144163c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                    !(revised.equals(mLocale))) {
144263c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                    mLocale = revised;
144363c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer
144463c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                    synchronized (mAppWidgetIds) {
144515d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey                        ensureStateLoadedLocked();
144663c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                        int N = mInstalledProviders.size();
144763c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                        for (int i=N-1; i>=0; i--) {
144863c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                            Provider p = mInstalledProviders.get(i);
144963c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                            String pkgName = p.info.provider.getPackageName();
145063c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                            updateProvidersForPackageLocked(pkgName);
145163c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                        }
145263c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                        saveStateLocked();
145363c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                    }
145463c2d9ed9cb2174137ee43acb6ee2a86ff4451eaEric Fischer                }
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
145608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                boolean added = false;
1457d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato                boolean changed = false;
145808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                String pkgList[] = null;
1459b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu                if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
146008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
146108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    added = true;
146294258cd70438e444e139a26da12fd7e5a8782332Joe Onorato                } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
146308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
146408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    added = false;
146508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                } else  {
146608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    Uri uri = intent.getData();
146708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (uri == null) {
146808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        return;
146908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
147008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    String pkgName = uri.getSchemeSpecificPart();
147108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (pkgName == null) {
147208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        return;
147308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
147408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    pkgList = new String[] { pkgName };
147508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    added = Intent.ACTION_PACKAGE_ADDED.equals(action);
1476d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato                    changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
147808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (pkgList == null || pkgList.length == 0) {
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1481d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato                if (added || changed) {
1482c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    synchronized (mAppWidgetIds) {
148315d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey                        ensureStateLoadedLocked();
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Bundle extras = intent.getExtras();
1485d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato                        if (changed || (extras != null &&
1486d070e89396e250782c015bc993bcae6e7e03af7aJoe Onorato                                    extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
148708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (String pkgName : pkgList) {
148808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                // The package was just upgraded
148908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                updateProvidersForPackageLocked(pkgName);
149008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // The package was just added
149308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (String pkgName : pkgList) {
149408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                addProvidersForPackageLocked(pkgName);
149508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        saveStateLocked();
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
149908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                } else {
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Bundle extras = intent.getExtras();
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // The package is being updated.  We'll receive a PACKAGE_ADDED shortly.
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
1504c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        synchronized (mAppWidgetIds) {
150515d161f61bd97e937e95fe8a8e520a947113c7b1Jeff Sharkey                            ensureStateLoadedLocked();
150608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (String pkgName : pkgList) {
150708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                removeProvidersForPackageLocked(pkgName);
150808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                saveStateLocked();
150908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void addProvidersForPackageLocked(String pkgName) {
1518c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1519f6133febaead08d597c4454d543ee3cba5158a90Joe Onorato        intent.setPackage(pkgName);
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.GET_META_DATA);
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15235f85780db058d3babb435466b33834c3cc70f5c1Bjorn Bringert        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = broadcastReceivers.get(i);
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ActivityInfo ai = ri.activityInfo;
1527331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
1528331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato                continue;
1529331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato            }
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkgName.equals(ai.packageName)) {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addProviderLocked(ri);
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void updateProvidersForPackageLocked(String pkgName) {
1537a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        HashSet<String> keep = new HashSet<String>();
1538c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1539f6133febaead08d597c4454d543ee3cba5158a90Joe Onorato        intent.setPackage(pkgName);
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.GET_META_DATA);
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // add the missing ones and collect which ones to keep
15445f85780db058d3babb435466b33834c3cc70f5c1Bjorn Bringert        int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = broadcastReceivers.get(i);
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ActivityInfo ai = ri.activityInfo;
1548331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
1549331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato                continue;
1550331fbdc7e9588018dac28de8b6196653cea1f08bJoe Onorato            }
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkgName.equals(ai.packageName)) {
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ComponentName component = new ComponentName(ai.packageName, ai.name);
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Provider p = lookupProviderLocked(component);
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p == null) {
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (addProviderLocked(ri)) {
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        keep.add(ai.name);
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Provider parsed = parseProviderInfoXml(component, ri);
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (parsed != null) {
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        keep.add(ai.name);
1562c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                        // Use the new AppWidgetProviderInfo.
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.info = parsed.info;
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // If it's enabled
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final int M = p.instances.size();
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (M > 0) {
1567c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            int[] appWidgetIds = getAppWidgetIds(p);
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Reschedule for the new updatePeriodMillis (don't worry about handling
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // it specially if updatePeriodMillis didn't change because we just sent
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // an update, and the next one will be updatePeriodMillis from now).
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            cancelBroadcasts(p);
1572c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            registerForBroadcastsLocked(p, appWidgetIds);
1573c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            // If it's currently showing, call back with the new AppWidgetProviderInfo.
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int j=0; j<M; j++) {
1575c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                                AppWidgetId id = p.instances.get(j);
1576a8a8a42f8570bdbe66a09fc278564e7a549158daJoe Onorato                                id.views = null;
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (id.host != null && id.host.callbacks != null) {
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    try {
1579c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                                        id.host.callbacks.providerChanged(id.appWidgetId, p.info);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    } catch (RemoteException ex) {
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        // It failed; remove the callback. No need to prune because
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        // we know that this host is still referenced by this
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        // instance.
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        id.host.callbacks = null;
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Now that we've told the host, push out an update.
1589c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                            sendUpdateIntentLocked(p, appWidgetIds);
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // prune the ones we don't want to keep
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        N = mInstalledProviders.size();
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=N-1; i>=0; i--) {
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Provider p = mInstalledProviders.get(i);
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkgName.equals(p.info.provider.getPackageName())
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && !keep.contains(p.info.provider.getClassName())) {
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeProviderLocked(i, p);
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeProvidersForPackageLocked(String pkgName) {
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int N = mInstalledProviders.size();
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=N-1; i>=0; i--) {
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Provider p = mInstalledProviders.get(i);
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkgName.equals(p.info.provider.getPackageName())) {
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeProviderLocked(i, p);
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Delete the hosts for this package too
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //
1618c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        // By now, we have removed any AppWidgets that were in any hosts here,
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so we don't need to worry about sending DISABLE broadcasts to them.
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        N = mHosts.size();
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=N-1; i>=0; i--) {
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Host host = mHosts.get(i);
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkgName.equals(host.packageName)) {
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                deleteHostLocked(host);
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1630