1742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani/*
2742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Copyright (C) 2011 The Android Open Source Project
3742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
4742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
5742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * you may not use this file except in compliance with the License.
6742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * You may obtain a copy of the License at
7742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
8742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
9742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
10742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Unless required by applicable law or agreed to in writing, software
11742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
12742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * See the License for the specific language governing permissions and
14742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * limitations under the License.
15742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani */
16742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
17742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasanipackage com.android.server;
18742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
19742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.app.AlarmManager;
20483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasaniimport android.app.AppGlobals;
21742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.app.PendingIntent;
22742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetManager;
23742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetProviderInfo;
24742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.ComponentName;
25742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Context;
26742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent;
27742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent.FilterComparison;
2861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurkaimport android.content.ServiceConnection;
29742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ActivityInfo;
30742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ApplicationInfo;
31483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasaniimport android.content.pm.IPackageManager;
32742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageInfo;
33742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageManager;
34742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ResolveInfo;
35742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ServiceInfo;
36742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.Resources;
37742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.TypedArray;
38742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.XmlResourceParser;
39a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.graphics.Point;
40742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.net.Uri;
41742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Binder;
42742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Bundle;
4361f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment;
44a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohenimport android.os.Handler;
45a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohenimport android.os.HandlerThread;
46742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.IBinder;
47a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohenimport android.os.Looper;
48f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.Process;
49742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.RemoteException;
50742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.SystemClock;
51f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
5239606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
53742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.AttributeSet;
54742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Log;
55742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Pair;
56742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Slog;
57742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.TypedValue;
58742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Xml;
59a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.view.Display;
60311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohenimport android.view.WindowManager;
61742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.widget.RemoteViews;
62742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
63742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.appwidget.IAppWidgetHost;
64742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.util.FastXmlSerializer;
65742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsAdapterConnection;
66742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsFactory;
67742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
68742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParser;
69742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParserException;
70742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlSerializer;
71742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
72742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.File;
73742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileDescriptor;
74742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileInputStream;
75742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileNotFoundException;
76742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileOutputStream;
77742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.IOException;
78742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.PrintWriter;
79742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.ArrayList;
80742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashMap;
81742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashSet;
82742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Iterator;
83742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.List;
84742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Locale;
85742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Set;
86742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
87742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniclass AppWidgetServiceImpl {
88742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
8939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller    private static final String KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
9039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller    private static final int KEYGUARD_HOST_ID = 0x4b455947;
91742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private static final String TAG = "AppWidgetServiceImpl";
92742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private static final String SETTINGS_FILENAME = "appwidgets.xml";
93742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes
9439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller    private static final int CURRENT_VERSION = 1; // Bump if the stored widgets need to be upgraded.
95742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
968320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani    private static boolean DBG = false;
978320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani
98742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    /*
99742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * When identifying a Host or Provider based on the calling process, use the uid field. When
100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * identifying a Host or Provider based on a package manager broadcast, use the package given.
101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     */
102742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    static class Provider {
104742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int uid;
105742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        AppWidgetProviderInfo info;
106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
107742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        PendingIntent broadcast;
108742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
109742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
110742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int tag; // for use while saving state (the index)
111742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
112742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
113742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    static class Host {
114742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int uid;
115742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int hostId;
116742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        String packageName;
117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
118742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        IAppWidgetHost callbacks;
119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
121742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int tag; // for use while saving state (the index)
122c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani
123c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        boolean uidMatches(int callingUid) {
124c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani            if (UserHandle.getAppId(callingUid) == Process.myUid()) {
125c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                // For a host that's in the system process, ignore the user id
126c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                return UserHandle.isSameApp(this.uid, callingUid);
127c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani            } else {
128c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                return this.uid == callingUid;
129c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani            }
130c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        }
131742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
132742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
133742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    static class AppWidgetId {
134742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int appWidgetId;
135742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Provider provider;
136742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        RemoteViews views;
137d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen        Bundle options;
138742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Host host;
139742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
140742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
141742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    /**
142742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection. This
143742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * needs to be a static inner class since a reference to the ServiceConnection is held globally
144742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * and may lead us to leak AppWidgetService instances (if there were more than one).
145742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     */
146742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    static class ServiceConnectionProxy implements ServiceConnection {
147742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        private final IBinder mConnectionCb;
148742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
149742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
150742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mConnectionCb = connectionCb;
151742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
152742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
153742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        public void onServiceConnected(ComponentName name, IBinder service) {
154742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final IRemoteViewsAdapterConnection cb = IRemoteViewsAdapterConnection.Stub
155742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    .asInterface(mConnectionCb);
156742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
157742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                cb.onServiceConnected(service);
158742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } catch (Exception e) {
159742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                e.printStackTrace();
160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
161742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
163742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        public void onServiceDisconnected(ComponentName name) {
164742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            disconnect();
165742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
166742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
167742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        public void disconnect() {
168742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final IRemoteViewsAdapterConnection cb = IRemoteViewsAdapterConnection.Stub
169742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    .asInterface(mConnectionCb);
170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
171742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                cb.onServiceDisconnected();
172742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } catch (Exception e) {
173742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                e.printStackTrace();
174742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
175742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
176742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
177742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
178742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Manages active connections to RemoteViewsServices
179742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection> mBoundRemoteViewsServices = new HashMap<Pair<Integer, FilterComparison>, ServiceConnection>();
180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Manages persistent references to RemoteViewsServices from different App Widgets
181742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private final HashMap<FilterComparison, HashSet<Integer>> mRemoteViewsServicesAppWidgets = new HashMap<FilterComparison, HashSet<Integer>>();
182742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
183119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final Context mContext;
184119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final IPackageManager mPm;
185119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final AlarmManager mAlarmManager;
186119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
187119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final int mUserId;
188119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
189119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn
190742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    Locale mLocale;
191742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
192742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
193119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final ArrayList<Host> mHosts = new ArrayList<Host>();
19461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    // set of package names
195119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final HashSet<String> mPackagesWithBindWidgetPermission = new HashSet<String>();
196742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    boolean mSafeMode;
197742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    boolean mStateLoaded;
198311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen    int mMaxWidgetBitmapMemory;
199742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
200a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    private final Handler mSaveStateHandler;
201a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen
202742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // These are for debugging only -- widgets are going missing in some rare instances
203742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>();
204742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ArrayList<Host> mDeletedHosts = new ArrayList<Host>();
205742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
206a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    AppWidgetServiceImpl(Context context, int userId, Handler saveStateHandler) {
207742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mContext = context;
208483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        mPm = AppGlobals.getPackageManager();
209742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
210742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mUserId = userId;
211a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen        mSaveStateHandler = saveStateHandler;
212119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
213119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_APP_WIDGETS);
214311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen        computeMaximumWidgetBitmapMemory();
215311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen    }
216311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen
217311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen    void computeMaximumWidgetBitmapMemory() {
218311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
219a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown        Display display = wm.getDefaultDisplay();
220a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown        Point size = new Point();
221a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown        display.getRealSize(size);
222e92aad432add317793a69a34eab5d271962df220Winson Chung        // Cap memory usage at 1.5 times the size of the display
223e92aad432add317793a69a34eab5d271962df220Winson Chung        // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
224a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown        mMaxWidgetBitmapMemory = 6 * size.x * size.y;
225742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
226742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
227742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void systemReady(boolean safeMode) {
228742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mSafeMode = safeMode;
229742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
230742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
231742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
232742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
233742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
234742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
2358320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani    private void log(String msg) {
2368320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        Slog.i(TAG, "u=" + mUserId + ": " + msg);
2378320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani    }
2388320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani
239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void onConfigurationChanged() {
2408320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("Got onConfigurationChanged()");
241742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Locale revised = Locale.getDefault();
242742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (revised == null || mLocale == null || !(revised.equals(mLocale))) {
243742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mLocale = revised;
244742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
245742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            synchronized (mAppWidgetIds) {
246742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ensureStateLoadedLocked();
247a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
248a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                // list of installed providers and skip providers that we don't need to update.
249a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                // Also note that remove the provider does not clear the Provider component data.
250a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                ArrayList<Provider> installedProviders =
251a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                        new ArrayList<Provider>(mInstalledProviders);
252a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
253a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                int N = installedProviders.size();
254742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                for (int i = N - 1; i >= 0; i--) {
255a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                    Provider p = installedProviders.get(i);
256a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                    ComponentName cn = p.info.provider;
257a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                    if (!removedProviders.contains(cn)) {
258a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                        updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
259a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                    }
260742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
261a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
262742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
263742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
264742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
265742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
266742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void onBroadcastReceived(Intent intent) {
2678320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("onBroadcast " + intent);
268742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final String action = intent.getAction();
269742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        boolean added = false;
270742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        boolean changed = false;
2717fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        boolean providersModified = false;
272742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        String pkgList[] = null;
273742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
274742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
275742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            added = true;
276742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
277742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
278742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            added = false;
279742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
280742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Uri uri = intent.getData();
281742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (uri == null) {
282742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return;
283742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
284742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            String pkgName = uri.getSchemeSpecificPart();
285742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName == null) {
286742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return;
287742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
288742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pkgList = new String[] { pkgName };
289742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            added = Intent.ACTION_PACKAGE_ADDED.equals(action);
290742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
291742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
292742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (pkgList == null || pkgList.length == 0) {
293742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
294742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
295742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (added || changed) {
296742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            synchronized (mAppWidgetIds) {
297742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ensureStateLoadedLocked();
298742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Bundle extras = intent.getExtras();
299742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (changed
300742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        || (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
301742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    for (String pkgName : pkgList) {
302742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // The package was just upgraded
303a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                        providersModified |= updateProvidersForPackageLocked(pkgName, null);
304742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
305742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } else {
306742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // The package was just added
307742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    for (String pkgName : pkgList) {
3087fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                        providersModified |= addProvidersForPackageLocked(pkgName);
309742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
310742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
311a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
314742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Bundle extras = intent.getExtras();
315742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
316742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // The package is being updated. We'll receive a PACKAGE_ADDED shortly.
317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } else {
318742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                synchronized (mAppWidgetIds) {
319742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    ensureStateLoadedLocked();
320742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    for (String pkgName : pkgList) {
3217fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                        providersModified |= removeProvidersForPackageLocked(pkgName);
322a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                        saveStateAsync();
323742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
324742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
326742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
3277fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
3287fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        if (providersModified) {
3297fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            // If the set of providers has been modified, notify each active AppWidgetHost
3307fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            synchronized (mAppWidgetIds) {
3317fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                ensureStateLoadedLocked();
3327fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                notifyHostsForProvidersChangedLocked();
3337fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            }
3347fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        }
335742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
336742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
337742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void dumpProvider(Provider p, int index, PrintWriter pw) {
338742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        AppWidgetProviderInfo info = p.info;
339742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("  ["); pw.print(index); pw.print("] provider ");
340742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(info.provider.flattenToShortString());
341742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.println(':');
342742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("    min=("); pw.print(info.minWidth);
343742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print("x"); pw.print(info.minHeight);
344742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print(")   minResize=("); pw.print(info.minResizeWidth);
345742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print("x"); pw.print(info.minResizeHeight);
346742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(") updatePeriodMillis=");
347742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(info.updatePeriodMillis);
348742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(" resizeMode=");
349742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(info.resizeMode);
3500aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                pw.print(info.widgetCategory);
351742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(" autoAdvanceViewId=");
352742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(info.autoAdvanceViewId);
353742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(" initialLayout=#");
354742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(Integer.toHexString(info.initialLayout));
355791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani                pw.print(" uid="); pw.print(p.uid);
356742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(" zombie="); pw.println(p.zombie);
357742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
358742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
359742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void dumpHost(Host host, int index, PrintWriter pw) {
360742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("  ["); pw.print(index); pw.print("] hostId=");
361742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(host.hostId); pw.print(' ');
362742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(host.packageName); pw.print('/');
363742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print(host.uid); pw.println(':');
364742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("    callbacks="); pw.println(host.callbacks);
365742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("    instances.size="); pw.print(host.instances.size());
366742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(" zombie="); pw.println(host.zombie);
367742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
368742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
369742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void dumpAppWidgetId(AppWidgetId id, int index, PrintWriter pw) {
370742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("  ["); pw.print(index); pw.print("] id=");
371742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.println(id.appWidgetId);
372742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pw.print("    hostId=");
373742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(id.host.hostId); pw.print(' ');
374742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.print(id.host.packageName); pw.print('/');
375742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pw.println(id.host.uid);
376742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id.provider != null) {
377742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print("    provider=");
378742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    pw.println(id.provider.info.provider.flattenToShortString());
379742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
380742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id.host != null) {
381742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print("    host.callbacks="); pw.println(id.host.callbacks);
382742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
383742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id.views != null) {
384742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print("    views="); pw.println(id.views);
385742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
386742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
387742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
388742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
389742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
390742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                != PackageManager.PERMISSION_GRANTED) {
391742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("Permission Denial: can't dump from from pid="
392742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    + Binder.getCallingPid()
393742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    + ", uid=" + Binder.getCallingUid());
394742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
395742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
396742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
397742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
398742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int N = mInstalledProviders.size();
399742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("Providers:");
400742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i=0; i<N; i++) {
401742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                dumpProvider(mInstalledProviders.get(i), i, pw);
402742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
403742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
404742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mAppWidgetIds.size();
405742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println(" ");
406742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("AppWidgetIds:");
407742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i=0; i<N; i++) {
408742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                dumpAppWidgetId(mAppWidgetIds.get(i), i, pw);
409742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
410742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
411742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mHosts.size();
412742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println(" ");
413742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("Hosts:");
414742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i=0; i<N; i++) {
415742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                dumpHost(mHosts.get(i), i, pw);
416742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
417742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
418742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mDeletedProviders.size();
419742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println(" ");
420742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("Deleted Providers:");
421742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i=0; i<N; i++) {
422742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                dumpProvider(mDeletedProviders.get(i), i, pw);
423742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
424742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
425742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mDeletedHosts.size();
426742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println(" ");
427742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.println("Deleted Hosts:");
428742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i=0; i<N; i++) {
429742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                dumpHost(mDeletedHosts.get(i), i, pw);
430742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
431742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
432742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
433742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
434742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void ensureStateLoadedLocked() {
435742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (!mStateLoaded) {
436119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
437119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
438119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
439a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            loadAppWidgetListLocked();
440742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            loadStateLocked();
441742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mStateLoaded = true;
442742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
443742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
444742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
445742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public int allocateAppWidgetId(String packageName, int hostId) {
446f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        int callingUid = enforceSystemOrCallingUid(packageName);
447742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
448119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
449119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return -1;
450119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
451742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
452742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int appWidgetId = mNextAppWidgetId++;
453742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
454742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);
455742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
456742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = new AppWidgetId();
457742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            id.appWidgetId = appWidgetId;
458742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            id.host = host;
459742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
460742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            host.instances.add(id);
461742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mAppWidgetIds.add(id);
462742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
463a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            saveStateAsync();
4648320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani            if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId
4658320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                    + " id=" + appWidgetId);
466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return appWidgetId;
467742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
468742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
469742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
470742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void deleteAppWidgetId(int appWidgetId) {
471742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
472119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
473119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
474119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
475742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
476742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
477742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id != null) {
478742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                deleteAppWidgetLocked(id);
479a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
481742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
482742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
483742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
484742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void deleteHost(int hostId) {
485742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
486119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
487119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
488119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
489742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
490742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int callingUid = Binder.getCallingUid();
491742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host host = lookupHostLocked(callingUid, hostId);
492742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (host != null) {
493742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                deleteHostLocked(host);
494a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
495742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
496742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
497742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
498742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
499742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void deleteAllHosts() {
500742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
501119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
502119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
503119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
504742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
505742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int callingUid = Binder.getCallingUid();
506742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int N = mHosts.size();
507742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            boolean changed = false;
508742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = N - 1; i >= 0; i--) {
509742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Host host = mHosts.get(i);
510c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                if (host.uidMatches(callingUid)) {
511742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    deleteHostLocked(host);
512742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    changed = true;
513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
514742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
515742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (changed) {
516a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
517742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
518742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
519742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
520742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
521742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void deleteHostLocked(Host host) {
522742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = host.instances.size();
523742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = N - 1; i >= 0; i--) {
524742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = host.instances.get(i);
525742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            deleteAppWidgetLocked(id);
526742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
527742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.instances.clear();
528742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mHosts.remove(host);
529742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mDeletedHosts.add(host);
530742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // it's gone or going away, abruptly drop the callback connection
531742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.callbacks = null;
532742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
533742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
534742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void deleteAppWidgetLocked(AppWidgetId id) {
535742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // We first unbind all services that are bound to this id
536742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        unbindAppWidgetRemoteViewsServicesLocked(id);
537742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
538742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Host host = id.host;
539742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.instances.remove(id);
540742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        pruneHostLocked(host);
541742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mAppWidgetIds.remove(id);
543742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
544742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Provider p = id.provider;
545742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (p != null) {
546742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            p.instances.remove(id);
547742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (!p.zombie) {
548742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // send the broacast saying that this appWidgetId has been deleted
549742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
550742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                intent.setComponent(p.info.provider);
551742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
55279af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn                mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
553742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p.instances.size() == 0) {
554742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // cancel the future updates
555742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    cancelBroadcasts(p);
556742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
557742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // send the broacast saying that the provider is not in use any more
558742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
559742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    intent.setComponent(p.info.provider);
56079af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn                    mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
561742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
562742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
563742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
564742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
565742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
566742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void cancelBroadcasts(Provider p) {
5678320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("cancelBroadcasts for " + p);
568742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (p.broadcast != null) {
569742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mAlarmManager.cancel(p.broadcast);
570742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            long token = Binder.clearCallingIdentity();
571742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
572742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                p.broadcast.cancel();
573742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } finally {
574742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Binder.restoreCallingIdentity(token);
575742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
576742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            p.broadcast = null;
577742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
578742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
579742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
5800aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider, Bundle options) {
5818320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("bindAppWidgetIdImpl appwid=" + appWidgetId
5828320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                + " provider=" + provider);
583742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final long ident = Binder.clearCallingIdentity();
584742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
585742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            synchronized (mAppWidgetIds) {
586119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                if (!mHasFeature) {
587119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                    return;
588119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                }
5893ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                options = cloneIfLocalBinder(options);
590742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ensureStateLoadedLocked();
591742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
592742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (id == null) {
593742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new IllegalArgumentException("bad appWidgetId");
594742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
595742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (id.provider != null) {
596742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new IllegalArgumentException("appWidgetId " + appWidgetId
597742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            + " already bound to " + id.provider.info.provider);
598742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
599742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Provider p = lookupProviderLocked(provider);
600742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p == null) {
601742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new IllegalArgumentException("not a appwidget provider: " + provider);
602742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
603742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p.zombie) {
604742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new IllegalArgumentException("can't bind to a 3rd party provider in"
605742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            + " safe mode: " + provider);
606742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
607742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
608742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                id.provider = p;
6090aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                if (options == null) {
6100aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    options = new Bundle();
6110aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                }
6120aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                id.options = options;
6130aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen
6140aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                // We need to provide a default value for the widget category if it is not specified
6150aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                if (!options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
6160aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
6170aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
6180aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                }
6190aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen
620742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                p.instances.add(id);
621742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                int instancesSize = p.instances.size();
622742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (instancesSize == 1) {
623742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // tell the provider that it's ready
624742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    sendEnableIntentLocked(p);
625742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
626742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
627742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // send an update now -- We need this update now, and just for this appWidgetId.
628742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // It's less critical when the next one happens, so when we schedule the next one,
629742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // we add updatePeriodMillis to its start time. That time will have some slop,
630742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // but that's okay.
631742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                sendUpdateIntentLocked(p, new int[] { appWidgetId });
632742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
633742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // schedule the future updates
634742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                registerForBroadcastsLocked(p, getAppWidgetIds(p));
635a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateAsync();
636742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
637742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } finally {
638742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Binder.restoreCallingIdentity(ident);
639742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
640742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
641742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
6420aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
64367a871d85732e582c70a2a1d85ef4419eb658a12Michael Jurka        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET,
64461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            "bindAppWidgetId appWidgetId=" + appWidgetId + " provider=" + provider);
6450aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen        bindAppWidgetIdImpl(appWidgetId, provider, options);
64661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    }
64761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
64861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    public boolean bindAppWidgetIdIfAllowed(
6490aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            String packageName, int appWidgetId, ComponentName provider, Bundle options) {
650119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
651119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return false;
652119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
65361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        try {
65467a871d85732e582c70a2a1d85ef4419eb658a12Michael Jurka            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
65561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        } catch (SecurityException se) {
65661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            if (!callerHasBindAppWidgetPermission(packageName)) {
65761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                return false;
65861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            }
65961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        }
6600aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen        bindAppWidgetIdImpl(appWidgetId, provider, options);
66161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        return true;
66261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    }
66361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
66461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    private boolean callerHasBindAppWidgetPermission(String packageName) {
66561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        int callingUid = Binder.getCallingUid();
66661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        try {
667f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            if (!UserHandle.isSameApp(callingUid, getUidForPackage(packageName))) {
66861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                return false;
66961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            }
67061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        } catch (Exception e) {
67161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            return false;
67261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        }
67361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        synchronized (mAppWidgetIds) {
67461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            ensureStateLoadedLocked();
67561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            return mPackagesWithBindWidgetPermission.contains(packageName);
67661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        }
67761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    }
67861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
67961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    public boolean hasBindAppWidgetPermission(String packageName) {
680119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
681119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return false;
682119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
68361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        mContext.enforceCallingPermission(
68461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
68561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                "hasBindAppWidgetPermission packageName=" + packageName);
68661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
68761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        synchronized (mAppWidgetIds) {
68861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            ensureStateLoadedLocked();
68961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            return mPackagesWithBindWidgetPermission.contains(packageName);
69061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        }
69161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    }
69261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
69361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    public void setBindAppWidgetPermission(String packageName, boolean permission) {
694119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
695119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
696119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
69761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        mContext.enforceCallingPermission(
69861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
69961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                "setBindAppWidgetPermission packageName=" + packageName);
70061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
70161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        synchronized (mAppWidgetIds) {
70261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            ensureStateLoadedLocked();
70361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            if (permission) {
70461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                mPackagesWithBindWidgetPermission.add(packageName);
70561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            } else {
70661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                mPackagesWithBindWidgetPermission.remove(packageName);
70761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            }
708a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            saveStateAsync();
70961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka        }
71061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka    }
71161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
712742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Binds to a specific RemoteViewsService
713742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
714742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
715119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
716119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
717119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
718742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
719742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
720742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id == null) {
721742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                throw new IllegalArgumentException("bad appWidgetId");
722742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
723742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final ComponentName componentName = intent.getComponent();
724742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
72598edc951712823dbf5db2b7e9c203a0e98fc616bAmith Yamasani                final ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(componentName,
72698edc951712823dbf5db2b7e9c203a0e98fc616bAmith Yamasani                        PackageManager.GET_PERMISSIONS, mUserId);
727742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(si.permission)) {
728742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new SecurityException("Selected service does not require "
729742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            + android.Manifest.permission.BIND_REMOTEVIEWS + ": " + componentName);
730742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
73198edc951712823dbf5db2b7e9c203a0e98fc616bAmith Yamasani            } catch (RemoteException e) {
732742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                throw new IllegalArgumentException("Unknown component " + componentName);
733742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
734742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
735742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // If there is already a connection made for this service intent, then disconnect from
736742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // that first. (This does not allow multiple connections to the same service under
737742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // the same key)
738742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ServiceConnectionProxy conn = null;
739742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            FilterComparison fc = new FilterComparison(intent);
740742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
741742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (mBoundRemoteViewsServices.containsKey(key)) {
742742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                conn = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
743742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                conn.disconnect();
744742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mContext.unbindService(conn);
745742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mBoundRemoteViewsServices.remove(key);
746742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
747742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
748f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            int userId = UserHandle.getUserId(id.provider.uid);
749791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani            if (userId != mUserId) {
750791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani                Slog.w(TAG, "AppWidgetServiceImpl of user " + mUserId
751791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani                        + " binding to provider on user " + userId);
752791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani            }
753742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Bind to the RemoteViewsService (which will trigger a callback to the
754742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // RemoteViewsAdapter.onServiceConnected())
755742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final long token = Binder.clearCallingIdentity();
756742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
757742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                conn = new ServiceConnectionProxy(key, connection);
75827b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
75927b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                        new UserHandle(userId));
760742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mBoundRemoteViewsServices.put(key, conn);
761742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } finally {
762742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Binder.restoreCallingIdentity(token);
763742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
764742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
765742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Add it to the mapping of RemoteViewsService to appWidgetIds so that we can determine
766742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // when we can call back to the RemoteViewsService later to destroy associated
767742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // factories.
768742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            incrementAppWidgetServiceRefCount(appWidgetId, fc);
769742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
770742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
771742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
772742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Unbinds from a specific RemoteViewsService
773742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
774742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
775119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
776119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
777119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
778742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
779742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Unbind from the RemoteViewsService (which will trigger a callback to the bound
780742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // RemoteViewsAdapter)
781742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, new FilterComparison(
782742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    intent));
783742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (mBoundRemoteViewsServices.containsKey(key)) {
784742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // We don't need to use the appWidgetId until after we are sure there is something
785742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // to unbind. Note that this may mask certain issues with apps calling unbind()
786742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // more than necessary.
787742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
788742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (id == null) {
789742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    throw new IllegalArgumentException("bad appWidgetId");
790742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
791742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
792742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ServiceConnectionProxy conn = (ServiceConnectionProxy) mBoundRemoteViewsServices
793742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        .get(key);
794742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                conn.disconnect();
795742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mContext.unbindService(conn);
796742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mBoundRemoteViewsServices.remove(key);
797742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
798742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
799742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
800742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
801742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Unbinds from a RemoteViewsService when we delete an app widget
802742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void unbindAppWidgetRemoteViewsServicesLocked(AppWidgetId id) {
803742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int appWidgetId = id.appWidgetId;
804742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Unbind all connections to Services bound to this AppWidgetId
805742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet()
806742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                .iterator();
807742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        while (it.hasNext()) {
808742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final Pair<Integer, Intent.FilterComparison> key = it.next();
809742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (key.first.intValue() == appWidgetId) {
810742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                final ServiceConnectionProxy conn = (ServiceConnectionProxy) mBoundRemoteViewsServices
811742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        .get(key);
812742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                conn.disconnect();
813742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mContext.unbindService(conn);
814742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                it.remove();
815742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
816742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
817742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
818742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Check if we need to destroy any services (if no other app widgets are
819742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // referencing the same service)
82037ce3a8af6faab675319d0803b288ab1dddc76beAmith Yamasani        decrementAppWidgetServiceRefCount(id);
821742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
822742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
823742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Destroys the cached factory on the RemoteViewsService's side related to the specified intent
82437ce3a8af6faab675319d0803b288ab1dddc76beAmith Yamasani    private void destroyRemoteViewsService(final Intent intent, AppWidgetId id) {
825742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final ServiceConnection conn = new ServiceConnection() {
826742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            @Override
827742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            public void onServiceConnected(ComponentName name, IBinder service) {
828742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service);
829742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                try {
830742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    cb.onDestroy(intent);
831742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } catch (RemoteException e) {
832742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    e.printStackTrace();
833742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } catch (RuntimeException e) {
834742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    e.printStackTrace();
835742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
836742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mContext.unbindService(this);
837742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
838742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
839742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            @Override
840742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            public void onServiceDisconnected(android.content.ComponentName name) {
841742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // Do nothing
842742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
843742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        };
844742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
845f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        int userId = UserHandle.getUserId(id.provider.uid);
846742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Bind to the service and remove the static intent->factory mapping in the
847742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // RemoteViewsService.
848742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final long token = Binder.clearCallingIdentity();
849742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
85027b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
85127b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    new UserHandle(userId));
852742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } finally {
853742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Binder.restoreCallingIdentity(token);
854742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
855742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
856742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
857742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Adds to the ref-count for a given RemoteViewsService intent
858742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private void incrementAppWidgetServiceRefCount(int appWidgetId, FilterComparison fc) {
859742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        HashSet<Integer> appWidgetIds = null;
860742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (mRemoteViewsServicesAppWidgets.containsKey(fc)) {
861742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            appWidgetIds = mRemoteViewsServicesAppWidgets.get(fc);
862742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
863742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            appWidgetIds = new HashSet<Integer>();
864742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mRemoteViewsServicesAppWidgets.put(fc, appWidgetIds);
865742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
866742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        appWidgetIds.add(appWidgetId);
867742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
868742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
869742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if
870742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // the ref-count reaches zero.
87137ce3a8af6faab675319d0803b288ab1dddc76beAmith Yamasani    private void decrementAppWidgetServiceRefCount(AppWidgetId id) {
872742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Iterator<FilterComparison> it = mRemoteViewsServicesAppWidgets.keySet().iterator();
873742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        while (it.hasNext()) {
874742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final FilterComparison key = it.next();
875742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
87637ce3a8af6faab675319d0803b288ab1dddc76beAmith Yamasani            if (ids.remove(id.appWidgetId)) {
877742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // If we have removed the last app widget referencing this service, then we
878742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // should destroy it and remove it from this set
879742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (ids.isEmpty()) {
88037ce3a8af6faab675319d0803b288ab1dddc76beAmith Yamasani                    destroyRemoteViewsService(key.getIntent(), id);
881742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    it.remove();
882742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
883742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
884742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
885742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
886742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
887742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
888742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
889119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
890119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return null;
891119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
892742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
893742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
894742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id != null && id.provider != null && !id.provider.zombie) {
8953ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                return cloneIfLocalBinder(id.provider.info);
896742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
897742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return null;
898742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
899742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
900742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
901742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public RemoteViews getAppWidgetViews(int appWidgetId) {
9028320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("getAppWidgetViews id=" + appWidgetId);
903742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
904119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
905119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return null;
906119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
907742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
908742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
909742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id != null) {
9103ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                return cloneIfLocalBinder(id.views);
911742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
9128320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani            if (DBG) log("   couldn't find appwidgetid");
913742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return null;
914742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
915742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
916742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
917d9e5af3851f592a00549b689dec325dc46268606Adam Cohen    public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
918742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
919119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
920119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return new ArrayList<AppWidgetProviderInfo>(0);
921119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
922742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
923742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int N = mInstalledProviders.size();
924742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>(N);
925742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
926742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Provider p = mInstalledProviders.get(i);
9273fcc6b26c3302f47c911730f81cbc3dc9b71484dAdam Cohen                if (!p.zombie && (p.info.widgetCategory & categoryFilter) != 0) {
9283ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                    result.add(cloneIfLocalBinder(p.info));
929742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
930742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
931742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return result;
932742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
933742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
934742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
935742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
936119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
937119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
938119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
939742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds == null) {
940742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
941742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
9428320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani        if (DBG) log("updateAppWidgetIds views: " + views);
943f08a8b78b61bc7f1a6a71c70da25ec3ef41b8cffAdam Cohen        int bitmapMemoryUsage = 0;
944f08a8b78b61bc7f1a6a71c70da25ec3ef41b8cffAdam Cohen        if (views != null) {
945f08a8b78b61bc7f1a6a71c70da25ec3ef41b8cffAdam Cohen            bitmapMemoryUsage = views.estimateMemoryUsage();
946f08a8b78b61bc7f1a6a71c70da25ec3ef41b8cffAdam Cohen        }
947311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen        if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) {
948311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen            throw new IllegalArgumentException("RemoteViews for widget update exceeds maximum" +
949311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen                    " bitmap memory usage (used: " + bitmapMemoryUsage + ", max: " +
950311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen                    mMaxWidgetBitmapMemory + ") The total memory cannot exceed that required to" +
951311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen                    " fill the device's screen once.");
952311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen        }
953311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen
954742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds.length == 0) {
955742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
956742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
957742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = appWidgetIds.length;
958742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
959742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
960742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
961742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
962742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
963742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                updateAppWidgetInstanceLocked(id, views);
964742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
965742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
966742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
967742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
968a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    private void saveStateAsync() {
969a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen        mSaveStateHandler.post(mSaveStateRunnable);
970a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    }
971a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen
972a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    private final Runnable mSaveStateRunnable = new Runnable() {
973a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen        @Override
974a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen        public void run() {
975a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            synchronized (mAppWidgetIds) {
976a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                ensureStateLoadedLocked();
977a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen                saveStateLocked();
978a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            }
979a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen        }
980a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    };
981a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen
982d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen    public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
983e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen        synchronized (mAppWidgetIds) {
984119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
985119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
986119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
9873ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            options = cloneIfLocalBinder(options);
988e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            ensureStateLoadedLocked();
989e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
990e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
991e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            if (id == null) {
992e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen                return;
993e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            }
9940aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen
995e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            Provider p = id.provider;
9960aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            // Merge the options
9970aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            id.options.putAll(options);
998e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
999e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            // send the broacast saying that this appWidgetId has been deleted
1000d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
1001e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            intent.setComponent(p.info.provider);
1002e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
10030aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options);
100479af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
1005a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen            saveStateAsync();
1006e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen        }
1007e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen    }
1008e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
1009d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen    public Bundle getAppWidgetOptions(int appWidgetId) {
1010e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen        synchronized (mAppWidgetIds) {
1011119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
1012119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return Bundle.EMPTY;
1013119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
1014e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            ensureStateLoadedLocked();
1015e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
1016d2097ebacf3a3658624cad10669a4d98e8d7d846Adam Cohen            if (id != null && id.options != null) {
10173ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                return cloneIfLocalBinder(id.options);
1018e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            } else {
1019e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen                return Bundle.EMPTY;
1020e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen            }
1021e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen        }
1022e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen    }
1023e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen
1024742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
1025119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
1026119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
1027119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
1028742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds == null) {
1029742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
1030742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1031742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds.length == 0) {
1032742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
1033742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1034742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = appWidgetIds.length;
1035742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1036742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1037742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1038742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1039742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
1040791f877473cc6b3e8e484b741012c95aba70c3b0Amith Yamasani                if (id == null) {
1041c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                    Slog.w(TAG, "widget id " + appWidgetIds[i] + " not found!");
1042c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani                } else if (id.views != null) {
10436611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung                    // Only trigger a partial update for a widget if it has received a full update
10446611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung                    updateAppWidgetInstanceLocked(id, views, true);
10456611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung                }
1046742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1047742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1048742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1049742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1050742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
1051119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
1052119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
1053119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
1054742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds == null) {
1055742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
1056742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1057742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds.length == 0) {
1058742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return;
1059742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1060742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = appWidgetIds.length;
1061742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1062742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1063742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1064742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1065742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
1066742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                notifyAppWidgetViewDataChangedInstanceLocked(id, viewId);
1067742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1068742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1069742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1070742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1071742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) {
1072119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
1073119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
1074119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
1075742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1076742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1077742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Provider p = lookupProviderLocked(provider);
1078742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (p == null) {
1079742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.w(TAG, "updateAppWidgetProvider: provider doesn't exist: " + provider);
1080742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return;
1081742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1082742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ArrayList<AppWidgetId> instances = p.instances;
1083742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int callingUid = Binder.getCallingUid();
1084742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int N = instances.size();
1085742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1086742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = instances.get(i);
1087742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (canAccessAppWidgetId(id, callingUid)) {
1088742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    updateAppWidgetInstanceLocked(id, views);
1089742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1090742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1091742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1092742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1093742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1094742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views) {
1095742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        updateAppWidgetInstanceLocked(id, views, false);
1096742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1097742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1098742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views, boolean isPartialUpdate) {
1099742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // allow for stale appWidgetIds and other badness
1100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // lookup also checks that the calling process can access the appWidgetId
1101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
1102742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
1103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
11046611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung            if (!isPartialUpdate) {
1105fbe44b7d5e2d9d06a238a54f8ed460fb8bc49585Adam Cohen                // For a full update we replace the RemoteViews completely.
1106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                id.views = views;
1107fbe44b7d5e2d9d06a238a54f8ed460fb8bc49585Adam Cohen            } else {
1108fbe44b7d5e2d9d06a238a54f8ed460fb8bc49585Adam Cohen                // For a partial update, we merge the new RemoteViews with the old.
1109fbe44b7d5e2d9d06a238a54f8ed460fb8bc49585Adam Cohen                id.views.mergeRemoteViews(views);
1110fbe44b7d5e2d9d06a238a54f8ed460fb8bc49585Adam Cohen            }
1111742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1112742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // is anyone listening?
1113742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id.host.callbacks != null) {
1114742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                try {
1115742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // the lock is held, but this is a oneway call
1116a75a883fe9ea1790803148f0a561473073e3f264Jim Miller                    id.host.callbacks.updateAppWidget(id.appWidgetId, views, mUserId);
1117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } catch (RemoteException e) {
1118742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // It failed; remove the callback. No need to prune because
1119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // we know that this host is still referenced by this instance.
1120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    id.host.callbacks = null;
1121742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1122742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1123742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1124742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1126742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, int viewId) {
1127742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // allow for stale appWidgetIds and other badness
1128742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // lookup also checks that the calling process can access the appWidgetId
1129742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
1130742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
1131742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // is anyone listening?
1132742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id.host.callbacks != null) {
1133742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                try {
1134742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // the lock is held, but this is a oneway call
1135a75a883fe9ea1790803148f0a561473073e3f264Jim Miller                    id.host.callbacks.viewDataChanged(id.appWidgetId, viewId, mUserId);
1136742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } catch (RemoteException e) {
1137742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // It failed; remove the callback. No need to prune because
1138742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    // we know that this host is still referenced by this instance.
1139742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    id.host.callbacks = null;
1140742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1141742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1142742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1143742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // If the host is unavailable, then we call the associated
1144742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // RemoteViewsFactory.onDataSetChanged() directly
1145742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id.host.callbacks == null) {
1146742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Set<FilterComparison> keys = mRemoteViewsServicesAppWidgets.keySet();
1147742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                for (FilterComparison key : keys) {
1148742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    if (mRemoteViewsServicesAppWidgets.get(key).contains(id.appWidgetId)) {
1149742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        Intent intent = key.getIntent();
1150742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1151742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        final ServiceConnection conn = new ServiceConnection() {
1152742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            @Override
1153742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            public void onServiceConnected(ComponentName name, IBinder service) {
1154742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                IRemoteViewsFactory cb = IRemoteViewsFactory.Stub
1155742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        .asInterface(service);
1156742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                try {
1157742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    cb.onDataSetChangedAsync();
1158742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                } catch (RemoteException e) {
1159742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    e.printStackTrace();
1160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                } catch (RuntimeException e) {
1161742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    e.printStackTrace();
1162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                }
1163742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                mContext.unbindService(this);
1164742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            }
1165742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1166742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            @Override
1167742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            public void onServiceDisconnected(android.content.ComponentName name) {
1168742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                // Do nothing
1169742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            }
1170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        };
1171742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1172f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn                        int userId = UserHandle.getUserId(id.provider.uid);
1173742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // Bind to the service and call onDataSetChanged()
1174742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        final long token = Binder.clearCallingIdentity();
1175742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        try {
117627b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                            mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
117727b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                                    new UserHandle(userId));
1178742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        } finally {
1179742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            Binder.restoreCallingIdentity(token);
1180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1181742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
1182742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1183742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1184742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1185742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1186742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
11873ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    private boolean isLocalBinder() {
11883ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        return Process.myPid() == Binder.getCallingPid();
11893ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    }
11903ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen
11913ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    private RemoteViews cloneIfLocalBinder(RemoteViews rv) {
11923ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        if (isLocalBinder() && rv != null) {
11933ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            return rv.clone();
11943ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        }
11953ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        return rv;
11963ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    }
11973ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen
11983ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    private AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) {
11993ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        if (isLocalBinder() && info != null) {
12003ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            return info.clone();
12013ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        }
12023ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        return info;
12033ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    }
12043ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen
12053ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    private Bundle cloneIfLocalBinder(Bundle bundle) {
12063ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        // Note: this is only a shallow copy. For now this will be fine, but it could be problematic
12073ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        // if we start adding objects to the options. Further, it would only be an issue if keyguard
12083ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        // used such options.
12093ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        if (isLocalBinder() && bundle != null) {
12103ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            return (Bundle) bundle.clone();
12113ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        }
12123ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen        return bundle;
12133ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen    }
12143ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen
1215742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
1216742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            List<RemoteViews> updatedViews) {
1217119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
1218119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return new int[0];
1219119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
1220742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int callingUid = enforceCallingUid(packageName);
1221742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1222742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1223742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);
1224742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            host.callbacks = callbacks;
1225742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1226742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            updatedViews.clear();
1227742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1228742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ArrayList<AppWidgetId> instances = host.instances;
1229742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int N = instances.size();
1230742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int[] updatedIds = new int[N];
1231742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1232742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = instances.get(i);
1233742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                updatedIds[i] = id.appWidgetId;
12343ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                updatedViews.add(cloneIfLocalBinder(id.views));
1235742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1236742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return updatedIds;
1237742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1238742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1240742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public void stopListening(int hostId) {
1241742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1242119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            if (!mHasFeature) {
1243119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                return;
1244119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            }
1245742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1246742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host host = lookupHostLocked(Binder.getCallingUid(), hostId);
1247742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (host != null) {
1248742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                host.callbacks = null;
1249742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pruneHostLocked(host);
1250742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1251742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1252742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1253742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1254742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    boolean canAccessAppWidgetId(AppWidgetId id, int callingUid) {
1255c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        if (id.host.uidMatches(callingUid)) {
1256742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Apps hosting the AppWidget have access to it.
1257742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return true;
1258742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1259742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (id.provider != null && id.provider.uid == callingUid) {
1260742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Apps providing the AppWidget have access to it (if the appWidgetId has been bound)
1261742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return true;
1262742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1263742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET) == PackageManager.PERMISSION_GRANTED) {
1264742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Apps that can bind have access to all appWidgetIds.
1265742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return true;
1266742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1267742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Nobody else can access it.
1268742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return false;
1269742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1270742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1271742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    AppWidgetId lookupAppWidgetIdLocked(int appWidgetId) {
1272742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int callingUid = Binder.getCallingUid();
1273742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = mAppWidgetIds.size();
1274742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1275742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = mAppWidgetIds.get(i);
1276742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (id.appWidgetId == appWidgetId && canAccessAppWidgetId(id, callingUid)) {
1277742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return id;
1278742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1279742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1280742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return null;
1281742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1282742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1283742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    Provider lookupProviderLocked(ComponentName provider) {
1284742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = mInstalledProviders.size();
1285742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1286742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Provider p = mInstalledProviders.get(i);
1287742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (p.info.provider.equals(provider)) {
1288742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return p;
1289742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1290742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1291742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return null;
1292742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1293742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1294742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    Host lookupHostLocked(int uid, int hostId) {
1295742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = mHosts.size();
1296742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1297742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host h = mHosts.get(i);
1298c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani            if (h.uidMatches(uid) && h.hostId == hostId) {
1299742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return h;
1300742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1301742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1302742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return null;
1303742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1304742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1305742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    Host lookupOrAddHostLocked(int uid, String packageName, int hostId) {
1306742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = mHosts.size();
1307742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1308742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host h = mHosts.get(i);
1309742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (h.hostId == hostId && h.packageName.equals(packageName)) {
1310742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return h;
1311742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Host host = new Host();
1314742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.packageName = packageName;
1315742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.uid = uid;
1316742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        host.hostId = hostId;
1317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mHosts.add(host);
1318742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return host;
1319742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1320742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1321742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void pruneHostLocked(Host host) {
1322742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (host.instances.size() == 0 && host.callbacks == null) {
1323742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mHosts.remove(host);
1324742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1326742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1327a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen    void loadAppWidgetListLocked() {
1328742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1329483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        try {
1330483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
1331483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1332483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    PackageManager.GET_META_DATA, mUserId);
1333742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1334483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
1335483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            for (int i = 0; i < N; i++) {
1336483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                ResolveInfo ri = broadcastReceivers.get(i);
1337483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                addProviderLocked(ri);
1338483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            }
1339483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        } catch (RemoteException re) {
1340483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            // Shouldn't happen, local call
1341742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1342742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1343742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1344742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    boolean addProviderLocked(ResolveInfo ri) {
1345742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
1346742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return false;
1347742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1348742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (!ri.activityInfo.isEnabled()) {
1349742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return false;
1350742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1351742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
1352742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ri.activityInfo.name), ri);
1353742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (p != null) {
1354742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mInstalledProviders.add(p);
1355742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return true;
1356742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
1357742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return false;
1358742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1359742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1360742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1361742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void removeProviderLocked(int index, Provider p) {
1362742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int N = p.instances.size();
1363742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1364742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetId id = p.instances.get(i);
1365742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Call back with empty RemoteViews
1366742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            updateAppWidgetInstanceLocked(id, null);
1367742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Stop telling the host about updates for this from now on
1368742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            cancelBroadcasts(p);
1369742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // clear out references to this appWidgetId
1370742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            id.host.instances.remove(id);
1371742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mAppWidgetIds.remove(id);
1372742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            id.provider = null;
1373742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pruneHostLocked(id.host);
1374742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            id.host = null;
1375742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1376742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        p.instances.clear();
1377742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mInstalledProviders.remove(index);
1378742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        mDeletedProviders.add(p);
1379742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // no need to send the DISABLE broadcast, since the receiver is gone anyway
1380742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        cancelBroadcasts(p);
1381742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1382742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1383742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void sendEnableIntentLocked(Provider p) {
1384742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
1385742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        intent.setComponent(p.info.provider);
138679af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn        mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
1387742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1388742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1389742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) {
1390742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (appWidgetIds != null && appWidgetIds.length > 0) {
1391742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1392742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
1393742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            intent.setComponent(p.info.provider);
139479af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
1395742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1396742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1397742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1398742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void registerForBroadcastsLocked(Provider p, int[] appWidgetIds) {
1399742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (p.info.updatePeriodMillis > 0) {
1400742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // if this is the first instance, set the alarm. otherwise,
1401742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // rely on the fact that we've already set it and that
1402742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // PendingIntent.getBroadcast will update the extras.
1403742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            boolean alreadyRegistered = p.broadcast != null;
1404742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1405742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
1406742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            intent.setComponent(p.info.provider);
1407742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            long token = Binder.clearCallingIdentity();
1408742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            try {
14098320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                p.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
14108320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                        PendingIntent.FLAG_UPDATE_CURRENT, new UserHandle(mUserId));
1411742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } finally {
1412742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Binder.restoreCallingIdentity(token);
1413742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1414742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (!alreadyRegistered) {
1415742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                long period = p.info.updatePeriodMillis;
1416742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (period < MIN_UPDATE_PERIOD) {
1417742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    period = MIN_UPDATE_PERIOD;
1418742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1419742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock
1420742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        .elapsedRealtime()
1421742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        + period, period, p.broadcast);
1422742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1423742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1424742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1425742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1426742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    static int[] getAppWidgetIds(Provider p) {
1427742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int instancesSize = p.instances.size();
1428742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int appWidgetIds[] = new int[instancesSize];
1429742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < instancesSize; i++) {
1430742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            appWidgetIds[i] = p.instances.get(i).appWidgetId;
1431742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1432742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return appWidgetIds;
1433742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1434742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1435742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public int[] getAppWidgetIds(ComponentName provider) {
1436742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1437742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1438742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Provider p = lookupProviderLocked(provider);
1439742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (p != null && Binder.getCallingUid() == p.uid) {
1440742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return getAppWidgetIds(p);
1441742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } else {
1442742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return new int[0];
1443742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1444742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1445742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1446742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
144775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    static int[] getAppWidgetIds(Host h) {
144875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        int instancesSize = h.instances.size();
144975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        int appWidgetIds[] = new int[instancesSize];
145075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        for (int i = 0; i < instancesSize; i++) {
145175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            appWidgetIds[i] = h.instances.get(i).appWidgetId;
145275b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        }
145375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        return appWidgetIds;
145475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    }
145575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka
145675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    public int[] getAppWidgetIdsForHost(int hostId) {
145775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        synchronized (mAppWidgetIds) {
145875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            ensureStateLoadedLocked();
145975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            int callingUid = Binder.getCallingUid();
146075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            Host host = lookupHostLocked(callingUid, hostId);
146175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            if (host != null) {
146275b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka                return getAppWidgetIds(host);
146375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            } else {
146475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka                return new int[0];
146575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            }
146675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        }
146775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    }
146875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka
1469742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {
1470742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Provider p = null;
1471742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1472742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        ActivityInfo activityInfo = ri.activityInfo;
1473742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        XmlResourceParser parser = null;
1474742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1475483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
1476742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
1477742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (parser == null) {
1478742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
1479742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        + " meta-data for " + "AppWidget provider '" + component + '\'');
1480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return null;
1481742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1482742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1483742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AttributeSet attrs = Xml.asAttributeSet(parser);
1484742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1485742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int type;
1486742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1487742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    && type != XmlPullParser.START_TAG) {
1488742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                // drain whitespace, comments, etc.
1489742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1490742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1491742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            String nodeName = parser.getName();
1492742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (!"appwidget-provider".equals(nodeName)) {
1493742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for"
1494742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        + " AppWidget provider '" + component + '\'');
1495742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                return null;
1496742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1497742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1498742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            p = new Provider();
1499742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            AppWidgetProviderInfo info = p.info = new AppWidgetProviderInfo();
1500742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.provider = component;
1501742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            p.uid = activityInfo.applicationInfo.uid;
1502742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1503483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            Resources res = mContext.getPackageManager()
15048320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                    .getResourcesForApplicationAsUser(activityInfo.packageName, mUserId);
1505742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1506742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            TypedArray sa = res.obtainAttributes(attrs,
1507742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo);
1508742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1509742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // These dimensions has to be resolved in the application's context.
1510742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // We simply send back the raw complex data, which will be
1511742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
1512742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            TypedValue value = sa
1513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    .peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
1514742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.minWidth = value != null ? value.data : 0;
1515742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
1516742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.minHeight = value != null ? value.data : 0;
1517742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            value = sa.peekValue(
1518742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
1519742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.minResizeWidth = value != null ? value.data : info.minWidth;
1520742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            value = sa.peekValue(
1521742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
1522742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.minResizeHeight = value != null ? value.data : info.minHeight;
1523742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.updatePeriodMillis = sa.getInt(
1524742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
1525742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.initialLayout = sa.getResourceId(
1526742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
15270aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
15280aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    AppWidgetProviderInfo_initialKeyguardLayout, 0);
1529742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            String className = sa
1530742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
1531742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (className != null) {
1532742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                info.configure = new ComponentName(component.getPackageName(), className);
1533742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1534483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
1535742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.icon = ri.getIconResource();
1536742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.previewImage = sa.getResourceId(
1537742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
1538742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.autoAdvanceViewId = sa.getResourceId(
1539742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
1540742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            info.resizeMode = sa.getInt(
1541742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
1542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    AppWidgetProviderInfo.RESIZE_NONE);
15430aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen            info.widgetCategory = sa.getInt(
1544ca5e341574774379f157a4ea579a1732bd4cf7fbMichael Jurka                    com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
15450aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
1546742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1547742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            sa.recycle();
1548742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (Exception e) {
1549742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // Ok to catch Exception here, because anything going wrong because
1550742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // of what a client process passes to us should not be fatal for the
1551742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // system process.
1552742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "XML parsing failed for AppWidget provider '" + component + '\'', e);
1553742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return null;
1554742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } finally {
1555742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (parser != null)
1556742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                parser.close();
1557742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1558742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return p;
1559742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1560742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1561742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
1562483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        PackageInfo pkgInfo = null;
1563483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        try {
1564483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            pkgInfo = mPm.getPackageInfo(packageName, 0, mUserId);
1565483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        } catch (RemoteException re) {
1566483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            // Shouldn't happen, local call
1567483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        }
1568742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (pkgInfo == null || pkgInfo.applicationInfo == null) {
1569742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            throw new PackageManager.NameNotFoundException();
1570742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1571742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return pkgInfo.applicationInfo.uid;
1572742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1573742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1574f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    int enforceSystemOrCallingUid(String packageName) throws IllegalArgumentException {
1575f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        int callingUid = Binder.getCallingUid();
157603bdc8a8f756a951b460b01cbd4d01c2ffd05041Michael Jurka        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID || callingUid == 0) {
1577f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller            return callingUid;
1578f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        }
1579f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        return enforceCallingUid(packageName);
1580f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    }
1581f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller
1582742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    int enforceCallingUid(String packageName) throws IllegalArgumentException {
1583742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int callingUid = Binder.getCallingUid();
1584742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int packageUid;
1585742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1586742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            packageUid = getUidForPackage(packageName);
1587742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (PackageManager.NameNotFoundException ex) {
1588742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            throw new IllegalArgumentException("packageName and uid don't match packageName="
1589742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    + packageName);
1590742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1591f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        if (!UserHandle.isSameApp(callingUid, packageUid)) {
1592742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            throw new IllegalArgumentException("packageName and uid don't match packageName="
1593742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    + packageName);
1594742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1595742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return callingUid;
1596742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1597742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1598742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void sendInitialBroadcasts() {
1599742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        synchronized (mAppWidgetIds) {
1600742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ensureStateLoadedLocked();
1601742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int N = mInstalledProviders.size();
1602742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1603742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Provider p = mInstalledProviders.get(i);
1604742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p.instances.size() > 0) {
1605742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    sendEnableIntentLocked(p);
1606742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    int[] appWidgetIds = getAppWidgetIds(p);
1607742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    sendUpdateIntentLocked(p, appWidgetIds);
1608742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    registerForBroadcastsLocked(p, appWidgetIds);
1609742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1610742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1611742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1612742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1613742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1614742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    // only call from initialization -- it assumes that the data structures are all empty
1615742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void loadStateLocked() {
1616742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        AtomicFile file = savedStateFile();
1617742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1618742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            FileInputStream stream = file.openRead();
1619742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            readStateFromFileLocked(stream);
1620742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1621742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (stream != null) {
1622742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                try {
1623742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    stream.close();
1624742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } catch (IOException e) {
1625742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    Slog.w(TAG, "Failed to close state FileInputStream " + e);
1626742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1627742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1628742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (FileNotFoundException e) {
1629742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "Failed to read state: " + e);
1630742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1631742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1632742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1633742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void saveStateLocked() {
1634119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        if (!mHasFeature) {
1635119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn            return;
1636119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        }
1637742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        AtomicFile file = savedStateFile();
1638742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        FileOutputStream stream;
1639742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1640742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            stream = file.startWrite();
1641742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (writeStateToFileLocked(stream)) {
1642742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                file.finishWrite(stream);
1643742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } else {
1644742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                file.failWrite(stream);
1645742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.w(TAG, "Failed to save state, restoring backup.");
1646742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1647742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (IOException e) {
1648742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "Failed open state file for write: " + e);
1649742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1650742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1651742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1652742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    boolean writeStateToFileLocked(FileOutputStream stream) {
1653742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int N;
1654742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1655742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1656742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            XmlSerializer out = new FastXmlSerializer();
1657742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            out.setOutput(stream, "utf-8");
1658742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            out.startDocument(null, true);
1659742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            out.startTag(null, "gs");
166039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            out.attribute(null, "version", String.valueOf(CURRENT_VERSION));
1661742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int providerIndex = 0;
1662742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mInstalledProviders.size();
1663742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1664742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Provider p = mInstalledProviders.get(i);
1665742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p.instances.size() > 0) {
1666742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    out.startTag(null, "p");
1667742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    out.attribute(null, "pkg", p.info.provider.getPackageName());
1668742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    out.attribute(null, "cl", p.info.provider.getClassName());
1669742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    out.endTag(null, "p");
1670742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    p.tag = providerIndex;
1671742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    providerIndex++;
1672742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1673742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1674742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1675742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mHosts.size();
1676742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1677742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Host host = mHosts.get(i);
1678742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.startTag(null, "h");
1679742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.attribute(null, "pkg", host.packageName);
1680742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.attribute(null, "id", Integer.toHexString(host.hostId));
1681742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.endTag(null, "h");
1682742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                host.tag = i;
1683742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1684742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1685742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            N = mAppWidgetIds.size();
1686742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1687742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                AppWidgetId id = mAppWidgetIds.get(i);
1688742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.startTag(null, "g");
1689742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.attribute(null, "id", Integer.toHexString(id.appWidgetId));
1690742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.attribute(null, "h", Integer.toHexString(id.host.tag));
1691742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (id.provider != null) {
1692742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    out.attribute(null, "p", Integer.toHexString(id.provider.tag));
1693742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
16940aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                if (id.options != null) {
16950aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    out.attribute(null, "min_width", Integer.toHexString(id.options.getInt(
16960aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
16970aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    out.attribute(null, "min_height", Integer.toHexString(id.options.getInt(
16980aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
16990aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    out.attribute(null, "max_width", Integer.toHexString(id.options.getInt(
17000aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
17010aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    out.attribute(null, "max_height", Integer.toHexString(id.options.getInt(
17020aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
17030aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                    out.attribute(null, "host_category", Integer.toHexString(id.options.getInt(
17040aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
17050aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                }
1706742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                out.endTag(null, "g");
1707742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1708742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
170961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            Iterator<String> it = mPackagesWithBindWidgetPermission.iterator();
171061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            while (it.hasNext()) {
171161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                out.startTag(null, "b");
171261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                out.attribute(null, "packageName", it.next());
171361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                out.endTag(null, "b");
171461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka            }
171561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka
1716742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            out.endTag(null, "gs");
1717742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1718742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            out.endDocument();
1719742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return true;
1720742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (IOException e) {
1721742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "Failed to write state: " + e);
1722742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return false;
1723742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1724742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1725742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
17260aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen    @SuppressWarnings("unused")
1727742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void readStateFromFileLocked(FileInputStream stream) {
1728742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        boolean success = false;
172939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        int version = 0;
1730742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        try {
1731742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            XmlPullParser parser = Xml.newPullParser();
1732742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            parser.setInput(stream, null);
1733742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1734742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int type;
1735742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            int providerIndex = 0;
1736742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            HashMap<Integer, Provider> loadedProviders = new HashMap<Integer, Provider>();
1737742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            do {
1738742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                type = parser.next();
1739742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (type == XmlPullParser.START_TAG) {
1740742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    String tag = parser.getName();
174139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                    if ("gs".equals(tag)) {
174239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                        String attributeValue = parser.getAttributeValue(null, "version");
174339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                        try {
174439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                            version = Integer.parseInt(attributeValue);
174539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                        } catch (NumberFormatException e) {
174639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                            version = 0;
174739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                        }
174839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                    } else if ("p".equals(tag)) {
1749742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // TODO: do we need to check that this package has the same signature
1750742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // as before?
1751742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        String pkg = parser.getAttributeValue(null, "pkg");
1752742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        String cl = parser.getAttributeValue(null, "cl");
1753742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1754f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani                        final IPackageManager packageManager = AppGlobals.getPackageManager();
1755742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        try {
17568320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani                            packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0, mUserId);
1757f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani                        } catch (RemoteException e) {
1758f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani                            String[] pkgs = mContext.getPackageManager()
1759742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    .currentToCanonicalPackageNames(new String[] { pkg });
1760742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            pkg = pkgs[0];
1761742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1762742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1763742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        Provider p = lookupProviderLocked(new ComponentName(pkg, cl));
1764742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (p == null && mSafeMode) {
1765742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // if we're in safe mode, make a temporary one
1766742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            p = new Provider();
1767742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            p.info = new AppWidgetProviderInfo();
1768742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            p.info.provider = new ComponentName(pkg, cl);
1769742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            p.zombie = true;
1770742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            mInstalledProviders.add(p);
1771742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1772742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (p != null) {
1773742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // if it wasn't uninstalled or something
1774742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            loadedProviders.put(providerIndex, p);
1775742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1776742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        providerIndex++;
1777742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    } else if ("h".equals(tag)) {
1778742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        Host host = new Host();
1779742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1780742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // TODO: do we need to check that this package has the same signature
1781742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // as before?
1782742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        host.packageName = parser.getAttributeValue(null, "pkg");
1783742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        try {
1784742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            host.uid = getUidForPackage(host.packageName);
1785742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        } catch (PackageManager.NameNotFoundException ex) {
1786742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            host.zombie = true;
1787742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1788742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (!host.zombie || mSafeMode) {
1789742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // In safe mode, we don't discard the hosts we don't recognize
1790742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // so that they're not pruned from our list. Otherwise, we do.
1791742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            host.hostId = Integer
1792742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    .parseInt(parser.getAttributeValue(null, "id"), 16);
1793742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            mHosts.add(host);
1794742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
179561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                    } else if ("b".equals(tag)) {
179661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                        String packageName = parser.getAttributeValue(null, "packageName");
179761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                        if (packageName != null) {
179861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                            mPackagesWithBindWidgetPermission.add(packageName);
179961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka                        }
1800742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    } else if ("g".equals(tag)) {
1801742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        AppWidgetId id = new AppWidgetId();
1802742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        id.appWidgetId = Integer.parseInt(parser.getAttributeValue(null, "id"), 16);
1803742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (id.appWidgetId >= mNextAppWidgetId) {
1804742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            mNextAppWidgetId = id.appWidgetId + 1;
1805742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1806742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
18070aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        Bundle options = new Bundle();
18080aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        String minWidthString = parser.getAttributeValue(null, "min_width");
18090aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        if (minWidthString != null) {
18100aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
18110aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                                    Integer.parseInt(minWidthString, 16));
18120aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        }
18130aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        String minHeightString = parser.getAttributeValue(null, "min_height");
1814db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen                        if (minHeightString != null) {
18150aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
18160aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                                    Integer.parseInt(minHeightString, 16));
18170aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        }
1818db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen                        String maxWidthString = parser.getAttributeValue(null, "max_width");
1819db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen                        if (maxWidthString != null) {
18200aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
18210aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                                    Integer.parseInt(maxWidthString, 16));
18220aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        }
18230aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        String maxHeightString = parser.getAttributeValue(null, "max_height");
1824db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen                        if (maxHeightString != null) {
18250aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
18260aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                                    Integer.parseInt(maxHeightString, 16));
18270aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        }
18280aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        String categoryString = parser.getAttributeValue(null, "host_category");
1829db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen                        if (categoryString != null) {
18300aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
18310aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                                    Integer.parseInt(categoryString, 16));
18320aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        }
18330aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen                        id.options = options;
18340aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen
1835742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        String providerString = parser.getAttributeValue(null, "p");
1836742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (providerString != null) {
1837742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // there's no provider if it hasn't been bound yet.
1838742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // maybe we don't have to save this, but it brings the system
1839742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // to the state it was in.
1840742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            int pIndex = Integer.parseInt(providerString, 16);
1841742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            id.provider = loadedProviders.get(pIndex);
1842742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            if (false) {
1843742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                Slog.d(TAG, "bound appWidgetId=" + id.appWidgetId + " to provider "
1844742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        + pIndex + " which is " + id.provider);
1845742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            }
1846742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            if (id.provider == null) {
1847742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                // This provider is gone. We just let the host figure out
1848742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                // that this happened when it fails to load it.
1849742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                continue;
1850742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            }
1851742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1852742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1853742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        int hIndex = Integer.parseInt(parser.getAttributeValue(null, "h"), 16);
1854742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        id.host = mHosts.get(hIndex);
1855742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (id.host == null) {
1856742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // This host is gone.
1857742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            continue;
1858742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1859742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1860742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (id.provider != null) {
1861742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            id.provider.instances.add(id);
1862742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
1863742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        id.host.instances.add(id);
1864742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        mAppWidgetIds.add(id);
1865742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
1866742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
1867742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            } while (type != XmlPullParser.END_DOCUMENT);
1868742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            success = true;
1869742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (NullPointerException e) {
1870742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "failed parsing " + e);
1871742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (NumberFormatException e) {
1872742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "failed parsing " + e);
1873742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (XmlPullParserException e) {
1874742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "failed parsing " + e);
1875742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (IOException e) {
1876742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "failed parsing " + e);
1877742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } catch (IndexOutOfBoundsException e) {
1878742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "failed parsing " + e);
1879742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1880742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1881742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (success) {
1882742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // delete any hosts that didn't manage to get connected (should happen)
1883742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // if it matters, they'll be reconnected.
1884742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = mHosts.size() - 1; i >= 0; i--) {
1885742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                pruneHostLocked(mHosts.get(i));
1886742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
188739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            // upgrade the database if needed
188839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            performUpgrade(version);
1889742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
1890742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            // failed reading, clean up
1891742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
1892742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1893742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mAppWidgetIds.clear();
1894742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mHosts.clear();
1895742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            final int N = mInstalledProviders.size();
1896742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < N; i++) {
1897742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                mInstalledProviders.get(i).instances.clear();
1898742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1899742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1900742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1901742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
190239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller    private void performUpgrade(int fromVersion) {
190339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        if (fromVersion < CURRENT_VERSION) {
190439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to " + CURRENT_VERSION
190539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                    + " for user " + mUserId);
190639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        }
190739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller
190839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        int version = fromVersion;
190939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller
191039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        // Update 1: keyguard moved from package "android" to "com.android.keyguard"
191139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        if (version == 0) {
191239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            for (int i = 0; i < mHosts.size(); i++) {
191339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                Host host = mHosts.get(i);
191439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                if (host != null && "android".equals(host.packageName)
191539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                        && host.hostId == KEYGUARD_HOST_ID) {
191639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                    host.packageName = KEYGUARD_HOST_PACKAGE;
191739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller                }
191839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            }
191939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            version = 1;
192039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        }
192139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller
192239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        if (version != CURRENT_VERSION) {
192339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller            throw new IllegalStateException("Failed to upgrade widget database");
192439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller        }
192539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller    }
192639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller
1927135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    static File getSettingsFile(int userId) {
192861f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani        return new File(Environment.getUserSystemDirectory(userId), SETTINGS_FILENAME);
1929135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    }
1930135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
1931742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    AtomicFile savedStateFile() {
193261f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani        File dir = Environment.getUserSystemDirectory(mUserId);
1933135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        File settingsFile = getSettingsFile(mUserId);
1934e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani        if (!settingsFile.exists() && mUserId == 0) {
1935e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            if (!dir.exists()) {
1936e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani                dir.mkdirs();
1937e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            }
1938e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            // Migrate old data
1939e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            File oldFile = new File("/data/system/" + SETTINGS_FILENAME);
1940e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            // Method doesn't throw an exception on failure. Ignore any errors
1941e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            // in moving the file (like non-existence)
1942e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani            oldFile.renameTo(settingsFile);
1943742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1944742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return new AtomicFile(settingsFile);
1945742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1946742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1947756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani    void onUserStopping() {
1948135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        // prune the ones we don't want to keep
1949135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        int N = mInstalledProviders.size();
1950135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        for (int i = N - 1; i >= 0; i--) {
1951135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            Provider p = mInstalledProviders.get(i);
1952135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            cancelBroadcasts(p);
1953135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
1954756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani    }
1955756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani
1956756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani    void onUserRemoved() {
1957135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        getSettingsFile(mUserId).delete();
1958135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    }
1959135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
19607fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    boolean addProvidersForPackageLocked(String pkgName) {
19617fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        boolean providersAdded = false;
1962742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1963742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        intent.setPackage(pkgName);
1964483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        List<ResolveInfo> broadcastReceivers;
1965483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        try {
1966483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            broadcastReceivers = mPm.queryIntentReceivers(intent,
1967483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1968483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    PackageManager.GET_META_DATA, mUserId);
1969483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        } catch (RemoteException re) {
1970483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            // Shouldn't happen, local call
19717fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            return false;
1972483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        }
1973742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
1974742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
1975742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ResolveInfo ri = broadcastReceivers.get(i);
1976742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ActivityInfo ai = ri.activityInfo;
1977742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
1978742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                continue;
1979742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1980742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName.equals(ai.packageName)) {
1981742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                addProviderLocked(ri);
19827fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                providersAdded = true;
1983742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
1984742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
19857fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
19867fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        return providersAdded;
1987742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
1988742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1989a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung    /**
1990a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung     * Updates all providers with the specified package names, and records any providers that were
1991a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung     * pruned.
1992a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung     *
1993a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung     * @return whether any providers were updated
1994a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung     */
1995a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung    boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
19967fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        boolean providersUpdated = false;
1997742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        HashSet<String> keep = new HashSet<String>();
1998742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
1999742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        intent.setPackage(pkgName);
2000483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        List<ResolveInfo> broadcastReceivers;
2001483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        try {
2002483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            broadcastReceivers = mPm.queryIntentReceivers(intent,
2003483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2004483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                PackageManager.GET_META_DATA, mUserId);
2005483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        } catch (RemoteException re) {
2006483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            // Shouldn't happen, local call
20077fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            return false;
2008483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani        }
2009742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
2010742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // add the missing ones and collect which ones to keep
2011742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
2012742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = 0; i < N; i++) {
2013742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ResolveInfo ri = broadcastReceivers.get(i);
2014742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ActivityInfo ai = ri.activityInfo;
2015742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
2016742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                continue;
2017742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
2018742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName.equals(ai.packageName)) {
2019742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                ComponentName component = new ComponentName(ai.packageName, ai.name);
2020742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Provider p = lookupProviderLocked(component);
2021742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                if (p == null) {
2022742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    if (addProviderLocked(ri)) {
2023742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        keep.add(ai.name);
20247fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                        providersUpdated = true;
2025742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
2026742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                } else {
2027742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    Provider parsed = parseProviderInfoXml(component, ri);
2028742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    if (parsed != null) {
2029742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        keep.add(ai.name);
2030742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // Use the new AppWidgetProviderInfo.
2031742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        p.info = parsed.info;
2032742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        // If it's enabled
2033742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        final int M = p.instances.size();
2034742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        if (M > 0) {
2035742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            int[] appWidgetIds = getAppWidgetIds(p);
2036742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // Reschedule for the new updatePeriodMillis (don't worry about handling
2037742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // it specially if updatePeriodMillis didn't change because we just sent
2038742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // an update, and the next one will be updatePeriodMillis from now).
2039742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            cancelBroadcasts(p);
2040742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            registerForBroadcastsLocked(p, appWidgetIds);
2041742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // If it's currently showing, call back with the new
2042742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // AppWidgetProviderInfo.
2043742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            for (int j = 0; j < M; j++) {
2044742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                AppWidgetId id = p.instances.get(j);
2045742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                id.views = null;
2046742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                if (id.host != null && id.host.callbacks != null) {
2047742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    try {
2048a75a883fe9ea1790803148f0a561473073e3f264Jim Miller                                        id.host.callbacks.providerChanged(id.appWidgetId, p.info,
2049a75a883fe9ea1790803148f0a561473073e3f264Jim Miller                                                mUserId);
2050742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    } catch (RemoteException ex) {
2051742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        // It failed; remove the callback. No need to prune because
2052742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        // we know that this host is still referenced by this
2053742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        // instance.
2054742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                        id.host.callbacks = null;
2055742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                    }
2056742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                                }
2057742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            }
2058742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            // Now that we've told the host, push out an update.
2059742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                            sendUpdateIntentLocked(p, appWidgetIds);
20607fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                            providersUpdated = true;
2061742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                        }
2062742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    }
2063742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                }
2064742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
2065742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
2066742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
2067742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // prune the ones we don't want to keep
2068742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        N = mInstalledProviders.size();
2069742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = N - 1; i >= 0; i--) {
2070742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Provider p = mInstalledProviders.get(i);
2071742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName.equals(p.info.provider.getPackageName())
2072742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                    && !keep.contains(p.info.provider.getClassName())) {
2073a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                if (removedProviders != null) {
2074a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                    removedProviders.add(p.info.provider);
2075a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung                }
2076742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                removeProviderLocked(i, p);
20777fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                providersUpdated = true;
2078742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
2079742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
20807fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
20817fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        return providersUpdated;
2082742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
2083742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
20847fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    boolean removeProvidersForPackageLocked(String pkgName) {
20857fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        boolean providersRemoved = false;
2086742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        int N = mInstalledProviders.size();
2087742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = N - 1; i >= 0; i--) {
2088742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Provider p = mInstalledProviders.get(i);
2089742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName.equals(p.info.provider.getPackageName())) {
2090742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                removeProviderLocked(i, p);
20917fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                providersRemoved = true;
2092742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
2093742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
2094742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
2095742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Delete the hosts for this package too
2096742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        //
2097742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // By now, we have removed any AppWidgets that were in any hosts here,
2098742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // so we don't need to worry about sending DISABLE broadcasts to them.
2099742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        N = mHosts.size();
2100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        for (int i = N - 1; i >= 0; i--) {
2101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Host host = mHosts.get(i);
2102742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (pkgName.equals(host.packageName)) {
2103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                deleteHostLocked(host);
2104742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
2105742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
21067fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
21077fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        return providersRemoved;
21087fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    }
21097fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
21107fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    void notifyHostsForProvidersChangedLocked() {
21117fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        final int N = mHosts.size();
21127fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        for (int i = N - 1; i >= 0; i--) {
21137fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            Host host = mHosts.get(i);
21147fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            try {
21157fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                if (host.callbacks != null) {
2116a75a883fe9ea1790803148f0a561473073e3f264Jim Miller                    host.callbacks.providersChanged(mUserId);
21177fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                }
21187fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            } catch (RemoteException ex) {
21197fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                // It failed; remove the callback. No need to prune because
21207fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                // we know that this host is still referenced by this
21217fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                // instance.
21227fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                host.callbacks = null;
21237fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung            }
21247fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        }
2125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
2126742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani}
2127