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