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