AppWidgetServiceImpl.java revision c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0c
1742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani/* 2742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Copyright (C) 2011 The Android Open Source Project 3742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * 4742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 5742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * you may not use this file except in compliance with the License. 6742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * You may obtain a copy of the License at 7742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * 8742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 9742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * 10742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Unless required by applicable law or agreed to in writing, software 11742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 12742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * See the License for the specific language governing permissions and 14742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * limitations under the License. 15742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani */ 16742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1730f8eb472e44228069c2ffb8bd0b43213edbf04eAmith Yamasanipackage com.android.server.appwidget; 18742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 19742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.app.AlarmManager; 20483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasaniimport android.app.AppGlobals; 21742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.app.PendingIntent; 22976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.app.admin.DevicePolicyManagerInternal; 23742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetManager; 24742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetProviderInfo; 25976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.BroadcastReceiver; 26742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.ComponentName; 27742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Context; 28742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent; 29742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent.FilterComparison; 30976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.IntentFilter; 31976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.IntentSender; 3261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurkaimport android.content.ServiceConnection; 33742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ActivityInfo; 34742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ApplicationInfo; 35483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasaniimport android.content.pm.IPackageManager; 36742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageInfo; 37742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageManager; 38742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ResolveInfo; 39742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ServiceInfo; 40976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.pm.UserInfo; 41742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.Resources; 42742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.TypedArray; 43742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.XmlResourceParser; 44a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.graphics.Point; 45742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.net.Uri; 46742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Binder; 47742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Bundle; 4861f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment; 49a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohenimport android.os.Handler; 50742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.IBinder; 51976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.Looper; 52976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.Message; 53f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.Process; 54742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.RemoteException; 55742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.SystemClock; 56f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 57976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.UserManager; 58976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.text.TextUtils; 59976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.util.ArraySet; 6039606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile; 61742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.AttributeSet; 62742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Pair; 63742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Slog; 64976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.util.SparseIntArray; 65742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.TypedValue; 66742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Xml; 67a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.view.Display; 68311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohenimport android.view.WindowManager; 69742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.widget.RemoteViews; 70742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 71742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.appwidget.IAppWidgetHost; 72976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.appwidget.IAppWidgetService; 73976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.os.BackgroundThread; 74976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.os.SomeArgs; 75742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.util.FastXmlSerializer; 76742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsAdapterConnection; 77742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsFactory; 78742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 79976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.server.LocalServices; 80976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.server.WidgetBackupProvider; 81976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport libcore.io.IoUtils; 82742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParser; 83742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParserException; 84742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlSerializer; 85742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 86adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tateimport java.io.ByteArrayInputStream; 87adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tateimport java.io.ByteArrayOutputStream; 88742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.File; 89742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileDescriptor; 90742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileInputStream; 91742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileNotFoundException; 92742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileOutputStream; 93742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.IOException; 94742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.PrintWriter; 95742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.ArrayList; 96976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport java.util.Collections; 97742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashMap; 98742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashSet; 99742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Iterator; 100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.List; 101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Locale; 102976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport java.util.Map; 103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Set; 104742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 105976e8bd2017d0263216c62111454438cc0f130e3Svetoslavclass AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider { 106976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String TAG = "AppWidgetServiceImpl"; 107976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static boolean DEBUG = false; 109742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String OLD_KEYGUARD_HOST_PACKAGE = "android"; 111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard"; 11239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller private static final int KEYGUARD_HOST_ID = 0x4b455947; 113742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String STATE_FILENAME = "appwidgets.xml"; 1158320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani 116976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int MIN_UPDATE_PERIOD = DEBUG ? 0 : 30 * 60 * 1000; // 30 minutes 117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 118976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int TAG_UNDEFINED = -1; 119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 120976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int UNKNOWN_UID = -1; 121adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 122976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int LOADED_PROFILE_ID = -1; 123adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 124976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int DISABLED_PROFILE = -1; 125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int UNKNOWN_USER_ID = -10; 127742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 128976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bump if the stored widgets need to be upgraded. 129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int CURRENT_VERSION = 1; 130c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani 131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onReceive(Context context, Intent intent) { 133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String action = intent.getAction(); 134adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 135976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Received broadcast: " + action); 137adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 138adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onConfigurationChanged(); 141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (Intent.ACTION_USER_STARTED.equals(action)) { 142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onUserStarted(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_NULL)); 144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onUserStopped(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_NULL)); 147976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onPackageBroadcastReceived(intent, intent.getIntExtra( 149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)); 150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 151adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 152976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 153742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 154976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Manages active connections to RemoteViewsServices. 155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection> 156976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices = new HashMap<>(); 157adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 158976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Manages persistent references to RemoteViewsServices from different App Widgets. 159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Pair<Integer, FilterComparison>, HashSet<Integer>> 160976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mRemoteViewsServicesAppWidgets = new HashMap<>(); 161adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 162976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Object mLock = new Object(); 163adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 164976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Widget> mWidgets = new ArrayList<>(); 165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Host> mHosts = new ArrayList<>(); 166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Provider> mProviders = new ArrayList<>(); 167adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 168976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArraySet<Pair<Integer, String>> mPackagesWithBindWidgetPermission = 169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new ArraySet<>(); 170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SparseIntArray mLoadedUserIds = new SparseIntArray(); 172742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final BackupRestoreController mBackupRestoreController; 174742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 175976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Context mContext; 176742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 177976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final IPackageManager mPackageManager; 178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final AlarmManager mAlarmManager; 179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final UserManager mUserManager; 180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SecurityPolicy mSecurityPolicy; 182adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 183a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen private final Handler mSaveStateHandler; 184976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Handler mCallbackHandler; 185a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Locale mLocale; 187742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SparseIntArray mNextAppWidgetIds = new SparseIntArray(); 189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean mSafeMode; 191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int mMaxWidgetBitmapMemory; 192976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetServiceImpl(Context context) { 194742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mContext = context; 195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackageManager = AppGlobals.getPackageManager(); 196742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSaveStateHandler = BackgroundThread.getHandler(); 199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler = new CallbackHandler(mContext.getMainLooper()); 200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController = new BackupRestoreController(); 201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy = new SecurityPolicy(); 202311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen computeMaximumWidgetBitmapMemory(); 203976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerBroadcastReceiver(); 204311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen } 205311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen 206976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void computeMaximumWidgetBitmapMemory() { 207311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 208a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown Display display = wm.getDefaultDisplay(); 209a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown Point size = new Point(); 210a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown display.getRealSize(size); 211e92aad432add317793a69a34eab5d271962df220Winson Chung // Cap memory usage at 1.5 times the size of the display 212e92aad432add317793a69a34eab5d271962df220Winson Chung // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h 213a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown mMaxWidgetBitmapMemory = 6 * size.x * size.y; 214742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 215742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void registerBroadcastReceiver() { 217976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for configuration changes so we can update the names 218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // of the widgets when the locale changes. 219976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter configFilter = new IntentFilter(); 220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav configFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 221976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav configFilter, null, null); 223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for broadcasts about package install, etc., so we can 225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // update the provider list. 226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter packageFilter = new IntentFilter(); 227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addDataScheme("package"); 231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 232976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter, null, null); 233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for events related to sdcard installation. 235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter sdFilter = new IntentFilter(); 236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter, null, null); 240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter userFilter = new IntentFilter(); 242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter.addAction(Intent.ACTION_USER_STARTED); 243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter.addAction(Intent.ACTION_USER_STOPPED); 244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter, null, null); 246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 247976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void setSafeMode(boolean safeMode) { 249742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mSafeMode = safeMode; 250742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 251742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onConfigurationChanged() { 253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "onConfigurationChanged()"); 255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2568320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani 257742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Locale revised = Locale.getDefault(); 258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (revised == null || mLocale == null || !revised.equals(mLocale)) { 259742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mLocale = revised; 260742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SparseIntArray changedGroups = null; 263976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 264a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the 265a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // list of installed providers and skip providers that we don't need to update. 266a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // Also note that remove the provider does not clear the Provider component data. 267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Provider> installedProviders = new ArrayList<>(mProviders); 268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<ProviderId> removedProviders = new HashSet<>(); 269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 270a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung int N = installedProviders.size(); 271742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 272976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = installedProviders.get(i); 273976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(provider.getUserId()); 275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!removedProviders.contains(provider.id)) { 277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean changed = updateProvidersForPackageLocked( 278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id.componentName.getPackageName(), 279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.getUserId(), removedProviders); 280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changed) { 282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changedGroups == null) { 283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changedGroups = new SparseIntArray(); 284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupId = mSecurityPolicy.getGroupParent( 286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.getUserId()); 287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changedGroups.put(groupId, groupId); 288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changedGroups != null) { 293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupCount = changedGroups.size(); 294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < groupCount; i++) { 295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupId = changedGroups.get(i); 296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(groupId); 297a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung } 298742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 299742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 300742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 301742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 302742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onPackageBroadcastReceived(Intent intent, int userId) { 304742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani final String action = intent.getAction(); 305742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani boolean added = false; 306742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani boolean changed = false; 307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean componentsModified = false; 308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 309742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkgList[] = null; 310742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { 311742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = true; 313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 314742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 315742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = false; 316742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Uri uri = intent.getData(); 318742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (uri == null) { 319742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 320742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 321742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkgName = uri.getSchemeSpecificPart(); 322742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgName == null) { 323742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 324742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = new String[] { pkgName }; 326742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = Intent.ACTION_PACKAGE_ADDED.equals(action); 327742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani changed = Intent.ACTION_PACKAGE_CHANGED.equals(action); 328742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 329742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgList == null || pkgList.length == 0) { 330742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 331742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle extras = intent.getExtras(); 337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (added || changed) { 339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean newPackageAdded = added && (extras == null 340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || !extras.getBoolean(Intent.EXTRA_REPLACING, false)); 341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (String pkgName : pkgList) { 343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Fix up the providers - add/remove/update. 344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentsModified |= updateProvidersForPackageLocked(pkgName, userId, null); 345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // ... and see if these are hosts we've been awaiting. 347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: We are backing up and restoring only the owner. 348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (newPackageAdded && userId == UserHandle.USER_OWNER) { 349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkgName, userId); 350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0 ) { 351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resolveHostUidLocked(pkgName, uid); 352adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 353adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 354742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 355742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the package is being updated, we'll receive a PACKAGE_ADDED 357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // shortly, otherwise it is removed permanently. 358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean packageRemovedPermanently = (extras == null 359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || !extras.getBoolean(Intent.EXTRA_REPLACING, false)); 360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageRemovedPermanently) { 362742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (String pkgName : pkgList) { 363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentsModified |= removeHostsAndProvidersForPackageLocked( 364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkgName, userId); 365742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 366742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 367742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 3687fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (componentsModified) { 370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the set of providers has been modified, notify each active AppWidgetHost 373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyHostsForProvidersChangedLocked(); 3747fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 3757fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 376742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 377742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void resolveHostUidLocked(String pkg, int uid) { 379adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate final int N = mHosts.size(); 380adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate for (int i = 0; i < N; i++) { 381976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid == UNKNOWN_UID && pkg.equals(host.id.packageName)) { 383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "host " + host.id + " resolved to uid " + uid); 385adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, host.id.hostId, host.id.packageName); 387976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 388adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 389adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 390adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 391adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void ensureGroupStateLoadedLocked(int userId) { 393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); 394742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Careful lad, we may have already loaded the state for some 396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // group members, so check before loading and read only the 397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // state for the new member(s). 398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int newMemberCount = 0; 399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileIdCount = profileIds.length; 400976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 401976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mLoadedUserIds.indexOfKey(profileId) >= 0) { 403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds[i] = LOADED_PROFILE_ID; 404976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newMemberCount++; 406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 407742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (newMemberCount <= 0) { 410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 411742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int newMemberIndex = 0; 414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] newProfileIds = new int[newMemberCount]; 415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId != LOADED_PROFILE_ID) { 418976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mLoadedUserIds.put(profileId, profileId); 419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newProfileIds[newMemberIndex] = profileId; 420976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newMemberIndex++; 421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 422742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav loadGroupWidgetProvidersLocked(newProfileIds); 425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav loadGroupStateLocked(newProfileIds); 426742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 427742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 428976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 429976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 430742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 431742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani != PackageManager.PERMISSION_GRANTED) { 432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Permission Denial: can't dump from from pid=" 433742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani + Binder.getCallingPid() 434742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani + ", uid=" + Binder.getCallingUid()); 435742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 436742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 437976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 438976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 439742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println("Providers:"); 440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 441976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpProvider(mProviders.get(i), i, pw); 442742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 443742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 445742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println("Widgets:"); 447976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpWidget(mWidgets.get(i), i, pw); 449742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 450742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 451742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 452742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 453742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println("Hosts:"); 454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 455742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani dumpHost(mHosts.get(i), i, pw); 456742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 457742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 458742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mPackagesWithBindWidgetPermission.size(); 460742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println("Grants:"); 462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> grant = mPackagesWithBindWidgetPermission.valueAt(i); 464976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpGrant(grant, i, pw); 465742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 467742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 468742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] startListening(IAppWidgetHost callbacks, String callingPackage, 471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int hostId, List<RemoteViews> updatedViews) { 472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 473976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 474976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 475976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "startListening() " + userId); 476742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 477742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 479976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 481976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 482976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 483742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 485976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 486976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 487976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupOrAddHostLocked(id); 488742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 489976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = callbacks; 490742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedViews.clear(); 492742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 493976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> instances = host.widgets; 494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = instances.size(); 495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] updatedIds = new int[N]; 496976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = instances.get(i); 498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedIds[i] = widget.appWidgetId; 499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedViews.add(cloneIfLocalBinder(widget.views)); 500742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return updatedIds; 503742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 504742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 505742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void stopListening(String callingPackage, int hostId) { 508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "stopListening() " + userId); 512742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 526976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 527976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(host); 528742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 529742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 530742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 531742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int allocateAppWidgetId(String callingPackage, int hostId) { 534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "allocateAppWidgetId() " + userId); 538742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 539742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 543976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 545742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mNextAppWidgetIds.indexOfKey(userId) < 0) { 547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, AppWidgetManager.INVALID_APPWIDGET_ID + 1); 548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 549742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = incrementAndGetAppWidgetIdLocked(userId); 551742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupOrAddHostLocked(id); 556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 557976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = new Widget(); 558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.appWidgetId = appWidgetId; 559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = host; 560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.add(widget); 562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(widget); 563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Allocated widget id " + appWidgetId 568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for host " + host.id); 569742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetId; 572742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 573742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 574742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 575976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 576976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteAppWidgetId(String callingPackage, int appWidgetId) { 577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteAppWidgetId() " + userId); 581742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 582742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 585742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 586976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 587976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 5880aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 592976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 5930aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 595976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 597742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 598976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteAppWidgetLocked(widget); 599742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted widget id " + appWidgetId 604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for host " + widget.host.id); 605742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 606742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 607742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 608742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hasBindAppWidgetPermission(String packageName, int grantId) { 611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "hasBindAppWidgetPermission() " + UserHandle.getCallingUserId()); 613119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission is required for managing white listing. 616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName); 617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 618976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 619976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The grants are stored in user state wich gets the grant. 620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(grantId); 621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, grantId); 623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 62461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka return false; 62561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(grantId, packageName); 628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mPackagesWithBindWidgetPermission.contains(packageId); 62961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 63061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 63161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void setBindAppWidgetPermission(String packageName, int grantId, 634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean grantPermission) { 635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "setBindAppWidgetPermission() " + UserHandle.getCallingUserId()); 63761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission is required for managing white listing. 640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName); 641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The grants are stored in user state wich gets the grant. 644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(grantId); 645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, grantId); 647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(grantId, packageName); 652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (grantPermission) { 653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.add(packageId); 654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.remove(packageId); 656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(grantId); 65961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 66061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 66161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public IntentSender createAppWidgetConfigIntentSender(String callingPackage, Intent intent) { 664976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "createAppWidgetConfigIntentSender() " + userId); 668119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 66961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 672976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The only allowed action is the one to start the configure activity. 674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) { 675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Only allowed action is " 676976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); 67761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 67861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Verify that widget id is provided. 680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.INVALID_APPWIDGET_ID); 682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { 683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Widget id required"); 684119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 68561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure a component name is provided. 687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName component = intent.getComponent(); 688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (component == null) { 689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Component name required"); 69061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 69161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Verify the user handle. 693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle userHandle = intent.getParcelableExtra( 694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE); 695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (userHandle != null) { 696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove the profile extra as the receiver already runs under this 697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // user and this information is of no use to this receiver. 698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.removeExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE); 699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the user handle is not the caller, check if it is an enabled 701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // profile for which the package is white-listed. 702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = userHandle.getIdentifier(); 703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId != userId) { 704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the passed user handle is a profile in the group. 705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles( 706976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new int[]{profileId}); 707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileIds.length <= 0) { 708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The profile is not in the group or not enabled, done. 709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the provider is white-listed. 713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed( 714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav component.getPackageName(), profileId)) { 715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Cannot access provider " 716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + component + " in user " + profileIds); 717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 718119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If a profile is not specified use the caller user id. 721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userHandle = new UserHandle(userId); 722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id " + appWidgetId); 734742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 736976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 738976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Widget not bound " + appWidgetId); 739742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 740742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the component refers to the provider config activity. 742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!component.equals(provider.info.configure) 743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || !provider.info.getProfile().equals(userHandle)) { 744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("No component" + component 745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for user " + userHandle.getIdentifier()); 7461c5bffbf5bae6762c8df07350abca61e460653bbAdam Cohen } 7471c5bffbf5bae6762c8df07350abca61e460653bbAdam Cohen 748976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // All right, create the sender. 749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 750742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 751976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return PendingIntent.getActivityAsUser( 752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT 753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | PendingIntent.FLAG_CANCEL_CURRENT, null, userHandle) 754976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getIntentSender(); 755742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 757742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 758742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 759742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 760742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean bindAppWidgetId(String callingPackage, int appWidgetId, 763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int providerProfileId, ComponentName providerComponent, Bundle options) { 764976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "bindAppWidgetId() " + userId); 768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 770976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 771976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check that if a cross-profile binding is attempted, it is allowed. 774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles( 775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new int[] {providerProfileId}); 776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileIds.length <= 0) { 777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 779976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the provider is not under the calling user, make sure this 781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // provider is white listed for access from the parent. 782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed( 783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav providerComponent.getPackageName(), providerProfileId)) { 784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 789976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 790976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission or white listing is required to bind widgets. 791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mSecurityPolicy.hasCallerBindPermissionOrBindWhiteListedLocked( 792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callingPackage)) { 793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 794119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 795742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Bad widget id " + appWidgetId); 803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 804742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 805742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 807976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget id " + appWidgetId 808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already bound to: " + widget.provider.id); 809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 810742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 811742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 812976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerUid = getUidForPackage(providerComponent.getPackageName(), 813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav providerProfileId); 814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (providerUid < 0) { 815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Package " + providerComponent.getPackageName() + " not installed " 816976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for profile " + providerProfileId); 817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 819742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the provider is in the already vetted user profile. 822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(providerUid, providerComponent); 823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "No widget provider " + providerComponent + " for profile " 827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + providerProfileId); 828976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 829742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 830742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 831976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.zombie) { 832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Can't bind to a 3rd party provider in" 833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " safe mode " + provider); 834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 835742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 836742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = provider; 838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle(); 839976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We need to provide a default value for the widget category if it is not specified 841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) { 842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); 844976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.add(widget); 847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int widgetCount = provider.widgets.size(); 849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widgetCount == 1) { 850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Tell the provider that it's ready. 851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendEnableIntentLocked(provider); 852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send an update now -- We need this update now, and just for this appWidgetId. 855976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // It's less critical when the next one happens, so when we schedule the next one, 856976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we add updatePeriodMillis to its start time. That time will have some slop, 857976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // but that's okay. 858976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, new int[] {appWidgetId}); 859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Schedule the future updates. 861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets)); 862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 864976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id); 867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 868742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 871742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 872742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getAppWidgetIds(ComponentName componentName) { 875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetIds() " + userId); 879742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 880742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName()); 883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can access only its providers. 889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName); 890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getWidgetIds(provider.widgets); 894742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new int[0]; 897742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 898742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 899742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getAppWidgetIdsForHost(String callingPackage, int hostId) { 902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetIdsForHost() " + userId); 906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access its hosts. 916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getWidgetIds(host.widgets); 921742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new int[0]; 924742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 925742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 926742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void bindRemoteViewsService(String callingPackage, int appWidgetId, 929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent, IBinder callbacks) { 930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "bindRemoteViewsService() " + userId); 934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id"); 946119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the widget has a provider. 949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider == null) { 950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("No provider for widget " 951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + appWidgetId); 952742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 953742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = intent.getComponent(); 955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Ensure that the service belongs to the same package as the provider. 957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // But this is not enough as they may be under different users - see below... 958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String providerPackage = widget.provider.id.componentName.getPackageName(); 959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String servicePackage = componentName.getPackageName(); 960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!servicePackage.equals(providerPackage)) { 961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("The taget service not in the same package" 962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " as the widget provider"); 963119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure this service exists under the same user as the provider and 966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // requires a permission which allows only the system to bind to it. 967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceServiceExistsAndRequiresBindRemoteViewsPermission( 968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentName, widget.provider.getUserId()); 969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Good to go - the service pakcage is correct, it exists for the correct 971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // user, and requires the bind permission. 972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If there is already a connection made for this service intent, then 974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // disconnect from that first. (This does not allow multiple connections 975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // to the same service under the same key). 976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy connection = null; 977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FilterComparison fc = new FilterComparison(intent); 978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc); 979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mBoundRemoteViewsServices.containsKey(key)) { 981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key); 982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection.disconnect(); 983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindService(connection); 984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.remove(key); 985742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the RemoteViewsService (which will trigger a callback to the 988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsAdapter.onServiceConnected()) 989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection = new ServiceConnectionProxy(callbacks); 990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindService(intent, connection, widget.provider.info.getProfile()); 991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.put(key, connection); 992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Add it to the mapping of RemoteViewsService to appWidgetIds so that we 994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // can determine when we can call back to the RemoteViewsService later to 995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // destroy associated factories. 996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> serviceId = Pair.create(widget.provider.id.uid, fc); 997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav incrementAppWidgetServiceRefCount(appWidgetId, serviceId); 998742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 999742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1000742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void unbindRemoteViewsService(String callingPackage, int appWidgetId, Intent intent) { 1003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1004311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen 1005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "unbindRemoteViewsService() " + userId); 1007742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1008742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbind from the RemoteViewsService (which will trigger a callback to the bound 1016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsAdapter) 1017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, 1018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new FilterComparison(intent)); 1019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mBoundRemoteViewsServices.containsKey(key)) { 1020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We don't need to use the appWidgetId until after we are sure there is something 1021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // to unbind. Note that this may mask certain issues with apps calling unbind() 1022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // more than necessary. 1023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 1030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id " + appWidgetId); 1031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy connection = (ServiceConnectionProxy) 1034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.get(key); 1035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection.disconnect(); 1036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(connection); 1037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.remove(key); 1038742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1039742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1040742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1041742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteHost(String callingPackage, int hostId) { 1044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1045a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 1046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteHost() " + userId); 1048a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen } 1049a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 1050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts in its uid and package. 1058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 1059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 1060e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host == null) { 1062e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen return; 1063e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 10640aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 1065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 1066e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1068e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1069976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1070976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted host " + host.id); 1071e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1072e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1073e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1074e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1075976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1076976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteAllHosts() { 1077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1078976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1079976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1080976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteAllHosts() " + userId); 1081742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1082742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1083976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1084976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1085976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1086976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean changed = false; 1087976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1088976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1089976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1090976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1091976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1092976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Delete only hosts in the calling uid. 1093976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid == Binder.getCallingUid()) { 1094976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 1095976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changed = true; 1096976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1098976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted host " + host.id); 1099976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 11006611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung } 1101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1102976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1103976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changed) { 1104976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1105976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1107742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1108742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId) { 1111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1112976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetInfo() " + userId); 1115119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1116976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1117976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1118976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1119976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1120976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1121976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1122976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1123976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1124976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1125976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1127976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1128976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.provider != null && !widget.provider.zombie) { 1129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.provider.info); 1130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1133742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1135976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId) { 1138976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetViews() " + userId); 1142742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1143742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1147976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1151976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1152976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1153976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1154976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1156976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.views); 1157742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1158976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1161742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1163976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1164976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetOptions(String callingPackage, int appWidgetId, Bundle options) { 1165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1167976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1168976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetOptions() " + userId); 1169119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1170976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1172976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1175976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1177976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1180976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1182976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 1183742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 1184742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1185976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Merge the options. 1187976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options.putAll(options); 1188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send the broacast to notify the provider that options changed. 1190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendOptionsChangedIntentLocked(widget); 1191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1192976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1193742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1194742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1195742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1196976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public Bundle getAppWidgetOptions(String callingPackage, int appWidgetId) { 1198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1199742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetOptions() " + userId); 1202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1203742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1204976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1205976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1206742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1207976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1209976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1210976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1211976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1212976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1213976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1214976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1215976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.options != null) { 1216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.options); 1217742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1219976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Bundle.EMPTY; 1220742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1221742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1222742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views) { 1226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetIds() " + UserHandle.getCallingUserId()); 1228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1229742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetIds(callingPackage, appWidgetIds, views, false); 1231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1232742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void partiallyUpdateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views) { 1236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "partiallyUpdateAppWidgetIds() " + UserHandle.getCallingUserId()); 1238742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetIds(callingPackage, appWidgetIds, views, true); 12413ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 12423ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void notifyAppWidgetViewDataChanged(String callingPackage, int[] appWidgetIds, 1245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int viewId) { 1246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 12473ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1249976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "notifyAppWidgetViewDataChanged() " + userId); 12503ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 12513ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 12543ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (appWidgetIds == null || appWidgetIds.length == 0) { 1256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1257119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1258742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1261742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = appWidgetIds.length; 1263742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 1264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = appWidgetIds[i]; 1265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1270976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1271976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1272976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyAppWidgetViewDataChanged(widget, viewId); 1273976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1274742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1275742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1276742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1277742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetProvider(ComponentName componentName, RemoteViews views) { 1280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetProvider() " + userId); 1284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName()); 1288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can access only its providers. 1294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName); 1295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 1296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 1298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Provider doesn't exist " + providerId); 1299119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn return; 1300119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> instances = provider.widgets; 1303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = instances.size(); 1304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = instances.get(i); 1306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, views, false); 1307742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1308742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1309742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1310742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1311976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1312976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int[] profileIds) { 1313976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1314976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getInstalledProvidersForProfiles() " + userId); 1317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1318976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileIds != null && profileIds.length > 0) { 1320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the profile ids are children of the calling user. 1321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles(profileIds); 1322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds = new int[] {userId}; 1324742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1326976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileIds.length == 0) { 1327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1328742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1329742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1332adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<AppWidgetProviderInfo> result = new ArrayList<>(); 1334742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 1336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 1337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 1338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info; 1339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Ignore an invalid provider or one not matching the filter. 1341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) { 1342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 1343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Add providers only for the requested profiles ... 1346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerProfileId = info.getProfile().getIdentifier(); 1347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 1348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int j = 0; j < profileCount; j++) { 1349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[j]; 1350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (providerProfileId == profileId) { 1351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // ... that are white-listed by the profile manager. 1352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed( 1353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id.componentName.getPackageName(), providerProfileId)) { 1354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result.add(cloneIfLocalBinder(info)); 1355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav break; 1357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1359742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 1362742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1363742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1364742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void updateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1366976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views, boolean partially) { 1367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (appWidgetIds == null || appWidgetIds.length == 0) { 1370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1371742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1372742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1375976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int bitmapMemoryUsage = (views != null) ? views.estimateMemoryUsage() : 0; 1377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) { 1378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("RemoteViews for widget update exceeds" 1379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " maximum bitmap memory usage (used: " + bitmapMemoryUsage 1380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + ", max: " + mMaxWidgetBitmapMemory + ")"); 1381742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1382742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1385742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = appWidgetIds.length; 1387483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani for (int i = 0; i < N; i++) { 1388976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = appWidgetIds[i]; 1389976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1390976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, views, partially); 1397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1398483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } 1399742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1400742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1401742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int incrementAndGetAppWidgetIdLocked(int userId) { 1403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = peekNextAppWidgetIdLocked(userId) + 1; 1404976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, appWidgetId); 1405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetId; 1406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void setMinAppWidgetIdLocked(int userId, int minWidgetId) { 1409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int nextAppWidgetId = peekNextAppWidgetIdLocked(userId); 1410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (nextAppWidgetId < minWidgetId) { 1411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, minWidgetId); 1412742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int peekNextAppWidgetIdLocked(int userId) { 1416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mNextAppWidgetIds.indexOfKey(userId) < 0) { 1417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return AppWidgetManager.INVALID_APPWIDGET_ID + 1; 1418742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 1419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mNextAppWidgetIds.get(userId); 1420742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1421742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1422742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host lookupOrAddHostLocked(HostId id) { 1424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 1425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 1426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1427976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1428976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1429976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host = new Host(); 1430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = id; 1431976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.add(host); 1432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1434742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1435742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1436976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteHostLocked(Host host) { 1437976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = host.widgets.size(); 1438976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1439976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = host.widgets.remove(i); 1440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteAppWidgetLocked(widget); 1441976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.remove(host); 1443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // it's gone or going away, abruptly drop the callback connection 1445976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1446742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1447742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteAppWidgetLocked(Widget widget) { 1449976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We first unbind all services that are bound to this id 1450976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindAppWidgetRemoteViewsServicesLocked(widget); 1451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1452976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = widget.host; 1453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.remove(widget); 1454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(host); 1455976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1456976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(widget); 1457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1458976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 1459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 1460976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.remove(widget); 1461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!provider.zombie) { 1462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send the broacast saying that this appWidgetId has been deleted 1463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendDeletedIntentLocked(widget); 1464976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1465976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.isEmpty()) { 1466976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // cancel the future updates 1467976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 1468976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send the broacast saying that the provider is not in use any more 1470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendDisabledIntentLocked(provider); 1471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1473742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1474742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1475742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1476976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void cancelBroadcasts(Provider provider) { 1477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "cancelBroadcasts() for " + provider); 1479976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1480976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.broadcast != null) { 1481976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mAlarmManager.cancel(provider.broadcast); 1482742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani long token = Binder.clearCallingIdentity(); 1483742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 1484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast.cancel(); 1485742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 1486742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Binder.restoreCallingIdentity(token); 1487742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1488976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast = null; 1489742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1490742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1491742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbinds from a RemoteViewsService when we delete an app widget 1493976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void unbindAppWidgetRemoteViewsServicesLocked(Widget widget) { 1494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId = widget.appWidgetId; 1495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbind all connections to Services bound to this AppWidgetId 1496976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet() 1497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .iterator(); 1498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav while (it.hasNext()) { 1499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Pair<Integer, Intent.FilterComparison> key = it.next(); 1500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (key.first == appWidgetId) { 1501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnectionProxy conn = (ServiceConnectionProxy) 1502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.get(key); 1503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav conn.disconnect(); 1504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(conn); 1505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav it.remove(); 1506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1507742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check if we need to destroy any services (if no other app widgets are 1510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // referencing the same service) 1511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav decrementAppWidgetServiceRefCount(widget); 1512742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Destroys the cached factory on the RemoteViewsService's side related to the specified intent 1515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void destroyRemoteViewsService(final Intent intent, Widget widget) { 1516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnection conn = new ServiceConnection() { 1517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 1519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service); 1520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cb.onDestroy(intent); 1522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error calling remove view factory", re); 1524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(this); 1526742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1527976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1528976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(ComponentName name) { 1530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Do nothing 1531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 1533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the service and remove the static intent->factory mapping in the 1535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsService. 1536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 1537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, 1539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.info.getProfile()); 1540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 1541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 1542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1543742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1544742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Adds to the ref-count for a given RemoteViewsService intent 1546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void incrementAppWidgetServiceRefCount(int appWidgetId, 1547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> serviceId) { 1548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<Integer> appWidgetIds = null; 1549976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mRemoteViewsServicesAppWidgets.containsKey(serviceId)) { 1550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds = mRemoteViewsServicesAppWidgets.get(serviceId); 1551976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds = new HashSet<>(); 1553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mRemoteViewsServicesAppWidgets.put(serviceId, appWidgetIds); 155475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 1555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds.add(appWidgetId); 155675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 155775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka 1558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if 1559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // the ref-count reaches zero. 1560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void decrementAppWidgetServiceRefCount(Widget widget) { 1561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, FilterComparison>> it = mRemoteViewsServicesAppWidgets 1562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .keySet().iterator(); 1563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav while (it.hasNext()) { 1564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Pair<Integer, FilterComparison> key = it.next(); 1565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key); 1566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (ids.remove(widget.appWidgetId)) { 1567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If we have removed the last app widget referencing this service, then we 1568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // should destroy it and remove it from this set 1569976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (ids.isEmpty()) { 1570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav destroyRemoteViewsService(key.second.getIntent(), widget); 1571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav it.remove(); 1572976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 157375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 157475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 157575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 157675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka 1577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void saveGroupStateAsync(int groupId) { 1578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSaveStateHandler.post(new SaveStateRunnable(groupId)); 1579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1581976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void updateAppWidgetInstanceLocked(Widget widget, RemoteViews views, 1582976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean isPartialUpdate) { 1583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.provider != null 1584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && !widget.provider.zombie && !widget.host.zombie) { 1585976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1586976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isPartialUpdate && widget.views != null) { 1587976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For a partial update, we merge the new RemoteViews with the old. 1588976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views.mergeRemoteViews(views); 1589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For a full update we replace the RemoteViews completely. 1591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views = views; 1592adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1593976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyUpdateAppWidgetLocked(widget); 1595adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1596adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1597adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1598976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyAppWidgetViewDataChanged(Widget widget, int viewId) { 1599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.host == null || widget.host.zombie 1600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.provider == null 1601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.provider.zombie) { 1602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 1608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi2 = viewId; 1610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_VIEW_DATA_CHANGED, 1613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1614adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1615adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyAppWidgetViewDataChanged(Host host, IAppWidgetHost callbacks, 1618976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, int viewId) { 1619976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.viewDataChanged(appWidgetId, viewId); 1621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // It failed; remove the callback. No need to prune because 1623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we know that this host is still referenced by this instance. 1624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks = null; 1625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the host is unavailable, then we call the associated 1628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsFactory.onDataSetChanged() directly 1629976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (callbacks == null) { 1631976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Pair<Integer, FilterComparison>> keys = mRemoteViewsServicesAppWidgets.keySet(); 1634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Pair<Integer, FilterComparison> key : keys) { 1635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mRemoteViewsServicesAppWidgets.get(key).contains(appWidgetId)) { 1636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnection connection = new ServiceConnection() { 1637976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 1639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IRemoteViewsFactory cb = IRemoteViewsFactory.Stub 1640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .asInterface(service); 1641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cb.onDataSetChangedAsync(); 1643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException e) { 1644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error calling onDataSetChangedAsync()", e); 1645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(this); 1647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(android.content.ComponentName name) { 1651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Do nothing 1652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 1654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getUserId(key.first); 1656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = key.second.getIntent(); 1657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the service and call onDataSetChanged() 1659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindService(intent, connection, new UserHandle(userId)); 1660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1661976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1664adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1665adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyUpdateAppWidgetLocked(Widget widget) { 1667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.provider == null || widget.provider.zombie 1668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.host.zombie) { 1669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1672976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 1675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg3 = widget.views; 1676976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1677976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1678976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET, 1680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks, 1684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, RemoteViews views) { 1685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.updateAppWidget(appWidgetId, views); 1687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1692adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1693adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1694adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyProviderChangedLocked(Widget widget) { 1696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.provider == null || widget.provider.zombie 1697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.host.zombie) { 1698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 1704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg3 = widget.provider.info; 1705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1706976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_PROVIDER_CHANGED, 1709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyProviderChanged(Host host, IAppWidgetHost callbacks, 1713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, AppWidgetProviderInfo info) { 1714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.providerChanged(appWidgetId, info); 1716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock){ 1718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyHostsForProvidersChangedLocked() { 1725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host == null || host.zombie || host.callbacks == null) { 1730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 1731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = host; 1735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = host.callbacks; 1736976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1738976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_PROVIDERS_CHANGED, 1739976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1740adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyProvidersChanged(Host host, IAppWidgetHost callbacks) { 1744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.providersChanged(); 1746976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1747976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1748976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1750976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1751adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1754976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static boolean isLocalBinder() { 1755976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Process.myPid() == Binder.getCallingPid(); 1756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static RemoteViews cloneIfLocalBinder(RemoteViews rv) { 1759976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && rv != null) { 1760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return rv.clone(); 1761adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return rv; 1763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1764976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) { 1766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && info != null) { 1767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return info.clone(); 1768adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return info; 1770976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1771976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static Bundle cloneIfLocalBinder(Bundle bundle) { 1773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Note: this is only a shallow copy. For now this will be fine, but it could be problematic 1774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if we start adding objects to the options. Further, it would only be an issue if keyguard 1775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // used such options. 1776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && bundle != null) { 1777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return (Bundle) bundle.clone(); 1778adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1779976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return bundle; 1780adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1781adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Widget lookupWidgetLocked(int appWidgetId, int uid, String packageName) { 1783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 1784adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate for (int i = 0; i < N; i++) { 1785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 1786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.appWidgetId == appWidgetId 1787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && mSecurityPolicy.canAccessAppWidget(widget, uid, packageName)) { 1788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget; 1789adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1790976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1794976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider lookupProviderLocked(ProviderId id) { 1795976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 1796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 1798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.id.equals(id)) { 1799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 1800adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1801adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1803adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1804adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host lookupHostLocked(HostId hostId) { 1806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1807976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.equals(hostId)) { 1810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1811976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1812adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1815adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1816976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void pruneHostLocked(Host host) { 1817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.widgets.size() == 0 && host.callbacks == null) { 1818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Pruning host " + host.id); 1820adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.remove(host); 1822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1824adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void loadGroupWidgetProvidersLocked(int[] profileIds) { 1826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> allReceivers = null; 1827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1828adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1829976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 1830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 1831976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 1832adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> receivers = queryIntentReceivers(intent, profileId); 1834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (receivers != null && !receivers.isEmpty()) { 1835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (allReceivers == null) { 1836976e8bd2017d0263216c62111454438cc0f130e3Svetoslav allReceivers = new ArrayList<>(); 1837adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav allReceivers.addAll(receivers); 1839adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1841adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = (allReceivers == null) ? 0 : allReceivers.size(); 1843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1844976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ResolveInfo receiver = allReceivers.get(i); 1845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav addProviderLocked(receiver); 1846adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1847adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1848adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean addProviderLocked(ResolveInfo ri) { 1850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { 1851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1852adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!ri.activityInfo.isEnabled()) { 1855976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1856adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1857adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1858976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(ri.activityInfo.packageName, 1859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ri.activityInfo.name); 1860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName); 1861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = parseProviderInfoXml(providerId, ri); 1863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 1864976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we might have an inactive entry for this provider already due to 1865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // a preceding restore operation. if so, fix it up in place; otherwise 1866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // just add this new one. 1867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider existing = lookupProviderLocked(providerId); 1868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the provider was not found it may be because it was restored and 1870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we did not know its UID so let us find if there is such one. 1871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing == null) { 1872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav providerId = new ProviderId(UNKNOWN_UID, componentName); 1873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav existing = lookupProviderLocked(providerId); 1874adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1875adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing != null) { 1877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing.zombie && !mSafeMode) { 1878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // it's a placeholder that was set up during an app restore 1879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav existing.zombie = false; 1880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav existing.info = provider.info; // the real one filled out from the ResolveInfo 1881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Provider placeholder now reified: " + existing); 1883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1884adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(provider); 1887adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 1889adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1890adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1893adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteProviderLocked(Provider provider) { 1895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = provider.widgets.size(); 1896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = provider.widgets.remove(i); 1898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Call back with empty RemoteViews 1899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, null, false); 1900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // clear out references to this appWidgetId 1901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.remove(widget); 1902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(widget); 1903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = null; 1904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(widget.host); 1905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = null; 1906adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.remove(provider); 1908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // no need to send the DISABLE broadcast, since the receiver is gone anyway 1910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 1911adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1912adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendEnableIntentLocked(Provider p) { 1914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED); 1915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(p.info.provider); 1916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, p.info.getProfile()); 1917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1918adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds) { 1920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); 1922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, provider.info.getProfile()); 1924adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1925adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1926976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendDeletedIntentLocked(Widget widget) { 1927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED); 1928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(widget.provider.info.provider); 1929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId); 1930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, widget.provider.info.getProfile()); 1931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendDisabledIntentLocked(Provider provider) { 1934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED); 1935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, provider.info.getProfile()); 1937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void sendOptionsChangedIntentLocked(Widget widget) { 1940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED); 1941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(widget.provider.info.provider); 1942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId); 1943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, widget.options); 1944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, widget.provider.info.getProfile()); 1945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) { 1948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.info.updatePeriodMillis > 0) { 1949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if this is the first instance, set the alarm. otherwise, 1950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // rely on the fact that we've already set it and that 1951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // PendingIntent.getBroadcast will update the extras. 1952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean alreadyRegistered = provider.broadcast != null; 1953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); 1955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav long token = Binder.clearCallingIdentity(); 1957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent, 1959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PendingIntent.FLAG_UPDATE_CURRENT, provider.info.getProfile()); 1960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 1961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 1962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!alreadyRegistered) { 1964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav long period = provider.info.updatePeriodMillis; 1965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (period < MIN_UPDATE_PERIOD) { 1966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav period = MIN_UPDATE_PERIOD; 1967adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SystemClock.elapsedRealtime() + period, period, provider.broadcast); 1970adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1971adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1972adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1973adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static int[] getWidgetIds(ArrayList<Widget> widgets) { 1975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int instancesSize = widgets.size(); 1976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetIds[] = new int[instancesSize]; 1977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < instancesSize; i++) { 1978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds[i] = widgets.get(i).appWidgetId; 1979adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetIds; 1981adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1982adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpProvider(Provider provider, int index, PrintWriter pw) { 1984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info; 1985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] provider "); 1986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(provider.id); 1987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" min=("); pw.print(info.minWidth); 1988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print("x"); pw.print(info.minHeight); 1989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(") minResize=("); pw.print(info.minResizeWidth); 1990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print("x"); pw.print(info.minResizeHeight); 1991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(") updatePeriodMillis="); 1992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.updatePeriodMillis); 1993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" resizeMode="); 1994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.resizeMode); 1995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.widgetCategory); 1996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" autoAdvanceViewId="); 1997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.autoAdvanceViewId); 1998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" initialLayout=#"); 1999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(Integer.toHexString(info.initialLayout)); 2000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" initialKeyguardLayout=#"); 2001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(Integer.toHexString(info.initialKeyguardLayout)); 2002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" zombie="); pw.println(provider.zombie); 2003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpHost(Host host, int index, PrintWriter pw) { 2006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] hostId="); 2007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(host.id); 2008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" callbacks="); pw.println(host.callbacks); 2009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" widgets.size="); pw.print(host.widgets.size()); 2010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" zombie="); pw.println(host.zombie); 2011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpGrant(Pair<Integer, String> grant, int index, PrintWriter pw) { 2014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print(']'); 2015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" user="); pw.print(grant.first); 2016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" package="); pw.println(grant.second); 2017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpWidget(Widget widget, int index, PrintWriter pw) { 2020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] id="); 2021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(widget.appWidgetId); 2022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" host="); 2023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(widget.host.id); 2024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 2025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" provider="); pw.println(widget.provider.id); 2026adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 2027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host != null) { 2028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" host.callbacks="); pw.println(widget.host.callbacks); 2029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.views != null) { 2031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" views="); pw.println(widget.views); 2032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeProvider(XmlSerializer out, Provider p) throws IOException { 2036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "p"); 2037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", p.info.provider.getPackageName()); 2038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "cl", p.info.provider.getClassName()); 2039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "tag", Integer.toHexString(p.tag)); 2040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "p"); 2041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeHost(XmlSerializer out, Host host) throws IOException { 2044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "h"); 2045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", host.id.packageName); 2046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "id", Integer.toHexString(host.id.hostId)); 2047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "tag", Integer.toHexString(host.tag)); 2048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "h"); 2049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2050adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeAppWidget(XmlSerializer out, Widget widget) throws IOException { 2052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "g"); 2053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "id", Integer.toHexString(widget.appWidgetId)); 2054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "rid", Integer.toHexString(widget.restoredId)); 2055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "h", Integer.toHexString(widget.host.tag)); 2056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 2057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "p", Integer.toHexString(widget.provider.tag)); 2058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.options != null) { 2060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt( 2061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH))); 2062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt( 2063976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT))); 2064976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt( 2065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH))); 2066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt( 2067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT))); 2068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt( 2069976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY))); 2070adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 2071976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "g"); 2072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2073adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2074976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2075976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public List<String> getWidgetParticipants(int userId) { 2076976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mBackupRestoreController.getWidgetParticipants(userId); 2077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2078adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2079976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2080976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public byte[] getWidgetState(String packageName, int userId) { 2081976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mBackupRestoreController.getWidgetState(packageName, userId); 2082976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2083adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2084976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2085976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreStarting(int userId) { 2086976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreStarting(userId); 2087976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2088adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2089976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2090976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreWidgetState(String packageName, byte[] restoredState, int userId) { 2091976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreWidgetState(packageName, restoredState, userId); 2092976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2093adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2094976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2095976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreFinished(int userId) { 2096976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreFinished(userId); 2097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2098adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2099976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @SuppressWarnings("deprecation") 2100976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri) { 2101976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = null; 2102742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ActivityInfo activityInfo = ri.activityInfo; 2104742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlResourceParser parser = null; 2105742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2106483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(), 2107742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AppWidgetManager.META_DATA_APPWIDGET_PROVIDER); 2108742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (parser == null) { 2109742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER 2110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " meta-data for " + "AppWidget provider '" + providerId + '\''); 2111742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2112742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2113742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2114742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AttributeSet attrs = Xml.asAttributeSet(parser); 2115742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2116742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int type; 2117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2118742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani && type != XmlPullParser.START_TAG) { 2119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // drain whitespace, comments, etc. 2120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2121742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2122742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String nodeName = parser.getName(); 2123742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (!"appwidget-provider".equals(nodeName)) { 2124742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for" 2125976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " AppWidget provider " + providerId.componentName 2126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for user " + providerId.uid); 2127742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2128742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2129742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider = new Provider(); 2131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id = providerId; 2132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info = new AppWidgetProviderInfo(); 2133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.provider = providerId.componentName; 2134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.providerInfo = activityInfo; 2135742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Resources resources; 2137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2138976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resources = mContext.getPackageManager() 2140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getResourcesForApplicationAsUser(activityInfo.packageName, 2141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.getUserId(providerId.uid)); 2142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2145742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav TypedArray sa = resources.obtainAttributes(attrs, 2147742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo); 2148742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2149742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // These dimensions has to be resolved in the application's context. 2150742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // We simply send back the raw complex data, which will be 2151742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}. 2152742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani TypedValue value = sa 2153742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani .peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth); 2154742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minWidth = value != null ? value.data : 0; 2155742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight); 2156742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minHeight = value != null ? value.data : 0; 2157742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue( 2158742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth); 2159742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minResizeWidth = value != null ? value.data : info.minWidth; 2160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue( 2161742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight); 2162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minResizeHeight = value != null ? value.data : info.minHeight; 2163742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.updatePeriodMillis = sa.getInt( 2164742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0); 2165742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.initialLayout = sa.getResourceId( 2166742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0); 21670aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable. 21680aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen AppWidgetProviderInfo_initialKeyguardLayout, 0); 2169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String className = sa 2171742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure); 2172742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (className != null) { 2173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.configure = new ComponentName(providerId.componentName.getPackageName(), 2174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav className); 2175742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2176483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString(); 2177742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.icon = ri.getIconResource(); 2178742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.previewImage = sa.getResourceId( 2179742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0); 2180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.autoAdvanceViewId = sa.getResourceId( 2181742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1); 2182742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.resizeMode = sa.getInt( 2183742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode, 2184742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AppWidgetProviderInfo.RESIZE_NONE); 21850aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen info.widgetCategory = sa.getInt( 2186ca5e341574774379f157a4ea579a1732bd4cf7fbMichael Jurka com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory, 21870aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); 2188742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2189742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani sa.recycle(); 2190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) { 2191742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Ok to catch Exception here, because anything going wrong because 2192742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // of what a client process passes to us should not be fatal for the 2193742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // system process. 2194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "XML parsing failed for AppWidget provider " 2195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + providerId.componentName + " for user " + providerId.uid, e); 2196742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2197742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 2198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parser != null) { 2199742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani parser.close(); 2200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2201742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 2203742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2204742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2205976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int getUidForPackage(String packageName, int userId) { 2206483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani PackageInfo pkgInfo = null; 2207976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2209483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani try { 2210976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkgInfo = mPackageManager.getPackageInfo(packageName, 0, userId); 2211483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } catch (RemoteException re) { 2212483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani // Shouldn't happen, local call 2213976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2214976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2215483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } 2216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2217742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgInfo == null || pkgInfo.applicationInfo == null) { 2218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return -1; 2219742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2221742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return pkgInfo.applicationInfo.uid; 2222742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2223742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private ActivityInfo getProviderInfo(ComponentName componentName, int userId) { 2225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 2226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(componentName); 2227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> receivers = queryIntentReceivers(intent, userId); 2229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We are setting component, so there is only one or none. 2230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!receivers.isEmpty()) { 2231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return receivers.get(0).activityInfo; 2232f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 2233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2235f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 2236f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 2237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private List<ResolveInfo> queryIntentReceivers(Intent intent, int userId) { 2238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mPackageManager.queryIntentReceivers(intent, 2241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PackageManager.GET_META_DATA, userId); 2243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 2244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Collections.emptyList(); 2245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2247742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2248742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2249742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2250976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onUserStarted(int userId) { 2251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 2252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 2253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 2255742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send broadcast only to the providers of the user. 2259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() != userId) { 2260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2263976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.size() > 0) { 2264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendEnableIntentLocked(provider); 2265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] appWidgetIds = getWidgetIds(provider.widgets); 2266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, appWidgetIds); 2267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, appWidgetIds); 2268742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2269742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2270742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2271742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2272742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2273742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // only call from initialization -- it assumes that the data structures are all empty 2274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void loadGroupStateLocked(int[] profileIds) { 2275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We can bind the widgets to host and providers only after 2276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // reading the host and providers for all users since a widget 2277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // can have a host and a provider in different users. 2278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<LoadedWidgetState> loadedWidgets = new ArrayList<>(); 2279742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int version = 0; 2281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileIdCount = profileIds.length; 2283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 2284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // No file written for this user - nothing to do. 2287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AtomicFile file = getSavedStateFile(profileId); 2288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FileInputStream stream = file.openRead(); 2290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav version = readProfileStateFromFileLocked(stream, profileId, loadedWidgets); 2291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IoUtils.closeQuietly(stream); 2292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (FileNotFoundException e) { 2293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to read state: " + e); 2294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (version >= 0) { 2298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Hooke'm up... 2299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindLoadedWidgets(loadedWidgets); 2300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // upgrade the database if needed 2302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav performUpgradeLocked(version); 2303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 2304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // failed reading, clean up 2305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to read state, clearing widgets and hosts."); 2306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.clear(); 2307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.clear(); 2308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 2309976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 2310976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.get(i).widgets.clear(); 2311742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2314742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void bindLoadedWidgets(List<LoadedWidgetState> loadedWidgets) { 2316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int loadedWidgetCount = loadedWidgets.size(); 2317976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = loadedWidgetCount - 1; i >= 0; i--) { 2318976e8bd2017d0263216c62111454438cc0f130e3Svetoslav LoadedWidgetState loadedWidget = loadedWidgets.remove(i); 2319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = loadedWidget.widget; 2320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = findProviderByTag(loadedWidget.providerTag); 2322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider == null) { 2323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // This provider is gone. We just let the host figure out 2324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // that this happened when it fails to load it. 2325976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2326976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2328976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = findHostByTag(loadedWidget.hostTag); 2329976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host == null) { 2330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // This host is gone. 2331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.widgets.add(widget); 2335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.add(widget); 2336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(widget); 2337119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 2338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider findProviderByTag(int tag) { 2341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (tag < 0) { 2342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 2346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.tag == tag) { 2348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 2349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host findHostByTag(int tag) { 2355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (tag < 0) { 2356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < hostCount; i++) { 2360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.tag == tag) { 2362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 2363742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2366976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void saveStateLocked(int userId) { 2369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav tagProvidersAndHosts(); 2370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); 2372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 2374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 2375976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AtomicFile file = getSavedStateFile(profileId); 2378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FileOutputStream stream; 2379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stream = file.startWrite(); 2381976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (writeProfileStateToFileLocked(stream, profileId)) { 2382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav file.finishWrite(stream); 2383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 2384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav file.failWrite(stream); 2385976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to save state, restoring backup."); 2386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2387976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException e) { 2388976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed open state file for write: " + e); 2389976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2390976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void tagProvidersAndHosts() { 2394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 2396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = i; 2398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2400976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2401976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < hostCount; i++) { 2402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = i; 2404742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2405742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2406742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean writeProfileStateToFileLocked(FileOutputStream stream, int userId) { 2408742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int N; 2409742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2410742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2411742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlSerializer out = new FastXmlSerializer(); 2412742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.setOutput(stream, "utf-8"); 2413742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.startDocument(null, true); 2414742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.startTag(null, "gs"); 241539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller out.attribute(null, "version", String.valueOf(CURRENT_VERSION)); 2416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mProviders.size(); 2418742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2420976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only providers for the user. 2421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() != userId) { 2422976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.size() > 0) { 2425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeProvider(out, provider); 2426742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2427742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2428742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2429742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 2430742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2431742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = mHosts.get(i); 2432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only hosts for the user. 2433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.getUserId() != userId) { 2434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2435976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2436adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate serializeHost(out, host); 2437742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2438742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2439976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 2440742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2441976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 2442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only widgets hosted by the user. 2443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.getUserId() != userId) { 2444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2445976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeAppWidget(out, widget); 2447742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2448742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2449976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, String>> it = mPackagesWithBindWidgetPermission.iterator(); 245061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka while (it.hasNext()) { 2451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> binding = it.next(); 2452976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only white listings for the user. 2453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (binding.first != userId) { 2454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2455976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 245661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka out.startTag(null, "b"); 2457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "packageName", binding.second); 245861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka out.endTag(null, "b"); 245961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 246061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 2461742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.endTag(null, "gs"); 2462742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.endDocument(); 2463742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return true; 2464742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } catch (IOException e) { 2465742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "Failed to write state: " + e); 2466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return false; 2467742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2468742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2469742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int readProfileStateFromFileLocked(FileInputStream stream, int userId, 2471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<LoadedWidgetState> outLoadedWidgets) { 2472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int version = -1; 2473742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2474742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlPullParser parser = Xml.newPullParser(); 2475742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani parser.setInput(stream, null); 2476742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int legacyProviderIndex = -1; 2478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int legacyHostIndex = -1; 2479742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int type; 2480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani do { 2481742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani type = parser.next(); 2482742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (type == XmlPullParser.START_TAG) { 2483742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String tag = parser.getName(); 248439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if ("gs".equals(tag)) { 248539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller String attributeValue = parser.getAttributeValue(null, "version"); 248639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller try { 248739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = Integer.parseInt(attributeValue); 248839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } catch (NumberFormatException e) { 248939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = 0; 249039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 249139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } else if ("p".equals(tag)) { 2492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav legacyProviderIndex++; 2493742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // TODO: do we need to check that this package has the same signature 2494742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // as before? 2495742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkg = parser.getAttributeValue(null, "pkg"); 2496742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String cl = parser.getAttributeValue(null, "cl"); 2497742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkg = getCanonicalPackageName(pkg, cl, userId); 2499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkg == null) { 2500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2501742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2502742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 2504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid < 0) { 2505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(pkg, cl); 2509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ActivityInfo providerInfo = getProviderInfo(componentName, userId); 2511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (providerInfo == null) { 2512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(uid, componentName); 2516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 2517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null && mSafeMode) { 2519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if we're in safe mode, make a temporary one 2520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider = new Provider(); 2521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info = new AppWidgetProviderInfo(); 2522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info.provider = providerId.componentName; 2523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info.providerInfo = providerInfo; 2524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.zombie = true; 2525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id = providerId; 2526976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(provider); 2527742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2528976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String tagAttribute = parser.getAttributeValue(null, "tag"); 2530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag = !TextUtils.isEmpty(tagAttribute) 2531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? Integer.parseInt(tagAttribute, 16) : legacyProviderIndex; 2532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = providerTag; 2533742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if ("h".equals(tag)) { 2534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav legacyHostIndex++; 2535742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = new Host(); 2536742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // TODO: do we need to check that this package has the same signature 2537742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // as before? 2538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 2539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 2541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid < 0) { 2542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani host.zombie = true; 2543742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2545742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (!host.zombie || mSafeMode) { 2546742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // In safe mode, we don't discard the hosts we don't recognize 2547742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // so that they're not pruned from our list. Otherwise, we do. 2548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId = Integer.parseInt(parser.getAttributeValue( 2549976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "id"), 16); 2550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2551976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String tagAttribute = parser.getAttributeValue(null, "tag"); 2552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag = !TextUtils.isEmpty(tagAttribute) 2553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? Integer.parseInt(tagAttribute, 16) : legacyHostIndex; 2554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = hostTag; 2556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, hostId, pkg); 2557742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mHosts.add(host); 2558742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 255961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } else if ("b".equals(tag)) { 256061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka String packageName = parser.getAttributeValue(null, "packageName"); 2561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(packageName, userId); 2562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0) { 2563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(userId, packageName); 2564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.add(packageId); 256561a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 2566742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if ("g".equals(tag)) { 2567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = new Widget(); 2568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.appWidgetId = Integer.parseInt(parser.getAttributeValue( 2569976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "id"), 16); 2570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav setMinAppWidgetIdLocked(userId, widget.appWidgetId + 1); 2571742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2572adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate // restored ID is allowed to be absent 2573adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate String restoredIdString = parser.getAttributeValue(null, "rid"); 2574976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.restoredId = (restoredIdString == null) ? 0 2575adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate : Integer.parseInt(restoredIdString, 16); 2576adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 25770aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Bundle options = new Bundle(); 25780aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String minWidthString = parser.getAttributeValue(null, "min_width"); 25790aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen if (minWidthString != null) { 25800aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 25810aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(minWidthString, 16)); 25820aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25830aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String minHeightString = parser.getAttributeValue(null, "min_height"); 2584db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (minHeightString != null) { 25850aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 25860aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(minHeightString, 16)); 25870aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 2588db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen String maxWidthString = parser.getAttributeValue(null, "max_width"); 2589db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (maxWidthString != null) { 25900aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 25910aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(maxWidthString, 16)); 25920aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25930aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String maxHeightString = parser.getAttributeValue(null, "max_height"); 2594db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (maxHeightString != null) { 25950aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 25960aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(maxHeightString, 16)); 25970aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25980aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String categoryString = parser.getAttributeValue(null, "host_category"); 2599db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (categoryString != null) { 26000aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 26010aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(categoryString, 16)); 26020aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 2603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options = options; 26040aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 2605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag = Integer.parseInt(parser.getAttributeValue( 2606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "h"), 16); 2607742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String providerString = parser.getAttributeValue(null, "p"); 2608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag = (providerString != null) ? Integer.parseInt( 2609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "p"), 16) : TAG_UNDEFINED; 2610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We can match widgets with hosts and providers only after hosts 2612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // and providers for all users have been loaded since the widget 2613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // host and provider can be in different user profiles. 2614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav LoadedWidgetState loadedWidgets = new LoadedWidgetState(widget, 2615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav hostTag, providerTag); 2616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav outLoadedWidgets.add(loadedWidgets); 2617742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2618742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2619742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } while (type != XmlPullParser.END_DOCUMENT); 2620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (NullPointerException 2621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | NumberFormatException 2622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | XmlPullParserException 2623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | IOException 2624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | IndexOutOfBoundsException e) { 2625742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "failed parsing " + e); 2626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return -1; 2627742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2628742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2629976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return version; 2630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2631742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void performUpgradeLocked(int fromVersion) { 263339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (fromVersion < CURRENT_VERSION) { 2634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to " 2635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + CURRENT_VERSION); 263639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 263739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 263839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller int version = fromVersion; 263939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 264039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller // Update 1: keyguard moved from package "android" to "com.android.keyguard" 264139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (version == 0) { 2642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId oldHostId = new HostId(Process.myUid(), 2643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav KEYGUARD_HOST_ID, OLD_KEYGUARD_HOST_PACKAGE); 2644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(oldHostId); 2646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 2647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(NEW_KEYGUARD_HOST_PACKAGE, 2648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_OWNER); 2649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0) { 2650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, KEYGUARD_HOST_ID, NEW_KEYGUARD_HOST_PACKAGE); 265139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 265239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 2653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 265439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = 1; 265539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 265639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 265739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (version != CURRENT_VERSION) { 265839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller throw new IllegalStateException("Failed to upgrade widget database"); 265939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 266039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 266139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 2662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static File getStateFile(int userId) { 2663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new File(Environment.getUserSystemDirectory(userId), STATE_FILENAME); 2664135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani } 2665135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani 2666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static AtomicFile getSavedStateFile(int userId) { 2667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File dir = Environment.getUserSystemDirectory(userId); 2668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File settingsFile = getStateFile(userId); 2669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!settingsFile.exists() && userId == UserHandle.USER_OWNER) { 2670e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani if (!dir.exists()) { 2671e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani dir.mkdirs(); 2672e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani } 2673e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // Migrate old data 2674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File oldFile = new File("/data/system/" + STATE_FILENAME); 2675e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // Method doesn't throw an exception on failure. Ignore any errors 2676e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // in moving the file (like non-existence) 2677e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani oldFile.renameTo(settingsFile); 2678742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2679742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return new AtomicFile(settingsFile); 2680742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2681742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onUserStopped(int userId) { 2683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 2684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove widgets that have both host and provider in the user. 2685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int widgetCount = mWidgets.size(); 2686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = widgetCount - 1; i >= 0; i--) { 2687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 2688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean hostInUser = widget.host.getUserId() == userId; 2690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean hasProvider = widget.provider != null; 2691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean providerInUser = hasProvider && widget.provider.getUserId() == userId; 2692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If both host and provider are in the user, just drop the widgets 2694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // as we do not want to make host callbacks and provider broadcasts 2695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // as the host and the provider will be killed. 2696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hostInUser && (!hasProvider || providerInUser)) { 2697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(i); 2698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.remove(widget); 2699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = null; 2700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hasProvider) { 2701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.widgets.remove(widget); 2702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = null; 2703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2706756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani 2707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove hosts and notify providers in other profiles. 2708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = hostCount - 1; i >= 0; i--) { 2710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.getUserId() == userId) { 2712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 2713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2715135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani 2716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove the providers and notify hosts in other profiles. 2717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = providerCount - 1; i >= 0; i--) { 2719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() == userId) { 2721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 2722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove grants for this user. 2726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int grantCount = mPackagesWithBindWidgetPermission.size(); 2727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = grantCount - 1; i >= 0; i--) { 2728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = mPackagesWithBindWidgetPermission.valueAt(i); 2729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageId.first == userId) { 2730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.removeAt(i); 2731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2732742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Take a note we no longer have state for this user. 2735c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav final int userIndex = mLoadedUserIds.indexOfKey(userId); 2736c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav if (userIndex >= 0) { 2737c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav mLoadedUserIds.removeAt(userIndex); 2738742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 27397fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2740976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove the widget id counter. 2741c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav final int nextIdIndex = mNextAppWidgetIds.indexOfKey(userId); 2742c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav if (nextIdIndex >= 0) { 2743c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav mNextAppWidgetIds.removeAt(nextIdIndex); 2744c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav } 2745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2746742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2747742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2748a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung /** 2749a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * Updates all providers with the specified package names, and records any providers that were 2750a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * pruned. 2751a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * 2752a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * @return whether any providers were updated 2753a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung */ 2754976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean updateProvidersForPackageLocked(String packageName, int userId, 2755976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<ProviderId> removedProviders) { 27567fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung boolean providersUpdated = false; 2757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<ProviderId> keep = new HashSet<>(); 2759742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 2760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setPackage(packageName); 2761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> broadcastReceivers = queryIntentReceivers(intent, userId); 2762742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2763742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // add the missing ones and collect which ones to keep 2764742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int N = broadcastReceivers == null ? 0 : broadcastReceivers.size(); 2765742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2766742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ResolveInfo ri = broadcastReceivers.get(i); 2767742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ActivityInfo ai = ri.activityInfo; 2768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2769742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { 2770742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani continue; 2771742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(ai.packageName)) { 2774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(ai.applicationInfo.uid, 2775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new ComponentName(ai.packageName, ai.name)); 2776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 2778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 2779742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (addProviderLocked(ri)) { 2780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav keep.add(providerId); 27817fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2782742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2783742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 2784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider parsed = parseProviderInfoXml(providerId, ri); 2785742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (parsed != null) { 2786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav keep.add(providerId); 2787742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Use the new AppWidgetProviderInfo. 2788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info = parsed.info; 2789742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // If it's enabled 2790976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int M = provider.widgets.size(); 2791742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (M > 0) { 2792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] appWidgetIds = getWidgetIds(provider.widgets); 2793742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Reschedule for the new updatePeriodMillis (don't worry about handling 2794742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // it specially if updatePeriodMillis didn't change because we just sent 2795742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // an update, and the next one will be updatePeriodMillis from now). 2796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 2797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, appWidgetIds); 2798742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // If it's currently showing, call back with the new 2799742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // AppWidgetProviderInfo. 2800742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int j = 0; j < M; j++) { 2801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = provider.widgets.get(j); 2802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views = null; 2803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyProviderChangedLocked(widget); 2804742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2805742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Now that we've told the host, push out an update. 2806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, appWidgetIds); 28077fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2808742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2809742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2810742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2811742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2812742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2813742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2814742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // prune the ones we don't want to keep 2815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mProviders.size(); 2816742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(provider.info.provider.getPackageName()) 2819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.getUserId() == userId 2820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && !keep.contains(provider.id)) { 2821a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung if (removedProviders != null) { 2822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removedProviders.add(provider.id); 2823a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung } 2824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 28257fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2826742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2827742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 28287fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 28297fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung return providersUpdated; 2830742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2831742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) { 2833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean removed = false; 2834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 2836742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkgName.equals(provider.info.provider.getPackageName()) 2839976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.getUserId() == userId) { 2840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 2841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removed = true; 2842742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2843742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2844742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2845742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Delete the hosts for this package too 2846742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // By now, we have removed any AppWidgets that were in any hosts here, 2847742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // so we don't need to worry about sending DISABLE broadcasts to them. 2848742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 2849742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2850742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = mHosts.get(i); 2851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkgName.equals(host.id.packageName) 2852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && host.getUserId() == userId) { 2853742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani deleteHostLocked(host); 2854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removed = true; 2855742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2856742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 28577fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2858976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return removed; 28597fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 28607fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private String getCanonicalPackageName(String packageName, String className, int userId) { 2862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 28647fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung try { 2865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppGlobals.getPackageManager().getReceiverInfo(new ComponentName(packageName, 2866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav className), 0, userId); 2867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return packageName; 2868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 2869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String[] packageNames = mContext.getPackageManager() 2870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .currentToCanonicalPackageNames(new String[]{packageName}); 2871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageNames != null && packageNames.length > 0) { 2872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return packageNames[0]; 28737fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 2874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendBroadcastAsUser(Intent intent, UserHandle userHandle) { 2882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.sendBroadcastAsUser(intent, userHandle); 2885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void bindService(Intent intent, ServiceConnection connection, 2891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle userHandle) { 2892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 2893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, 2895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userHandle); 2896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 2898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void unbindService(ServiceConnection connection) { 2902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 2903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(connection); 2905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 2907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class CallbackHandler extends Handler { 2911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1; 2912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2; 2913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3; 2914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4; 2915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public CallbackHandler(Looper looper) { 2917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav super(looper, null, false); 2918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void handleMessage(Message message) { 2922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav switch (message.what) { 2923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_UPDATE_APP_WIDGET: { 2924976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2925976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2926976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views = (RemoteViews) args.arg3; 2928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views); 2932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_PROVIDER_CHANGED: { 2935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = (AppWidgetProviderInfo)args.arg3; 2939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyProviderChanged(host, callbacks, appWidgetId, info); 2943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_PROVIDERS_CHANGED: { 2946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyProvidersChanged(host, callbacks); 2952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_VIEW_DATA_CHANGED: { 2955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int viewId = args.argi2; 2960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId); 2963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class SecurityPolicy { 2969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] resolveCallerEnabledGroupProfiles(int[] profileIds) { 2971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = UserHandle.getCallingUserId(); 2972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int enabledProfileCount = 0; 2974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 2975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 2976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isParentOrProfile(parentId, profileId)) { 2978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Not the current user or" 2979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " a child profile: " + profileId); 2980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isProfileEnabled(profileId)) { 2982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds[i] = DISABLED_PROFILE; 2983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 2984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav enabledProfileCount++; 2985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int resolvedProfileIndex = 0; 2989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] resolvedProfiles = new int[enabledProfileCount]; 2990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 2991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId != DISABLED_PROFILE) { 2993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resolvedProfiles[resolvedProfileIndex] = profileId; 2994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resolvedProfileIndex++; 2995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return resolvedProfiles; 2999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getEnabledGroupProfileIds(int userId) { 3002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = getGroupParent(userId); 3003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final List<UserInfo> profiles; 3005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profiles = mUserManager.getProfiles(parentId); 3008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int enabledProfileCount = 0; 3013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profiles.size(); 3014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 3015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profiles.get(i).isEnabled()) { 3016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav enabledProfileCount++; 3017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int enabledProfileIndex = 0; 3021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = new int[enabledProfileCount]; 3022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 3023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo profile = profiles.get(i); 3024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profile.isEnabled()) { 3025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds[enabledProfileIndex] = profile.getUserHandle().getIdentifier(); 3026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav enabledProfileIndex++; 3027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return profileIds; 3031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceServiceExistsAndRequiresBindRemoteViewsPermission( 3034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName, int userId) { 3035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceInfo serviceInfo = mPackageManager.getServiceInfo(componentName, 3038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PackageManager.GET_PERMISSIONS, userId); 3039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (serviceInfo == null) { 3040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Service " + componentName 3041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " not installed for user " + userId); 3042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(serviceInfo.permission)) { 3044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Service " + componentName 3045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " in user " + userId + "does not require " 3046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + android.Manifest.permission.BIND_REMOTEVIEWS); 3047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Local call - shouldn't happen. 3050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceModifyAppWidgetBindPermissions(String packageName) { 3056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.enforceCallingPermission( 3057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS, 3058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav "hasBindAppWidgetPermission packageName=" + packageName); 3059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceCallFromPackage(String packageName) { 3062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isCallFromPackage(packageName)) { 3063976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Package " + packageName 3064976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " not running under user " + UserHandle.getCallingUserId()); 3065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isCallFromPackage(String packageName) { 3069976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // System and root call all from anywhere they want. 3070976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int callingUid = Binder.getCallingUid(); 3071976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (callingUid == Process.SYSTEM_UID || callingUid == 0 /* root */) { 3072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3073976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3074976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check if the package is present for the given profile. 3075976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, 3076976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.getUserId(callingUid)); 3077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 3078976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3079976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3080976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check if the call for a package is coming from that package. 3081976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.isSameApp(callingUid, packageUid); 3082976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3083976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3084976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hasCallerBindPermissionOrBindWhiteListedLocked(String packageName) { 3085976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3086976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.enforceCallingOrSelfPermission( 3087976e8bd2017d0263216c62111454438cc0f130e3Svetoslav android.Manifest.permission.BIND_APPWIDGET, null); 3088976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (SecurityException se) { 3089976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isCallerBindAppWidgetWhiteListedLocked(packageName)) { 3090976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3091976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3092976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3093976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3094976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3095976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3096976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isCallerBindAppWidgetWhiteListedLocked(String packageName) { 3097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 3098976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, userId); 3099976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 3100976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("No package " + packageName 3101976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for user " + userId); 3102976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3103976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3104976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 3105976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3106976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(userId, packageName); 3107976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mPackagesWithBindWidgetPermission.contains(packageId)) { 3108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3112976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3115976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean canAccessAppWidget(Widget widget, int uid, String packageName) { 3116976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isHostInPackageForUid(widget.host, uid, packageName)) { 3117976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps hosting the AppWidget have access to it. 3118976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3119976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3120976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isProviderInPackageForUid(widget.provider, uid, packageName)) { 3121976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps providing the AppWidget have access to it. 3122976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3123976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3124976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isHostAccessingProvider(widget.host, widget.provider, uid, packageName)) { 3125976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps hosting the AppWidget get to bind to a remote view service in the provider. 3126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3127976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3128976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mContext.checkCallingPermission(android.Manifest.permission.BIND_APPWIDGET) 3129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav == PackageManager.PERMISSION_GRANTED) { 3130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps that can bind have access to all appWidgetIds. 3131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3135976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isParentOrProfile(int parentId, int profileId) { 3137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parentId == profileId) { 3138976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getProfileParent(profileId) == parentId; 3141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderInCallerOrInProfileAndWhitelListed(String packageName, 3144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int profileId) { 3145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int callerId = UserHandle.getCallingUserId(); 3146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId == callerId) { 3147976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = getProfileParent(profileId); 3150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parentId != callerId) { 3151976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3152976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3153976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return isProviderWhitelListed(packageName, profileId); 3154976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3156976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderWhitelListed(String packageName, int profileId) { 3157976e8bd2017d0263216c62111454438cc0f130e3Svetoslav DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( 3158976e8bd2017d0263216c62111454438cc0f130e3Svetoslav DevicePolicyManagerInternal.class); 3159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3160976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the policy manager is not available on the device we deny it all. 3161976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (devicePolicyManager == null) { 3162976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3163976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3164976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<String> crossProfilePackages = devicePolicyManager 3166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getCrossProfileWidgetProviders(profileId); 3167976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3168976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return crossProfilePackages.contains(packageName); 3169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3170976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getProfileParent(int profileId) { 3172976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo parent = mUserManager.getProfileParent(profileId); 3175976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parent != null) { 3176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return parent.getUserHandle().getIdentifier(); 3177976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3180976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UNKNOWN_USER_ID; 3182976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3183976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3184976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getGroupParent(int profileId) { 3185976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = mSecurityPolicy.getProfileParent(profileId); 3186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return (parentId != UNKNOWN_USER_ID) ? parentId : profileId; 3187976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isHostInPackageForUid(Host host, int uid, String packageName) { 3190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (UserHandle.getAppId(uid) == Process.myUid()) { 3191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For a host that's in the system process, ignore the user id. 3192976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.isSameApp(host.id.uid, uid) 3193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && host.id.packageName.equals(packageName); 3194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host.id.uid == uid 3196976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && host.id.packageName.equals(packageName); 3197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderInPackageForUid(Provider provider, int uid, 3201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String packageName) { 3202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Packages providing the AppWidget have access to it. 3203976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider != null && provider.id.uid == uid 3204976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.getPackageName().equals(packageName); 3205976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3206976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3207976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isHostAccessingProvider(Host host, Provider provider, int uid, 3208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String packageName) { 3209976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The host creates a package context to bind to remote views service in the provider. 3210976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host.id.uid == uid && provider != null 3211976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.getPackageName().equals(packageName); 3212976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3213976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3214976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isProfileEnabled(int profileId) { 3215976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3217976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo userInfo = mUserManager.getUserInfo(profileId); 3218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (userInfo == null || !userInfo.isEnabled()) { 3219976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3221976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Provider { 3229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId id; 3230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info; 3231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> widgets = new ArrayList<>(); 3232976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PendingIntent broadcast; 3233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean zombie; // if we're in safe mode, don't prune this just because nobody references it 3234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int tag = TAG_UNDEFINED; // for use while saving state (the index) 3236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getUserId() { 3238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.getUserId(id.uid); 3239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isInPackageForUser(String packageName, int userId) { 3242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getUserId() == userId 3243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && id.componentName.getPackageName().equals(packageName); 3244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // is there an instance of this provider hosted by the given app? 3247976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hostedByPackageForUser(String packageName, int userId) { 3248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = widgets.size(); 3249976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3250976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = widgets.get(i); 3251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(widget.host.id.packageName) 3252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.host.getUserId() == userId) { 3253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "Provider{" + id + (zombie ? " Z" : "") + '}'; 3262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3263976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class ProviderId { 3266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid; 3267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ComponentName componentName; 3268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private ProviderId(int uid, ComponentName componentName) { 3270976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.uid = uid; 3271976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.componentName = componentName; 3272976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3273976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean equals(Object obj) { 3276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (this == obj) { 3277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (obj == null) { 3280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (getClass() != obj.getClass()) { 3283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId other = (ProviderId) obj; 3286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid != other.uid) { 3287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (componentName == null) { 3290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (other.componentName != null) { 3291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (!componentName.equals(other.componentName)) { 3294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int hashCode() { 3301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int result = uid; 3302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + ((componentName != null) 3303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? componentName.hashCode() : 0); 3304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 3305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3309976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "ProviderId{user:" + UserHandle.getUserId(uid) + ", app:" 3310976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + UserHandle.getAppId(uid) + ", cmp:" + componentName + '}'; 3311976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3312976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3313976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3314976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Host { 3315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id; 3316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> widgets = new ArrayList<>(); 3317976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks; 3318976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean zombie; // if we're in safe mode, don't prune this just because nobody references it 3319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int tag = TAG_UNDEFINED; // for use while saving state (the index) 3321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getUserId() { 3323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.getUserId(id.uid); 3324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3325976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3326976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isInPackageForUser(String packageName, int userId) { 3327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getUserId() == userId && id.packageName.equals(packageName); 3328976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3329976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean hostsPackageForUser(String pkg, int userId) { 3331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = widgets.size(); 3332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widgets.get(i).provider; 3334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null && provider.getUserId() == userId && provider.info != null 3335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && pkg.equals(provider.info.provider.getPackageName())) { 3336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "Host{" + id + (zombie ? " Z" : "") + '}'; 3345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class HostId { 3349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid; 3350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId; 3351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final String packageName; 3352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public HostId(int uid, int hostId, String packageName) { 3354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.uid = uid; 3355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.hostId = hostId; 3356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.packageName = packageName; 3357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean equals(Object obj) { 3361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (this == obj) { 3362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (obj == null) { 3365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3366976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (getClass() != obj.getClass()) { 3368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId other = (HostId) obj; 3371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid != other.uid) { 3372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hostId != other.hostId) { 3375976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName == null) { 3378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (other.packageName != null) { 3379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3381976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (!packageName.equals(other.packageName)) { 3382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3385976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3387976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3388976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int hashCode() { 3389976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int result = uid; 3390976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + hostId; 3391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + ((packageName != null) 3392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? packageName.hashCode() : 0); 3393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 3394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "HostId{user:" + UserHandle.getUserId(uid) + ", app:" 3399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + UserHandle.getAppId(uid) + ", hostId:" + hostId 3400976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + ", pkg:" + packageName + '}'; 3401976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3404976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Widget { 3405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId; 3406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int restoredId; // tracking & remapping any restored state 3407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider; 3408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views; 3409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle options; 3410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host; 3411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}'; 3415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3418976e8bd2017d0263216c62111454438cc0f130e3Svetoslav /** 3419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection. This 3420976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * needs to be a static inner class since a reference to the ServiceConnection is held globally 3421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * and may lead us to leak AppWidgetService instances (if there were more than one). 3422976e8bd2017d0263216c62111454438cc0f130e3Svetoslav */ 3423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class ServiceConnectionProxy implements ServiceConnection { 3424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final IRemoteViewsAdapterConnection mConnectionCb; 3425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy(IBinder connectionCb) { 3427976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb = IRemoteViewsAdapterConnection.Stub 3428976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .asInterface(connectionCb); 3429976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3431976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 3432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb.onServiceConnected(service); 3434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3435976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error passing service interface", re); 3436976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3437976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3438976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3439976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(ComponentName name) { 3440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav disconnect(); 3441976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void disconnect() { 3444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3445976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb.onServiceDisconnected(); 3446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3447976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error clearing service interface", re); 3448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3449976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3450976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3452976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private class LoadedWidgetState { 3453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Widget widget; 3454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag; 3455976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag; 3456976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public LoadedWidgetState(Widget widget, int hostTag, int providerTag) { 3458976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.widget = widget; 3459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.hostTag = hostTag; 3460976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.providerTag = providerTag; 3461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3464976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class SaveStateRunnable implements Runnable { 3465976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int mUserId; 3466976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3467976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public SaveStateRunnable(int userId) { 3468976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUserId = userId; 3469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void run() { 3473976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3474976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(mUserId); 3475976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveStateLocked(mUserId); 3476976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3479976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3480976e8bd2017d0263216c62111454438cc0f130e3Svetoslav /** 3481976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * This class encapsulates the backup and restore logic for a user group state. 3482976e8bd2017d0263216c62111454438cc0f130e3Svetoslav */ 3483976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class BackupRestoreController { 3484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String TAG = "BackupRestoreController"; 3485976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3486976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final boolean DEBUG = true; 3487976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3488976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Version of backed-up widget state. 3489976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int WIDGET_STATE_VERSION = 2; 3490976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We need to make sure to wipe the pre-restore widget state only once for 3492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // a given package. Keep track of what we've done so far here; the list is 3493976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // cleared at the start of every system restore pass, but preserved through 3494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // any install-time restore operations. 3495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashSet<String> mPrunedApps = new HashSet<>(); 3496976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Provider, ArrayList<RestoreUpdateRecord>> mUpdatesByProvider = 3498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new HashMap<>(); 3499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost = 3500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new HashMap<>(); 3501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public List<String> getWidgetParticipants(int userId) { 3503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Getting widget participants for user: " + userId); 3505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<String> packages = new HashSet<>(); 3508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 3510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3513976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Skip cross-user widgets. 3514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isProviderAndHostInUser(widget, userId)) { 3515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 3516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packages.add(widget.host.id.packageName); 3519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 3521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packages.add(provider.id.componentName.getPackageName()); 3522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new ArrayList<>(packages); 3526976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3527976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3528976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public byte[] getWidgetState(String backedupPackage, int userId) { 3529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Getting widget state for user: " + userId); 3531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ByteArrayOutputStream stream = new ByteArrayOutputStream(); 3534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Preflight: if this app neither hosts nor provides any live widgets 3536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we have no work to do. 3537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!packageNeedsWidgetBackupLocked(backedupPackage, userId)) { 3538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3542976e8bd2017d0263216c62111454438cc0f130e3Svetoslav XmlSerializer out = new FastXmlSerializer(); 3543976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.setOutput(stream, "utf-8"); 3544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startDocument(null, true); 3545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "ws"); // widget state 3546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "version", String.valueOf(WIDGET_STATE_VERSION)); 3547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", backedupPackage); 3548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3549976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remember all the providers that are currently hosted or published 3550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // by this package: that is, all of the entities related to this app 3551976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // which will need to be told about id remapping. 3552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int index = 0; 3553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 3554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 3556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3557976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!provider.widgets.isEmpty() 3558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && (provider.isInPackageForUser(backedupPackage, userId) 3559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || provider.hostedByPackageForUser(backedupPackage, userId))) { 3560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = index; 3561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeProvider(out, provider); 3562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index++; 3563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mHosts.size(); 3567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index = 0; 3568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3569976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 3570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!host.widgets.isEmpty() 3572976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && (host.isInPackageForUser(backedupPackage, userId) 3573976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || host.hostsPackageForUser(backedupPackage, userId))) { 3574976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = index; 3575976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeHost(out, host); 3576976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index++; 3577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // All widget instances involving this package, 3581976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // either as host or as provider 3582976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 3583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3585976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3586976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3587976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.isInPackageForUser(backedupPackage, userId) 3588976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || (provider != null 3589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.isInPackageForUser(backedupPackage, userId))) { 3590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeAppWidget(out, widget); 3591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3592976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3593976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "ws"); 3595976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endDocument(); 3596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException e) { 3597976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to save widget state for " + backedupPackage); 3598976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return stream.toByteArray(); 3603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreStarting(int userId) { 3606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Restore starting for user: " + userId); 3608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We're starting a new "system" restore operation, so any widget restore 3612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // state that we see from here on is intended to replace the current 3613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // widget configuration of any/all of the affected apps. 3614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPrunedApps.clear(); 3615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByProvider.clear(); 3616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByHost.clear(); 3617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3618976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3619976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreWidgetState(String packageName, byte[] restoredState, int userId) { 3621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Restoring widget state for user:" + userId 3623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " package: " + packageName); 3624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ByteArrayInputStream stream = new ByteArrayInputStream(restoredState); 3627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Providers mentioned in the widget dataset by ordinal 3629976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Provider> restoredProviders = new ArrayList<>(); 3630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3631976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Hosts mentioned in the widget dataset by ordinal 3632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Host> restoredHosts = new ArrayList<>(); 3633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav XmlPullParser parser = Xml.newPullParser(); 3635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.setInput(stream, null); 3636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3637976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int type; 3639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav do { 3640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav type = parser.next(); 3641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (type == XmlPullParser.START_TAG) { 3642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final String tag = parser.getName(); 3643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if ("ws".equals(tag)) { 3644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String version = parser.getAttributeValue(null, "version"); 3645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int versionNumber = Integer.parseInt(version); 3647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (versionNumber > WIDGET_STATE_VERSION) { 3648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to process state version " + version); 3649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // TODO: fix up w.r.t. canonical vs current package names 3653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!packageName.equals(pkg)) { 3655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Package mismatch in ws"); 3656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("p".equals(tag)) { 3659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String cl = parser.getAttributeValue(null, "cl"); 3661976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // hostedProviders index will match 'p' attribute in widget's 3663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // entry in the xml file being restored 3664976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If there's no live entry for this provider, add an inactive one 3665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // so that widget IDs referring to them can be properly allocated 3666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Backup and resotre only for the parent profile. 3668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(pkg, cl); 3669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider p = findProviderLocked(componentName, userId); 3671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p == null) { 3672976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p = new Provider(); 3673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.id = new ProviderId(UNKNOWN_UID, componentName); 3674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.info = new AppWidgetProviderInfo(); 3675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.info.provider = componentName; 3676976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.zombie = true; 3677976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(p); 3678976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " provider " + p.id); 3681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredProviders.add(p); 3683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("h".equals(tag)) { 3684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The host app may not yet exist on the device. If it's here we 3685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // just use the existing Host entry, otherwise we create a 3686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // placeholder whose uid will be fixed up at PACKAGE_ADDED time. 3687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 3690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId = Integer.parseInt( 3691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "id"), 16); 3692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(uid, hostId, pkg); 3694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host h = lookupOrAddHostLocked(id); 3695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredHosts.add(h); 3696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " host[" + restoredHosts.size() 3699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + "]: {" + h.id + "}"); 3700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("g".equals(tag)) { 3702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int restoredId = Integer.parseInt( 3703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "id"), 16); 3704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int hostIndex = Integer.parseInt( 3705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "h"), 16); 3706976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = restoredHosts.get(hostIndex); 3707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider p = null; 3708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String prov = parser.getAttributeValue(null, "p"); 3709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (prov != null) { 3710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // could have been null if the app had allocated an id 3711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // but not yet established a binding under that id 3712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int which = Integer.parseInt(prov, 16); 3713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p = restoredProviders.get(which); 3714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We'll be restoring widget state for both the host and 3717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // provider sides of this widget ID, so make sure we are 3718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // beginning from a clean slate on both fronts. 3719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneWidgetStateLocked(host.id.packageName, userId); 3720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p != null) { 3721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneWidgetStateLocked(p.id.componentName.getPackageName(), 3722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userId); 3723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Have we heard about this ancestral widget instance before? 3726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget id = findRestoredWidgetLocked(restoredId, host, p); 3727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id == null) { 3728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id = new Widget(); 3729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.appWidgetId = incrementAndGetAppWidgetIdLocked(userId); 3730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.restoredId = restoredId; 3731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.options = parseWidgetIdOptions(parser); 3732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.host = host; 3733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.host.widgets.add(id); 3734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.provider = p; 3735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id.provider != null) { 3736976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.provider.widgets.add(id); 3737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3738976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3739976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "New restored id " + restoredId 3740976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " now " + id); 3741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(id); 3743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id.provider.info != null) { 3745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stashProviderRestoreUpdateLocked(id.provider, 3746976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredId, id.appWidgetId); 3747976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3748976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Missing provider for restored widget " + id); 3749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3750976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stashHostRestoreUpdateLocked(id.host, restoredId, id.appWidgetId); 3751976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " instance: " + restoredId 3754976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " -> " + id.appWidgetId 3755976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " :: p=" + id.provider); 3756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3759976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } while (type != XmlPullParser.END_DOCUMENT); 3760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We've updated our own bookkeeping. We'll need to notify the hosts and 3762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // providers about the changes, but we can't do that yet because the restore 3763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // target is not necessarily fully live at this moment. Set aside the 3764976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // information for now; the backup manager will call us once more at the 3765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // end of the process when all of the targets are in a known state, and we 3766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // will update at that point. 3767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (XmlPullParserException | IOException e) { 3769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to restore widget state for " + packageName); 3770976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3771976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 3772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Called once following the conclusion of a restore operation. This is when we 3776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send out updates to apps involved in widget-state restore telling them about 3777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // the new widget ID space. 3778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreFinished(int userId) { 3779976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "restoreFinished for " + userId); 3781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final UserHandle userHandle = new UserHandle(userId); 3784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Build the providers' broadcasts and send them off 3786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries 3787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav = mUpdatesByProvider.entrySet(); 3788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) { 3789976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For each provider there's a list of affected IDs 3790976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = e.getKey(); 3791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> updates = e.getValue(); 3792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int pending = countPendingUpdates(updates); 3793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3794976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Provider " + provider + " pending: " + pending); 3795976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pending > 0) { 3797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] oldIds = new int[pending]; 3798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] newIds = new int[pending]; 3799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 3800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int nextPending = 0; 3801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 3803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 3804976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.notified = true; 3805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldIds[nextPending] = r.oldId; 3806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newIds[nextPending] = r.newId; 3807976e8bd2017d0263216c62111454438cc0f130e3Svetoslav nextPending++; 3808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " " + r.oldId + " => " + r.newId); 3810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3811976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3812976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendWidgetRestoreBroadcastLocked( 3814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.ACTION_APPWIDGET_RESTORED, 3815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider, null, oldIds, newIds, userHandle); 3816976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // same thing per host 3820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries 3821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav = mUpdatesByHost.entrySet(); 3822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) { 3823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = e.getKey(); 3824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid != UNKNOWN_UID) { 3825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> updates = e.getValue(); 3826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int pending = countPendingUpdates(updates); 3827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3828976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Host " + host + " pending: " + pending); 3829976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pending > 0) { 3831976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] oldIds = new int[pending]; 3832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] newIds = new int[pending]; 3833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 3834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int nextPending = 0; 3835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3836976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 3837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 3838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.notified = true; 3839976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldIds[nextPending] = r.oldId; 3840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newIds[nextPending] = r.newId; 3841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav nextPending++; 3842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " " + r.oldId + " => " + r.newId); 3844976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendWidgetRestoreBroadcastLocked( 3848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED, 3849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, host, oldIds, newIds, userHandle); 3850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3855976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3856976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider findProviderLocked(ComponentName componentName, int userId) { 3857976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 3858976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 3859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 3860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() == userId 3861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.equals(componentName)) { 3862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 3863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3864976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Widget findRestoredWidgetLocked(int restoredId, Host host, Provider p) { 3869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Find restored widget: id=" + restoredId 3871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " host=" + host + " provider=" + p); 3872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p == null || host == null) { 3875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 3879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.restoredId == restoredId 3882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.host.id.equals(host.id) 3883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.provider.id.equals(p.id)) { 3884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " Found at " + i + " : " + widget); 3886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget; 3888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean packageNeedsWidgetBackupLocked(String packageName, int userId) { 3894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mWidgets.size(); 3895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Skip cross-user widgets. 3899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isProviderAndHostInUser(widget, userId)) { 3900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 3901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.isInPackageForUser(packageName, userId)) { 3904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // this package is hosting widgets, so it knows widget IDs. 3905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null && provider.isInPackageForUser(packageName, userId)) { 3910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // someone is hosting this app's widgets, so it knows widget IDs. 3911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void stashProviderRestoreUpdateLocked(Provider provider, int oldId, int newId) { 3918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> r = mUpdatesByProvider.get(provider); 3919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r == null) { 3920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r = new ArrayList<>(); 3921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByProvider.put(provider, r); 3922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // don't duplicate 3924976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (alreadyStashed(r, oldId, newId)) { 3925976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3926976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "ID remap " + oldId + " -> " + newId 3927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already stashed for " + provider); 3928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.add(new RestoreUpdateRecord(oldId, newId)); 3933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean alreadyStashed(ArrayList<RestoreUpdateRecord> stash, 3936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int oldId, final int newId) { 3937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = stash.size(); 3938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = stash.get(i); 3940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r.oldId == oldId && r.newId == newId) { 3941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void stashHostRestoreUpdateLocked(Host host, int oldId, int newId) { 3948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> r = mUpdatesByHost.get(host); 3949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r == null) { 3950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r = new ArrayList<>(); 3951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByHost.put(host, r); 3952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (alreadyStashed(r, oldId, newId)) { 3954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "ID remap " + oldId + " -> " + newId 3956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already stashed for " + host); 3957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.add(new RestoreUpdateRecord(oldId, newId)); 3962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendWidgetRestoreBroadcastLocked(String action, Provider provider, 3965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host, int[] oldIds, int[] newIds, UserHandle userHandle) { 3966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(action); 3967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds); 3968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds); 3969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 3970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 3971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, userHandle); 3972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 3974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(null); 3975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setPackage(host.id.packageName); 3976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_HOST_ID, host.id.hostId); 3977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, userHandle); 3978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We're restoring widget state for 'pkg', so we start by wiping (a) all widget 3982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // instances that are hosted by that app, and (b) all instances in other hosts 3983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // for which 'pkg' is the provider. We assume that we'll be restoring all of 3984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // these hosts & providers, so will be reconstructing a correct live state. 3985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void pruneWidgetStateLocked(String pkg, int userId) { 3986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mPrunedApps.contains(pkg)) { 3987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "pruning widget state for restoring package " + pkg); 3989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = mWidgets.size() - 1; i >= 0; i--) { 3991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = widget.host; 3994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.hostsPackageForUser(pkg, userId) 3997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || (provider != null && provider.isInPackageForUser(pkg, userId))) { 3998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // 'pkg' is either the host or the provider for this instances, 3999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // so we tear it down in anticipation of it (possibly) being 4000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // reconstructed due to the restore 4001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.remove(widget); 4002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.remove(widget); 4003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindAppWidgetRemoteViewsServicesLocked(widget); 4004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(i); 4005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPrunedApps.add(pkg); 4008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 4009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 4010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "already pruned " + pkg + ", continuing normally"); 4011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isProviderAndHostInUser(Widget widget, int userId) { 4016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Backup only widgets hosted or provided by the owner profile. 4017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget.host.getUserId() == userId && (widget.provider == null 4018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.provider.getUserId() == userId); 4019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Bundle parseWidgetIdOptions(XmlPullParser parser) { 4022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle options = new Bundle(); 4023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String minWidthString = parser.getAttributeValue(null, "min_width"); 4024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (minWidthString != null) { 4025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 4026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(minWidthString, 16)); 4027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String minHeightString = parser.getAttributeValue(null, "min_height"); 4029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (minHeightString != null) { 4030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 4031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(minHeightString, 16)); 4032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String maxWidthString = parser.getAttributeValue(null, "max_width"); 4034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (maxWidthString != null) { 4035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 4036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(maxWidthString, 16)); 4037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String maxHeightString = parser.getAttributeValue(null, "max_height"); 4039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (maxHeightString != null) { 4040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 4041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(maxHeightString, 16)); 4042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String categoryString = parser.getAttributeValue(null, "host_category"); 4044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (categoryString != null) { 4045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 4046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(categoryString, 16)); 4047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return options; 4049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int countPendingUpdates(ArrayList<RestoreUpdateRecord> updates) { 4052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int pending = 0; 4053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 4054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 4055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 4056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 4057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pending++; 4058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return pending; 4061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4063976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Accumulate a list of updates that affect the given provider for a final 4064976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // coalesced notification broadcast once restore is over. 4065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private class RestoreUpdateRecord { 4066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int oldId; 4067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int newId; 4068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean notified; 4069976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4070976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public RestoreUpdateRecord(int theOldId, int theNewId) { 4071976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldId = theOldId; 4072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newId = theNewId; 4073976e8bd2017d0263216c62111454438cc0f130e3Svetoslav notified = false; 40747fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 40757fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 4076742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 4077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav}