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; 215771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganovimport android.app.AppOpsManager; 22742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.app.PendingIntent; 23976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.app.admin.DevicePolicyManagerInternal; 246bd702538d90005add1cfc33746da19404090dc1Svet Ganovimport android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener; 25742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetManager; 26742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.appwidget.AppWidgetProviderInfo; 27976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.BroadcastReceiver; 28742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.ComponentName; 29742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Context; 30742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent; 31742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.Intent.FilterComparison; 32976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.IntentFilter; 33976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.IntentSender; 3461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurkaimport android.content.ServiceConnection; 35742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ActivityInfo; 36742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ApplicationInfo; 37483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasaniimport android.content.pm.IPackageManager; 38742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageInfo; 39742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.PackageManager; 40742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ResolveInfo; 41742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.pm.ServiceInfo; 42976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.pm.UserInfo; 43742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.Resources; 44742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.TypedArray; 45742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.res.XmlResourceParser; 46a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.graphics.Point; 47742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.net.Uri; 48742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Binder; 49742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Bundle; 5061f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment; 51a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohenimport android.os.Handler; 52742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.IBinder; 53976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.Looper; 54976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.Message; 55f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.Process; 56742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.RemoteException; 57742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.SystemClock; 58f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 59976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.os.UserManager; 60976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.text.TextUtils; 61976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.util.ArraySet; 6239606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile; 63742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.AttributeSet; 64742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Pair; 65742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Slog; 66976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.util.SparseIntArray; 67742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.TypedValue; 68742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Xml; 69a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brownimport android.view.Display; 70311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohenimport android.view.WindowManager; 71742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.widget.RemoteViews; 72742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 73742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.appwidget.IAppWidgetHost; 74976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.appwidget.IAppWidgetService; 75976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.os.BackgroundThread; 76976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.internal.os.SomeArgs; 77742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.util.FastXmlSerializer; 78742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsAdapterConnection; 79742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport com.android.internal.widget.IRemoteViewsFactory; 80742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 81976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.server.LocalServices; 82976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport com.android.server.WidgetBackupProvider; 83976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport libcore.io.IoUtils; 84742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParser; 85742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlPullParserException; 86742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport org.xmlpull.v1.XmlSerializer; 87742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 88adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tateimport java.io.ByteArrayInputStream; 89adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tateimport java.io.ByteArrayOutputStream; 90742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.File; 91742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileDescriptor; 92742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileInputStream; 93742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileNotFoundException; 94742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.FileOutputStream; 95742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.IOException; 96742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.PrintWriter; 97742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.ArrayList; 98976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport java.util.Collections; 99742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashMap; 100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashSet; 101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Iterator; 102742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.List; 103742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Locale; 104976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport java.util.Map; 105742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Set; 106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1076bd702538d90005add1cfc33746da19404090dc1Svet Ganovclass AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider, 1086bd702538d90005add1cfc33746da19404090dc1Svet Ganov OnCrossProfileWidgetProvidersChangeListener { 109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String TAG = "AppWidgetServiceImpl"; 110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static boolean DEBUG = false; 112742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String OLD_KEYGUARD_HOST_PACKAGE = "android"; 114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard"; 11539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller private static final int KEYGUARD_HOST_ID = 0x4b455947; 116742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 117976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String STATE_FILENAME = "appwidgets.xml"; 1188320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani 119976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int MIN_UPDATE_PERIOD = DEBUG ? 0 : 30 * 60 * 1000; // 30 minutes 120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 121976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int TAG_UNDEFINED = -1; 122742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 123976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int UNKNOWN_UID = -1; 124adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 125976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int LOADED_PROFILE_ID = -1; 126adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 127976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int UNKNOWN_USER_ID = -10; 128742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bump if the stored widgets need to be upgraded. 130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int CURRENT_VERSION = 1; 131c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani 132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onReceive(Context context, Intent intent) { 134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String action = intent.getAction(); 135adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Received broadcast: " + action); 138adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 139adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onConfigurationChanged(); 142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (Intent.ACTION_USER_STARTED.equals(action)) { 143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onUserStarted(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_NULL)); 145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onUserStopped(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 147976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_NULL)); 148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav onPackageBroadcastReceived(intent, intent.getIntExtra( 150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)); 151976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 152adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 153976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 154742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Manages active connections to RemoteViewsServices. 156976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection> 157976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices = new HashMap<>(); 158adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Manages persistent references to RemoteViewsServices from different App Widgets. 160976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Pair<Integer, FilterComparison>, HashSet<Integer>> 161976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mRemoteViewsServicesAppWidgets = new HashMap<>(); 162adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 163976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Object mLock = new Object(); 164adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Widget> mWidgets = new ArrayList<>(); 166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Host> mHosts = new ArrayList<>(); 167976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArrayList<Provider> mProviders = new ArrayList<>(); 168adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final ArraySet<Pair<Integer, String>> mPackagesWithBindWidgetPermission = 170976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new ArraySet<>(); 171742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 172976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SparseIntArray mLoadedUserIds = new SparseIntArray(); 173742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final BackupRestoreController mBackupRestoreController; 175742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Context mContext; 177742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final IPackageManager mPackageManager; 179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final AlarmManager mAlarmManager; 180976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final UserManager mUserManager; 1815771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov private final AppOpsManager mAppOpsManager; 182742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 183976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SecurityPolicy mSecurityPolicy; 184adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 185a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen private final Handler mSaveStateHandler; 186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final Handler mCallbackHandler; 187a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Locale mLocale; 189742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final SparseIntArray mNextAppWidgetIds = new SparseIntArray(); 191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 192976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean mSafeMode; 193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int mMaxWidgetBitmapMemory; 194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetServiceImpl(Context context) { 196742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mContext = context; 197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackageManager = AppGlobals.getPackageManager(); 198742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 2005771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSaveStateHandler = BackgroundThread.getHandler(); 202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler = new CallbackHandler(mContext.getMainLooper()); 203976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController = new BackupRestoreController(); 204976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy = new SecurityPolicy(); 205311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen computeMaximumWidgetBitmapMemory(); 206976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerBroadcastReceiver(); 2076bd702538d90005add1cfc33746da19404090dc1Svet Ganov registerOnCrossProfileProvidersChangedListener(); 208311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen } 209311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen 210976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void computeMaximumWidgetBitmapMemory() { 211311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 212a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown Display display = wm.getDefaultDisplay(); 213a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown Point size = new Point(); 214a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown display.getRealSize(size); 215e92aad432add317793a69a34eab5d271962df220Winson Chung // Cap memory usage at 1.5 times the size of the display 216e92aad432add317793a69a34eab5d271962df220Winson Chung // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h 217a8b9defade5b937d4ad64f9aff4bca792298f43cJeff Brown mMaxWidgetBitmapMemory = 6 * size.x * size.y; 218742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 219742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void registerBroadcastReceiver() { 221976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for configuration changes so we can update the names 222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // of the widgets when the locale changes. 223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter configFilter = new IntentFilter(); 224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav configFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav configFilter, null, null); 227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for broadcasts about package install, etc., so we can 229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // update the provider list. 230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter packageFilter = new IntentFilter(); 231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 232976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter.addDataScheme("package"); 235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packageFilter, null, null); 237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Register for events related to sdcard installation. 239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter sdFilter = new IntentFilter(); 240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sdFilter, null, null); 244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IntentFilter userFilter = new IntentFilter(); 246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter.addAction(Intent.ACTION_USER_STARTED); 247976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter.addAction(Intent.ACTION_USER_STOPPED); 248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 249976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userFilter, null, null); 250976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2526bd702538d90005add1cfc33746da19404090dc1Svet Ganov private void registerOnCrossProfileProvidersChangedListener() { 2536bd702538d90005add1cfc33746da19404090dc1Svet Ganov DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( 2546bd702538d90005add1cfc33746da19404090dc1Svet Ganov DevicePolicyManagerInternal.class); 2556bd702538d90005add1cfc33746da19404090dc1Svet Ganov // The device policy is an optional component. 2566bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (devicePolicyManager != null) { 2576bd702538d90005add1cfc33746da19404090dc1Svet Ganov devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this); 2586bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 2596bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 2606bd702538d90005add1cfc33746da19404090dc1Svet Ganov 261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void setSafeMode(boolean safeMode) { 262742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mSafeMode = safeMode; 263742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 264742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onConfigurationChanged() { 266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "onConfigurationChanged()"); 268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2698320de8e29819963845d3d386d6d087844a5ae31Amith Yamasani 270742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Locale revised = Locale.getDefault(); 271976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (revised == null || mLocale == null || !revised.equals(mLocale)) { 272742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mLocale = revised; 273742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SparseIntArray changedGroups = null; 276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 277a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the 278a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // list of installed providers and skip providers that we don't need to update. 279a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung // Also note that remove the provider does not clear the Provider component data. 280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Provider> installedProviders = new ArrayList<>(mProviders); 281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<ProviderId> removedProviders = new HashSet<>(); 282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 283a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung int N = installedProviders.size(); 284742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = installedProviders.get(i); 286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(provider.getUserId()); 288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!removedProviders.contains(provider.id)) { 290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean changed = updateProvidersForPackageLocked( 291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id.componentName.getPackageName(), 292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.getUserId(), removedProviders); 293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changed) { 295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changedGroups == null) { 296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changedGroups = new SparseIntArray(); 297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupId = mSecurityPolicy.getGroupParent( 299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.getUserId()); 300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changedGroups.put(groupId, groupId); 301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changedGroups != null) { 306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupCount = changedGroups.size(); 307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < groupCount; i++) { 308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int groupId = changedGroups.get(i); 309976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(groupId); 310a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung } 311742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 314742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 315742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onPackageBroadcastReceived(Intent intent, int userId) { 317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani final String action = intent.getAction(); 318742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani boolean added = false; 319742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani boolean changed = false; 320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean componentsModified = false; 321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 322742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkgList[] = null; 323742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { 324742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = true; 326742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 327742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 328742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = false; 329742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 330742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Uri uri = intent.getData(); 331742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (uri == null) { 332742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 333742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 334742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkgName = uri.getSchemeSpecificPart(); 335742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgName == null) { 336742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 337742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 338742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pkgList = new String[] { pkgName }; 339742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani added = Intent.ACTION_PACKAGE_ADDED.equals(action); 340742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani changed = Intent.ACTION_PACKAGE_CHANGED.equals(action); 341742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 342742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgList == null || pkgList.length == 0) { 343742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 344742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle extras = intent.getExtras(); 350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (added || changed) { 352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean newPackageAdded = added && (extras == null 353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || !extras.getBoolean(Intent.EXTRA_REPLACING, false)); 354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (String pkgName : pkgList) { 356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Fix up the providers - add/remove/update. 357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentsModified |= updateProvidersForPackageLocked(pkgName, userId, null); 358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // ... and see if these are hosts we've been awaiting. 360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: We are backing up and restoring only the owner. 361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (newPackageAdded && userId == UserHandle.USER_OWNER) { 362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkgName, userId); 363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0 ) { 364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resolveHostUidLocked(pkgName, uid); 365adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 366adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 367742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 368742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the package is being updated, we'll receive a PACKAGE_ADDED 370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // shortly, otherwise it is removed permanently. 371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean packageRemovedPermanently = (extras == null 372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || !extras.getBoolean(Intent.EXTRA_REPLACING, false)); 373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageRemovedPermanently) { 375742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (String pkgName : pkgList) { 376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentsModified |= removeHostsAndProvidersForPackageLocked( 377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkgName, userId); 378742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 379742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 380742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 3817fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (componentsModified) { 383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 385976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the set of providers has been modified, notify each active AppWidgetHost 3866bd702538d90005add1cfc33746da19404090dc1Svet Ganov scheduleNotifyGroupHostsForProvidersChangedLocked(userId); 3877fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 3887fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 389742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 390742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void resolveHostUidLocked(String pkg, int uid) { 392adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate final int N = mHosts.size(); 393adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate for (int i = 0; i < N; i++) { 394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid == UNKNOWN_UID && pkg.equals(host.id.packageName)) { 396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "host " + host.id + " resolved to uid " + uid); 398adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, host.id.hostId, host.id.packageName); 400976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 401adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 402adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 403adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 404adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void ensureGroupStateLoadedLocked(int userId) { 406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); 407742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Careful lad, we may have already loaded the state for some 409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // group members, so check before loading and read only the 410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // state for the new member(s). 411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int newMemberCount = 0; 412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileIdCount = profileIds.length; 413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mLoadedUserIds.indexOfKey(profileId) >= 0) { 416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds[i] = LOADED_PROFILE_ID; 417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 418976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newMemberCount++; 419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 420742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 422976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (newMemberCount <= 0) { 423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 424742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int newMemberIndex = 0; 427976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] newProfileIds = new int[newMemberCount]; 428976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 429976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId != LOADED_PROFILE_ID) { 431976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mLoadedUserIds.put(profileId, profileId); 432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newProfileIds[newMemberIndex] = profileId; 433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newMemberIndex++; 434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 435742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 436976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 437c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav clearProvidersAndHostsTagsLocked(); 438c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav 439976e8bd2017d0263216c62111454438cc0f130e3Svetoslav loadGroupWidgetProvidersLocked(newProfileIds); 440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav loadGroupStateLocked(newProfileIds); 441742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 442742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 44575d8c0b8bc28f61658c62b870ae8705e0be191cbNick Kralevich mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, 44675d8c0b8bc28f61658c62b870ae8705e0be191cbNick Kralevich "Permission Denial: can't dump from from pid=" 44775d8c0b8bc28f61658c62b870ae8705e0be191cbNick Kralevich + Binder.getCallingPid() 44875d8c0b8bc28f61658c62b870ae8705e0be191cbNick Kralevich + ", uid=" + Binder.getCallingUid()); 449742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 450976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 452742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println("Providers:"); 453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpProvider(mProviders.get(i), i, pw); 455742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 456742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 458742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println("Widgets:"); 460976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpWidget(mWidgets.get(i), i, pw); 462742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 463742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 464742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 465742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println("Hosts:"); 467976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 468742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani dumpHost(mHosts.get(i), i, pw); 469742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 470742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 471742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mPackagesWithBindWidgetPermission.size(); 473742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani pw.println(" "); 474976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println("Grants:"); 475976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 476976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> grant = mPackagesWithBindWidgetPermission.valueAt(i); 477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav dumpGrant(grant, i, pw); 478742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 479742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 481742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 482976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 483976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] startListening(IAppWidgetHost callbacks, String callingPackage, 484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int hostId, List<RemoteViews> updatedViews) { 485976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 486976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 487976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 488976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "startListening() " + userId); 489742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 490742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 493742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 496742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupOrAddHostLocked(id); 501742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = callbacks; 503742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedViews.clear(); 505742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> instances = host.widgets; 507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = instances.size(); 508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] updatedIds = new int[N]; 509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = instances.get(i); 511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedIds[i] = widget.appWidgetId; 512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updatedViews.add(cloneIfLocalBinder(widget.views)); 513742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return updatedIds; 516742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 517742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 518742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void stopListening(String callingPackage, int hostId) { 521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "stopListening() " + userId); 525742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 526742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 527976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 528976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(host); 541742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 542742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 543742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 544742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int allocateAppWidgetId(String callingPackage, int hostId) { 547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 549976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "allocateAppWidgetId() " + userId); 551742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 552742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 555742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 557976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 558742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mNextAppWidgetIds.indexOfKey(userId) < 0) { 560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, AppWidgetManager.INVALID_APPWIDGET_ID + 1); 561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 562742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = incrementAndGetAppWidgetIdLocked(userId); 564742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts it owns. 567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupOrAddHostLocked(id); 569976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = new Widget(); 571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.appWidgetId = appWidgetId; 572976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = host; 573976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 574976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.add(widget); 575976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(widget); 576976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Allocated widget id " + appWidgetId 581976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for host " + host.id); 582742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetId; 585742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 586742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 587742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 588976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteAppWidgetId(String callingPackage, int appWidgetId) { 590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 592976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 593976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteAppWidgetId() " + userId); 594742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 595742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 597976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 598742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 6010aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 6060aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 610742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteAppWidgetLocked(widget); 612742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted widget id " + appWidgetId 617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for host " + widget.host.id); 618742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 619742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 620742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 621742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hasBindAppWidgetPermission(String packageName, int grantId) { 624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "hasBindAppWidgetPermission() " + UserHandle.getCallingUserId()); 626119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission is required for managing white listing. 629976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName); 630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 631976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The grants are stored in user state wich gets the grant. 633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(grantId); 634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, grantId); 636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 63761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka return false; 63861a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(grantId, packageName); 641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mPackagesWithBindWidgetPermission.contains(packageId); 64261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 64361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 64461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void setBindAppWidgetPermission(String packageName, int grantId, 647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean grantPermission) { 648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "setBindAppWidgetPermission() " + UserHandle.getCallingUserId()); 65061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission is required for managing white listing. 653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName); 654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The grants are stored in user state wich gets the grant. 657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(grantId); 658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, grantId); 660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 661976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 664976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(grantId, packageName); 665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (grantPermission) { 666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.add(packageId); 667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.remove(packageId); 669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(grantId); 67261a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 67361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 67461a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 6768e1d299da27da534b508b1da51ebe351a689cefaSvetoslav public IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId, 6778e1d299da27da534b508b1da51ebe351a689cefaSvetoslav int intentFlags) { 678976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "createAppWidgetConfigIntentSender() " + userId); 682119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 68361a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id " + appWidgetId); 697742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Widget not bound " + appWidgetId); 702742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 703742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 7048e1d299da27da534b508b1da51ebe351a689cefaSvetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); 7058e1d299da27da534b508b1da51ebe351a689cefaSvetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 7068e1d299da27da534b508b1da51ebe351a689cefaSvetoslav intent.setComponent(provider.info.configure); 7078e1d299da27da534b508b1da51ebe351a689cefaSvetoslav intent.setFlags(intentFlags); 7081c5bffbf5bae6762c8df07350abca61e460653bbAdam Cohen 709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // All right, create the sender. 710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 711742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return PendingIntent.getActivityAsUser( 713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT 7148e1d299da27da534b508b1da51ebe351a689cefaSvetoslav | PendingIntent.FLAG_CANCEL_CURRENT, null, 7158e1d299da27da534b508b1da51ebe351a689cefaSvetoslav new UserHandle(provider.getUserId())) 716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getIntentSender(); 717742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 719742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 720742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 721742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 722742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean bindAppWidgetId(String callingPackage, int appWidgetId, 725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int providerProfileId, ComponentName providerComponent, Bundle options) { 726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "bindAppWidgetId() " + userId); 730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check that if a cross-profile binding is attempted, it is allowed. 7368e1d299da27da534b508b1da51ebe351a689cefaSvetoslav if (!mSecurityPolicy.isEnabledGroupProfile(providerProfileId)) { 737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 738976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 739976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 740976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the provider is not under the calling user, make sure this 741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // provider is white listed for access from the parent. 742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed( 743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav providerComponent.getPackageName(), providerProfileId)) { 744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 746976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 747976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 748976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 750976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // A special permission or white listing is required to bind widgets. 751976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mSecurityPolicy.hasCallerBindPermissionOrBindWhiteListedLocked( 752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callingPackage)) { 753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 754119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 755742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 759976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Bad widget id " + appWidgetId); 763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 764742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 765742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget id " + appWidgetId 768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already bound to: " + widget.provider.id); 769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 770742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 771742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerUid = getUidForPackage(providerComponent.getPackageName(), 773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav providerProfileId); 774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (providerUid < 0) { 775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Package " + providerComponent.getPackageName() + " not installed " 776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for profile " + providerProfileId); 777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 779742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the provider is in the already vetted user profile. 782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(providerUid, providerComponent); 783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "No widget provider " + providerComponent + " for profile " 787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + providerProfileId); 788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 789742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 790742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.zombie) { 792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Can't bind to a 3rd party provider in" 793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " safe mode " + provider); 794976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 795742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 796742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = provider; 798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle(); 799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We need to provide a default value for the widget category if it is not specified 801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) { 802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); 804976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.add(widget); 807976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int widgetCount = provider.widgets.size(); 809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widgetCount == 1) { 810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Tell the provider that it's ready. 811976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendEnableIntentLocked(provider); 812976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send an update now -- We need this update now, and just for this appWidgetId. 815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // It's less critical when the next one happens, so when we schedule the next one, 816976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we add updatePeriodMillis to its start time. That time will have some slop, 817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // but that's okay. 818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, new int[] {appWidgetId}); 819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Schedule the future updates. 821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets)); 822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id); 827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 828742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 829976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 831742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 832742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getAppWidgetIds(ComponentName componentName) { 835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 836976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetIds() " + userId); 839742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 840742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName()); 843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 844976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can access only its providers. 849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName); 850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getWidgetIds(provider.widgets); 854742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 855976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 856976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new int[0]; 857742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 858742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 859742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getAppWidgetIdsForHost(String callingPackage, int hostId) { 862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 864976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetIdsForHost() " + userId); 866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access its hosts. 876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getWidgetIds(host.widgets); 881742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new int[0]; 884742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 885742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 886742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void bindRemoteViewsService(String callingPackage, int appWidgetId, 889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent, IBinder callbacks) { 890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "bindRemoteViewsService() " + userId); 894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 8965771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov // Make sure the package runs under the caller uid. 8975771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov mSecurityPolicy.enforceCallFromPackage(callingPackage); 8985771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov 899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id"); 909119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the widget has a provider. 912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider == null) { 913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("No provider for widget " 914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + appWidgetId); 915742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 916742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = intent.getComponent(); 918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Ensure that the service belongs to the same package as the provider. 920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // But this is not enough as they may be under different users - see below... 921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String providerPackage = widget.provider.id.componentName.getPackageName(); 922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String servicePackage = componentName.getPackageName(); 923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!servicePackage.equals(providerPackage)) { 924976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("The taget service not in the same package" 925976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " as the widget provider"); 926119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure this service exists under the same user as the provider and 929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // requires a permission which allows only the system to bind to it. 930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceServiceExistsAndRequiresBindRemoteViewsPermission( 931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav componentName, widget.provider.getUserId()); 932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Good to go - the service pakcage is correct, it exists for the correct 934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // user, and requires the bind permission. 935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If there is already a connection made for this service intent, then 937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // disconnect from that first. (This does not allow multiple connections 938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // to the same service under the same key). 939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy connection = null; 940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FilterComparison fc = new FilterComparison(intent); 941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc); 942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mBoundRemoteViewsServices.containsKey(key)) { 944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key); 945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection.disconnect(); 946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindService(connection); 947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.remove(key); 948742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the RemoteViewsService (which will trigger a callback to the 951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsAdapter.onServiceConnected()) 952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection = new ServiceConnectionProxy(callbacks); 953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindService(intent, connection, widget.provider.info.getProfile()); 954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.put(key, connection); 955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Add it to the mapping of RemoteViewsService to appWidgetIds so that we 957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // can determine when we can call back to the RemoteViewsService later to 958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // destroy associated factories. 959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> serviceId = Pair.create(widget.provider.id.uid, fc); 960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav incrementAppWidgetServiceRefCount(appWidgetId, serviceId); 961742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 962742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 963742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void unbindRemoteViewsService(String callingPackage, int appWidgetId, Intent intent) { 966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 967311c79c3e93589c6fc720fe6c58ed522af591376Adam Cohen 968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "unbindRemoteViewsService() " + userId); 970742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 971742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbind from the RemoteViewsService (which will trigger a callback to the bound 979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsAdapter) 980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, 981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new FilterComparison(intent)); 982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mBoundRemoteViewsServices.containsKey(key)) { 983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We don't need to use the appWidgetId until after we are sure there is something 984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // to unbind. Note that this may mask certain issues with apps calling unbind() 985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // more than necessary. 986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("Bad widget id " + appWidgetId); 994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy connection = (ServiceConnectionProxy) 997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.get(key); 998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav connection.disconnect(); 999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(connection); 1000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.remove(key); 1001742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1002742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1003742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1004742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteHost(String callingPackage, int hostId) { 1007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1008a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 1009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteHost() " + userId); 1011a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen } 1012a1a2f967e2a0de4c4190a775ac314ad32288727eAdam Cohen 1013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access hosts in its uid and package. 1021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); 1022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 1023e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host == null) { 1025e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen return; 1026e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 10270aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 1028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 1029e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1031e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted host " + host.id); 1034e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1035e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1036e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen } 1037e8724c82ab1479f13c85a2c6219841e1fd95f2d2Adam Cohen 1038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void deleteAllHosts() { 1040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "deleteAllHosts() " + userId); 1044742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1045742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean changed = false; 1050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Delete only hosts in the calling uid. 1056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid == Binder.getCallingUid()) { 1057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 1058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav changed = true; 1059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Deleted host " + host.id); 1062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 10636611988429d1d70ec429f87bbf2b093cf1e2e31fWinson Chung } 1064742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (changed) { 1067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1069742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1070742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1071742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1073976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId) { 1074976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1075976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1076976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetInfo() " + userId); 1078119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1079976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1080976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1081976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1082976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1083976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1084976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1085976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1086976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1087976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1088976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1089976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1090976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1091976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.provider != null && !widget.provider.zombie) { 1092976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.provider.info); 1093976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1094976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1095976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1096742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1098976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1099976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1100976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId) { 1101976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1102976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1103976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1104976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetViews() " + userId); 1105742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1107976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1112976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1115976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1116976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1117976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1118976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1119976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.views); 1120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1121976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1122976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1123742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1124742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1127976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetOptions(String callingPackage, int appWidgetId, Bundle options) { 1128976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetOptions() " + userId); 1132119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1135976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1138976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null) { 1146742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return; 1147742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Merge the options. 1150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options.putAll(options); 1151976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1152976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send the broacast to notify the provider that options changed. 1153976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendOptionsChangedIntentLocked(widget); 1154976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 1156742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1157742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1158742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1160976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public Bundle getAppWidgetOptions(String callingPackage, int appWidgetId) { 1161976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1163976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1164976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getAppWidgetOptions() " + userId); 1165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1166742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1167976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1168976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1169742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1170976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1172976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1175976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1177976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.options != null) { 1179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return cloneIfLocalBinder(widget.options); 1180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1182976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Bundle.EMPTY; 1183742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1184742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1185742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1187976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views) { 1189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetIds() " + UserHandle.getCallingUserId()); 1191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1192742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetIds(callingPackage, appWidgetIds, views, false); 1194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1195742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1196976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void partiallyUpdateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views) { 1199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "partiallyUpdateAppWidgetIds() " + UserHandle.getCallingUserId()); 1201742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1202742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1203976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetIds(callingPackage, appWidgetIds, views, true); 12043ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 12053ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1206976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1207976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void notifyAppWidgetViewDataChanged(String callingPackage, int[] appWidgetIds, 1208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int viewId) { 1209976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 12103ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1211976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1212976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "notifyAppWidgetViewDataChanged() " + userId); 12133ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 12143ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1215976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 12173ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 1218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (appWidgetIds == null || appWidgetIds.length == 0) { 1219976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1220119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1221742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1224742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = appWidgetIds.length; 1226742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 1227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = appWidgetIds[i]; 1228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1232976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyAppWidgetViewDataChanged(widget, viewId); 1236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1237742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1238742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1240742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void updateAppWidgetProvider(ComponentName componentName, RemoteViews views) { 1243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "updateAppWidgetProvider() " + userId); 1247976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1249976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1250976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName()); 1251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can access only its providers. 1257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName); 1258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 1259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 1261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Provider doesn't exist " + providerId); 1262119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn return; 1263119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 1264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> instances = provider.widgets; 1266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = instances.size(); 1267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = instances.get(i); 1269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, views, false); 1270742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1271742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1272742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1273742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 12758e1d299da27da534b508b1da51ebe351a689cefaSvetoslav public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter, 12768e1d299da27da534b508b1da51ebe351a689cefaSvetoslav int profileId) { 1277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "getInstalledProvidersForProfiles() " + userId); 1281742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 12838e1d299da27da534b508b1da51ebe351a689cefaSvetoslav // Ensure the profile is in the group and enabled. 12848e1d299da27da534b508b1da51ebe351a689cefaSvetoslav if (!mSecurityPolicy.isEnabledGroupProfile(profileId)) { 1285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1286742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1287742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1290adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 12918e1d299da27da534b508b1da51ebe351a689cefaSvetoslav ArrayList<AppWidgetProviderInfo> result = null; 1292742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 1294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 1295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 1296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info; 1297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Ignore an invalid provider or one not matching the filter. 1299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) { 1300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 1301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 13038e1d299da27da534b508b1da51ebe351a689cefaSvetoslav // Add providers only for the requested profile that are white-listed. 1304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerProfileId = info.getProfile().getIdentifier(); 13058e1d299da27da534b508b1da51ebe351a689cefaSvetoslav if (providerProfileId == profileId 13068e1d299da27da534b508b1da51ebe351a689cefaSvetoslav && mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed( 13078e1d299da27da534b508b1da51ebe351a689cefaSvetoslav provider.id.componentName.getPackageName(), providerProfileId)) { 13088e1d299da27da534b508b1da51ebe351a689cefaSvetoslav if (result == null) { 13098e1d299da27da534b508b1da51ebe351a689cefaSvetoslav result = new ArrayList<>(); 1310976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 13118e1d299da27da534b508b1da51ebe351a689cefaSvetoslav result.add(cloneIfLocalBinder(info)); 1312976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1314976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 1316742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1317742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1318742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void updateAppWidgetIds(String callingPackage, int[] appWidgetIds, 1320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views, boolean partially) { 1321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 1322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (appWidgetIds == null || appWidgetIds.length == 0) { 1324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1325742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1326742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Make sure the package runs under the caller uid. 1328976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSecurityPolicy.enforceCallFromPackage(callingPackage); 1329976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int bitmapMemoryUsage = (views != null) ? views.estimateMemoryUsage() : 0; 1331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) { 1332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("RemoteViews for widget update exceeds" 1333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " maximum bitmap memory usage (used: " + bitmapMemoryUsage 1334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + ", max: " + mMaxWidgetBitmapMemory + ")"); 1335742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1336742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 1339742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = appWidgetIds.length; 1341483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani for (int i = 0; i < N; i++) { 1342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = appWidgetIds[i]; 1343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // NOTE: The lookup is enforcing security across users by making 1345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // sure the caller can only access widgets it hosts or provides. 1346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = lookupWidgetLocked(appWidgetId, 1347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.getCallingUid(), callingPackage); 1348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null) { 1350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, views, partially); 1351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1352483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } 1353742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1354742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1355742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int incrementAndGetAppWidgetIdLocked(int userId) { 1357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = peekNextAppWidgetIdLocked(userId) + 1; 1358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, appWidgetId); 1359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetId; 1360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void setMinAppWidgetIdLocked(int userId, int minWidgetId) { 1363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int nextAppWidgetId = peekNextAppWidgetIdLocked(userId); 1364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (nextAppWidgetId < minWidgetId) { 1365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mNextAppWidgetIds.put(userId, minWidgetId); 1366742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int peekNextAppWidgetIdLocked(int userId) { 1370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mNextAppWidgetIds.indexOfKey(userId) < 0) { 1371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return AppWidgetManager.INVALID_APPWIDGET_ID + 1; 1372742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 1373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mNextAppWidgetIds.get(userId); 1374742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1375742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1376742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host lookupOrAddHostLocked(HostId id) { 1378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(id); 1379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 1380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1381976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host = new Host(); 1384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = id; 1385976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.add(host); 1386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1387976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1388742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1389742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1390976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteHostLocked(Host host) { 1391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = host.widgets.size(); 1392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = host.widgets.remove(i); 1394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteAppWidgetLocked(widget); 1395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.remove(host); 1397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // it's gone or going away, abruptly drop the callback connection 1399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1400742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1401742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteAppWidgetLocked(Widget widget) { 1403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We first unbind all services that are bound to this id 1404976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindAppWidgetRemoteViewsServicesLocked(widget); 1405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = widget.host; 1407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.remove(widget); 1408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(host); 1409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(widget); 1411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 1413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 1414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.remove(widget); 1415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!provider.zombie) { 1416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send the broacast saying that this appWidgetId has been deleted 1417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendDeletedIntentLocked(widget); 1418976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.isEmpty()) { 1420976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // cancel the future updates 1421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 1422976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send the broacast saying that the provider is not in use any more 1424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendDisabledIntentLocked(provider); 1425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1427742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1428742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1429742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void cancelBroadcasts(Provider provider) { 1431976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "cancelBroadcasts() for " + provider); 1433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.broadcast != null) { 1435976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mAlarmManager.cancel(provider.broadcast); 1436742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani long token = Binder.clearCallingIdentity(); 1437742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 1438976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast.cancel(); 1439742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 1440742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Binder.restoreCallingIdentity(token); 1441742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast = null; 1443742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1444742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1445742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbinds from a RemoteViewsService when we delete an app widget 1447976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void unbindAppWidgetRemoteViewsServicesLocked(Widget widget) { 1448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId = widget.appWidgetId; 1449976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Unbind all connections to Services bound to this AppWidgetId 1450976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet() 1451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .iterator(); 1452976e8bd2017d0263216c62111454438cc0f130e3Svetoslav while (it.hasNext()) { 1453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Pair<Integer, Intent.FilterComparison> key = it.next(); 1454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (key.first == appWidgetId) { 1455976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnectionProxy conn = (ServiceConnectionProxy) 1456976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBoundRemoteViewsServices.get(key); 1457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav conn.disconnect(); 1458976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(conn); 1459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav it.remove(); 1460976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1461742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Check if we need to destroy any services (if no other app widgets are 1464976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // referencing the same service) 1465976e8bd2017d0263216c62111454438cc0f130e3Svetoslav decrementAppWidgetServiceRefCount(widget); 1466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1467742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1468976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Destroys the cached factory on the RemoteViewsService's side related to the specified intent 1469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void destroyRemoteViewsService(final Intent intent, Widget widget) { 1470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnection conn = new ServiceConnection() { 1471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 1473976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service); 1474976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1475976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cb.onDestroy(intent); 1476976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error calling remove view factory", re); 1478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1479976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(this); 1480742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1481976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1482976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1483976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(ComponentName name) { 1484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Do nothing 1485976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1486976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 1487976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1488976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the service and remove the static intent->factory mapping in the 1489976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsService. 1490976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 1491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, 1493976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.info.getProfile()); 1494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 1495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 1496742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1497742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 1498742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 1499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Adds to the ref-count for a given RemoteViewsService intent 1500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void incrementAppWidgetServiceRefCount(int appWidgetId, 1501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, FilterComparison> serviceId) { 1502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<Integer> appWidgetIds = null; 1503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mRemoteViewsServicesAppWidgets.containsKey(serviceId)) { 1504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds = mRemoteViewsServicesAppWidgets.get(serviceId); 1505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds = new HashSet<>(); 1507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mRemoteViewsServicesAppWidgets.put(serviceId, appWidgetIds); 150875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 1509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds.add(appWidgetId); 151075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 151175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka 1512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if 1513976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // the ref-count reaches zero. 1514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void decrementAppWidgetServiceRefCount(Widget widget) { 1515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, FilterComparison>> it = mRemoteViewsServicesAppWidgets 1516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .keySet().iterator(); 1517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav while (it.hasNext()) { 1518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Pair<Integer, FilterComparison> key = it.next(); 1519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key); 1520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (ids.remove(widget.appWidgetId)) { 1521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If we have removed the last app widget referencing this service, then we 1522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // should destroy it and remove it from this set 1523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (ids.isEmpty()) { 1524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav destroyRemoteViewsService(key.second.getIntent(), widget); 1525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav it.remove(); 1526976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 152775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 152875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 152975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 153075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka 1531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void saveGroupStateAsync(int groupId) { 1532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mSaveStateHandler.post(new SaveStateRunnable(groupId)); 1533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void updateAppWidgetInstanceLocked(Widget widget, RemoteViews views, 1536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean isPartialUpdate) { 1537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget != null && widget.provider != null 1538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && !widget.provider.zombie && !widget.host.zombie) { 1539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isPartialUpdate && widget.views != null) { 1541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For a partial update, we merge the new RemoteViews with the old. 1542976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views.mergeRemoteViews(views); 1543976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For a full update we replace the RemoteViews completely. 1545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views = views; 1546adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 15483de01b2e3474ac2eaccbcf72b6693bb19d254824Svet Ganov scheduleNotifyUpdateAppWidgetLocked(widget, views); 1549adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1550adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1551adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyAppWidgetViewDataChanged(Widget widget, int viewId) { 1553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.host == null || widget.host.zombie 1554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.provider == null 1555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.provider.zombie) { 1556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1557976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 1562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi2 = viewId; 1564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_VIEW_DATA_CHANGED, 1567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1568adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1569adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyAppWidgetViewDataChanged(Host host, IAppWidgetHost callbacks, 1572976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, int viewId) { 1573976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1574976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.viewDataChanged(appWidgetId, viewId); 1575976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1576976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // It failed; remove the callback. No need to prune because 1577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we know that this host is still referenced by this instance. 1578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks = null; 1579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1581976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the host is unavailable, then we call the associated 1582976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // RemoteViewsFactory.onDataSetChanged() directly 1583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (callbacks == null) { 1585976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1586976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1587976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Pair<Integer, FilterComparison>> keys = mRemoteViewsServicesAppWidgets.keySet(); 1588976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Pair<Integer, FilterComparison> key : keys) { 1589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mRemoteViewsServicesAppWidgets.get(key).contains(appWidgetId)) { 1590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ServiceConnection connection = new ServiceConnection() { 1591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1592976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 1593976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IRemoteViewsFactory cb = IRemoteViewsFactory.Stub 1594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .asInterface(service); 1595976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cb.onDataSetChangedAsync(); 1597976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException e) { 1598976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error calling onDataSetChangedAsync()", e); 1599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(this); 1601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 1604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(android.content.ComponentName name) { 1605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Do nothing 1606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav }; 1608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getUserId(key.first); 1610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = key.second.getIntent(); 1611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Bind to the service and call onDataSetChanged() 1613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindService(intent, connection, new UserHandle(userId)); 1614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1618adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1619adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 16203de01b2e3474ac2eaccbcf72b6693bb19d254824Svet Ganov private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) { 1621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.provider == null || widget.provider.zombie 1622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.host.zombie) { 1623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 16293de01b2e3474ac2eaccbcf72b6693bb19d254824Svet Ganov args.arg3 = updateViews; 1630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1631976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET, 1634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1637976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks, 1638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, RemoteViews views) { 1639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.updateAppWidget(appWidgetId, views); 1641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1646adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1647adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1648adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void scheduleNotifyProviderChangedLocked(Widget widget) { 1650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget == null || widget.provider == null || widget.provider.zombie 1651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.host.callbacks == null || widget.host.zombie) { 1652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 1653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = widget.host; 1657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = widget.host.callbacks; 1658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg3 = widget.provider.info; 1659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.argi1 = widget.appWidgetId; 1660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1661976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_PROVIDER_CHANGED, 1663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1664976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyProviderChanged(Host host, IAppWidgetHost callbacks, 1667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId, AppWidgetProviderInfo info) { 1668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.providerChanged(appWidgetId, info); 1670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock){ 1672976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1676976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1677976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 16786bd702538d90005add1cfc33746da19404090dc1Svet Ganov private void scheduleNotifyGroupHostsForProvidersChangedLocked(int userId) { 16796bd702538d90005add1cfc33746da19404090dc1Svet Ganov final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); 16806bd702538d90005add1cfc33746da19404090dc1Svet Ganov 1681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = N - 1; i >= 0; i--) { 1683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 16856bd702538d90005add1cfc33746da19404090dc1Svet Ganov boolean hostInGroup = false; 16866bd702538d90005add1cfc33746da19404090dc1Svet Ganov final int M = profileIds.length; 16876bd702538d90005add1cfc33746da19404090dc1Svet Ganov for (int j = 0; j < M; j++) { 16886bd702538d90005add1cfc33746da19404090dc1Svet Ganov final int profileId = profileIds[j]; 16896bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (host.getUserId() == profileId) { 16906bd702538d90005add1cfc33746da19404090dc1Svet Ganov hostInGroup = true; 16916bd702538d90005add1cfc33746da19404090dc1Svet Ganov break; 16926bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 16936bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 16946bd702538d90005add1cfc33746da19404090dc1Svet Ganov 16956bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (!hostInGroup) { 16966bd702538d90005add1cfc33746da19404090dc1Svet Ganov continue; 16976bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 16986bd702538d90005add1cfc33746da19404090dc1Svet Ganov 1699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host == null || host.zombie || host.callbacks == null) { 1700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 1701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = SomeArgs.obtain(); 1704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg1 = host; 1705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.arg2 = host.callbacks; 1706976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mCallbackHandler.obtainMessage( 1708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav CallbackHandler.MSG_NOTIFY_PROVIDERS_CHANGED, 1709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args).sendToTarget(); 1710adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void handleNotifyProvidersChanged(Host host, IAppWidgetHost callbacks) { 1714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav callbacks.providersChanged(); 1716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 1717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 1718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Widget host dead: " + host.id, re); 1719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.callbacks = null; 1720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1721adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static boolean isLocalBinder() { 1725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Process.myPid() == Binder.getCallingPid(); 1726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static RemoteViews cloneIfLocalBinder(RemoteViews rv) { 1729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && rv != null) { 1730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return rv.clone(); 1731adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return rv; 1733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) { 1736976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && info != null) { 1737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return info.clone(); 1738adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1739976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return info; 1740976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static Bundle cloneIfLocalBinder(Bundle bundle) { 1743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Note: this is only a shallow copy. For now this will be fine, but it could be problematic 1744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if we start adding objects to the options. Further, it would only be an issue if keyguard 1745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // used such options. 1746976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isLocalBinder() && bundle != null) { 1747976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return (Bundle) bundle.clone(); 1748adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return bundle; 1750adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1751adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Widget lookupWidgetLocked(int appWidgetId, int uid, String packageName) { 1753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 1754adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate for (int i = 0; i < N; i++) { 1755976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 1756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.appWidgetId == appWidgetId 1757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && mSecurityPolicy.canAccessAppWidget(widget, uid, packageName)) { 1758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget; 1759adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1764976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider lookupProviderLocked(ProviderId id) { 1765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 1766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 1768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.id.equals(id)) { 1769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 1770adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1771adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1773adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1774adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host lookupHostLocked(HostId hostId) { 1776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mHosts.size(); 1777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 1779976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.equals(hostId)) { 1780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 1781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1782adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 1784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1785adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void pruneHostLocked(Host host) { 1787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.widgets.size() == 0 && host.callbacks == null) { 1788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1789976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Pruning host " + host.id); 1790adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.remove(host); 1792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1794adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1795976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void loadGroupWidgetProvidersLocked(int[] profileIds) { 1796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> allReceivers = null; 1797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1798adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 1800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 1801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 1802adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> receivers = queryIntentReceivers(intent, profileId); 1804976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (receivers != null && !receivers.isEmpty()) { 1805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (allReceivers == null) { 1806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav allReceivers = new ArrayList<>(); 1807adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav allReceivers.addAll(receivers); 1809adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1811adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1812976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = (allReceivers == null) ? 0 : allReceivers.size(); 1813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 1814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ResolveInfo receiver = allReceivers.get(i); 1815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav addProviderLocked(receiver); 1816adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1817adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1818adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean addProviderLocked(ResolveInfo ri) { 1820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { 1821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1822adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!ri.activityInfo.isEnabled()) { 1825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1826adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1827adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1828976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(ri.activityInfo.packageName, 1829976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ri.activityInfo.name); 1830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName); 1831976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = parseProviderInfoXml(providerId, ri); 1833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 1834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we might have an inactive entry for this provider already due to 1835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // a preceding restore operation. if so, fix it up in place; otherwise 1836976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // just add this new one. 1837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider existing = lookupProviderLocked(providerId); 1838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1839976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the provider was not found it may be because it was restored and 1840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we did not know its UID so let us find if there is such one. 1841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing == null) { 1842ad870c3d9c58a9ee31cdf4a9807a4cec2e68ab04Svetoslav ProviderId restoredProviderId = new ProviderId(UNKNOWN_UID, componentName); 1843ad870c3d9c58a9ee31cdf4a9807a4cec2e68ab04Svetoslav existing = lookupProviderLocked(restoredProviderId); 1844adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1845adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing != null) { 1847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (existing.zombie && !mSafeMode) { 1848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // it's a placeholder that was set up during an app restore 1849ad870c3d9c58a9ee31cdf4a9807a4cec2e68ab04Svetoslav existing.id = providerId; 1850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav existing.zombie = false; 1851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav existing.info = provider.info; // the real one filled out from the ResolveInfo 1852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 1853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Provider placeholder now reified: " + existing); 1854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1855adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1856976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 1857976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(provider); 1858adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 1860adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1861adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 1863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1864adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void deleteProviderLocked(Provider provider) { 1866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = provider.widgets.size(); 1867298a6c6b29798647b3d8f12d0723b1e49fc8b8daSvetoslav for (int i = N - 1; i >= 0; i--) { 1868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = provider.widgets.remove(i); 1869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Call back with empty RemoteViews 1870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav updateAppWidgetInstanceLocked(widget, null, false); 1871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // clear out references to this appWidgetId 1872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.remove(widget); 1873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(widget); 1874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = null; 1875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneHostLocked(widget.host); 1876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = null; 1877adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.remove(provider); 1879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // no need to send the DISABLE broadcast, since the receiver is gone anyway 1881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 1882adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1883adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendEnableIntentLocked(Provider p) { 1885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED); 1886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(p.info.provider); 1887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, p.info.getProfile()); 1888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1889adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds) { 1891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); 1893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, provider.info.getProfile()); 1895adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1896adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendDeletedIntentLocked(Widget widget) { 1898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED); 1899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(widget.provider.info.provider); 1900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId); 1901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, widget.provider.info.getProfile()); 1902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendDisabledIntentLocked(Provider provider) { 1905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED); 1906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, provider.info.getProfile()); 1908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void sendOptionsChangedIntentLocked(Widget widget) { 1911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED); 1912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(widget.provider.info.provider); 1913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId); 1914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, widget.options); 1915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, widget.provider.info.getProfile()); 1916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) { 1919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.info.updatePeriodMillis > 0) { 1920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if this is the first instance, set the alarm. otherwise, 1921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // rely on the fact that we've already set it and that 1922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // PendingIntent.getBroadcast will update the extras. 1923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean alreadyRegistered = provider.broadcast != null; 1924976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 1925976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); 1926976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 1927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav long token = Binder.clearCallingIdentity(); 1928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 1929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent, 1930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PendingIntent.FLAG_UPDATE_CURRENT, provider.info.getProfile()); 1931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 1932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 1933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!alreadyRegistered) { 1935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav long period = provider.info.updatePeriodMillis; 1936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (period < MIN_UPDATE_PERIOD) { 1937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav period = MIN_UPDATE_PERIOD; 1938adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SystemClock.elapsedRealtime() + period, period, provider.broadcast); 1941adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1942adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1943adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1944adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static int[] getWidgetIds(ArrayList<Widget> widgets) { 1946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int instancesSize = widgets.size(); 1947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetIds[] = new int[instancesSize]; 1948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < instancesSize; i++) { 1949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav appWidgetIds[i] = widgets.get(i).appWidgetId; 1950adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return appWidgetIds; 1952adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1953adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 1954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpProvider(Provider provider, int index, PrintWriter pw) { 1955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info; 1956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] provider "); 1957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(provider.id); 1958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" min=("); pw.print(info.minWidth); 1959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print("x"); pw.print(info.minHeight); 1960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(") minResize=("); pw.print(info.minResizeWidth); 1961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print("x"); pw.print(info.minResizeHeight); 1962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(") updatePeriodMillis="); 1963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.updatePeriodMillis); 1964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" resizeMode="); 1965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.resizeMode); 1966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.widgetCategory); 1967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" autoAdvanceViewId="); 1968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(info.autoAdvanceViewId); 1969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" initialLayout=#"); 1970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(Integer.toHexString(info.initialLayout)); 1971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" initialKeyguardLayout=#"); 1972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(Integer.toHexString(info.initialKeyguardLayout)); 1973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" zombie="); pw.println(provider.zombie); 1974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpHost(Host host, int index, PrintWriter pw) { 1977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] hostId="); 1978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(host.id); 1979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" callbacks="); pw.println(host.callbacks); 1980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" widgets.size="); pw.print(host.widgets.size()); 1981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" zombie="); pw.println(host.zombie); 1982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpGrant(Pair<Integer, String> grant, int index, PrintWriter pw) { 1985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print(']'); 1986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" user="); pw.print(grant.first); 1987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" package="); pw.println(grant.second); 1988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 1989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 1990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void dumpWidget(Widget widget, int index, PrintWriter pw) { 1991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" ["); pw.print(index); pw.print("] id="); 1992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(widget.appWidgetId); 1993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" host="); 1994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.println(widget.host.id); 1995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 1996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" provider="); pw.println(widget.provider.id); 1997adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 1998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host != null) { 1999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" host.callbacks="); pw.println(widget.host.callbacks); 2000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.views != null) { 2002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pw.print(" views="); pw.println(widget.views); 2003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeProvider(XmlSerializer out, Provider p) throws IOException { 2007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "p"); 2008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", p.info.provider.getPackageName()); 2009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "cl", p.info.provider.getClassName()); 2010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "tag", Integer.toHexString(p.tag)); 2011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "p"); 2012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeHost(XmlSerializer out, Host host) throws IOException { 2015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "h"); 2016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", host.id.packageName); 2017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "id", Integer.toHexString(host.id.hostId)); 2018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "tag", Integer.toHexString(host.tag)); 2019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "h"); 2020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2021adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static void serializeAppWidget(XmlSerializer out, Widget widget) throws IOException { 2023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "g"); 2024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "id", Integer.toHexString(widget.appWidgetId)); 2025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "rid", Integer.toHexString(widget.restoredId)); 2026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "h", Integer.toHexString(widget.host.tag)); 2027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider != null) { 2028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "p", Integer.toHexString(widget.provider.tag)); 2029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.options != null) { 2031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt( 2032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH))); 2033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt( 2034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT))); 2035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt( 2036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH))); 2037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt( 2038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT))); 2039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt( 2040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY))); 2041adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 2042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "g"); 2043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2044adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public List<String> getWidgetParticipants(int userId) { 2047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mBackupRestoreController.getWidgetParticipants(userId); 2048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2049adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public byte[] getWidgetState(String packageName, int userId) { 2052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mBackupRestoreController.getWidgetState(packageName, userId); 2053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2054adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreStarting(int userId) { 2057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreStarting(userId); 2058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2059adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreWidgetState(String packageName, byte[] restoredState, int userId) { 2062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreWidgetState(packageName, restoredState, userId); 2063976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2064adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreFinished(int userId) { 2067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mBackupRestoreController.restoreFinished(userId); 2068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2069adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 2070976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @SuppressWarnings("deprecation") 2071976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri) { 2072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = null; 2073742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2074742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ActivityInfo activityInfo = ri.activityInfo; 2075742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlResourceParser parser = null; 2076742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2077483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(), 2078742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AppWidgetManager.META_DATA_APPWIDGET_PROVIDER); 2079742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (parser == null) { 2080742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER 2081976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " meta-data for " + "AppWidget provider '" + providerId + '\''); 2082742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2083742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2084742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2085742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AttributeSet attrs = Xml.asAttributeSet(parser); 2086742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2087742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int type; 2088742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2089742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani && type != XmlPullParser.START_TAG) { 2090742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // drain whitespace, comments, etc. 2091742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2092742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2093742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String nodeName = parser.getName(); 2094742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (!"appwidget-provider".equals(nodeName)) { 2095742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for" 2096976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " AppWidget provider " + providerId.componentName 2097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for user " + providerId.uid); 2098742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2099742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2101976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider = new Provider(); 2102976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id = providerId; 2103976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = provider.info = new AppWidgetProviderInfo(); 2104976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.provider = providerId.componentName; 2105976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.providerInfo = activityInfo; 2106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2107976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Resources resources; 2108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav resources = mContext.getPackageManager() 2111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getResourcesForApplicationAsUser(activityInfo.packageName, 2112976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.getUserId(providerId.uid)); 2113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2115976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2116742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2117976e8bd2017d0263216c62111454438cc0f130e3Svetoslav TypedArray sa = resources.obtainAttributes(attrs, 2118742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo); 2119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // These dimensions has to be resolved in the application's context. 2121742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // We simply send back the raw complex data, which will be 2122742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}. 2123742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani TypedValue value = sa 2124742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani .peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth); 2125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minWidth = value != null ? value.data : 0; 2126742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight); 2127742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minHeight = value != null ? value.data : 0; 2128742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue( 2129742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth); 2130742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minResizeWidth = value != null ? value.data : info.minWidth; 2131742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani value = sa.peekValue( 2132742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight); 2133742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.minResizeHeight = value != null ? value.data : info.minHeight; 2134742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.updatePeriodMillis = sa.getInt( 2135742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0); 2136742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.initialLayout = sa.getResourceId( 2137742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0); 21380aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable. 21390aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen AppWidgetProviderInfo_initialKeyguardLayout, 0); 2140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2141742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String className = sa 2142742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure); 2143742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (className != null) { 2144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav info.configure = new ComponentName(providerId.componentName.getPackageName(), 2145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav className); 2146742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2147483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString(); 2148742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.icon = ri.getIconResource(); 2149742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.previewImage = sa.getResourceId( 2150742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0); 2151742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.autoAdvanceViewId = sa.getResourceId( 2152742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1); 2153742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani info.resizeMode = sa.getInt( 2154742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode, 2155742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani AppWidgetProviderInfo.RESIZE_NONE); 21560aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen info.widgetCategory = sa.getInt( 2157ca5e341574774379f157a4ea579a1732bd4cf7fbMichael Jurka com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory, 21580aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); 2159742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani sa.recycle(); 2161976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) { 2162742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Ok to catch Exception here, because anything going wrong because 2163742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // of what a client process passes to us should not be fatal for the 2164742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // system process. 2165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "XML parsing failed for AppWidget provider " 2166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + providerId.componentName + " for user " + providerId.uid, e); 2167742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return null; 2168742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } finally { 2169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parser != null) { 2170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani parser.close(); 2171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2172742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 2174742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2175742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int getUidForPackage(String packageName, int userId) { 2177483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani PackageInfo pkgInfo = null; 2178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2180483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani try { 2181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkgInfo = mPackageManager.getPackageInfo(packageName, 0, userId); 2182483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } catch (RemoteException re) { 2183483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani // Shouldn't happen, local call 2184976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2185976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2186483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani } 2187976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2188742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (pkgInfo == null || pkgInfo.applicationInfo == null) { 2189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return -1; 2190742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2192742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return pkgInfo.applicationInfo.uid; 2193742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2194742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private ActivityInfo getProviderInfo(ComponentName componentName, int userId) { 2196976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 2197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(componentName); 2198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> receivers = queryIntentReceivers(intent, userId); 2200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We are setting component, so there is only one or none. 2201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!receivers.isEmpty()) { 2202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return receivers.get(0).activityInfo; 2203f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 2204976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2205976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2206f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 2207f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 2208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private List<ResolveInfo> queryIntentReceivers(Intent intent, int userId) { 2209976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2210742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2211d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski int flags = PackageManager.GET_META_DATA; 2212d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski 2213d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski // Widgets referencing shared libraries need to have their 2214d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski // dependencies loaded. 2215d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski flags |= PackageManager.GET_SHARED_LIBRARY_FILES; 2216d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski 2217976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return mPackageManager.queryIntentReceivers(intent, 2218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2219d00bb5edcfc8ee5c2026f66785b703b388314b22Adam Lesinski flags, userId); 2220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 2221976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return Collections.emptyList(); 2222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2224742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2225742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2226742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onUserStarted(int userId) { 2228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 2229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 2230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 2232742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Send broadcast only to the providers of the user. 2236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() != userId) { 2237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.size() > 0) { 2241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendEnableIntentLocked(provider); 2242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] appWidgetIds = getWidgetIds(provider.widgets); 2243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, appWidgetIds); 2244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, appWidgetIds); 2245742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2246742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2247742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2248742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2249742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2250742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // only call from initialization -- it assumes that the data structures are all empty 2251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void loadGroupStateLocked(int[] profileIds) { 2252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We can bind the widgets to host and providers only after 2253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // reading the host and providers for all users since a widget 2254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // can have a host and a provider in different users. 2255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<LoadedWidgetState> loadedWidgets = new ArrayList<>(); 2256742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int version = 0; 2258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileIdCount = profileIds.length; 2260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileIdCount; i++) { 2261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2263976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // No file written for this user - nothing to do. 2264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AtomicFile file = getSavedStateFile(profileId); 2265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FileInputStream stream = file.openRead(); 2267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav version = readProfileStateFromFileLocked(stream, profileId, loadedWidgets); 2268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IoUtils.closeQuietly(stream); 2269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (FileNotFoundException e) { 2270976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to read state: " + e); 2271976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2272976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2273976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (version >= 0) { 2275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Hooke'm up... 2276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav bindLoadedWidgets(loadedWidgets); 2277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // upgrade the database if needed 2279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav performUpgradeLocked(version); 2280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 2281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // failed reading, clean up 2282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to read state, clearing widgets and hosts."); 2283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.clear(); 2284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mHosts.clear(); 2285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mProviders.size(); 2286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 2287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.get(i).widgets.clear(); 2288742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2289742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2290742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2291742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void bindLoadedWidgets(List<LoadedWidgetState> loadedWidgets) { 2293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int loadedWidgetCount = loadedWidgets.size(); 2294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = loadedWidgetCount - 1; i >= 0; i--) { 2295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav LoadedWidgetState loadedWidget = loadedWidgets.remove(i); 2296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = loadedWidget.widget; 2297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = findProviderByTag(loadedWidget.providerTag); 2299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.provider == null) { 2300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // This provider is gone. We just let the host figure out 2301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // that this happened when it fails to load it. 2302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = findHostByTag(loadedWidget.hostTag); 2306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host == null) { 2307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // This host is gone. 2308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2309976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2310976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2311976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.widgets.add(widget); 2312976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.add(widget); 2313976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(widget); 2314119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn } 2315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2317976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider findProviderByTag(int tag) { 2318976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (tag < 0) { 2319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 2323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.tag == tag) { 2325976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 2326976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2328976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2329976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Host findHostByTag(int tag) { 2332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (tag < 0) { 2333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < hostCount; i++) { 2337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.tag == tag) { 2339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host; 2340742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void saveStateLocked(int userId) { 2346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav tagProvidersAndHosts(); 2347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); 2349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profileIds.length; 2351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 2352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileId = profileIds[i]; 2353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AtomicFile file = getSavedStateFile(profileId); 2355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav FileOutputStream stream; 2356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stream = file.startWrite(); 2358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (writeProfileStateToFileLocked(stream, profileId)) { 2359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav file.finishWrite(stream); 2360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 2361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav file.failWrite(stream); 2362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed to save state, restoring backup."); 2363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException e) { 2365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Failed open state file for write: " + e); 2366976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void tagProvidersAndHosts() { 2371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 2373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = i; 2375976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < hostCount; i++) { 2379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = i; 2381742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2382742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2383742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2384c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav private void clearProvidersAndHostsTagsLocked() { 2385c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav final int providerCount = mProviders.size(); 2386c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav for (int i = 0; i < providerCount; i++) { 2387c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav Provider provider = mProviders.get(i); 2388c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav provider.tag = TAG_UNDEFINED; 2389c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav } 2390c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav 2391c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav final int hostCount = mHosts.size(); 2392c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav for (int i = 0; i < hostCount; i++) { 2393c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav Host host = mHosts.get(i); 2394c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav host.tag = TAG_UNDEFINED; 2395c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav } 2396c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav } 2397c616b3e2f16c99c51e0543256c219e799ff32232Svetoslav 2398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean writeProfileStateToFileLocked(FileOutputStream stream, int userId) { 2399742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int N; 2400742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2401742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2402742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlSerializer out = new FastXmlSerializer(); 2403742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.setOutput(stream, "utf-8"); 2404742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.startDocument(null, true); 2405742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.startTag(null, "gs"); 240639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller out.attribute(null, "version", String.valueOf(CURRENT_VERSION)); 2407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mProviders.size(); 2409742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only providers for the user. 2412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() != userId) { 2413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.widgets.size() > 0) { 2416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeProvider(out, provider); 2417742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2418742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2419742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2420742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 2421742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2422742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = mHosts.get(i); 2423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only hosts for the user. 2424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.getUserId() != userId) { 2425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2427adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate serializeHost(out, host); 2428742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2429742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 2431742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 2433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only widgets hosted by the user. 2434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.getUserId() != userId) { 2435976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2436976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2437976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeAppWidget(out, widget); 2438742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2439742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Iterator<Pair<Integer, String>> it = mPackagesWithBindWidgetPermission.iterator(); 244161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka while (it.hasNext()) { 2442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> binding = it.next(); 2443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Save only white listings for the user. 2444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (binding.first != userId) { 2445976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 244761a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka out.startTag(null, "b"); 2448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "packageName", binding.second); 244961a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka out.endTag(null, "b"); 245061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 245161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka 2452742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.endTag(null, "gs"); 2453742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani out.endDocument(); 2454742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return true; 2455742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } catch (IOException e) { 2456742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "Failed to write state: " + e); 2457742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return false; 2458742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2459742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2460742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int readProfileStateFromFileLocked(FileInputStream stream, int userId, 2462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<LoadedWidgetState> outLoadedWidgets) { 2463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int version = -1; 2464742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani try { 2465742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani XmlPullParser parser = Xml.newPullParser(); 2466742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani parser.setInput(stream, null); 2467742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2468976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int legacyProviderIndex = -1; 2469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int legacyHostIndex = -1; 2470742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int type; 2471742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani do { 2472742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani type = parser.next(); 2473742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (type == XmlPullParser.START_TAG) { 2474742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String tag = parser.getName(); 247539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if ("gs".equals(tag)) { 247639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller String attributeValue = parser.getAttributeValue(null, "version"); 247739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller try { 247839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = Integer.parseInt(attributeValue); 247939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } catch (NumberFormatException e) { 248039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = 0; 248139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 248239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } else if ("p".equals(tag)) { 2483976e8bd2017d0263216c62111454438cc0f130e3Svetoslav legacyProviderIndex++; 2484742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // TODO: do we need to check that this package has the same signature 2485742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // as before? 2486742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String pkg = parser.getAttributeValue(null, "pkg"); 2487742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String cl = parser.getAttributeValue(null, "cl"); 2488742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2489976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pkg = getCanonicalPackageName(pkg, cl, userId); 2490976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkg == null) { 2491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2492742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2493742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 2495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid < 0) { 2496976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(pkg, cl); 2500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ActivityInfo providerInfo = getProviderInfo(componentName, userId); 2502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (providerInfo == null) { 2503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 2504742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(uid, componentName); 2507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 2508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null && mSafeMode) { 2510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // if we're in safe mode, make a temporary one 2511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider = new Provider(); 2512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info = new AppWidgetProviderInfo(); 2513976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info.provider = providerId.componentName; 2514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info.providerInfo = providerInfo; 2515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.zombie = true; 2516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.id = providerId; 2517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(provider); 2518742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String tagAttribute = parser.getAttributeValue(null, "tag"); 2521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag = !TextUtils.isEmpty(tagAttribute) 2522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? Integer.parseInt(tagAttribute, 16) : legacyProviderIndex; 2523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = providerTag; 2524742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if ("h".equals(tag)) { 2525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav legacyHostIndex++; 2526742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = new Host(); 2527742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // TODO: do we need to check that this package has the same signature 2528742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // as before? 2529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 2530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 2532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid < 0) { 2533742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani host.zombie = true; 2534742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2536742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (!host.zombie || mSafeMode) { 2537742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // In safe mode, we don't discard the hosts we don't recognize 2538742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // so that they're not pruned from our list. Otherwise, we do. 2539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId = Integer.parseInt(parser.getAttributeValue( 2540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "id"), 16); 2541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2542976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String tagAttribute = parser.getAttributeValue(null, "tag"); 2543976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag = !TextUtils.isEmpty(tagAttribute) 2544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? Integer.parseInt(tagAttribute, 16) : legacyHostIndex; 2545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = hostTag; 2547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, hostId, pkg); 2548742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani mHosts.add(host); 2549742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 255061a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } else if ("b".equals(tag)) { 255161a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka String packageName = parser.getAttributeValue(null, "packageName"); 2552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(packageName, userId); 2553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0) { 2554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(userId, packageName); 2555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.add(packageId); 255661a5b0160d9f2e53ef4d4b451212a63032dad32dMichael Jurka } 2557742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else if ("g".equals(tag)) { 2558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = new Widget(); 2559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.appWidgetId = Integer.parseInt(parser.getAttributeValue( 2560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "id"), 16); 2561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav setMinAppWidgetIdLocked(userId, widget.appWidgetId + 1); 2562742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2563adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate // restored ID is allowed to be absent 2564adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate String restoredIdString = parser.getAttributeValue(null, "rid"); 2565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.restoredId = (restoredIdString == null) ? 0 2566adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate : Integer.parseInt(restoredIdString, 16); 2567adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate 25680aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Bundle options = new Bundle(); 25690aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String minWidthString = parser.getAttributeValue(null, "min_width"); 25700aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen if (minWidthString != null) { 25710aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 25720aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(minWidthString, 16)); 25730aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25740aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String minHeightString = parser.getAttributeValue(null, "min_height"); 2575db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (minHeightString != null) { 25760aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 25770aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(minHeightString, 16)); 25780aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 2579db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen String maxWidthString = parser.getAttributeValue(null, "max_width"); 2580db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (maxWidthString != null) { 25810aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 25820aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(maxWidthString, 16)); 25830aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25840aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String maxHeightString = parser.getAttributeValue(null, "max_height"); 2585db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (maxHeightString != null) { 25860aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 25870aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(maxHeightString, 16)); 25880aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 25890aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen String categoryString = parser.getAttributeValue(null, "host_category"); 2590db38d8a4ff28caef8f2565a8ba5dca2a7efe9d83Adam Cohen if (categoryString != null) { 25910aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 25920aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen Integer.parseInt(categoryString, 16)); 25930aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen } 2594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.options = options; 25950aa2d42e87e4a1ed5b83f356690e465d6a3587ccAdam Cohen 2596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag = Integer.parseInt(parser.getAttributeValue( 2597976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, "h"), 16); 2598742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani String providerString = parser.getAttributeValue(null, "p"); 2599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag = (providerString != null) ? Integer.parseInt( 2600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "p"), 16) : TAG_UNDEFINED; 2601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We can match widgets with hosts and providers only after hosts 2603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // and providers for all users have been loaded since the widget 2604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // host and provider can be in different user profiles. 2605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav LoadedWidgetState loadedWidgets = new LoadedWidgetState(widget, 2606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav hostTag, providerTag); 2607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav outLoadedWidgets.add(loadedWidgets); 2608742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2609742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2610742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } while (type != XmlPullParser.END_DOCUMENT); 2611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (NullPointerException 2612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | NumberFormatException 2613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | XmlPullParserException 2614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | IOException 2615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav | IndexOutOfBoundsException e) { 2616742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Slog.w(TAG, "failed parsing " + e); 2617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return -1; 2618742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2619742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return version; 2621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2622742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void performUpgradeLocked(int fromVersion) { 262439d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (fromVersion < CURRENT_VERSION) { 2625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to " 2626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + CURRENT_VERSION); 262739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 262839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 262939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller int version = fromVersion; 263039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 263139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller // Update 1: keyguard moved from package "android" to "com.android.keyguard" 263239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (version == 0) { 2633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId oldHostId = new HostId(Process.myUid(), 2634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav KEYGUARD_HOST_ID, OLD_KEYGUARD_HOST_PACKAGE); 2635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = lookupHostLocked(oldHostId); 2637976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 2638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(NEW_KEYGUARD_HOST_PACKAGE, 2639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle.USER_OWNER); 2640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid >= 0) { 2641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.id = new HostId(uid, KEYGUARD_HOST_ID, NEW_KEYGUARD_HOST_PACKAGE); 264239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 264339d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 2644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 264539d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller version = 1; 264639d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 264739d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 264839d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller if (version != CURRENT_VERSION) { 264939d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller throw new IllegalStateException("Failed to upgrade widget database"); 265039d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 265139d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller } 265239d129e59a1c3985cb1e68f8da6deeea7b2bcbe9Jim Miller 2653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static File getStateFile(int userId) { 2654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new File(Environment.getUserSystemDirectory(userId), STATE_FILENAME); 2655135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani } 2656135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani 2657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static AtomicFile getSavedStateFile(int userId) { 2658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File dir = Environment.getUserSystemDirectory(userId); 2659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File settingsFile = getStateFile(userId); 2660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!settingsFile.exists() && userId == UserHandle.USER_OWNER) { 2661e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani if (!dir.exists()) { 2662e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani dir.mkdirs(); 2663e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani } 2664e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // Migrate old data 2665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav File oldFile = new File("/data/system/" + STATE_FILENAME); 2666e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // Method doesn't throw an exception on failure. Ignore any errors 2667e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani // in moving the file (like non-existence) 2668e0eb39b54812b9403496f0d300395eee73ffa57aAmith Yamasani oldFile.renameTo(settingsFile); 2669742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2670742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani return new AtomicFile(settingsFile); 2671742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2672742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void onUserStopped(int userId) { 2674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 26756bd702538d90005add1cfc33746da19404090dc1Svet Ganov boolean providersChanged = false; 26766bd702538d90005add1cfc33746da19404090dc1Svet Ganov boolean crossProfileWidgetsChanged = false; 26776bd702538d90005add1cfc33746da19404090dc1Svet Ganov 2678976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove widgets that have both host and provider in the user. 2679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int widgetCount = mWidgets.size(); 2680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = widgetCount - 1; i >= 0; i--) { 2681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 2682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean hostInUser = widget.host.getUserId() == userId; 2684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean hasProvider = widget.provider != null; 2685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final boolean providerInUser = hasProvider && widget.provider.getUserId() == userId; 2686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If both host and provider are in the user, just drop the widgets 2688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // as we do not want to make host callbacks and provider broadcasts 2689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // as the host and the provider will be killed. 2690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hostInUser && (!hasProvider || providerInUser)) { 2691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(i); 2692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host.widgets.remove(widget); 2693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.host = null; 2694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hasProvider) { 2695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider.widgets.remove(widget); 2696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.provider = null; 2697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2700756901d82b41f50610a63b7cf4c7747a70f1f724Amith Yamasani 2701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove hosts and notify providers in other profiles. 2702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostCount = mHosts.size(); 2703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = hostCount - 1; i >= 0; i--) { 2704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 2705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.getUserId() == userId) { 27066bd702538d90005add1cfc33746da19404090dc1Svet Ganov crossProfileWidgetsChanged |= !host.widgets.isEmpty(); 2707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteHostLocked(host); 2708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2710135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani 2711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove the providers and notify hosts in other profiles. 2712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 2713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = providerCount - 1; i >= 0; i--) { 2714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() == userId) { 27166bd702538d90005add1cfc33746da19404090dc1Svet Ganov crossProfileWidgetsChanged |= !provider.widgets.isEmpty(); 27176bd702538d90005add1cfc33746da19404090dc1Svet Ganov providersChanged = true; 2718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 2719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove grants for this user. 2723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int grantCount = mPackagesWithBindWidgetPermission.size(); 2724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = grantCount - 1; i >= 0; i--) { 2725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = mPackagesWithBindWidgetPermission.valueAt(i); 2726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageId.first == userId) { 2727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPackagesWithBindWidgetPermission.removeAt(i); 2728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2729742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Take a note we no longer have state for this user. 2732c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav final int userIndex = mLoadedUserIds.indexOfKey(userId); 2733c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav if (userIndex >= 0) { 2734c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav mLoadedUserIds.removeAt(userIndex); 2735742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 27367fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remove the widget id counter. 2738c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav final int nextIdIndex = mNextAppWidgetIds.indexOfKey(userId); 2739c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav if (nextIdIndex >= 0) { 2740c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav mNextAppWidgetIds.removeAt(nextIdIndex); 2741c71c42fdb2ee54a419dc8eb0a5f4f82532b16c0cSvetoslav } 27426bd702538d90005add1cfc33746da19404090dc1Svet Ganov 27436bd702538d90005add1cfc33746da19404090dc1Svet Ganov // Announce removed provider changes to all hosts in the group. 27446bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (providersChanged) { 27456bd702538d90005add1cfc33746da19404090dc1Svet Ganov scheduleNotifyGroupHostsForProvidersChangedLocked(userId); 27466bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 27476bd702538d90005add1cfc33746da19404090dc1Svet Ganov 27486bd702538d90005add1cfc33746da19404090dc1Svet Ganov // Save state if removing a profile changed the group state. 27496bd702538d90005add1cfc33746da19404090dc1Svet Ganov // Nothing will be saved if the group parent was removed. 27506bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (crossProfileWidgetsChanged) { 27516bd702538d90005add1cfc33746da19404090dc1Svet Ganov saveGroupStateAsync(userId); 27526bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 2753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2754742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2755742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2756a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung /** 2757a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * Updates all providers with the specified package names, and records any providers that were 2758a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * pruned. 2759a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * 2760a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung * @return whether any providers were updated 2761a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung */ 2762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean updateProvidersForPackageLocked(String packageName, int userId, 2763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<ProviderId> removedProviders) { 27647fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung boolean providersUpdated = false; 2765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<ProviderId> keep = new HashSet<>(); 2767742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 2768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setPackage(packageName); 2769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<ResolveInfo> broadcastReceivers = queryIntentReceivers(intent, userId); 2770742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2771742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // add the missing ones and collect which ones to keep 2772742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani int N = broadcastReceivers == null ? 0 : broadcastReceivers.size(); 2773742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = 0; i < N; i++) { 2774742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ResolveInfo ri = broadcastReceivers.get(i); 2775742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani ActivityInfo ai = ri.activityInfo; 2776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2777742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { 2778742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani continue; 2779742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(ai.packageName)) { 2782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId providerId = new ProviderId(ai.applicationInfo.uid, 2783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new ComponentName(ai.packageName, ai.name)); 2784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = lookupProviderLocked(providerId); 2786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider == null) { 2787742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (addProviderLocked(ri)) { 2788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav keep.add(providerId); 27897fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2790742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2791742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } else { 2792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider parsed = parseProviderInfoXml(providerId, ri); 2793742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (parsed != null) { 2794976e8bd2017d0263216c62111454438cc0f130e3Svetoslav keep.add(providerId); 2795742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Use the new AppWidgetProviderInfo. 2796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.info = parsed.info; 2797742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // If it's enabled 2798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int M = provider.widgets.size(); 2799742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani if (M > 0) { 2800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] appWidgetIds = getWidgetIds(provider.widgets); 2801742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Reschedule for the new updatePeriodMillis (don't worry about handling 2802742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // it specially if updatePeriodMillis didn't change because we just sent 2803742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // an update, and the next one will be updatePeriodMillis from now). 2804976e8bd2017d0263216c62111454438cc0f130e3Svetoslav cancelBroadcasts(provider); 2805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav registerForBroadcastsLocked(provider, appWidgetIds); 2806742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // If it's currently showing, call back with the new 2807742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // AppWidgetProviderInfo. 2808742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int j = 0; j < M; j++) { 2809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = provider.widgets.get(j); 2810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav widget.views = null; 2811976e8bd2017d0263216c62111454438cc0f130e3Svetoslav scheduleNotifyProviderChangedLocked(widget); 2812742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2813742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Now that we've told the host, push out an update. 2814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendUpdateIntentLocked(provider, appWidgetIds); 28157fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2816742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2817742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2818742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2819742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2820742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2821742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2822742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // prune the ones we don't want to keep 2823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mProviders.size(); 2824742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(provider.info.provider.getPackageName()) 2827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.getUserId() == userId 2828976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && !keep.contains(provider.id)) { 2829a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung if (removedProviders != null) { 2830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removedProviders.add(provider.id); 2831a3195057fc5874d158cc8ea053aa75d5e016bdcfWinson Chung } 2832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 28337fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung providersUpdated = true; 2834742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2835742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 28367fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 28377fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung return providersUpdated; 2838742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2839742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) { 2841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean removed = false; 2842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 2844742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 2846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkgName.equals(provider.info.provider.getPackageName()) 2847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.getUserId() == userId) { 2848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav deleteProviderLocked(provider); 2849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removed = true; 2850742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2851742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2852742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani 2853742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // Delete the hosts for this package too 2854742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // By now, we have removed any AppWidgets that were in any hosts here, 2855742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani // so we don't need to worry about sending DISABLE broadcasts to them. 2856742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani N = mHosts.size(); 2857742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani for (int i = N - 1; i >= 0; i--) { 2858742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani Host host = mHosts.get(i); 2859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pkgName.equals(host.id.packageName) 2860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && host.getUserId() == userId) { 2861742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani deleteHostLocked(host); 2862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav removed = true; 2863742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 2864742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 28657fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return removed; 28677fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 28687fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 2869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private String getCanonicalPackageName(String packageName, String className, int userId) { 2870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 28727fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung try { 2873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppGlobals.getPackageManager().getReceiverInfo(new ComponentName(packageName, 2874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav className), 0, userId); 2875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return packageName; 2876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 2877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String[] packageNames = mContext.getPackageManager() 2878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .currentToCanonicalPackageNames(new String[]{packageName}); 2879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageNames != null && packageNames.length > 0) { 2880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return packageNames[0]; 28817fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 2882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 2887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendBroadcastAsUser(Intent intent, UserHandle userHandle) { 2890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 2891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.sendBroadcastAsUser(intent, userHandle); 2893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 2895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void bindService(Intent intent, ServiceConnection connection, 2899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserHandle userHandle) { 2900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 2901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, 2903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userHandle); 2904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 2906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void unbindService(ServiceConnection connection) { 2910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long token = Binder.clearCallingIdentity(); 2911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 2912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.unbindService(connection); 2913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 2914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(token); 2915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 29186bd702538d90005add1cfc33746da19404090dc1Svet Ganov @Override 29196bd702538d90005add1cfc33746da19404090dc1Svet Ganov public void onCrossProfileWidgetProvidersChanged(int userId, List<String> packages) { 29206bd702538d90005add1cfc33746da19404090dc1Svet Ganov final int parentId = mSecurityPolicy.getProfileParent(userId); 29216bd702538d90005add1cfc33746da19404090dc1Svet Ganov // We care only if the white-listed package is in a profile of 29226bd702538d90005add1cfc33746da19404090dc1Svet Ganov // the group parent as only the parent can add widgets from the 29236bd702538d90005add1cfc33746da19404090dc1Svet Ganov // profile and not the other way around. 29246bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (parentId != userId) { 29256bd702538d90005add1cfc33746da19404090dc1Svet Ganov synchronized (mLock) { 29266bd702538d90005add1cfc33746da19404090dc1Svet Ganov boolean providersChanged = false; 29276bd702538d90005add1cfc33746da19404090dc1Svet Ganov 29286bd702538d90005add1cfc33746da19404090dc1Svet Ganov final int packageCount = packages.size(); 29296bd702538d90005add1cfc33746da19404090dc1Svet Ganov for (int i = 0; i < packageCount; i++) { 29306bd702538d90005add1cfc33746da19404090dc1Svet Ganov String packageName = packages.get(i); 29316bd702538d90005add1cfc33746da19404090dc1Svet Ganov providersChanged |= updateProvidersForPackageLocked(packageName, 29326bd702538d90005add1cfc33746da19404090dc1Svet Ganov userId, null); 29336bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 29346bd702538d90005add1cfc33746da19404090dc1Svet Ganov 29356bd702538d90005add1cfc33746da19404090dc1Svet Ganov if (providersChanged) { 29366bd702538d90005add1cfc33746da19404090dc1Svet Ganov saveGroupStateAsync(userId); 29376bd702538d90005add1cfc33746da19404090dc1Svet Ganov scheduleNotifyGroupHostsForProvidersChangedLocked(userId); 29386bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 29396bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 29406bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 29416bd702538d90005add1cfc33746da19404090dc1Svet Ganov } 29426bd702538d90005add1cfc33746da19404090dc1Svet Ganov 2943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class CallbackHandler extends Handler { 2944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1; 2945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2; 2946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3; 2947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4; 2948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public CallbackHandler(Looper looper) { 2950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav super(looper, null, false); 2951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 2954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void handleMessage(Message message) { 2955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav switch (message.what) { 2956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_UPDATE_APP_WIDGET: { 2957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views = (RemoteViews) args.arg3; 2961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views); 2965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_PROVIDER_CHANGED: { 2968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info = (AppWidgetProviderInfo)args.arg3; 2972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyProviderChanged(host, callbacks, appWidgetId, info); 2976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_PROVIDERS_CHANGED: { 2979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyProvidersChanged(host, callbacks); 2985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav case MSG_NOTIFY_VIEW_DATA_CHANGED: { 2988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav SomeArgs args = (SomeArgs) message.obj; 2989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = (Host) args.arg1; 2990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; 2991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int appWidgetId = args.argi1; 2992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int viewId = args.argi2; 2993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav args.recycle(); 2994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 2995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId); 2996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } break; 2997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 2999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class SecurityPolicy { 3002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 30038e1d299da27da534b508b1da51ebe351a689cefaSvetoslav public boolean isEnabledGroupProfile(int profileId) { 3004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = UserHandle.getCallingUserId(); 30058e1d299da27da534b508b1da51ebe351a689cefaSvetoslav return isParentOrProfile(parentId, profileId) && isProfileEnabled(profileId); 3006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int[] getEnabledGroupProfileIds(int userId) { 3009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = getGroupParent(userId); 3010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final List<UserInfo> profiles; 3012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profiles = mUserManager.getProfiles(parentId); 3015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int enabledProfileCount = 0; 3020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int profileCount = profiles.size(); 3021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 3022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profiles.get(i).isEnabled()) { 3023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav enabledProfileCount++; 3024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int enabledProfileIndex = 0; 3028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int[] profileIds = new int[enabledProfileCount]; 3029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < profileCount; i++) { 3030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo profile = profiles.get(i); 3031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profile.isEnabled()) { 3032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav profileIds[enabledProfileIndex] = profile.getUserHandle().getIdentifier(); 3033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav enabledProfileIndex++; 3034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return profileIds; 3038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceServiceExistsAndRequiresBindRemoteViewsPermission( 3041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName, int userId) { 3042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceInfo serviceInfo = mPackageManager.getServiceInfo(componentName, 3045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PackageManager.GET_PERMISSIONS, userId); 3046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (serviceInfo == null) { 3047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Service " + componentName 3048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " not installed for user " + userId); 3049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(serviceInfo.permission)) { 3051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new SecurityException("Service " + componentName 3052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " in user " + userId + "does not require " 3053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + android.Manifest.permission.BIND_REMOTEVIEWS); 3054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Local call - shouldn't happen. 3057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3059976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3060976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3061976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3062976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceModifyAppWidgetBindPermissions(String packageName) { 3063976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.enforceCallingPermission( 3064976e8bd2017d0263216c62111454438cc0f130e3Svetoslav android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS, 3065976e8bd2017d0263216c62111454438cc0f130e3Svetoslav "hasBindAppWidgetPermission packageName=" + packageName); 3066976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3067976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3068976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void enforceCallFromPackage(String packageName) { 30695771ad7bc7533f4a9bc72ac1ecabfdf6ca493b16Svet Ganov mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName); 3070976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3071976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3072976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hasCallerBindPermissionOrBindWhiteListedLocked(String packageName) { 3073976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3074976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mContext.enforceCallingOrSelfPermission( 3075976e8bd2017d0263216c62111454438cc0f130e3Svetoslav android.Manifest.permission.BIND_APPWIDGET, null); 3076976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (SecurityException se) { 3077976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isCallerBindAppWidgetWhiteListedLocked(packageName)) { 3078976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3079976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3080976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3081976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3082976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3083976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3084976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isCallerBindAppWidgetWhiteListedLocked(String packageName) { 3085976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int userId = UserHandle.getCallingUserId(); 3086976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int packageUid = getUidForPackage(packageName, userId); 3087976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageUid < 0) { 3088976e8bd2017d0263216c62111454438cc0f130e3Svetoslav throw new IllegalArgumentException("No package " + packageName 3089976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " for user " + userId); 3090976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3091976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3092976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(userId); 3093976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3094976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Pair<Integer, String> packageId = Pair.create(userId, packageName); 3095976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (mPackagesWithBindWidgetPermission.contains(packageId)) { 3096976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3097976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3098976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3099976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3100976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3101976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3102976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3103976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean canAccessAppWidget(Widget widget, int uid, String packageName) { 3104976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isHostInPackageForUid(widget.host, uid, packageName)) { 3105976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps hosting the AppWidget have access to it. 3106976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3107976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isProviderInPackageForUid(widget.provider, uid, packageName)) { 3109976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps providing the AppWidget have access to it. 3110976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3111976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3112976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (isHostAccessingProvider(widget.host, widget.provider, uid, packageName)) { 3113976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Apps hosting the AppWidget get to bind to a remote view service in the provider. 3114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3115976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3116985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav final int userId = UserHandle.getUserId(uid); 3117985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav if ((widget.host.getUserId() == userId || (widget.provider != null 3118985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav && widget.provider.getUserId() == userId)) 3119985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav && mContext.checkCallingPermission(android.Manifest.permission.BIND_APPWIDGET) 3120976e8bd2017d0263216c62111454438cc0f130e3Svetoslav == PackageManager.PERMISSION_GRANTED) { 3121985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav // Apps that run in the same user as either the host or the provider and 3122985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav // have the bind widget permission have access to the widget. 3123976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3124976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3125976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3126976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3127976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3128976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isParentOrProfile(int parentId, int profileId) { 3129976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parentId == profileId) { 3130976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3132976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getProfileParent(profileId) == parentId; 3133976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3134976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3135976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderInCallerOrInProfileAndWhitelListed(String packageName, 3136976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int profileId) { 3137976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int callerId = UserHandle.getCallingUserId(); 3138976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (profileId == callerId) { 3139976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3140976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3141976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = getProfileParent(profileId); 3142976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parentId != callerId) { 3143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3144976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3145976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return isProviderWhitelListed(packageName, profileId); 3146976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3147976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3148976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderWhitelListed(String packageName, int profileId) { 3149976e8bd2017d0263216c62111454438cc0f130e3Svetoslav DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( 3150976e8bd2017d0263216c62111454438cc0f130e3Svetoslav DevicePolicyManagerInternal.class); 3151976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3152976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If the policy manager is not available on the device we deny it all. 3153976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (devicePolicyManager == null) { 3154976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3155976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3156976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3157976e8bd2017d0263216c62111454438cc0f130e3Svetoslav List<String> crossProfilePackages = devicePolicyManager 3158976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .getCrossProfileWidgetProviders(profileId); 3159976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3160976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return crossProfilePackages.contains(packageName); 3161976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3162976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3163976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getProfileParent(int profileId) { 3164976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3165976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3166976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo parent = mUserManager.getProfileParent(profileId); 3167976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (parent != null) { 3168976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return parent.getUserHandle().getIdentifier(); 3169976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3170976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3171976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3172976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3173976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UNKNOWN_USER_ID; 3174976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3175976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3176976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getGroupParent(int profileId) { 3177976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int parentId = mSecurityPolicy.getProfileParent(profileId); 3178976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return (parentId != UNKNOWN_USER_ID) ? parentId : profileId; 3179976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3180976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3181976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isHostInPackageForUid(Host host, int uid, String packageName) { 3182985e566ceca9c11d2f740499053f37dfaeb9033dSvetoslav return host.id.uid == uid && host.id.packageName.equals(packageName); 3183976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3184976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3185976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isProviderInPackageForUid(Provider provider, int uid, 3186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String packageName) { 3187976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Packages providing the AppWidget have access to it. 3188976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider != null && provider.id.uid == uid 3189976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.getPackageName().equals(packageName); 3190976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3191976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3192976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isHostAccessingProvider(Host host, Provider provider, int uid, 3193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String packageName) { 3194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The host creates a package context to bind to remote views service in the provider. 3195976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return host.id.uid == uid && provider != null 3196976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.getPackageName().equals(packageName); 3197976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3198976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3199976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isProfileEnabled(int profileId) { 3200976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final long identity = Binder.clearCallingIdentity(); 3201976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3202976e8bd2017d0263216c62111454438cc0f130e3Svetoslav UserInfo userInfo = mUserManager.getUserInfo(profileId); 3203976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (userInfo == null || !userInfo.isEnabled()) { 3204976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3205976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3206976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3207976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Binder.restoreCallingIdentity(identity); 3208976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3209976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3210976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3211976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3212976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3213976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Provider { 3214976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId id; 3215976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetProviderInfo info; 3216976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> widgets = new ArrayList<>(); 3217976e8bd2017d0263216c62111454438cc0f130e3Svetoslav PendingIntent broadcast; 3218976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean zombie; // if we're in safe mode, don't prune this just because nobody references it 3219976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3220976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int tag = TAG_UNDEFINED; // for use while saving state (the index) 3221976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3222976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getUserId() { 3223976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.getUserId(id.uid); 3224976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3225976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3226976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isInPackageForUser(String packageName, int userId) { 3227976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getUserId() == userId 3228976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && id.componentName.getPackageName().equals(packageName); 3229976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // is there an instance of this provider hosted by the given app? 3232976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean hostedByPackageForUser(String packageName, int userId) { 3233976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = widgets.size(); 3234976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3235976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = widgets.get(i); 3236976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName.equals(widget.host.id.packageName) 3237976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.host.getUserId() == userId) { 3238976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3240976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3242976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "Provider{" + id + (zombie ? " Z" : "") + '}'; 3247976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3248976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3249976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3250976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class ProviderId { 3251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid; 3252976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final ComponentName componentName; 3253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3254976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private ProviderId(int uid, ComponentName componentName) { 3255976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.uid = uid; 3256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.componentName = componentName; 3257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3258976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean equals(Object obj) { 3261976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (this == obj) { 3262976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3263976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3264976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (obj == null) { 3265976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3266976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3267976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (getClass() != obj.getClass()) { 3268976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3269976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3270976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ProviderId other = (ProviderId) obj; 3271976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid != other.uid) { 3272976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3273976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3274976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (componentName == null) { 3275976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (other.componentName != null) { 3276976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3277976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3278976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (!componentName.equals(other.componentName)) { 3279976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3280976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3281976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3282976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3283976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3284976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3285976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int hashCode() { 3286976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int result = uid; 3287976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + ((componentName != null) 3288976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? componentName.hashCode() : 0); 3289976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 3290976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3291976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3292976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3293976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3294976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "ProviderId{user:" + UserHandle.getUserId(uid) + ", app:" 3295976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + UserHandle.getAppId(uid) + ", cmp:" + componentName + '}'; 3296976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3297976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3298976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3299976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Host { 3300976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id; 3301976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Widget> widgets = new ArrayList<>(); 3302976e8bd2017d0263216c62111454438cc0f130e3Svetoslav IAppWidgetHost callbacks; 3303976e8bd2017d0263216c62111454438cc0f130e3Svetoslav boolean zombie; // if we're in safe mode, don't prune this just because nobody references it 3304976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3305976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int tag = TAG_UNDEFINED; // for use while saving state (the index) 3306976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3307976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int getUserId() { 3308976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return UserHandle.getUserId(id.uid); 3309976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3310976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3311976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean isInPackageForUser(String packageName, int userId) { 3312976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return getUserId() == userId && id.packageName.equals(packageName); 3313976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3314976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3315976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean hostsPackageForUser(String pkg, int userId) { 3316976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = widgets.size(); 3317976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3318976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widgets.get(i).provider; 3319976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null && provider.getUserId() == userId && provider.info != null 3320976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && pkg.equals(provider.info.provider.getPackageName())) { 3321976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3322976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3323976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3325976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3326976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3327976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3328976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3329976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "Host{" + id + (zombie ? " Z" : "") + '}'; 3330976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3331976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3332976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3333976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class HostId { 3334976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid; 3335976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId; 3336976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final String packageName; 3337976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3338976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public HostId(int uid, int hostId, String packageName) { 3339976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.uid = uid; 3340976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.hostId = hostId; 3341976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.packageName = packageName; 3342976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3343976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3344976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3345976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean equals(Object obj) { 3346976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (this == obj) { 3347976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3348976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3349976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (obj == null) { 3350976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3351976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3352976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (getClass() != obj.getClass()) { 3353976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3354976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3355976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId other = (HostId) obj; 3356976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (uid != other.uid) { 3357976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3358976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3359976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (hostId != other.hostId) { 3360976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3361976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3362976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (packageName == null) { 3363976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (other.packageName != null) { 3364976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3365976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3366976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if (!packageName.equals(other.packageName)) { 3367976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3368976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3369976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3370976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3371976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3372976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3373976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int hashCode() { 3374976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int result = uid; 3375976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + hostId; 3376976e8bd2017d0263216c62111454438cc0f130e3Svetoslav result = 31 * result + ((packageName != null) 3377976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ? packageName.hashCode() : 0); 3378976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return result; 3379976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3380976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3381976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3382976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3383976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "HostId{user:" + UserHandle.getUserId(uid) + ", app:" 3384976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + UserHandle.getAppId(uid) + ", hostId:" + hostId 3385976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + ", pkg:" + packageName + '}'; 3386976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3387976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3388976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3389976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class Widget { 3390976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int appWidgetId; 3391976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int restoredId; // tracking & remapping any restored state 3392976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider; 3393976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RemoteViews views; 3394976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle options; 3395976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host; 3396976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3398976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public String toString() { 3399976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}'; 3400976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3401976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3402976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3403976e8bd2017d0263216c62111454438cc0f130e3Svetoslav /** 3404976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection. This 3405976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * needs to be a static inner class since a reference to the ServiceConnection is held globally 3406976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * and may lead us to leak AppWidgetService instances (if there were more than one). 3407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav */ 3408976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final class ServiceConnectionProxy implements ServiceConnection { 3409976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final IRemoteViewsAdapterConnection mConnectionCb; 3410976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3411976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ServiceConnectionProxy(IBinder connectionCb) { 3412976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb = IRemoteViewsAdapterConnection.Stub 3413976e8bd2017d0263216c62111454438cc0f130e3Svetoslav .asInterface(connectionCb); 3414976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3415976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3416976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceConnected(ComponentName name, IBinder service) { 3417976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3418976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb.onServiceConnected(service); 3419976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3420976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error passing service interface", re); 3421976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3422976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3423976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3424976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void onServiceDisconnected(ComponentName name) { 3425976e8bd2017d0263216c62111454438cc0f130e3Svetoslav disconnect(); 3426976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3427976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3428976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void disconnect() { 3429976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3430976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mConnectionCb.onServiceDisconnected(); 3431976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (RemoteException re) { 3432976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.e(TAG, "Error clearing service interface", re); 3433976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3434976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3435976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3436976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3437976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private class LoadedWidgetState { 3438976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final Widget widget; 3439976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostTag; 3440976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerTag; 3441976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3442976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public LoadedWidgetState(Widget widget, int hostTag, int providerTag) { 3443976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.widget = widget; 3444976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.hostTag = hostTag; 3445976e8bd2017d0263216c62111454438cc0f130e3Svetoslav this.providerTag = providerTag; 3446976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3447976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3448976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3449976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class SaveStateRunnable implements Runnable { 3450976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int mUserId; 3451976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3452976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public SaveStateRunnable(int userId) { 3453976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUserId = userId; 3454976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3455976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3456976e8bd2017d0263216c62111454438cc0f130e3Svetoslav @Override 3457976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void run() { 3458976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3459976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ensureGroupStateLoadedLocked(mUserId); 3460976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveStateLocked(mUserId); 3461976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3462976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3463976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3464976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3465976e8bd2017d0263216c62111454438cc0f130e3Svetoslav /** 3466976e8bd2017d0263216c62111454438cc0f130e3Svetoslav * This class encapsulates the backup and restore logic for a user group state. 3467976e8bd2017d0263216c62111454438cc0f130e3Svetoslav */ 3468976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final class BackupRestoreController { 3469976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final String TAG = "BackupRestoreController"; 3470976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3471976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final boolean DEBUG = true; 3472976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3473976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Version of backed-up widget state. 3474976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private static final int WIDGET_STATE_VERSION = 2; 3475976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3476976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We need to make sure to wipe the pre-restore widget state only once for 3477976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // a given package. Keep track of what we've done so far here; the list is 3478976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // cleared at the start of every system restore pass, but preserved through 3479976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // any install-time restore operations. 3480976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashSet<String> mPrunedApps = new HashSet<>(); 3481976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3482976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Provider, ArrayList<RestoreUpdateRecord>> mUpdatesByProvider = 3483976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new HashMap<>(); 3484976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost = 3485976e8bd2017d0263216c62111454438cc0f130e3Svetoslav new HashMap<>(); 3486976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3487976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public List<String> getWidgetParticipants(int userId) { 3488976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3489976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Getting widget participants for user: " + userId); 3490976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3491976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3492976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HashSet<String> packages = new HashSet<>(); 3493976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3494976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 3495976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3496976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3497976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3498976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Skip cross-user widgets. 3499976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isProviderAndHostInUser(widget, userId)) { 3500976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 3501976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3502976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3503976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packages.add(widget.host.id.packageName); 3504976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3505976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 3506976e8bd2017d0263216c62111454438cc0f130e3Svetoslav packages.add(provider.id.componentName.getPackageName()); 3507976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3508976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3509976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3510976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return new ArrayList<>(packages); 3511976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3512976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3513976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public byte[] getWidgetState(String backedupPackage, int userId) { 3514976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3515976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Getting widget state for user: " + userId); 3516976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3517976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3518976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ByteArrayOutputStream stream = new ByteArrayOutputStream(); 3519976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3520976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Preflight: if this app neither hosts nor provides any live widgets 3521976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // we have no work to do. 3522976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!packageNeedsWidgetBackupLocked(backedupPackage, userId)) { 3523976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3524976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3525976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3526976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3527976e8bd2017d0263216c62111454438cc0f130e3Svetoslav XmlSerializer out = new FastXmlSerializer(); 3528976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.setOutput(stream, "utf-8"); 3529976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startDocument(null, true); 3530976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.startTag(null, "ws"); // widget state 3531976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "version", String.valueOf(WIDGET_STATE_VERSION)); 3532976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.attribute(null, "pkg", backedupPackage); 3533976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3534976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Remember all the providers that are currently hosted or published 3535976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // by this package: that is, all of the entities related to this app 3536976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // which will need to be told about id remapping. 3537976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int index = 0; 3538976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mProviders.size(); 3539976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3540976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 3541976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3542976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!provider.widgets.isEmpty() 3543976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && (provider.isInPackageForUser(backedupPackage, userId) 3544976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || provider.hostedByPackageForUser(backedupPackage, userId))) { 3545976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.tag = index; 3546976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeProvider(out, provider); 3547976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index++; 3548976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3549976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3550976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3551976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mHosts.size(); 3552976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index = 0; 3553976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3554976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = mHosts.get(i); 3555976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3556976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!host.widgets.isEmpty() 3557976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && (host.isInPackageForUser(backedupPackage, userId) 3558976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || host.hostsPackageForUser(backedupPackage, userId))) { 3559976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.tag = index; 3560976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeHost(out, host); 3561976e8bd2017d0263216c62111454438cc0f130e3Svetoslav index++; 3562976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3563976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3564976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3565976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // All widget instances involving this package, 3566976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // either as host or as provider 3567976e8bd2017d0263216c62111454438cc0f130e3Svetoslav N = mWidgets.size(); 3568976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3569976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3570976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3571976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3572976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.isInPackageForUser(backedupPackage, userId) 3573976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || (provider != null 3574976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.isInPackageForUser(backedupPackage, userId))) { 3575976e8bd2017d0263216c62111454438cc0f130e3Svetoslav serializeAppWidget(out, widget); 3576976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3577976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3578976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3579976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endTag(null, "ws"); 3580976e8bd2017d0263216c62111454438cc0f130e3Svetoslav out.endDocument(); 3581976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (IOException e) { 3582976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to save widget state for " + backedupPackage); 3583976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3584976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3585976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3586976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3587976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return stream.toByteArray(); 3588976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3589976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3590976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreStarting(int userId) { 3591976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3592976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Restore starting for user: " + userId); 3593976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3594976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3595976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3596976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We're starting a new "system" restore operation, so any widget restore 3597976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // state that we see from here on is intended to replace the current 3598976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // widget configuration of any/all of the affected apps. 3599976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPrunedApps.clear(); 3600976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByProvider.clear(); 3601976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByHost.clear(); 3602976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3603976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3604976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3605976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreWidgetState(String packageName, byte[] restoredState, int userId) { 3606976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3607976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Restoring widget state for user:" + userId 3608976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " package: " + packageName); 3609976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3610976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3611976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ByteArrayInputStream stream = new ByteArrayInputStream(restoredState); 3612976e8bd2017d0263216c62111454438cc0f130e3Svetoslav try { 3613976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Providers mentioned in the widget dataset by ordinal 3614976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Provider> restoredProviders = new ArrayList<>(); 3615976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3616976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Hosts mentioned in the widget dataset by ordinal 3617976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<Host> restoredHosts = new ArrayList<>(); 3618976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3619976e8bd2017d0263216c62111454438cc0f130e3Svetoslav XmlPullParser parser = Xml.newPullParser(); 3620976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.setInput(stream, null); 3621976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3622976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3623976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int type; 3624976e8bd2017d0263216c62111454438cc0f130e3Svetoslav do { 3625976e8bd2017d0263216c62111454438cc0f130e3Svetoslav type = parser.next(); 3626976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (type == XmlPullParser.START_TAG) { 3627976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final String tag = parser.getName(); 3628976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if ("ws".equals(tag)) { 3629976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String version = parser.getAttributeValue(null, "version"); 3630976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3631976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int versionNumber = Integer.parseInt(version); 3632976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (versionNumber > WIDGET_STATE_VERSION) { 3633976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to process state version " + version); 3634976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3635976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3636976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3637976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // TODO: fix up w.r.t. canonical vs current package names 3638976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3639976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!packageName.equals(pkg)) { 3640976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Package mismatch in ws"); 3641976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3642976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3643976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("p".equals(tag)) { 3644976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3645976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String cl = parser.getAttributeValue(null, "cl"); 3646976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3647976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // hostedProviders index will match 'p' attribute in widget's 3648976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // entry in the xml file being restored 3649976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // If there's no live entry for this provider, add an inactive one 3650976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // so that widget IDs referring to them can be properly allocated 3651976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3652976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Backup and resotre only for the parent profile. 3653976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ComponentName componentName = new ComponentName(pkg, cl); 3654976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3655976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider p = findProviderLocked(componentName, userId); 3656976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p == null) { 3657976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p = new Provider(); 3658976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.id = new ProviderId(UNKNOWN_UID, componentName); 3659976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.info = new AppWidgetProviderInfo(); 3660976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.info.provider = componentName; 3661976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p.zombie = true; 3662976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mProviders.add(p); 3663976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3664976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3665976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " provider " + p.id); 3666976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3667976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredProviders.add(p); 3668976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("h".equals(tag)) { 3669976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // The host app may not yet exist on the device. If it's here we 3670976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // just use the existing Host entry, otherwise we create a 3671976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // placeholder whose uid will be fixed up at PACKAGE_ADDED time. 3672976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String pkg = parser.getAttributeValue(null, "pkg"); 3673976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3674976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int uid = getUidForPackage(pkg, userId); 3675976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int hostId = Integer.parseInt( 3676976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "id"), 16); 3677976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3678976e8bd2017d0263216c62111454438cc0f130e3Svetoslav HostId id = new HostId(uid, hostId, pkg); 3679976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host h = lookupOrAddHostLocked(id); 3680976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredHosts.add(h); 3681976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3682976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3683976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " host[" + restoredHosts.size() 3684976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + "]: {" + h.id + "}"); 3685976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3686976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else if ("g".equals(tag)) { 3687976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int restoredId = Integer.parseInt( 3688976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "id"), 16); 3689976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int hostIndex = Integer.parseInt( 3690976e8bd2017d0263216c62111454438cc0f130e3Svetoslav parser.getAttributeValue(null, "h"), 16); 3691976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = restoredHosts.get(hostIndex); 3692976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider p = null; 3693976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String prov = parser.getAttributeValue(null, "p"); 3694976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (prov != null) { 3695976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // could have been null if the app had allocated an id 3696976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // but not yet established a binding under that id 3697976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int which = Integer.parseInt(prov, 16); 3698976e8bd2017d0263216c62111454438cc0f130e3Svetoslav p = restoredProviders.get(which); 3699976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3700976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3701976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We'll be restoring widget state for both the host and 3702976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // provider sides of this widget ID, so make sure we are 3703976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // beginning from a clean slate on both fronts. 3704976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneWidgetStateLocked(host.id.packageName, userId); 3705976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p != null) { 3706976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pruneWidgetStateLocked(p.id.componentName.getPackageName(), 3707976e8bd2017d0263216c62111454438cc0f130e3Svetoslav userId); 3708976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3709976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3710976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Have we heard about this ancestral widget instance before? 3711976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget id = findRestoredWidgetLocked(restoredId, host, p); 3712976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id == null) { 3713976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id = new Widget(); 3714976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.appWidgetId = incrementAndGetAppWidgetIdLocked(userId); 3715976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.restoredId = restoredId; 3716976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.options = parseWidgetIdOptions(parser); 3717976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.host = host; 3718976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.host.widgets.add(id); 3719976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.provider = p; 3720976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id.provider != null) { 3721976e8bd2017d0263216c62111454438cc0f130e3Svetoslav id.provider.widgets.add(id); 3722976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3723976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3724976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "New restored id " + restoredId 3725976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " now " + id); 3726976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3727976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.add(id); 3728976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3729976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (id.provider.info != null) { 3730976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stashProviderRestoreUpdateLocked(id.provider, 3731976e8bd2017d0263216c62111454438cc0f130e3Svetoslav restoredId, id.appWidgetId); 3732976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3733976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Missing provider for restored widget " + id); 3734976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3735976e8bd2017d0263216c62111454438cc0f130e3Svetoslav stashHostRestoreUpdateLocked(id.host, restoredId, id.appWidgetId); 3736976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3737976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3738976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " instance: " + restoredId 3739976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " -> " + id.appWidgetId 3740976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " :: p=" + id.provider); 3741976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3742976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3743976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3744976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } while (type != XmlPullParser.END_DOCUMENT); 3745976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3746976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We've updated our own bookkeeping. We'll need to notify the hosts and 3747976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // providers about the changes, but we can't do that yet because the restore 3748976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // target is not necessarily fully live at this moment. Set aside the 3749976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // information for now; the backup manager will call us once more at the 3750976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // end of the process when all of the targets are in a known state, and we 3751976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // will update at that point. 3752976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3753976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } catch (XmlPullParserException | IOException e) { 3754976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.w(TAG, "Unable to restore widget state for " + packageName); 3755976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } finally { 3756976e8bd2017d0263216c62111454438cc0f130e3Svetoslav saveGroupStateAsync(userId); 3757976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3758976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3759976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3760976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Called once following the conclusion of a restore operation. This is when we 3761976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // send out updates to apps involved in widget-state restore telling them about 3762976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // the new widget ID space. 3763976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public void restoreFinished(int userId) { 3764976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3765976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "restoreFinished for " + userId); 3766976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3767976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3768976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final UserHandle userHandle = new UserHandle(userId); 3769976e8bd2017d0263216c62111454438cc0f130e3Svetoslav synchronized (mLock) { 3770976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Build the providers' broadcasts and send them off 3771976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries 3772976e8bd2017d0263216c62111454438cc0f130e3Svetoslav = mUpdatesByProvider.entrySet(); 3773976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) { 3774976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // For each provider there's a list of affected IDs 3775976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = e.getKey(); 3776976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> updates = e.getValue(); 3777976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int pending = countPendingUpdates(updates); 3778976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3779976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Provider " + provider + " pending: " + pending); 3780976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3781976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pending > 0) { 3782976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] oldIds = new int[pending]; 3783976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] newIds = new int[pending]; 3784976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 3785976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int nextPending = 0; 3786976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3787976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 3788976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 3789976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.notified = true; 3790976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldIds[nextPending] = r.oldId; 3791976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newIds[nextPending] = r.newId; 3792976e8bd2017d0263216c62111454438cc0f130e3Svetoslav nextPending++; 3793976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3794976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " " + r.oldId + " => " + r.newId); 3795976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3796976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3797976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3798976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendWidgetRestoreBroadcastLocked( 3799976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.ACTION_APPWIDGET_RESTORED, 3800976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider, null, oldIds, newIds, userHandle); 3801976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3802976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3803976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3804976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // same thing per host 3805976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries 3806976e8bd2017d0263216c62111454438cc0f130e3Svetoslav = mUpdatesByHost.entrySet(); 3807976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) { 3808976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = e.getKey(); 3809976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.id.uid != UNKNOWN_UID) { 3810976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> updates = e.getValue(); 3811976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int pending = countPendingUpdates(updates); 3812976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3813976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Host " + host + " pending: " + pending); 3814976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3815976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (pending > 0) { 3816976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] oldIds = new int[pending]; 3817976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int[] newIds = new int[pending]; 3818976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 3819976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int nextPending = 0; 3820976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3821976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 3822976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 3823976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.notified = true; 3824976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldIds[nextPending] = r.oldId; 3825976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newIds[nextPending] = r.newId; 3826976e8bd2017d0263216c62111454438cc0f130e3Svetoslav nextPending++; 3827976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3828976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " " + r.oldId + " => " + r.newId); 3829976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3830976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3831976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3832976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendWidgetRestoreBroadcastLocked( 3833976e8bd2017d0263216c62111454438cc0f130e3Svetoslav AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED, 3834976e8bd2017d0263216c62111454438cc0f130e3Svetoslav null, host, oldIds, newIds, userHandle); 3835976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3836976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3837976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3838976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3839976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3840976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3841976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Provider findProviderLocked(ComponentName componentName, int userId) { 3842976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int providerCount = mProviders.size(); 3843976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < providerCount; i++) { 3844976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = mProviders.get(i); 3845976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider.getUserId() == userId 3846976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && provider.id.componentName.equals(componentName)) { 3847976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return provider; 3848976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3849976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3850976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3851976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3852976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3853976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Widget findRestoredWidgetLocked(int restoredId, Host host, Provider p) { 3854976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3855976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "Find restored widget: id=" + restoredId 3856976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " host=" + host + " provider=" + p); 3857976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3858976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3859976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (p == null || host == null) { 3860976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3861976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3862976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3863976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = mWidgets.size(); 3864976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3865976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3866976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.restoredId == restoredId 3867976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.host.id.equals(host.id) 3868976e8bd2017d0263216c62111454438cc0f130e3Svetoslav && widget.provider.id.equals(p.id)) { 3869976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3870976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, " Found at " + i + " : " + widget); 3871976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3872976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget; 3873976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3874976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3875976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return null; 3876976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3877976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3878976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean packageNeedsWidgetBackupLocked(String packageName, int userId) { 3879976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int N = mWidgets.size(); 3880976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3881976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3882976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3883976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Skip cross-user widgets. 3884976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!isProviderAndHostInUser(widget, userId)) { 3885976e8bd2017d0263216c62111454438cc0f130e3Svetoslav continue; 3886976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3887976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3888976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (widget.host.isInPackageForUser(packageName, userId)) { 3889976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // this package is hosting widgets, so it knows widget IDs. 3890976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3891976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3892976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3893976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3894976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null && provider.isInPackageForUser(packageName, userId)) { 3895976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // someone is hosting this app's widgets, so it knows widget IDs. 3896976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3897976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3898976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3899976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3900976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3901976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3902976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void stashProviderRestoreUpdateLocked(Provider provider, int oldId, int newId) { 3903976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> r = mUpdatesByProvider.get(provider); 3904976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r == null) { 3905976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r = new ArrayList<>(); 3906976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByProvider.put(provider, r); 3907976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3908976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // don't duplicate 3909976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (alreadyStashed(r, oldId, newId)) { 3910976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3911976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "ID remap " + oldId + " -> " + newId 3912976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already stashed for " + provider); 3913976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3914976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3915976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3916976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3917976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.add(new RestoreUpdateRecord(oldId, newId)); 3918976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3919976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3920976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean alreadyStashed(ArrayList<RestoreUpdateRecord> stash, 3921976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int oldId, final int newId) { 3922976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = stash.size(); 3923976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 3924976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = stash.get(i); 3925976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r.oldId == oldId && r.newId == newId) { 3926976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return true; 3927976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3928976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3929976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return false; 3930976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3931976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3932976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void stashHostRestoreUpdateLocked(Host host, int oldId, int newId) { 3933976e8bd2017d0263216c62111454438cc0f130e3Svetoslav ArrayList<RestoreUpdateRecord> r = mUpdatesByHost.get(host); 3934976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (r == null) { 3935976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r = new ArrayList<>(); 3936976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mUpdatesByHost.put(host, r); 3937976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3938976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (alreadyStashed(r, oldId, newId)) { 3939976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3940976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "ID remap " + oldId + " -> " + newId 3941976e8bd2017d0263216c62111454438cc0f130e3Svetoslav + " already stashed for " + host); 3942976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3943976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return; 3944976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3945976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3946976e8bd2017d0263216c62111454438cc0f130e3Svetoslav r.add(new RestoreUpdateRecord(oldId, newId)); 3947976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3948976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3949976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void sendWidgetRestoreBroadcastLocked(String action, Provider provider, 3950976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host, int[] oldIds, int[] newIds, UserHandle userHandle) { 3951976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Intent intent = new Intent(action); 3952976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds); 3953976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds); 3954976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (provider != null) { 3955976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(provider.info.provider); 3956976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, userHandle); 3957976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3958976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host != null) { 3959976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setComponent(null); 3960976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.setPackage(host.id.packageName); 3961976e8bd2017d0263216c62111454438cc0f130e3Svetoslav intent.putExtra(AppWidgetManager.EXTRA_HOST_ID, host.id.hostId); 3962976e8bd2017d0263216c62111454438cc0f130e3Svetoslav sendBroadcastAsUser(intent, userHandle); 3963976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3964976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3965976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3966976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // We're restoring widget state for 'pkg', so we start by wiping (a) all widget 3967976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // instances that are hosted by that app, and (b) all instances in other hosts 3968976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // for which 'pkg' is the provider. We assume that we'll be restoring all of 3969976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // these hosts & providers, so will be reconstructing a correct live state. 3970976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private void pruneWidgetStateLocked(String pkg, int userId) { 3971976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!mPrunedApps.contains(pkg)) { 3972976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3973976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "pruning widget state for restoring package " + pkg); 3974976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3975976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = mWidgets.size() - 1; i >= 0; i--) { 3976976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Widget widget = mWidgets.get(i); 3977976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3978976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Host host = widget.host; 3979976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Provider provider = widget.provider; 3980976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 3981976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (host.hostsPackageForUser(pkg, userId) 3982976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || (provider != null && provider.isInPackageForUser(pkg, userId))) { 3983976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // 'pkg' is either the host or the provider for this instances, 3984976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // so we tear it down in anticipation of it (possibly) being 3985976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // reconstructed due to the restore 3986976e8bd2017d0263216c62111454438cc0f130e3Svetoslav host.widgets.remove(widget); 3987976e8bd2017d0263216c62111454438cc0f130e3Svetoslav provider.widgets.remove(widget); 3988976e8bd2017d0263216c62111454438cc0f130e3Svetoslav unbindAppWidgetRemoteViewsServicesLocked(widget); 3989976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mWidgets.remove(i); 3990976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3991976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3992976e8bd2017d0263216c62111454438cc0f130e3Svetoslav mPrunedApps.add(pkg); 3993976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } else { 3994976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (DEBUG) { 3995976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Slog.i(TAG, "already pruned " + pkg + ", continuing normally"); 3996976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3997976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3998976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 3999976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4000976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private boolean isProviderAndHostInUser(Widget widget, int userId) { 4001976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Backup only widgets hosted or provided by the owner profile. 4002976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return widget.host.getUserId() == userId && (widget.provider == null 4003976e8bd2017d0263216c62111454438cc0f130e3Svetoslav || widget.provider.getUserId() == userId); 4004976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4005976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4006976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private Bundle parseWidgetIdOptions(XmlPullParser parser) { 4007976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Bundle options = new Bundle(); 4008976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String minWidthString = parser.getAttributeValue(null, "min_width"); 4009976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (minWidthString != null) { 4010976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 4011976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(minWidthString, 16)); 4012976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4013976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String minHeightString = parser.getAttributeValue(null, "min_height"); 4014976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (minHeightString != null) { 4015976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 4016976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(minHeightString, 16)); 4017976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4018976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String maxWidthString = parser.getAttributeValue(null, "max_width"); 4019976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (maxWidthString != null) { 4020976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 4021976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(maxWidthString, 16)); 4022976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4023976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String maxHeightString = parser.getAttributeValue(null, "max_height"); 4024976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (maxHeightString != null) { 4025976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 4026976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(maxHeightString, 16)); 4027976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4028976e8bd2017d0263216c62111454438cc0f130e3Svetoslav String categoryString = parser.getAttributeValue(null, "host_category"); 4029976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (categoryString != null) { 4030976e8bd2017d0263216c62111454438cc0f130e3Svetoslav options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 4031976e8bd2017d0263216c62111454438cc0f130e3Svetoslav Integer.parseInt(categoryString, 16)); 4032976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4033976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return options; 4034976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4035976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4036976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private int countPendingUpdates(ArrayList<RestoreUpdateRecord> updates) { 4037976e8bd2017d0263216c62111454438cc0f130e3Svetoslav int pending = 0; 4038976e8bd2017d0263216c62111454438cc0f130e3Svetoslav final int N = updates.size(); 4039976e8bd2017d0263216c62111454438cc0f130e3Svetoslav for (int i = 0; i < N; i++) { 4040976e8bd2017d0263216c62111454438cc0f130e3Svetoslav RestoreUpdateRecord r = updates.get(i); 4041976e8bd2017d0263216c62111454438cc0f130e3Svetoslav if (!r.notified) { 4042976e8bd2017d0263216c62111454438cc0f130e3Svetoslav pending++; 4043976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4044976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4045976e8bd2017d0263216c62111454438cc0f130e3Svetoslav return pending; 4046976e8bd2017d0263216c62111454438cc0f130e3Svetoslav } 4047976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4048976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // Accumulate a list of updates that affect the given provider for a final 4049976e8bd2017d0263216c62111454438cc0f130e3Svetoslav // coalesced notification broadcast once restore is over. 4050976e8bd2017d0263216c62111454438cc0f130e3Svetoslav private class RestoreUpdateRecord { 4051976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int oldId; 4052976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public int newId; 4053976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public boolean notified; 4054976e8bd2017d0263216c62111454438cc0f130e3Svetoslav 4055976e8bd2017d0263216c62111454438cc0f130e3Svetoslav public RestoreUpdateRecord(int theOldId, int theNewId) { 4056976e8bd2017d0263216c62111454438cc0f130e3Svetoslav oldId = theOldId; 4057976e8bd2017d0263216c62111454438cc0f130e3Svetoslav newId = theNewId; 4058976e8bd2017d0263216c62111454438cc0f130e3Svetoslav notified = false; 40597fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 40607fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 4061742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani } 40629ce72731f22caa07d90dcd016c6441bfeb90225cNick Kralevich} 4063