Home | History | Annotate | Download | only in appwidget
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.appwidget;
     18 
     19 import static android.content.Context.KEYGUARD_SERVICE;
     20 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
     21 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
     22 
     23 import android.annotation.UserIdInt;
     24 import android.app.AlarmManager;
     25 import android.app.AppGlobals;
     26 import android.app.AppOpsManager;
     27 import android.app.KeyguardManager;
     28 import android.app.PendingIntent;
     29 import android.app.admin.DevicePolicyManagerInternal;
     30 import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
     31 import android.appwidget.AppWidgetManager;
     32 import android.appwidget.AppWidgetProviderInfo;
     33 import android.content.BroadcastReceiver;
     34 import android.content.ComponentName;
     35 import android.content.Context;
     36 import android.content.Intent;
     37 import android.content.Intent.FilterComparison;
     38 import android.content.IntentFilter;
     39 import android.content.IntentSender;
     40 import android.content.ServiceConnection;
     41 import android.content.pm.ActivityInfo;
     42 import android.content.pm.ApplicationInfo;
     43 import android.content.pm.IPackageManager;
     44 import android.content.pm.PackageInfo;
     45 import android.content.pm.PackageManager;
     46 import android.content.pm.PackageManager.NameNotFoundException;
     47 import android.content.pm.ParceledListSlice;
     48 import android.content.pm.ResolveInfo;
     49 import android.content.pm.ServiceInfo;
     50 import android.content.pm.UserInfo;
     51 import android.content.res.Resources;
     52 import android.content.res.TypedArray;
     53 import android.content.res.XmlResourceParser;
     54 import android.graphics.Bitmap;
     55 import android.graphics.Point;
     56 import android.graphics.drawable.Drawable;
     57 import android.net.Uri;
     58 import android.os.Binder;
     59 import android.os.Bundle;
     60 import android.os.Environment;
     61 import android.os.Handler;
     62 import android.os.IBinder;
     63 import android.os.Looper;
     64 import android.os.Message;
     65 import android.os.Process;
     66 import android.os.RemoteException;
     67 import android.os.SystemClock;
     68 import android.os.UserHandle;
     69 import android.os.UserManager;
     70 import android.os.storage.StorageManager;
     71 import android.text.TextUtils;
     72 import android.util.ArraySet;
     73 import android.util.AtomicFile;
     74 import android.util.AttributeSet;
     75 import android.util.Pair;
     76 import android.util.Slog;
     77 import android.util.SparseArray;
     78 import android.util.SparseIntArray;
     79 import android.util.TypedValue;
     80 import android.util.Xml;
     81 import android.view.Display;
     82 import android.view.View;
     83 import android.view.WindowManager;
     84 import android.widget.RemoteViews;
     85 
     86 import com.android.internal.R;
     87 import com.android.internal.app.UnlaunchableAppActivity;
     88 import com.android.internal.appwidget.IAppWidgetHost;
     89 import com.android.internal.appwidget.IAppWidgetService;
     90 import com.android.internal.os.BackgroundThread;
     91 import com.android.internal.os.SomeArgs;
     92 import com.android.internal.util.FastXmlSerializer;
     93 import com.android.internal.widget.IRemoteViewsAdapterConnection;
     94 import com.android.internal.widget.IRemoteViewsFactory;
     95 import com.android.server.LocalServices;
     96 import com.android.server.WidgetBackupProvider;
     97 import com.android.server.policy.IconUtilities;
     98 
     99 import libcore.io.IoUtils;
    100 
    101 import org.xmlpull.v1.XmlPullParser;
    102 import org.xmlpull.v1.XmlPullParserException;
    103 import org.xmlpull.v1.XmlSerializer;
    104 
    105 import java.io.ByteArrayInputStream;
    106 import java.io.ByteArrayOutputStream;
    107 import java.io.File;
    108 import java.io.FileDescriptor;
    109 import java.io.FileInputStream;
    110 import java.io.FileNotFoundException;
    111 import java.io.FileOutputStream;
    112 import java.io.IOException;
    113 import java.io.PrintWriter;
    114 import java.nio.charset.StandardCharsets;
    115 import java.util.ArrayList;
    116 import java.util.Arrays;
    117 import java.util.Collections;
    118 import java.util.HashMap;
    119 import java.util.HashSet;
    120 import java.util.Iterator;
    121 import java.util.List;
    122 import java.util.Locale;
    123 import java.util.Map;
    124 import java.util.Set;
    125 
    126 class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider,
    127         OnCrossProfileWidgetProvidersChangeListener {
    128     private static final String TAG = "AppWidgetServiceImpl";
    129 
    130     private static boolean DEBUG = false;
    131 
    132     private static final String OLD_KEYGUARD_HOST_PACKAGE = "android";
    133     private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
    134     private static final int KEYGUARD_HOST_ID = 0x4b455947;
    135 
    136     private static final String STATE_FILENAME = "appwidgets.xml";
    137 
    138     private static final int MIN_UPDATE_PERIOD = DEBUG ? 0 : 30 * 60 * 1000; // 30 minutes
    139 
    140     private static final int TAG_UNDEFINED = -1;
    141 
    142     private static final int UNKNOWN_UID = -1;
    143 
    144     private static final int LOADED_PROFILE_ID = -1;
    145 
    146     private static final int UNKNOWN_USER_ID = -10;
    147 
    148     // Bump if the stored widgets need to be upgraded.
    149     private static final int CURRENT_VERSION = 1;
    150 
    151     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    152         @Override
    153         public void onReceive(Context context, Intent intent) {
    154             final String action = intent.getAction();
    155             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
    156 
    157             if (DEBUG) {
    158                 Slog.i(TAG, "Received broadcast: " + action + " on user " + userId);
    159             }
    160 
    161             if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
    162                 onConfigurationChanged();
    163             } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
    164                     || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
    165                 synchronized (mLock) {
    166                     reloadWidgetsMaskedState(userId);
    167                 }
    168             } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
    169                 String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
    170                 updateWidgetPackageSuspensionMaskedState(packages, true, getSendingUserId());
    171             } else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) {
    172                 String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
    173                 updateWidgetPackageSuspensionMaskedState(packages, false, getSendingUserId());
    174             } else {
    175                 onPackageBroadcastReceived(intent, userId);
    176             }
    177         }
    178     };
    179 
    180     // Manages active connections to RemoteViewsServices.
    181     private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection>
    182             mBoundRemoteViewsServices = new HashMap<>();
    183 
    184     // Manages persistent references to RemoteViewsServices from different App Widgets.
    185     private final HashMap<Pair<Integer, FilterComparison>, HashSet<Integer>>
    186             mRemoteViewsServicesAppWidgets = new HashMap<>();
    187 
    188     private final Object mLock = new Object();
    189 
    190     private final ArrayList<Widget> mWidgets = new ArrayList<>();
    191     private final ArrayList<Host> mHosts = new ArrayList<>();
    192     private final ArrayList<Provider> mProviders = new ArrayList<>();
    193 
    194     private final ArraySet<Pair<Integer, String>> mPackagesWithBindWidgetPermission =
    195             new ArraySet<>();
    196 
    197     private final SparseIntArray mLoadedUserIds = new SparseIntArray();
    198 
    199     private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
    200 
    201     private final BackupRestoreController mBackupRestoreController;
    202 
    203     private final Context mContext;
    204 
    205     private final IPackageManager mPackageManager;
    206     private final AlarmManager mAlarmManager;
    207     private final UserManager mUserManager;
    208     private final AppOpsManager mAppOpsManager;
    209     private final KeyguardManager mKeyguardManager;
    210     private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
    211 
    212     private final SecurityPolicy mSecurityPolicy;
    213 
    214     private final Handler mSaveStateHandler;
    215     private final Handler mCallbackHandler;
    216 
    217     private Locale mLocale;
    218 
    219     private final SparseIntArray mNextAppWidgetIds = new SparseIntArray();
    220 
    221     private boolean mSafeMode;
    222     private int mMaxWidgetBitmapMemory;
    223 
    224     private final IconUtilities mIconUtilities;
    225 
    226     AppWidgetServiceImpl(Context context) {
    227         mContext = context;
    228         mPackageManager = AppGlobals.getPackageManager();
    229         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
    230         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    231         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    232         mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
    233         mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
    234         mSaveStateHandler = BackgroundThread.getHandler();
    235         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
    236         mBackupRestoreController = new BackupRestoreController();
    237         mSecurityPolicy = new SecurityPolicy();
    238         mIconUtilities = new IconUtilities(context);
    239 
    240         computeMaximumWidgetBitmapMemory();
    241         registerBroadcastReceiver();
    242         registerOnCrossProfileProvidersChangedListener();
    243     }
    244 
    245     private void computeMaximumWidgetBitmapMemory() {
    246         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    247         Display display = wm.getDefaultDisplay();
    248         Point size = new Point();
    249         display.getRealSize(size);
    250         // Cap memory usage at 1.5 times the size of the display
    251         // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
    252         mMaxWidgetBitmapMemory = 6 * size.x * size.y;
    253     }
    254 
    255     private void registerBroadcastReceiver() {
    256         // Register for configuration changes so we can update the names
    257         // of the widgets when the locale changes.
    258         IntentFilter configFilter = new IntentFilter();
    259         configFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
    260         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
    261                 configFilter, null, null);
    262 
    263         // Register for broadcasts about package install, etc., so we can
    264         // update the provider list.
    265         IntentFilter packageFilter = new IntentFilter();
    266         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
    267         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
    268         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    269         packageFilter.addDataScheme("package");
    270         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
    271                 packageFilter, null, null);
    272 
    273         // Register for events related to sdcard installation.
    274         IntentFilter sdFilter = new IntentFilter();
    275         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
    276         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    277         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
    278                 sdFilter, null, null);
    279 
    280         IntentFilter offModeFilter = new IntentFilter();
    281         offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
    282         offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
    283         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
    284                 offModeFilter, null, null);
    285 
    286         IntentFilter suspendPackageFilter = new IntentFilter();
    287         suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
    288         suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
    289         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
    290                 suspendPackageFilter, null, null);
    291     }
    292 
    293     private void registerOnCrossProfileProvidersChangedListener() {
    294         // The device policy is an optional component.
    295         if (mDevicePolicyManagerInternal != null) {
    296             mDevicePolicyManagerInternal.addOnCrossProfileWidgetProvidersChangeListener(this);
    297         }
    298     }
    299 
    300     public void setSafeMode(boolean safeMode) {
    301         mSafeMode = safeMode;
    302     }
    303 
    304     private void onConfigurationChanged() {
    305         if (DEBUG) {
    306             Slog.i(TAG, "onConfigurationChanged()");
    307         }
    308 
    309         Locale revised = Locale.getDefault();
    310         if (revised == null || mLocale == null || !revised.equals(mLocale)) {
    311             mLocale = revised;
    312 
    313             synchronized (mLock) {
    314                 SparseIntArray changedGroups = null;
    315 
    316                 // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
    317                 // list of installed providers and skip providers that we don't need to update.
    318                 // Also note that remove the provider does not clear the Provider component data.
    319                 ArrayList<Provider> installedProviders = new ArrayList<>(mProviders);
    320                 HashSet<ProviderId> removedProviders = new HashSet<>();
    321 
    322                 int N = installedProviders.size();
    323                 for (int i = N - 1; i >= 0; i--) {
    324                     Provider provider = installedProviders.get(i);
    325 
    326                     final int userId = provider.getUserId();
    327                     if (!mUserManager.isUserUnlockingOrUnlocked(userId) ||
    328                             isProfileWithLockedParent(userId)) {
    329                         continue;
    330                     }
    331                     ensureGroupStateLoadedLocked(userId);
    332 
    333                     if (!removedProviders.contains(provider.id)) {
    334                         final boolean changed = updateProvidersForPackageLocked(
    335                                 provider.id.componentName.getPackageName(),
    336                                 provider.getUserId(), removedProviders);
    337 
    338                         if (changed) {
    339                             if (changedGroups == null) {
    340                                 changedGroups = new SparseIntArray();
    341                             }
    342                             final int groupId = mSecurityPolicy.getGroupParent(
    343                                     provider.getUserId());
    344                             changedGroups.put(groupId, groupId);
    345                         }
    346                     }
    347                 }
    348 
    349                 if (changedGroups != null) {
    350                     final int groupCount = changedGroups.size();
    351                     for (int i = 0; i < groupCount; i++) {
    352                         final int groupId = changedGroups.get(i);
    353                         saveGroupStateAsync(groupId);
    354                     }
    355                 }
    356             }
    357         }
    358     }
    359 
    360     private void onPackageBroadcastReceived(Intent intent, int userId) {
    361         if (!mUserManager.isUserUnlockingOrUnlocked(userId) ||
    362                 isProfileWithLockedParent(userId)) {
    363             return;
    364         }
    365 
    366         final String action = intent.getAction();
    367         boolean added = false;
    368         boolean changed = false;
    369         boolean componentsModified = false;
    370 
    371         String pkgList[] = null;
    372         if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
    373             pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
    374             added = true;
    375         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
    376             pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
    377             added = false;
    378         } else {
    379             Uri uri = intent.getData();
    380             if (uri == null) {
    381                 return;
    382             }
    383             String pkgName = uri.getSchemeSpecificPart();
    384             if (pkgName == null) {
    385                 return;
    386             }
    387             pkgList = new String[] { pkgName };
    388             added = Intent.ACTION_PACKAGE_ADDED.equals(action);
    389             changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
    390         }
    391         if (pkgList == null || pkgList.length == 0) {
    392             return;
    393         }
    394 
    395         synchronized (mLock) {
    396             ensureGroupStateLoadedLocked(userId);
    397 
    398             Bundle extras = intent.getExtras();
    399 
    400             if (added || changed) {
    401                 final boolean newPackageAdded = added && (extras == null
    402                         || !extras.getBoolean(Intent.EXTRA_REPLACING, false));
    403 
    404                 for (String pkgName : pkgList) {
    405                     // Fix up the providers - add/remove/update.
    406                     componentsModified |= updateProvidersForPackageLocked(pkgName, userId, null);
    407 
    408                     // ... and see if these are hosts we've been awaiting.
    409                     // NOTE: We are backing up and restoring only the owner.
    410                     // TODO: http://b/22388012
    411                     if (newPackageAdded && userId == UserHandle.USER_SYSTEM) {
    412                         final int uid = getUidForPackage(pkgName, userId);
    413                         if (uid >= 0 ) {
    414                             resolveHostUidLocked(pkgName, uid);
    415                         }
    416                     }
    417                 }
    418             } else {
    419                 // If the package is being updated, we'll receive a PACKAGE_ADDED
    420                 // shortly, otherwise it is removed permanently.
    421                 final boolean packageRemovedPermanently = (extras == null
    422                         || !extras.getBoolean(Intent.EXTRA_REPLACING, false));
    423 
    424                 if (packageRemovedPermanently) {
    425                     for (String pkgName : pkgList) {
    426                         componentsModified |= removeHostsAndProvidersForPackageLocked(
    427                                 pkgName, userId);
    428                     }
    429                 }
    430             }
    431 
    432             if (componentsModified) {
    433                 saveGroupStateAsync(userId);
    434 
    435                 // If the set of providers has been modified, notify each active AppWidgetHost
    436                 scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
    437             }
    438         }
    439     }
    440 
    441     /**
    442      * Reload all widgets' masked state for the given user and its associated profiles, including
    443      * due to user not being available and package suspension.
    444      * userId must be the group parent.
    445      */
    446     void reloadWidgetsMaskedStateForGroup(int userId) {
    447         if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
    448             return;
    449         }
    450         synchronized (mLock) {
    451             reloadWidgetsMaskedState(userId);
    452             int[] profileIds = mUserManager.getEnabledProfileIds(userId);
    453             for (int profileId : profileIds) {
    454                 reloadWidgetsMaskedState(profileId);
    455             }
    456         }
    457     }
    458 
    459     private void reloadWidgetsMaskedState(int userId) {
    460         final long identity = Binder.clearCallingIdentity();
    461         try {
    462             UserInfo user  = mUserManager.getUserInfo(userId);
    463 
    464             boolean lockedProfile = !mUserManager.isUserUnlockingOrUnlocked(userId);
    465             boolean quietProfile = user.isQuietModeEnabled();
    466             final int N = mProviders.size();
    467             for (int i = 0; i < N; i++) {
    468                 Provider provider = mProviders.get(i);
    469                 int providerUserId = provider.getUserId();
    470                 if (providerUserId != userId) {
    471                     continue;
    472                 }
    473 
    474                 boolean changed = provider.setMaskedByLockedProfileLocked(lockedProfile);
    475                 changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
    476                 try {
    477                     boolean suspended;
    478                     try {
    479                         suspended = mPackageManager.isPackageSuspendedForUser(
    480                                 provider.info.provider.getPackageName(), provider.getUserId());
    481                     } catch (IllegalArgumentException ex) {
    482                         // Package not found.
    483                         suspended = false;
    484                     }
    485                     changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
    486                 } catch (RemoteException e) {
    487                     Slog.e(TAG, "Failed to query application info", e);
    488                 }
    489                 if (changed) {
    490                     if (provider.isMaskedLocked()) {
    491                         maskWidgetsViewsLocked(provider, null);
    492                     } else {
    493                         unmaskWidgetsViewsLocked(provider);
    494                     }
    495                 }
    496             }
    497         } finally {
    498             Binder.restoreCallingIdentity(identity);
    499         }
    500     }
    501 
    502     /**
    503      * Incrementally update the masked state due to package suspension state.
    504      */
    505     private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
    506             int profileId) {
    507         if (packagesArray == null) {
    508             return;
    509         }
    510         Set<String> packages = new ArraySet<String>(Arrays.asList(packagesArray));
    511         synchronized (mLock) {
    512             final int N = mProviders.size();
    513             for (int i = 0; i < N; i++) {
    514                 Provider provider = mProviders.get(i);
    515                 int providerUserId = provider.getUserId();
    516                 if (providerUserId != profileId
    517                         || !packages.contains(provider.info.provider.getPackageName())) {
    518                     continue;
    519                 }
    520                 if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
    521                     if (provider.isMaskedLocked()) {
    522                         maskWidgetsViewsLocked(provider, null);
    523                     } else {
    524                         unmaskWidgetsViewsLocked(provider);
    525                     }
    526                 }
    527             }
    528         }
    529     }
    530 
    531     private Bitmap createMaskedWidgetBitmap(String providerPackage, int providerUserId) {
    532         final long identity = Binder.clearCallingIdentity();
    533         try {
    534             // Load the unbadged application icon and pass it to the widget to appear on
    535             // the masked view.
    536             Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
    537                     UserHandle.of(providerUserId));
    538             PackageManager pm = userContext.getPackageManager();
    539             Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
    540             // Create a bitmap of the icon which is what the widget's remoteview requires.
    541             return mIconUtilities.createIconBitmap(icon);
    542         } catch (NameNotFoundException e) {
    543             Slog.e(TAG, "Fail to get application icon", e);
    544             // Provider package removed, no need to mask its views as its state will be
    545             // purged very soon.
    546             return null;
    547         } finally {
    548             Binder.restoreCallingIdentity(identity);
    549         }
    550     }
    551 
    552     private RemoteViews createMaskedWidgetRemoteViews(Bitmap icon, boolean showBadge,
    553             PendingIntent onClickIntent) {
    554         RemoteViews views = new RemoteViews(mContext.getPackageName(),
    555                 R.layout.work_widget_mask_view);
    556         if (icon != null) {
    557             views.setImageViewBitmap(R.id.work_widget_app_icon, icon);
    558         }
    559         if (!showBadge) {
    560             views.setViewVisibility(R.id.work_widget_badge_icon, View.INVISIBLE);
    561         }
    562         if (onClickIntent != null) {
    563             views.setOnClickPendingIntent(R.id.work_widget_mask_frame, onClickIntent);
    564         }
    565         return views;
    566     }
    567 
    568     /**
    569      * Mask the target widget belonging to the specified provider, or all active widgets
    570      * of the provider if target widget == null.
    571      */
    572     private void maskWidgetsViewsLocked(Provider provider, Widget targetWidget) {
    573         final int widgetCount = provider.widgets.size();
    574         if (widgetCount == 0) {
    575             return;
    576         }
    577         final String providerPackage = provider.info.provider.getPackageName();
    578         final int providerUserId = provider.getUserId();
    579         Bitmap iconBitmap = createMaskedWidgetBitmap(providerPackage, providerUserId);
    580         if (iconBitmap == null) {
    581             return;
    582         }
    583         final boolean showBadge;
    584         final Intent onClickIntent;
    585         final long identity = Binder.clearCallingIdentity();
    586         try {
    587             if (provider.maskedBySuspendedPackage) {
    588                 UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
    589                 showBadge = userInfo.isManagedProfile();
    590                 onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent(
    591                         providerPackage, providerUserId);
    592             } else if (provider.maskedByQuietProfile) {
    593                 showBadge = true;
    594                 onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
    595                         providerUserId);
    596             } else /* provider.maskedByLockedProfile */ {
    597                 showBadge = true;
    598                 onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
    599                         providerUserId);
    600                 if (onClickIntent != null) {
    601                     onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK
    602                             | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    603                 }
    604             }
    605             for (int j = 0; j < widgetCount; j++) {
    606                 Widget widget = provider.widgets.get(j);
    607                 if (targetWidget != null && targetWidget != widget) continue;
    608                 PendingIntent intent = null;
    609                 if (onClickIntent != null) {
    610                     intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
    611                             onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    612                 }
    613                 RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
    614                 if (widget.replaceWithMaskedViewsLocked(views)) {
    615                     scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
    616                 }
    617             }
    618         } finally {
    619             Binder.restoreCallingIdentity(identity);
    620         }
    621     }
    622 
    623     private void unmaskWidgetsViewsLocked(Provider provider) {
    624         final int widgetCount = provider.widgets.size();
    625         for (int j = 0; j < widgetCount; j++) {
    626             Widget widget = provider.widgets.get(j);
    627             if (widget.clearMaskedViewsLocked()) {
    628                 scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
    629             }
    630         }
    631     }
    632 
    633     private void resolveHostUidLocked(String pkg, int uid) {
    634         final int N = mHosts.size();
    635         for (int i = 0; i < N; i++) {
    636             Host host = mHosts.get(i);
    637             if (host.id.uid == UNKNOWN_UID && pkg.equals(host.id.packageName)) {
    638                 if (DEBUG) {
    639                     Slog.i(TAG, "host " + host.id + " resolved to uid " + uid);
    640                 }
    641                 host.id = new HostId(uid, host.id.hostId, host.id.packageName);
    642                 return;
    643             }
    644         }
    645     }
    646 
    647     private void ensureGroupStateLoadedLocked(int userId) {
    648         ensureGroupStateLoadedLocked(userId, /* enforceUserUnlockingOrUnlocked */ true );
    649     }
    650 
    651     private void ensureGroupStateLoadedLocked(int userId, boolean enforceUserUnlockingOrUnlocked) {
    652         if (enforceUserUnlockingOrUnlocked && !isUserRunningAndUnlocked(userId)) {
    653             throw new IllegalStateException(
    654                     "User " + userId + " must be unlocked for widgets to be available");
    655         }
    656         if (enforceUserUnlockingOrUnlocked && isProfileWithLockedParent(userId)) {
    657             throw new IllegalStateException(
    658                     "Profile " + userId + " must have unlocked parent");
    659         }
    660         final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
    661 
    662         // Careful lad, we may have already loaded the state for some
    663         // group members, so check before loading and read only the
    664         // state for the new member(s).
    665         int newMemberCount = 0;
    666         final int profileIdCount = profileIds.length;
    667         for (int i = 0; i < profileIdCount; i++) {
    668             final int profileId = profileIds[i];
    669             if (mLoadedUserIds.indexOfKey(profileId) >= 0) {
    670                 profileIds[i] = LOADED_PROFILE_ID;
    671             } else {
    672                 newMemberCount++;
    673             }
    674         }
    675 
    676         if (newMemberCount <= 0) {
    677             return;
    678         }
    679 
    680         int newMemberIndex = 0;
    681         final int[] newProfileIds = new int[newMemberCount];
    682         for (int i = 0; i < profileIdCount; i++) {
    683             final int profileId = profileIds[i];
    684             if (profileId != LOADED_PROFILE_ID) {
    685                 mLoadedUserIds.put(profileId, profileId);
    686                 newProfileIds[newMemberIndex] = profileId;
    687                 newMemberIndex++;
    688             }
    689         }
    690 
    691         clearProvidersAndHostsTagsLocked();
    692 
    693         loadGroupWidgetProvidersLocked(newProfileIds);
    694         loadGroupStateLocked(newProfileIds);
    695     }
    696 
    697     private boolean isUserRunningAndUnlocked(@UserIdInt int userId) {
    698         return mUserManager.isUserRunning(userId) && StorageManager.isUserKeyUnlocked(userId);
    699     }
    700 
    701     @Override
    702     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    703         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
    704                                                 "Permission Denial: can't dump from from pid="
    705                                                 + Binder.getCallingPid()
    706                                                 + ", uid=" + Binder.getCallingUid());
    707 
    708         synchronized (mLock) {
    709             int N = mProviders.size();
    710             pw.println("Providers:");
    711             for (int i = 0; i < N; i++) {
    712                 dumpProvider(mProviders.get(i), i, pw);
    713             }
    714 
    715             N = mWidgets.size();
    716             pw.println(" ");
    717             pw.println("Widgets:");
    718             for (int i = 0; i < N; i++) {
    719                 dumpWidget(mWidgets.get(i), i, pw);
    720             }
    721 
    722             N = mHosts.size();
    723             pw.println(" ");
    724             pw.println("Hosts:");
    725             for (int i = 0; i < N; i++) {
    726                 dumpHost(mHosts.get(i), i, pw);
    727             }
    728 
    729 
    730             N = mPackagesWithBindWidgetPermission.size();
    731             pw.println(" ");
    732             pw.println("Grants:");
    733             for (int i = 0; i < N; i++) {
    734                 Pair<Integer, String> grant = mPackagesWithBindWidgetPermission.valueAt(i);
    735                 dumpGrant(grant, i, pw);
    736             }
    737         }
    738     }
    739 
    740     @Override
    741     public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
    742             String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
    743         final int userId = UserHandle.getCallingUserId();
    744 
    745         if (DEBUG) {
    746             Slog.i(TAG, "startListening() " + userId);
    747         }
    748 
    749         // Make sure the package runs under the caller uid.
    750         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    751 
    752         synchronized (mLock) {
    753             ensureGroupStateLoadedLocked(userId);
    754 
    755             // NOTE: The lookup is enforcing security across users by making
    756             // sure the caller can only access hosts it owns.
    757             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
    758             Host host = lookupOrAddHostLocked(id);
    759             host.callbacks = callbacks;
    760 
    761             int N = appWidgetIds.length;
    762             ArrayList<RemoteViews> outViews = new ArrayList<>(N);
    763             RemoteViews rv;
    764             int added = 0;
    765             for (int i = 0; i < N; i++) {
    766                 rv = host.getPendingViewsForId(appWidgetIds[i]);
    767                 if (rv != null) {
    768                     updatedIds[added] = appWidgetIds[i];
    769                     outViews.add(rv);
    770                     added++;
    771                 }
    772             }
    773             return new ParceledListSlice<>(outViews);
    774         }
    775     }
    776 
    777     @Override
    778     public void stopListening(String callingPackage, int hostId) {
    779         final int userId = UserHandle.getCallingUserId();
    780 
    781         if (DEBUG) {
    782             Slog.i(TAG, "stopListening() " + userId);
    783         }
    784 
    785         // Make sure the package runs under the caller uid.
    786         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    787 
    788         synchronized (mLock) {
    789             ensureGroupStateLoadedLocked(userId);
    790 
    791             // NOTE: The lookup is enforcing security across users by making
    792             // sure the caller can only access hosts it owns.
    793             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
    794             Host host = lookupHostLocked(id);
    795 
    796             if (host != null) {
    797                 host.callbacks = null;
    798                 pruneHostLocked(host);
    799             }
    800         }
    801     }
    802 
    803     @Override
    804     public int allocateAppWidgetId(String callingPackage, int hostId) {
    805         final int userId = UserHandle.getCallingUserId();
    806 
    807         if (DEBUG) {
    808             Slog.i(TAG, "allocateAppWidgetId() " + userId);
    809         }
    810 
    811         // Make sure the package runs under the caller uid.
    812         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    813 
    814         synchronized (mLock) {
    815             ensureGroupStateLoadedLocked(userId);
    816 
    817             if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
    818                 mNextAppWidgetIds.put(userId, AppWidgetManager.INVALID_APPWIDGET_ID + 1);
    819             }
    820 
    821             final int appWidgetId = incrementAndGetAppWidgetIdLocked(userId);
    822 
    823             // NOTE: The lookup is enforcing security across users by making
    824             // sure the caller can only access hosts it owns.
    825             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
    826             Host host = lookupOrAddHostLocked(id);
    827 
    828             Widget widget = new Widget();
    829             widget.appWidgetId = appWidgetId;
    830             widget.host = host;
    831 
    832             host.widgets.add(widget);
    833             addWidgetLocked(widget);
    834 
    835             saveGroupStateAsync(userId);
    836 
    837             if (DEBUG) {
    838                 Slog.i(TAG, "Allocated widget id " + appWidgetId
    839                         + " for host " + host.id);
    840             }
    841 
    842             return appWidgetId;
    843         }
    844     }
    845 
    846     @Override
    847     public void deleteAppWidgetId(String callingPackage, int appWidgetId) {
    848         final int userId = UserHandle.getCallingUserId();
    849 
    850         if (DEBUG) {
    851             Slog.i(TAG, "deleteAppWidgetId() " + userId);
    852         }
    853 
    854         // Make sure the package runs under the caller uid.
    855         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    856 
    857         synchronized (mLock) {
    858             ensureGroupStateLoadedLocked(userId);
    859 
    860             // NOTE: The lookup is enforcing security across users by making
    861             // sure the caller can only access widgets it hosts or provides.
    862             Widget widget = lookupWidgetLocked(appWidgetId,
    863                     Binder.getCallingUid(), callingPackage);
    864 
    865             if (widget == null) {
    866                 return;
    867             }
    868 
    869             deleteAppWidgetLocked(widget);
    870 
    871             saveGroupStateAsync(userId);
    872 
    873             if (DEBUG) {
    874                 Slog.i(TAG, "Deleted widget id " + appWidgetId
    875                         + " for host " + widget.host.id);
    876             }
    877         }
    878     }
    879 
    880     @Override
    881     public boolean hasBindAppWidgetPermission(String packageName, int grantId) {
    882         if (DEBUG) {
    883             Slog.i(TAG, "hasBindAppWidgetPermission() " + UserHandle.getCallingUserId());
    884         }
    885 
    886         // A special permission is required for managing white listing.
    887         mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName);
    888 
    889         synchronized (mLock) {
    890             // The grants are stored in user state wich gets the grant.
    891             ensureGroupStateLoadedLocked(grantId);
    892 
    893             final int packageUid = getUidForPackage(packageName, grantId);
    894             if (packageUid < 0) {
    895                 return false;
    896             }
    897 
    898             Pair<Integer, String> packageId = Pair.create(grantId, packageName);
    899             return mPackagesWithBindWidgetPermission.contains(packageId);
    900         }
    901     }
    902 
    903     @Override
    904     public void setBindAppWidgetPermission(String packageName, int grantId,
    905             boolean grantPermission) {
    906         if (DEBUG) {
    907             Slog.i(TAG, "setBindAppWidgetPermission() " + UserHandle.getCallingUserId());
    908         }
    909 
    910         // A special permission is required for managing white listing.
    911         mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName);
    912 
    913         synchronized (mLock) {
    914             // The grants are stored in user state wich gets the grant.
    915             ensureGroupStateLoadedLocked(grantId);
    916 
    917             final int packageUid = getUidForPackage(packageName, grantId);
    918             if (packageUid < 0) {
    919                 return;
    920             }
    921 
    922             Pair<Integer, String> packageId = Pair.create(grantId, packageName);
    923             if (grantPermission) {
    924                 mPackagesWithBindWidgetPermission.add(packageId);
    925             } else {
    926                 mPackagesWithBindWidgetPermission.remove(packageId);
    927             }
    928 
    929             saveGroupStateAsync(grantId);
    930         }
    931     }
    932 
    933     @Override
    934     public IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId,
    935             final int intentFlags) {
    936         final int userId = UserHandle.getCallingUserId();
    937 
    938         if (DEBUG) {
    939             Slog.i(TAG, "createAppWidgetConfigIntentSender() " + userId);
    940         }
    941 
    942         // Make sure the package runs under the caller uid.
    943         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    944 
    945         synchronized (mLock) {
    946             ensureGroupStateLoadedLocked(userId);
    947 
    948             // NOTE: The lookup is enforcing security across users by making
    949             // sure the caller can only access widgets it hosts or provides.
    950             Widget widget = lookupWidgetLocked(appWidgetId,
    951                     Binder.getCallingUid(), callingPackage);
    952 
    953             if (widget == null) {
    954                 throw new IllegalArgumentException("Bad widget id " + appWidgetId);
    955             }
    956 
    957             Provider provider = widget.provider;
    958             if (provider == null) {
    959                 throw new IllegalArgumentException("Widget not bound " + appWidgetId);
    960             }
    961 
    962             // Make sure only safe flags can be passed it.
    963             final int secureFlags = intentFlags & ~Intent.IMMUTABLE_FLAGS;
    964 
    965             Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
    966             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    967             intent.setComponent(provider.info.configure);
    968             intent.setFlags(secureFlags);
    969 
    970             // All right, create the sender.
    971             final long identity = Binder.clearCallingIdentity();
    972             try {
    973                 return PendingIntent.getActivityAsUser(
    974                         mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
    975                                 | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
    976                                 null, new UserHandle(provider.getUserId()))
    977                         .getIntentSender();
    978             } finally {
    979                 Binder.restoreCallingIdentity(identity);
    980             }
    981         }
    982     }
    983 
    984     @Override
    985     public boolean bindAppWidgetId(String callingPackage, int appWidgetId,
    986             int providerProfileId, ComponentName providerComponent, Bundle options) {
    987         final int userId = UserHandle.getCallingUserId();
    988 
    989         if (DEBUG) {
    990             Slog.i(TAG, "bindAppWidgetId() " + userId);
    991         }
    992 
    993         // Make sure the package runs under the caller uid.
    994         mSecurityPolicy.enforceCallFromPackage(callingPackage);
    995 
    996         // Check that if a cross-profile binding is attempted, it is allowed.
    997         if (!mSecurityPolicy.isEnabledGroupProfile(providerProfileId)) {
    998             return false;
    999         }
   1000 
   1001         // If the provider is not under the calling user, make sure this
   1002         // provider is white listed for access from the parent.
   1003         if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
   1004                 providerComponent.getPackageName(), providerProfileId)) {
   1005             return false;
   1006         }
   1007 
   1008         synchronized (mLock) {
   1009             ensureGroupStateLoadedLocked(userId);
   1010 
   1011             // A special permission or white listing is required to bind widgets.
   1012             if (!mSecurityPolicy.hasCallerBindPermissionOrBindWhiteListedLocked(
   1013                     callingPackage)) {
   1014                 return false;
   1015             }
   1016 
   1017             // NOTE: The lookup is enforcing security across users by making
   1018             // sure the caller can only access widgets it hosts or provides.
   1019             Widget widget = lookupWidgetLocked(appWidgetId,
   1020                     Binder.getCallingUid(), callingPackage);
   1021 
   1022             if (widget == null) {
   1023                 Slog.e(TAG, "Bad widget id " + appWidgetId);
   1024                 return false;
   1025             }
   1026 
   1027             if (widget.provider != null) {
   1028                 Slog.e(TAG, "Widget id " + appWidgetId
   1029                         + " already bound to: " + widget.provider.id);
   1030                 return false;
   1031             }
   1032 
   1033             final int providerUid = getUidForPackage(providerComponent.getPackageName(),
   1034                     providerProfileId);
   1035             if (providerUid < 0) {
   1036                 Slog.e(TAG, "Package " + providerComponent.getPackageName() + " not installed "
   1037                         + " for profile " + providerProfileId);
   1038                 return false;
   1039             }
   1040 
   1041             // NOTE: The lookup is enforcing security across users by making
   1042             // sure the provider is in the already vetted user profile.
   1043             ProviderId providerId = new ProviderId(providerUid, providerComponent);
   1044             Provider provider = lookupProviderLocked(providerId);
   1045 
   1046             if (provider == null) {
   1047                 Slog.e(TAG, "No widget provider " + providerComponent + " for profile "
   1048                         + providerProfileId);
   1049                 return false;
   1050             }
   1051 
   1052             if (provider.zombie) {
   1053                 Slog.e(TAG, "Can't bind to a 3rd party provider in"
   1054                         + " safe mode " + provider);
   1055                 return false;
   1056             }
   1057 
   1058             widget.provider = provider;
   1059             widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle();
   1060 
   1061             // We need to provide a default value for the widget category if it is not specified
   1062             if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
   1063                 widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
   1064                         AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
   1065             }
   1066 
   1067             provider.widgets.add(widget);
   1068 
   1069             onWidgetProviderAddedOrChangedLocked(widget);
   1070 
   1071             final int widgetCount = provider.widgets.size();
   1072             if (widgetCount == 1) {
   1073                 // Tell the provider that it's ready.
   1074                 sendEnableIntentLocked(provider);
   1075             }
   1076 
   1077             // Send an update now -- We need this update now, and just for this appWidgetId.
   1078             // It's less critical when the next one happens, so when we schedule the next one,
   1079             // we add updatePeriodMillis to its start time. That time will have some slop,
   1080             // but that's okay.
   1081             sendUpdateIntentLocked(provider, new int[] {appWidgetId});
   1082 
   1083             // Schedule the future updates.
   1084             registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets));
   1085 
   1086             saveGroupStateAsync(userId);
   1087 
   1088             if (DEBUG) {
   1089                 Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
   1090             }
   1091         }
   1092 
   1093         return true;
   1094     }
   1095 
   1096     @Override
   1097     public int[] getAppWidgetIds(ComponentName componentName) {
   1098         final int userId = UserHandle.getCallingUserId();
   1099 
   1100         if (DEBUG) {
   1101             Slog.i(TAG, "getAppWidgetIds() " + userId);
   1102         }
   1103 
   1104         // Make sure the package runs under the caller uid.
   1105         mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName());
   1106 
   1107         synchronized (mLock) {
   1108             ensureGroupStateLoadedLocked(userId);
   1109 
   1110             // NOTE: The lookup is enforcing security across users by making
   1111             // sure the caller can access only its providers.
   1112             ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName);
   1113             Provider provider = lookupProviderLocked(providerId);
   1114 
   1115             if (provider != null) {
   1116                 return getWidgetIds(provider.widgets);
   1117             }
   1118 
   1119             return new int[0];
   1120         }
   1121     }
   1122 
   1123     @Override
   1124     public int[] getAppWidgetIdsForHost(String callingPackage, int hostId) {
   1125         final int userId = UserHandle.getCallingUserId();
   1126 
   1127         if (DEBUG) {
   1128             Slog.i(TAG, "getAppWidgetIdsForHost() " + userId);
   1129         }
   1130 
   1131         // Make sure the package runs under the caller uid.
   1132         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1133 
   1134         synchronized (mLock) {
   1135             ensureGroupStateLoadedLocked(userId);
   1136 
   1137             // NOTE: The lookup is enforcing security across users by making
   1138             // sure the caller can only access its hosts.
   1139             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
   1140             Host host = lookupHostLocked(id);
   1141 
   1142             if (host != null) {
   1143                 return getWidgetIds(host.widgets);
   1144             }
   1145 
   1146             return new int[0];
   1147         }
   1148     }
   1149 
   1150     @Override
   1151     public void bindRemoteViewsService(String callingPackage, int appWidgetId,
   1152             Intent intent, IBinder callbacks) {
   1153         final int userId = UserHandle.getCallingUserId();
   1154 
   1155         if (DEBUG) {
   1156             Slog.i(TAG, "bindRemoteViewsService() " + userId);
   1157         }
   1158 
   1159         // Make sure the package runs under the caller uid.
   1160         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1161 
   1162         synchronized (mLock) {
   1163             ensureGroupStateLoadedLocked(userId);
   1164 
   1165             // NOTE: The lookup is enforcing security across users by making
   1166             // sure the caller can only access widgets it hosts or provides.
   1167             Widget widget = lookupWidgetLocked(appWidgetId,
   1168                     Binder.getCallingUid(), callingPackage);
   1169 
   1170             if (widget == null) {
   1171                 throw new IllegalArgumentException("Bad widget id");
   1172             }
   1173 
   1174             // Make sure the widget has a provider.
   1175             if (widget.provider == null) {
   1176                 throw new IllegalArgumentException("No provider for widget "
   1177                         + appWidgetId);
   1178             }
   1179 
   1180             ComponentName componentName = intent.getComponent();
   1181 
   1182             // Ensure that the service belongs to the same package as the provider.
   1183             // But this is not enough as they may be under different users - see below...
   1184             String providerPackage = widget.provider.id.componentName.getPackageName();
   1185             String servicePackage = componentName.getPackageName();
   1186             if (!servicePackage.equals(providerPackage)) {
   1187                 throw new SecurityException("The taget service not in the same package"
   1188                         + " as the widget provider");
   1189             }
   1190 
   1191             // Make sure this service exists under the same user as the provider and
   1192             // requires a permission which allows only the system to bind to it.
   1193             mSecurityPolicy.enforceServiceExistsAndRequiresBindRemoteViewsPermission(
   1194                     componentName, widget.provider.getUserId());
   1195 
   1196             // Good to go - the service pakcage is correct, it exists for the correct
   1197             // user, and requires the bind permission.
   1198 
   1199             // If there is already a connection made for this service intent, then
   1200             // disconnect from that first. (This does not allow multiple connections
   1201             // to the same service under the same key).
   1202             ServiceConnectionProxy connection = null;
   1203             FilterComparison fc = new FilterComparison(intent);
   1204             Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
   1205 
   1206             if (mBoundRemoteViewsServices.containsKey(key)) {
   1207                 connection = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
   1208                 connection.disconnect();
   1209                 unbindService(connection);
   1210                 mBoundRemoteViewsServices.remove(key);
   1211             }
   1212 
   1213             // Bind to the RemoteViewsService (which will trigger a callback to the
   1214             // RemoteViewsAdapter.onServiceConnected())
   1215             connection = new ServiceConnectionProxy(callbacks);
   1216             bindService(intent, connection, widget.provider.info.getProfile());
   1217             mBoundRemoteViewsServices.put(key, connection);
   1218 
   1219             // Add it to the mapping of RemoteViewsService to appWidgetIds so that we
   1220             // can determine when we can call back to the RemoteViewsService later to
   1221             // destroy associated factories.
   1222             Pair<Integer, FilterComparison> serviceId = Pair.create(widget.provider.id.uid, fc);
   1223             incrementAppWidgetServiceRefCount(appWidgetId, serviceId);
   1224         }
   1225     }
   1226 
   1227     @Override
   1228     public void unbindRemoteViewsService(String callingPackage, int appWidgetId, Intent intent) {
   1229         final int userId = UserHandle.getCallingUserId();
   1230 
   1231         if (DEBUG) {
   1232             Slog.i(TAG, "unbindRemoteViewsService() " + userId);
   1233         }
   1234 
   1235         // Make sure the package runs under the caller uid.
   1236         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1237 
   1238         synchronized (mLock) {
   1239             ensureGroupStateLoadedLocked(userId);
   1240 
   1241             // Unbind from the RemoteViewsService (which will trigger a callback to the bound
   1242             // RemoteViewsAdapter)
   1243             Pair<Integer, FilterComparison> key = Pair.create(appWidgetId,
   1244                     new FilterComparison(intent));
   1245             if (mBoundRemoteViewsServices.containsKey(key)) {
   1246                 // We don't need to use the appWidgetId until after we are sure there is something
   1247                 // to unbind. Note that this may mask certain issues with apps calling unbind()
   1248                 // more than necessary.
   1249 
   1250                 // NOTE: The lookup is enforcing security across users by making
   1251                 // sure the caller can only access widgets it hosts or provides.
   1252                 Widget widget = lookupWidgetLocked(appWidgetId,
   1253                         Binder.getCallingUid(), callingPackage);
   1254 
   1255                 if (widget == null) {
   1256                     throw new IllegalArgumentException("Bad widget id " + appWidgetId);
   1257                 }
   1258 
   1259                 ServiceConnectionProxy connection = (ServiceConnectionProxy)
   1260                         mBoundRemoteViewsServices.get(key);
   1261                 connection.disconnect();
   1262                 mContext.unbindService(connection);
   1263                 mBoundRemoteViewsServices.remove(key);
   1264             }
   1265         }
   1266     }
   1267 
   1268     @Override
   1269     public void deleteHost(String callingPackage, int hostId) {
   1270         final int userId = UserHandle.getCallingUserId();
   1271 
   1272         if (DEBUG) {
   1273             Slog.i(TAG, "deleteHost() " + userId);
   1274         }
   1275 
   1276         // Make sure the package runs under the caller uid.
   1277         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1278 
   1279         synchronized (mLock) {
   1280             ensureGroupStateLoadedLocked(userId);
   1281 
   1282             // NOTE: The lookup is enforcing security across users by making
   1283             // sure the caller can only access hosts in its uid and package.
   1284             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
   1285             Host host = lookupHostLocked(id);
   1286 
   1287             if (host == null) {
   1288                 return;
   1289             }
   1290 
   1291             deleteHostLocked(host);
   1292 
   1293             saveGroupStateAsync(userId);
   1294 
   1295             if (DEBUG) {
   1296                 Slog.i(TAG, "Deleted host " + host.id);
   1297             }
   1298         }
   1299     }
   1300 
   1301     @Override
   1302     public void deleteAllHosts() {
   1303         final int userId = UserHandle.getCallingUserId();
   1304 
   1305         if (DEBUG) {
   1306             Slog.i(TAG, "deleteAllHosts() " + userId);
   1307         }
   1308 
   1309         synchronized (mLock) {
   1310             ensureGroupStateLoadedLocked(userId);
   1311 
   1312             boolean changed = false;
   1313 
   1314             final int N = mHosts.size();
   1315             for (int i = N - 1; i >= 0; i--) {
   1316                 Host host = mHosts.get(i);
   1317 
   1318                 // Delete only hosts in the calling uid.
   1319                 if (host.id.uid == Binder.getCallingUid()) {
   1320                     deleteHostLocked(host);
   1321                     changed = true;
   1322 
   1323                     if (DEBUG) {
   1324                         Slog.i(TAG, "Deleted host " + host.id);
   1325                     }
   1326                 }
   1327             }
   1328 
   1329             if (changed) {
   1330                 saveGroupStateAsync(userId);
   1331             }
   1332         }
   1333     }
   1334 
   1335     @Override
   1336     public AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId) {
   1337         final int userId = UserHandle.getCallingUserId();
   1338 
   1339         if (DEBUG) {
   1340             Slog.i(TAG, "getAppWidgetInfo() " + userId);
   1341         }
   1342 
   1343         // Make sure the package runs under the caller uid.
   1344         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1345 
   1346         synchronized (mLock) {
   1347             ensureGroupStateLoadedLocked(userId);
   1348 
   1349             // NOTE: The lookup is enforcing security across users by making
   1350             // sure the caller can only access widgets it hosts or provides.
   1351             Widget widget = lookupWidgetLocked(appWidgetId,
   1352                     Binder.getCallingUid(), callingPackage);
   1353 
   1354             if (widget != null && widget.provider != null && !widget.provider.zombie) {
   1355                 return cloneIfLocalBinder(widget.provider.info);
   1356             }
   1357 
   1358             return null;
   1359         }
   1360     }
   1361 
   1362     @Override
   1363     public RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId) {
   1364         final int userId = UserHandle.getCallingUserId();
   1365 
   1366         if (DEBUG) {
   1367             Slog.i(TAG, "getAppWidgetViews() " + userId);
   1368         }
   1369 
   1370         // Make sure the package runs under the caller uid.
   1371         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1372 
   1373         synchronized (mLock) {
   1374             ensureGroupStateLoadedLocked(userId);
   1375 
   1376             // NOTE: The lookup is enforcing security across users by making
   1377             // sure the caller can only access widgets it hosts or provides.
   1378             Widget widget = lookupWidgetLocked(appWidgetId,
   1379                     Binder.getCallingUid(), callingPackage);
   1380 
   1381             if (widget != null) {
   1382                 return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
   1383             }
   1384 
   1385             return null;
   1386         }
   1387     }
   1388 
   1389     @Override
   1390     public void updateAppWidgetOptions(String callingPackage, int appWidgetId, Bundle options) {
   1391         final int userId = UserHandle.getCallingUserId();
   1392 
   1393         if (DEBUG) {
   1394             Slog.i(TAG, "updateAppWidgetOptions() " + userId);
   1395         }
   1396 
   1397         // Make sure the package runs under the caller uid.
   1398         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1399 
   1400         synchronized (mLock) {
   1401             ensureGroupStateLoadedLocked(userId);
   1402 
   1403             // NOTE: The lookup is enforcing security across users by making
   1404             // sure the caller can only access widgets it hosts or provides.
   1405             Widget widget = lookupWidgetLocked(appWidgetId,
   1406                     Binder.getCallingUid(), callingPackage);
   1407 
   1408             if (widget == null) {
   1409                 return;
   1410             }
   1411 
   1412             // Merge the options.
   1413             widget.options.putAll(options);
   1414 
   1415             // Send the broacast to notify the provider that options changed.
   1416             sendOptionsChangedIntentLocked(widget);
   1417 
   1418             saveGroupStateAsync(userId);
   1419         }
   1420     }
   1421 
   1422     @Override
   1423     public Bundle getAppWidgetOptions(String callingPackage, int appWidgetId) {
   1424         final int userId = UserHandle.getCallingUserId();
   1425 
   1426         if (DEBUG) {
   1427             Slog.i(TAG, "getAppWidgetOptions() " + userId);
   1428         }
   1429 
   1430         // Make sure the package runs under the caller uid.
   1431         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1432 
   1433         synchronized (mLock) {
   1434             ensureGroupStateLoadedLocked(userId);
   1435 
   1436             // NOTE: The lookup is enforcing security across users by making
   1437             // sure the caller can only access widgets it hosts or provides.
   1438             Widget widget = lookupWidgetLocked(appWidgetId,
   1439                     Binder.getCallingUid(), callingPackage);
   1440 
   1441             if (widget != null && widget.options != null) {
   1442                 return cloneIfLocalBinder(widget.options);
   1443             }
   1444 
   1445             return Bundle.EMPTY;
   1446         }
   1447     }
   1448 
   1449     @Override
   1450     public void updateAppWidgetIds(String callingPackage, int[] appWidgetIds,
   1451             RemoteViews views) {
   1452         if (DEBUG) {
   1453             Slog.i(TAG, "updateAppWidgetIds() " + UserHandle.getCallingUserId());
   1454         }
   1455 
   1456         updateAppWidgetIds(callingPackage, appWidgetIds, views, false);
   1457     }
   1458 
   1459     @Override
   1460     public void partiallyUpdateAppWidgetIds(String callingPackage, int[] appWidgetIds,
   1461             RemoteViews views) {
   1462         if (DEBUG) {
   1463             Slog.i(TAG, "partiallyUpdateAppWidgetIds() " + UserHandle.getCallingUserId());
   1464         }
   1465 
   1466         updateAppWidgetIds(callingPackage, appWidgetIds, views, true);
   1467     }
   1468 
   1469     @Override
   1470     public void notifyAppWidgetViewDataChanged(String callingPackage, int[] appWidgetIds,
   1471             int viewId) {
   1472         final int userId = UserHandle.getCallingUserId();
   1473 
   1474         if (DEBUG) {
   1475             Slog.i(TAG, "notifyAppWidgetViewDataChanged() " + userId);
   1476         }
   1477 
   1478         // Make sure the package runs under the caller uid.
   1479         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1480 
   1481         if (appWidgetIds == null || appWidgetIds.length == 0) {
   1482             return;
   1483         }
   1484 
   1485         synchronized (mLock) {
   1486             ensureGroupStateLoadedLocked(userId);
   1487 
   1488             final int N = appWidgetIds.length;
   1489             for (int i = 0; i < N; i++) {
   1490                 final int appWidgetId = appWidgetIds[i];
   1491 
   1492                 // NOTE: The lookup is enforcing security across users by making
   1493                 // sure the caller can only access widgets it hosts or provides.
   1494                 Widget widget = lookupWidgetLocked(appWidgetId,
   1495                         Binder.getCallingUid(), callingPackage);
   1496 
   1497                 if (widget != null) {
   1498                     scheduleNotifyAppWidgetViewDataChanged(widget, viewId);
   1499                 }
   1500             }
   1501         }
   1502     }
   1503 
   1504     @Override
   1505     public void updateAppWidgetProvider(ComponentName componentName, RemoteViews views) {
   1506         final int userId = UserHandle.getCallingUserId();
   1507 
   1508         if (DEBUG) {
   1509             Slog.i(TAG, "updateAppWidgetProvider() " + userId);
   1510         }
   1511 
   1512         // Make sure the package runs under the caller uid.
   1513         mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName());
   1514 
   1515         synchronized (mLock) {
   1516             ensureGroupStateLoadedLocked(userId);
   1517 
   1518             // NOTE: The lookup is enforcing security across users by making
   1519             // sure the caller can access only its providers.
   1520             ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName);
   1521             Provider provider = lookupProviderLocked(providerId);
   1522 
   1523             if (provider == null) {
   1524                 Slog.w(TAG, "Provider doesn't exist " + providerId);
   1525                 return;
   1526             }
   1527 
   1528             ArrayList<Widget> instances = provider.widgets;
   1529             final int N = instances.size();
   1530             for (int i = 0; i < N; i++) {
   1531                 Widget widget = instances.get(i);
   1532                 updateAppWidgetInstanceLocked(widget, views, false);
   1533             }
   1534         }
   1535     }
   1536 
   1537     @Override
   1538     public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
   1539             int profileId) {
   1540         final int userId = UserHandle.getCallingUserId();
   1541 
   1542         if (DEBUG) {
   1543             Slog.i(TAG, "getInstalledProvidersForProfiles() " + userId);
   1544         }
   1545 
   1546         // Ensure the profile is in the group and enabled.
   1547         if (!mSecurityPolicy.isEnabledGroupProfile(profileId)) {
   1548             return null;
   1549         }
   1550 
   1551         synchronized (mLock) {
   1552             ensureGroupStateLoadedLocked(userId);
   1553 
   1554             ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>();
   1555 
   1556             final int providerCount = mProviders.size();
   1557             for (int i = 0; i < providerCount; i++) {
   1558                 Provider provider = mProviders.get(i);
   1559                 AppWidgetProviderInfo info = provider.info;
   1560 
   1561                 // Ignore an invalid provider or one not matching the filter.
   1562                 if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
   1563                     continue;
   1564                 }
   1565 
   1566                 // Add providers only for the requested profile that are white-listed.
   1567                 final int providerProfileId = info.getProfile().getIdentifier();
   1568                 if (providerProfileId == profileId
   1569                         && mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
   1570                             provider.id.componentName.getPackageName(), providerProfileId)) {
   1571                     result.add(cloneIfLocalBinder(info));
   1572                 }
   1573             }
   1574 
   1575             return new ParceledListSlice<AppWidgetProviderInfo>(result);
   1576         }
   1577     }
   1578 
   1579     private void updateAppWidgetIds(String callingPackage, int[] appWidgetIds,
   1580             RemoteViews views, boolean partially) {
   1581         final int userId = UserHandle.getCallingUserId();
   1582 
   1583         if (appWidgetIds == null || appWidgetIds.length == 0) {
   1584             return;
   1585         }
   1586 
   1587         // Make sure the package runs under the caller uid.
   1588         mSecurityPolicy.enforceCallFromPackage(callingPackage);
   1589 
   1590         final int bitmapMemoryUsage = (views != null) ? views.estimateMemoryUsage() : 0;
   1591         if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) {
   1592             throw new IllegalArgumentException("RemoteViews for widget update exceeds"
   1593                     + " maximum bitmap memory usage (used: " + bitmapMemoryUsage
   1594                     + ", max: " + mMaxWidgetBitmapMemory + ")");
   1595         }
   1596 
   1597         synchronized (mLock) {
   1598             ensureGroupStateLoadedLocked(userId);
   1599 
   1600             final int N = appWidgetIds.length;
   1601             for (int i = 0; i < N; i++) {
   1602                 final int appWidgetId = appWidgetIds[i];
   1603 
   1604                 // NOTE: The lookup is enforcing security across users by making
   1605                 // sure the caller can only access widgets it hosts or provides.
   1606                 Widget widget = lookupWidgetLocked(appWidgetId,
   1607                         Binder.getCallingUid(), callingPackage);
   1608 
   1609                 if (widget != null) {
   1610                     updateAppWidgetInstanceLocked(widget, views, partially);
   1611                 }
   1612             }
   1613         }
   1614     }
   1615 
   1616     private int incrementAndGetAppWidgetIdLocked(int userId) {
   1617         final int appWidgetId = peekNextAppWidgetIdLocked(userId) + 1;
   1618         mNextAppWidgetIds.put(userId, appWidgetId);
   1619         return appWidgetId;
   1620     }
   1621 
   1622     private void setMinAppWidgetIdLocked(int userId, int minWidgetId) {
   1623         final int nextAppWidgetId = peekNextAppWidgetIdLocked(userId);
   1624         if (nextAppWidgetId < minWidgetId) {
   1625             mNextAppWidgetIds.put(userId, minWidgetId);
   1626         }
   1627     }
   1628 
   1629     private int peekNextAppWidgetIdLocked(int userId) {
   1630         if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
   1631             return AppWidgetManager.INVALID_APPWIDGET_ID + 1;
   1632         } else {
   1633             return mNextAppWidgetIds.get(userId);
   1634         }
   1635     }
   1636 
   1637     private Host lookupOrAddHostLocked(HostId id) {
   1638         Host host = lookupHostLocked(id);
   1639         if (host != null) {
   1640             return host;
   1641         }
   1642 
   1643         host = new Host();
   1644         host.id = id;
   1645         mHosts.add(host);
   1646 
   1647         return host;
   1648     }
   1649 
   1650     private void deleteHostLocked(Host host) {
   1651         final int N = host.widgets.size();
   1652         for (int i = N - 1; i >= 0; i--) {
   1653             Widget widget = host.widgets.remove(i);
   1654             deleteAppWidgetLocked(widget);
   1655         }
   1656         mHosts.remove(host);
   1657 
   1658         // it's gone or going away, abruptly drop the callback connection
   1659         host.callbacks = null;
   1660     }
   1661 
   1662     private void deleteAppWidgetLocked(Widget widget) {
   1663         // We first unbind all services that are bound to this id
   1664         unbindAppWidgetRemoteViewsServicesLocked(widget);
   1665 
   1666         Host host = widget.host;
   1667         host.widgets.remove(widget);
   1668         pruneHostLocked(host);
   1669 
   1670         removeWidgetLocked(widget);
   1671 
   1672         Provider provider = widget.provider;
   1673         if (provider != null) {
   1674             provider.widgets.remove(widget);
   1675             if (!provider.zombie) {
   1676                 // send the broacast saying that this appWidgetId has been deleted
   1677                 sendDeletedIntentLocked(widget);
   1678 
   1679                 if (provider.widgets.isEmpty()) {
   1680                     // cancel the future updates
   1681                     cancelBroadcasts(provider);
   1682 
   1683                     // send the broacast saying that the provider is not in use any more
   1684                     sendDisabledIntentLocked(provider);
   1685                 }
   1686             }
   1687         }
   1688     }
   1689 
   1690     private void cancelBroadcasts(Provider provider) {
   1691         if (DEBUG) {
   1692             Slog.i(TAG, "cancelBroadcasts() for " + provider);
   1693         }
   1694         if (provider.broadcast != null) {
   1695             mAlarmManager.cancel(provider.broadcast);
   1696             long token = Binder.clearCallingIdentity();
   1697             try {
   1698                 provider.broadcast.cancel();
   1699             } finally {
   1700                 Binder.restoreCallingIdentity(token);
   1701             }
   1702             provider.broadcast = null;
   1703         }
   1704     }
   1705 
   1706     // Unbinds from a RemoteViewsService when we delete an app widget
   1707     private void unbindAppWidgetRemoteViewsServicesLocked(Widget widget) {
   1708         int appWidgetId = widget.appWidgetId;
   1709         // Unbind all connections to Services bound to this AppWidgetId
   1710         Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet()
   1711                 .iterator();
   1712         while (it.hasNext()) {
   1713             final Pair<Integer, Intent.FilterComparison> key = it.next();
   1714             if (key.first == appWidgetId) {
   1715                 final ServiceConnectionProxy conn = (ServiceConnectionProxy)
   1716                         mBoundRemoteViewsServices.get(key);
   1717                 conn.disconnect();
   1718                 mContext.unbindService(conn);
   1719                 it.remove();
   1720             }
   1721         }
   1722 
   1723         // Check if we need to destroy any services (if no other app widgets are
   1724         // referencing the same service)
   1725         decrementAppWidgetServiceRefCount(widget);
   1726     }
   1727 
   1728     // Destroys the cached factory on the RemoteViewsService's side related to the specified intent
   1729     private void destroyRemoteViewsService(final Intent intent, Widget widget) {
   1730         final ServiceConnection conn = new ServiceConnection() {
   1731             @Override
   1732             public void onServiceConnected(ComponentName name, IBinder service) {
   1733                 final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service);
   1734                 try {
   1735                     cb.onDestroy(intent);
   1736                 } catch (RemoteException re) {
   1737                     Slog.e(TAG, "Error calling remove view factory", re);
   1738                 }
   1739                 mContext.unbindService(this);
   1740             }
   1741 
   1742             @Override
   1743             public void onServiceDisconnected(ComponentName name) {
   1744                 // Do nothing
   1745             }
   1746         };
   1747 
   1748         // Bind to the service and remove the static intent->factory mapping in the
   1749         // RemoteViewsService.
   1750         final long token = Binder.clearCallingIdentity();
   1751         try {
   1752             mContext.bindServiceAsUser(intent, conn,
   1753                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
   1754                     widget.provider.info.getProfile());
   1755         } finally {
   1756             Binder.restoreCallingIdentity(token);
   1757         }
   1758     }
   1759 
   1760     // Adds to the ref-count for a given RemoteViewsService intent
   1761     private void incrementAppWidgetServiceRefCount(int appWidgetId,
   1762             Pair<Integer, FilterComparison> serviceId) {
   1763         HashSet<Integer> appWidgetIds = null;
   1764         if (mRemoteViewsServicesAppWidgets.containsKey(serviceId)) {
   1765             appWidgetIds = mRemoteViewsServicesAppWidgets.get(serviceId);
   1766         } else {
   1767             appWidgetIds = new HashSet<>();
   1768             mRemoteViewsServicesAppWidgets.put(serviceId, appWidgetIds);
   1769         }
   1770         appWidgetIds.add(appWidgetId);
   1771     }
   1772 
   1773     // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if
   1774     // the ref-count reaches zero.
   1775     private void decrementAppWidgetServiceRefCount(Widget widget) {
   1776         Iterator<Pair<Integer, FilterComparison>> it = mRemoteViewsServicesAppWidgets
   1777                 .keySet().iterator();
   1778         while (it.hasNext()) {
   1779             final Pair<Integer, FilterComparison> key = it.next();
   1780             final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
   1781             if (ids.remove(widget.appWidgetId)) {
   1782                 // If we have removed the last app widget referencing this service, then we
   1783                 // should destroy it and remove it from this set
   1784                 if (ids.isEmpty()) {
   1785                     destroyRemoteViewsService(key.second.getIntent(), widget);
   1786                     it.remove();
   1787                 }
   1788             }
   1789         }
   1790     }
   1791 
   1792     private void saveGroupStateAsync(int groupId) {
   1793         mSaveStateHandler.post(new SaveStateRunnable(groupId));
   1794     }
   1795 
   1796     private void updateAppWidgetInstanceLocked(Widget widget, RemoteViews views,
   1797             boolean isPartialUpdate) {
   1798         if (widget != null && widget.provider != null
   1799                 && !widget.provider.zombie && !widget.host.zombie) {
   1800 
   1801             if (isPartialUpdate && widget.views != null) {
   1802                 // For a partial update, we merge the new RemoteViews with the old.
   1803                 widget.views.mergeRemoteViews(views);
   1804             } else {
   1805                 // For a full update we replace the RemoteViews completely.
   1806                 widget.views = views;
   1807             }
   1808             scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
   1809         }
   1810     }
   1811 
   1812     private void scheduleNotifyAppWidgetViewDataChanged(Widget widget, int viewId) {
   1813         if (widget == null || widget.host == null || widget.host.zombie
   1814                 || widget.host.callbacks == null || widget.provider == null
   1815                 || widget.provider.zombie) {
   1816             return;
   1817         }
   1818 
   1819         SomeArgs args = SomeArgs.obtain();
   1820         args.arg1 = widget.host;
   1821         args.arg2 = widget.host.callbacks;
   1822         args.argi1 = widget.appWidgetId;
   1823         args.argi2 = viewId;
   1824 
   1825         mCallbackHandler.obtainMessage(
   1826                 CallbackHandler.MSG_NOTIFY_VIEW_DATA_CHANGED,
   1827                 args).sendToTarget();
   1828     }
   1829 
   1830 
   1831     private void handleNotifyAppWidgetViewDataChanged(Host host, IAppWidgetHost callbacks,
   1832             int appWidgetId, int viewId) {
   1833         try {
   1834             callbacks.viewDataChanged(appWidgetId, viewId);
   1835         } catch (RemoteException re) {
   1836             // It failed; remove the callback. No need to prune because
   1837             // we know that this host is still referenced by this instance.
   1838             callbacks = null;
   1839         }
   1840 
   1841         // If the host is unavailable, then we call the associated
   1842         // RemoteViewsFactory.onDataSetChanged() directly
   1843         synchronized (mLock) {
   1844             if (callbacks == null) {
   1845                 host.callbacks = null;
   1846 
   1847                 Set<Pair<Integer, FilterComparison>> keys = mRemoteViewsServicesAppWidgets.keySet();
   1848                 for (Pair<Integer, FilterComparison> key : keys) {
   1849                     if (mRemoteViewsServicesAppWidgets.get(key).contains(appWidgetId)) {
   1850                         final ServiceConnection connection = new ServiceConnection() {
   1851                             @Override
   1852                             public void onServiceConnected(ComponentName name, IBinder service) {
   1853                                 IRemoteViewsFactory cb = IRemoteViewsFactory.Stub
   1854                                         .asInterface(service);
   1855                                 try {
   1856                                     cb.onDataSetChangedAsync();
   1857                                 } catch (RemoteException e) {
   1858                                     Slog.e(TAG, "Error calling onDataSetChangedAsync()", e);
   1859                                 }
   1860                                 mContext.unbindService(this);
   1861                             }
   1862 
   1863                             @Override
   1864                             public void onServiceDisconnected(android.content.ComponentName name) {
   1865                                 // Do nothing
   1866                             }
   1867                         };
   1868 
   1869                         final int userId = UserHandle.getUserId(key.first);
   1870                         Intent intent = key.second.getIntent();
   1871 
   1872                         // Bind to the service and call onDataSetChanged()
   1873                         bindService(intent, connection, new UserHandle(userId));
   1874                     }
   1875                 }
   1876             }
   1877         }
   1878     }
   1879 
   1880     private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
   1881         long requestTime = SystemClock.uptimeMillis();
   1882         if (widget != null) {
   1883             widget.lastUpdateTime = requestTime;
   1884         }
   1885         if (widget == null || widget.provider == null || widget.provider.zombie
   1886                 || widget.host.callbacks == null || widget.host.zombie) {
   1887             return;
   1888         }
   1889 
   1890         SomeArgs args = SomeArgs.obtain();
   1891         args.arg1 = widget.host;
   1892         args.arg2 = widget.host.callbacks;
   1893         args.arg3 = updateViews;
   1894         args.arg4 = requestTime;
   1895         args.argi1 = widget.appWidgetId;
   1896 
   1897         mCallbackHandler.obtainMessage(
   1898                 CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET,
   1899                 args).sendToTarget();
   1900     }
   1901 
   1902     private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
   1903             int appWidgetId, RemoteViews views, long requestTime) {
   1904         try {
   1905             callbacks.updateAppWidget(appWidgetId, views);
   1906             host.lastWidgetUpdateTime = requestTime;
   1907         } catch (RemoteException re) {
   1908             synchronized (mLock) {
   1909                 Slog.e(TAG, "Widget host dead: " + host.id, re);
   1910                 host.callbacks = null;
   1911             }
   1912         }
   1913     }
   1914 
   1915     private void scheduleNotifyProviderChangedLocked(Widget widget) {
   1916         if (widget == null || widget.provider == null || widget.provider.zombie
   1917                 || widget.host.callbacks == null || widget.host.zombie) {
   1918             return;
   1919         }
   1920 
   1921         SomeArgs args = SomeArgs.obtain();
   1922         args.arg1 = widget.host;
   1923         args.arg2 = widget.host.callbacks;
   1924         args.arg3 = widget.provider.info;
   1925         args.argi1 = widget.appWidgetId;
   1926 
   1927         mCallbackHandler.obtainMessage(
   1928                 CallbackHandler.MSG_NOTIFY_PROVIDER_CHANGED,
   1929                 args).sendToTarget();
   1930     }
   1931 
   1932     private void handleNotifyProviderChanged(Host host, IAppWidgetHost callbacks,
   1933             int appWidgetId, AppWidgetProviderInfo info) {
   1934         try {
   1935             callbacks.providerChanged(appWidgetId, info);
   1936         } catch (RemoteException re) {
   1937             synchronized (mLock){
   1938                 Slog.e(TAG, "Widget host dead: " + host.id, re);
   1939                 host.callbacks = null;
   1940             }
   1941         }
   1942     }
   1943 
   1944     private void scheduleNotifyGroupHostsForProvidersChangedLocked(int userId) {
   1945         final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
   1946 
   1947         final int N = mHosts.size();
   1948         for (int i = N - 1; i >= 0; i--) {
   1949             Host host = mHosts.get(i);
   1950 
   1951             boolean hostInGroup = false;
   1952             final int M = profileIds.length;
   1953             for (int j = 0; j < M; j++) {
   1954                 final int profileId = profileIds[j];
   1955                 if (host.getUserId() == profileId) {
   1956                     hostInGroup = true;
   1957                     break;
   1958                 }
   1959             }
   1960 
   1961             if (!hostInGroup) {
   1962                 continue;
   1963             }
   1964 
   1965             if (host == null || host.zombie || host.callbacks == null) {
   1966                 continue;
   1967             }
   1968 
   1969             SomeArgs args = SomeArgs.obtain();
   1970             args.arg1 = host;
   1971             args.arg2 = host.callbacks;
   1972 
   1973             mCallbackHandler.obtainMessage(
   1974                     CallbackHandler.MSG_NOTIFY_PROVIDERS_CHANGED,
   1975                     args).sendToTarget();
   1976         }
   1977     }
   1978 
   1979     private void handleNotifyProvidersChanged(Host host, IAppWidgetHost callbacks) {
   1980         try {
   1981             callbacks.providersChanged();
   1982         } catch (RemoteException re) {
   1983             synchronized (mLock) {
   1984                 Slog.e(TAG, "Widget host dead: " + host.id, re);
   1985                 host.callbacks = null;
   1986             }
   1987         }
   1988     }
   1989 
   1990     private static boolean isLocalBinder() {
   1991         return Process.myPid() == Binder.getCallingPid();
   1992     }
   1993 
   1994     private static RemoteViews cloneIfLocalBinder(RemoteViews rv) {
   1995         if (isLocalBinder() && rv != null) {
   1996             return rv.clone();
   1997         }
   1998         return rv;
   1999     }
   2000 
   2001     private static AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) {
   2002         if (isLocalBinder() && info != null) {
   2003             return info.clone();
   2004         }
   2005         return info;
   2006     }
   2007 
   2008     private static Bundle cloneIfLocalBinder(Bundle bundle) {
   2009         // Note: this is only a shallow copy. For now this will be fine, but it could be problematic
   2010         // if we start adding objects to the options. Further, it would only be an issue if keyguard
   2011         // used such options.
   2012         if (isLocalBinder() && bundle != null) {
   2013             return (Bundle) bundle.clone();
   2014         }
   2015         return bundle;
   2016     }
   2017 
   2018     private Widget lookupWidgetLocked(int appWidgetId, int uid, String packageName) {
   2019         final int N = mWidgets.size();
   2020         for (int i = 0; i < N; i++) {
   2021             Widget widget = mWidgets.get(i);
   2022             if (widget.appWidgetId == appWidgetId
   2023                     && mSecurityPolicy.canAccessAppWidget(widget, uid, packageName)) {
   2024                 return widget;
   2025             }
   2026         }
   2027         return null;
   2028     }
   2029 
   2030     private Provider lookupProviderLocked(ProviderId id) {
   2031         final int N = mProviders.size();
   2032         for (int i = 0; i < N; i++) {
   2033             Provider provider = mProviders.get(i);
   2034             if (provider.id.equals(id)) {
   2035                 return provider;
   2036             }
   2037         }
   2038         return null;
   2039     }
   2040 
   2041     private Host lookupHostLocked(HostId hostId) {
   2042         final int N = mHosts.size();
   2043         for (int i = 0; i < N; i++) {
   2044             Host host = mHosts.get(i);
   2045             if (host.id.equals(hostId)) {
   2046                 return host;
   2047             }
   2048         }
   2049         return null;
   2050     }
   2051 
   2052     private void pruneHostLocked(Host host) {
   2053         if (host.widgets.size() == 0 && host.callbacks == null) {
   2054             if (DEBUG) {
   2055                 Slog.i(TAG, "Pruning host " + host.id);
   2056             }
   2057             mHosts.remove(host);
   2058         }
   2059     }
   2060 
   2061     private void loadGroupWidgetProvidersLocked(int[] profileIds) {
   2062         List<ResolveInfo> allReceivers = null;
   2063         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
   2064 
   2065         final int profileCount = profileIds.length;
   2066         for (int i = 0; i < profileCount; i++) {
   2067             final int profileId = profileIds[i];
   2068 
   2069             List<ResolveInfo> receivers = queryIntentReceivers(intent, profileId);
   2070             if (receivers != null && !receivers.isEmpty()) {
   2071                 if (allReceivers == null) {
   2072                     allReceivers = new ArrayList<>();
   2073                 }
   2074                 allReceivers.addAll(receivers);
   2075             }
   2076         }
   2077 
   2078         final int N = (allReceivers == null) ? 0 : allReceivers.size();
   2079         for (int i = 0; i < N; i++) {
   2080             ResolveInfo receiver = allReceivers.get(i);
   2081             addProviderLocked(receiver);
   2082         }
   2083     }
   2084 
   2085     private boolean addProviderLocked(ResolveInfo ri) {
   2086         if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
   2087             return false;
   2088         }
   2089 
   2090         if (!ri.activityInfo.isEnabled()) {
   2091             return false;
   2092         }
   2093 
   2094         ComponentName componentName = new ComponentName(ri.activityInfo.packageName,
   2095                 ri.activityInfo.name);
   2096         ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName);
   2097 
   2098         Provider provider = parseProviderInfoXml(providerId, ri);
   2099         if (provider != null) {
   2100             // we might have an inactive entry for this provider already due to
   2101             // a preceding restore operation.  if so, fix it up in place; otherwise
   2102             // just add this new one.
   2103             Provider existing = lookupProviderLocked(providerId);
   2104 
   2105             // If the provider was not found it may be because it was restored and
   2106             // we did not know its UID so let us find if there is such one.
   2107             if (existing == null) {
   2108                 ProviderId restoredProviderId = new ProviderId(UNKNOWN_UID, componentName);
   2109                 existing = lookupProviderLocked(restoredProviderId);
   2110             }
   2111 
   2112             if (existing != null) {
   2113                 if (existing.zombie && !mSafeMode) {
   2114                     // it's a placeholder that was set up during an app restore
   2115                     existing.id = providerId;
   2116                     existing.zombie = false;
   2117                     existing.info = provider.info; // the real one filled out from the ResolveInfo
   2118                     if (DEBUG) {
   2119                         Slog.i(TAG, "Provider placeholder now reified: " + existing);
   2120                     }
   2121                 }
   2122             } else {
   2123                 mProviders.add(provider);
   2124             }
   2125             return true;
   2126         }
   2127 
   2128         return false;
   2129     }
   2130 
   2131     // Remove widgets for provider that are hosted in userId.
   2132     private void deleteWidgetsLocked(Provider provider, int userId) {
   2133         final int N = provider.widgets.size();
   2134         for (int i = N - 1; i >= 0; i--) {
   2135             Widget widget = provider.widgets.get(i);
   2136             if (userId == UserHandle.USER_ALL
   2137                     || userId == widget.host.getUserId()) {
   2138                 provider.widgets.remove(i);
   2139                 // Call back with empty RemoteViews
   2140                 updateAppWidgetInstanceLocked(widget, null, false);
   2141                 // clear out references to this appWidgetId
   2142                 widget.host.widgets.remove(widget);
   2143                 removeWidgetLocked(widget);
   2144                 widget.provider = null;
   2145                 pruneHostLocked(widget.host);
   2146                 widget.host = null;
   2147             }
   2148         }
   2149     }
   2150 
   2151     private void deleteProviderLocked(Provider provider) {
   2152         deleteWidgetsLocked(provider, UserHandle.USER_ALL);
   2153         mProviders.remove(provider);
   2154 
   2155         // no need to send the DISABLE broadcast, since the receiver is gone anyway
   2156         cancelBroadcasts(provider);
   2157     }
   2158 
   2159     private void sendEnableIntentLocked(Provider p) {
   2160         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
   2161         intent.setComponent(p.info.provider);
   2162         sendBroadcastAsUser(intent, p.info.getProfile());
   2163     }
   2164 
   2165     private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds) {
   2166         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
   2167         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
   2168         intent.setComponent(provider.info.provider);
   2169         sendBroadcastAsUser(intent, provider.info.getProfile());
   2170     }
   2171 
   2172     private void sendDeletedIntentLocked(Widget widget) {
   2173         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
   2174         intent.setComponent(widget.provider.info.provider);
   2175         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
   2176         sendBroadcastAsUser(intent, widget.provider.info.getProfile());
   2177     }
   2178 
   2179     private void sendDisabledIntentLocked(Provider provider) {
   2180         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
   2181         intent.setComponent(provider.info.provider);
   2182         sendBroadcastAsUser(intent, provider.info.getProfile());
   2183     }
   2184 
   2185     public void sendOptionsChangedIntentLocked(Widget widget) {
   2186         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
   2187         intent.setComponent(widget.provider.info.provider);
   2188         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
   2189         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, widget.options);
   2190         sendBroadcastAsUser(intent, widget.provider.info.getProfile());
   2191     }
   2192 
   2193     private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) {
   2194         if (provider.info.updatePeriodMillis > 0) {
   2195             // if this is the first instance, set the alarm. otherwise,
   2196             // rely on the fact that we've already set it and that
   2197             // PendingIntent.getBroadcast will update the extras.
   2198             boolean alreadyRegistered = provider.broadcast != null;
   2199             Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
   2200             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
   2201             intent.setComponent(provider.info.provider);
   2202             long token = Binder.clearCallingIdentity();
   2203             try {
   2204                 provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
   2205                         PendingIntent.FLAG_UPDATE_CURRENT, provider.info.getProfile());
   2206             } finally {
   2207                 Binder.restoreCallingIdentity(token);
   2208             }
   2209             if (!alreadyRegistered) {
   2210                 long period = provider.info.updatePeriodMillis;
   2211                 if (period < MIN_UPDATE_PERIOD) {
   2212                     period = MIN_UPDATE_PERIOD;
   2213                 }
   2214                 final long oldId = Binder.clearCallingIdentity();
   2215                 try {
   2216                     mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
   2217                             SystemClock.elapsedRealtime() + period, period, provider.broadcast);
   2218                 } finally {
   2219                     Binder.restoreCallingIdentity(oldId);
   2220                 }
   2221             }
   2222         }
   2223     }
   2224 
   2225     private static int[] getWidgetIds(ArrayList<Widget> widgets) {
   2226         int instancesSize = widgets.size();
   2227         int appWidgetIds[] = new int[instancesSize];
   2228         for (int i = 0; i < instancesSize; i++) {
   2229             appWidgetIds[i] = widgets.get(i).appWidgetId;
   2230         }
   2231         return appWidgetIds;
   2232     }
   2233 
   2234     private static void dumpProvider(Provider provider, int index, PrintWriter pw) {
   2235         AppWidgetProviderInfo info = provider.info;
   2236         pw.print("  ["); pw.print(index); pw.print("] provider ");
   2237         pw.println(provider.id);
   2238         pw.print("    min=("); pw.print(info.minWidth);
   2239         pw.print("x"); pw.print(info.minHeight);
   2240         pw.print(")   minResize=("); pw.print(info.minResizeWidth);
   2241         pw.print("x"); pw.print(info.minResizeHeight);
   2242         pw.print(") updatePeriodMillis=");
   2243         pw.print(info.updatePeriodMillis);
   2244         pw.print(" resizeMode=");
   2245         pw.print(info.resizeMode);
   2246         pw.print(info.widgetCategory);
   2247         pw.print(" autoAdvanceViewId=");
   2248         pw.print(info.autoAdvanceViewId);
   2249         pw.print(" initialLayout=#");
   2250         pw.print(Integer.toHexString(info.initialLayout));
   2251         pw.print(" initialKeyguardLayout=#");
   2252         pw.print(Integer.toHexString(info.initialKeyguardLayout));
   2253         pw.print(" zombie="); pw.println(provider.zombie);
   2254     }
   2255 
   2256     private static void dumpHost(Host host, int index, PrintWriter pw) {
   2257         pw.print("  ["); pw.print(index); pw.print("] hostId=");
   2258         pw.println(host.id);
   2259         pw.print("    callbacks="); pw.println(host.callbacks);
   2260         pw.print("    widgets.size="); pw.print(host.widgets.size());
   2261         pw.print(" zombie="); pw.println(host.zombie);
   2262     }
   2263 
   2264     private static void dumpGrant(Pair<Integer, String> grant, int index, PrintWriter pw) {
   2265         pw.print("  ["); pw.print(index); pw.print(']');
   2266         pw.print(" user="); pw.print(grant.first);
   2267         pw.print(" package="); pw.println(grant.second);
   2268     }
   2269 
   2270     private static void dumpWidget(Widget widget, int index, PrintWriter pw) {
   2271         pw.print("  ["); pw.print(index); pw.print("] id=");
   2272         pw.println(widget.appWidgetId);
   2273         pw.print("    host=");
   2274         pw.println(widget.host.id);
   2275         if (widget.provider != null) {
   2276             pw.print("    provider="); pw.println(widget.provider.id);
   2277         }
   2278         if (widget.host != null) {
   2279             pw.print("    host.callbacks="); pw.println(widget.host.callbacks);
   2280         }
   2281         if (widget.views != null) {
   2282             pw.print("    views="); pw.println(widget.views);
   2283         }
   2284     }
   2285 
   2286     private static void serializeProvider(XmlSerializer out, Provider p) throws IOException {
   2287         out.startTag(null, "p");
   2288         out.attribute(null, "pkg", p.info.provider.getPackageName());
   2289         out.attribute(null, "cl", p.info.provider.getClassName());
   2290         out.attribute(null, "tag", Integer.toHexString(p.tag));
   2291         out.endTag(null, "p");
   2292     }
   2293 
   2294     private static void serializeHost(XmlSerializer out, Host host) throws IOException {
   2295         out.startTag(null, "h");
   2296         out.attribute(null, "pkg", host.id.packageName);
   2297         out.attribute(null, "id", Integer.toHexString(host.id.hostId));
   2298         out.attribute(null, "tag", Integer.toHexString(host.tag));
   2299         out.endTag(null, "h");
   2300     }
   2301 
   2302     private static void serializeAppWidget(XmlSerializer out, Widget widget) throws IOException {
   2303         out.startTag(null, "g");
   2304         out.attribute(null, "id", Integer.toHexString(widget.appWidgetId));
   2305         out.attribute(null, "rid", Integer.toHexString(widget.restoredId));
   2306         out.attribute(null, "h", Integer.toHexString(widget.host.tag));
   2307         if (widget.provider != null) {
   2308             out.attribute(null, "p", Integer.toHexString(widget.provider.tag));
   2309         }
   2310         if (widget.options != null) {
   2311             out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt(
   2312                     AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
   2313             out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt(
   2314                     AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
   2315             out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt(
   2316                     AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
   2317             out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt(
   2318                     AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
   2319             out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt(
   2320                     AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
   2321         }
   2322         out.endTag(null, "g");
   2323     }
   2324 
   2325     @Override
   2326     public List<String> getWidgetParticipants(int userId) {
   2327         return mBackupRestoreController.getWidgetParticipants(userId);
   2328     }
   2329 
   2330     @Override
   2331     public byte[] getWidgetState(String packageName, int userId) {
   2332         return mBackupRestoreController.getWidgetState(packageName, userId);
   2333     }
   2334 
   2335     @Override
   2336     public void restoreStarting(int userId) {
   2337         mBackupRestoreController.restoreStarting(userId);
   2338     }
   2339 
   2340     @Override
   2341     public void restoreWidgetState(String packageName, byte[] restoredState, int userId) {
   2342         mBackupRestoreController.restoreWidgetState(packageName, restoredState, userId);
   2343     }
   2344 
   2345     @Override
   2346     public void restoreFinished(int userId) {
   2347         mBackupRestoreController.restoreFinished(userId);
   2348     }
   2349 
   2350     @SuppressWarnings("deprecation")
   2351     private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri) {
   2352         Provider provider = null;
   2353 
   2354         ActivityInfo activityInfo = ri.activityInfo;
   2355         XmlResourceParser parser = null;
   2356         try {
   2357             parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
   2358                     AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
   2359             if (parser == null) {
   2360                 Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
   2361                         + " meta-data for " + "AppWidget provider '" + providerId + '\'');
   2362                 return null;
   2363             }
   2364 
   2365             AttributeSet attrs = Xml.asAttributeSet(parser);
   2366 
   2367             int type;
   2368             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   2369                     && type != XmlPullParser.START_TAG) {
   2370                 // drain whitespace, comments, etc.
   2371             }
   2372 
   2373             String nodeName = parser.getName();
   2374             if (!"appwidget-provider".equals(nodeName)) {
   2375                 Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for"
   2376                         + " AppWidget provider " + providerId.componentName
   2377                         + " for user " + providerId.uid);
   2378                 return null;
   2379             }
   2380 
   2381             provider = new Provider();
   2382             provider.id = providerId;
   2383             AppWidgetProviderInfo info = provider.info = new AppWidgetProviderInfo();
   2384             info.provider = providerId.componentName;
   2385             info.providerInfo = activityInfo;
   2386 
   2387             final Resources resources;
   2388             final long identity = Binder.clearCallingIdentity();
   2389             try {
   2390                 final PackageManager pm = mContext.getPackageManager();
   2391                 final int userId = UserHandle.getUserId(providerId.uid);
   2392                 final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
   2393                         0, userId);
   2394                 resources = pm.getResourcesForApplication(app);
   2395             } finally {
   2396                 Binder.restoreCallingIdentity(identity);
   2397             }
   2398 
   2399             TypedArray sa = resources.obtainAttributes(attrs,
   2400                     com.android.internal.R.styleable.AppWidgetProviderInfo);
   2401 
   2402             // These dimensions has to be resolved in the application's context.
   2403             // We simply send back the raw complex data, which will be
   2404             // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
   2405             TypedValue value = sa
   2406                     .peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
   2407             info.minWidth = value != null ? value.data : 0;
   2408             value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
   2409             info.minHeight = value != null ? value.data : 0;
   2410             value = sa.peekValue(
   2411                     com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
   2412             info.minResizeWidth = value != null ? value.data : info.minWidth;
   2413             value = sa.peekValue(
   2414                     com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
   2415             info.minResizeHeight = value != null ? value.data : info.minHeight;
   2416             info.updatePeriodMillis = sa.getInt(
   2417                     com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
   2418             info.initialLayout = sa.getResourceId(
   2419                     com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
   2420             info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
   2421                     AppWidgetProviderInfo_initialKeyguardLayout, 0);
   2422 
   2423             String className = sa
   2424                     .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
   2425             if (className != null) {
   2426                 info.configure = new ComponentName(providerId.componentName.getPackageName(),
   2427                         className);
   2428             }
   2429             info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
   2430             info.icon = ri.getIconResource();
   2431             info.previewImage = sa.getResourceId(
   2432                     com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
   2433             info.autoAdvanceViewId = sa.getResourceId(
   2434                     com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
   2435             info.resizeMode = sa.getInt(
   2436                     com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
   2437                     AppWidgetProviderInfo.RESIZE_NONE);
   2438             info.widgetCategory = sa.getInt(
   2439                     com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
   2440                     AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
   2441 
   2442             sa.recycle();
   2443         } catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) {
   2444             // Ok to catch Exception here, because anything going wrong because
   2445             // of what a client process passes to us should not be fatal for the
   2446             // system process.
   2447             Slog.w(TAG, "XML parsing failed for AppWidget provider "
   2448                     + providerId.componentName + " for user " + providerId.uid, e);
   2449             return null;
   2450         } finally {
   2451             if (parser != null) {
   2452                 parser.close();
   2453             }
   2454         }
   2455         return provider;
   2456     }
   2457 
   2458     private int getUidForPackage(String packageName, int userId) {
   2459         PackageInfo pkgInfo = null;
   2460 
   2461         final long identity = Binder.clearCallingIdentity();
   2462         try {
   2463             pkgInfo = mPackageManager.getPackageInfo(packageName, 0, userId);
   2464         } catch (RemoteException re) {
   2465             // Shouldn't happen, local call
   2466         } finally {
   2467             Binder.restoreCallingIdentity(identity);
   2468         }
   2469 
   2470         if (pkgInfo == null || pkgInfo.applicationInfo == null) {
   2471             return -1;
   2472         }
   2473 
   2474         return pkgInfo.applicationInfo.uid;
   2475     }
   2476 
   2477     private ActivityInfo getProviderInfo(ComponentName componentName, int userId) {
   2478         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
   2479         intent.setComponent(componentName);
   2480 
   2481         List<ResolveInfo> receivers = queryIntentReceivers(intent, userId);
   2482         // We are setting component, so there is only one or none.
   2483         if (!receivers.isEmpty()) {
   2484             return receivers.get(0).activityInfo;
   2485         }
   2486 
   2487         return null;
   2488     }
   2489 
   2490     private List<ResolveInfo> queryIntentReceivers(Intent intent, int userId) {
   2491         final long identity = Binder.clearCallingIdentity();
   2492         try {
   2493             int flags = PackageManager.GET_META_DATA;
   2494 
   2495             // We really need packages to be around and parsed to know if they
   2496             // provide widgets.
   2497             flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
   2498 
   2499             // Widget hosts that are non-crypto aware may be hosting widgets
   2500             // from a profile that is still locked, so let them see those
   2501             // widgets.
   2502             if (isProfileWithUnlockedParent(userId)) {
   2503                 flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
   2504                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
   2505             }
   2506 
   2507             // Widgets referencing shared libraries need to have their
   2508             // dependencies loaded.
   2509             flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
   2510 
   2511             return mPackageManager.queryIntentReceivers(intent,
   2512                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
   2513                     flags, userId).getList();
   2514         } catch (RemoteException re) {
   2515             return Collections.emptyList();
   2516         } finally {
   2517             Binder.restoreCallingIdentity(identity);
   2518         }
   2519     }
   2520 
   2521     void onUserUnlocked(int userId) {
   2522         if (isProfileWithLockedParent(userId)) {
   2523             return;
   2524         }
   2525         if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
   2526             Slog.w(TAG, "User " + userId + " is no longer unlocked - exiting");
   2527             return;
   2528         }
   2529         synchronized (mLock) {
   2530             ensureGroupStateLoadedLocked(userId);
   2531             reloadWidgetsMaskedStateForGroup(mSecurityPolicy.getGroupParent(userId));
   2532 
   2533             final int N = mProviders.size();
   2534             for (int i = 0; i < N; i++) {
   2535                 Provider provider = mProviders.get(i);
   2536 
   2537                 // Send broadcast only to the providers of the user.
   2538                 if (provider.getUserId() != userId) {
   2539                     continue;
   2540                 }
   2541 
   2542                 if (provider.widgets.size() > 0) {
   2543                     sendEnableIntentLocked(provider);
   2544                     int[] appWidgetIds = getWidgetIds(provider.widgets);
   2545                     sendUpdateIntentLocked(provider, appWidgetIds);
   2546                     registerForBroadcastsLocked(provider, appWidgetIds);
   2547                 }
   2548             }
   2549         }
   2550     }
   2551 
   2552     // only call from initialization -- it assumes that the data structures are all empty
   2553     private void loadGroupStateLocked(int[] profileIds) {
   2554         // We can bind the widgets to host and providers only after
   2555         // reading the host and providers for all users since a widget
   2556         // can have a host and a provider in different users.
   2557         List<LoadedWidgetState> loadedWidgets = new ArrayList<>();
   2558 
   2559         int version = 0;
   2560 
   2561         final int profileIdCount = profileIds.length;
   2562         for (int i = 0; i < profileIdCount; i++) {
   2563             final int profileId = profileIds[i];
   2564 
   2565             // No file written for this user - nothing to do.
   2566             AtomicFile file = getSavedStateFile(profileId);
   2567             try {
   2568                 FileInputStream stream = file.openRead();
   2569                 version = readProfileStateFromFileLocked(stream, profileId, loadedWidgets);
   2570                 IoUtils.closeQuietly(stream);
   2571             } catch (FileNotFoundException e) {
   2572                 Slog.w(TAG, "Failed to read state: " + e);
   2573             }
   2574         }
   2575 
   2576         if (version >= 0) {
   2577             // Hooke'm up...
   2578             bindLoadedWidgetsLocked(loadedWidgets);
   2579 
   2580             // upgrade the database if needed
   2581             performUpgradeLocked(version);
   2582         } else {
   2583             // failed reading, clean up
   2584             Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
   2585             clearWidgetsLocked();
   2586             mHosts.clear();
   2587             final int N = mProviders.size();
   2588             for (int i = 0; i < N; i++) {
   2589                 mProviders.get(i).widgets.clear();
   2590             }
   2591         }
   2592     }
   2593 
   2594     private void bindLoadedWidgetsLocked(List<LoadedWidgetState> loadedWidgets) {
   2595         final int loadedWidgetCount = loadedWidgets.size();
   2596         for (int i = loadedWidgetCount - 1; i >= 0; i--) {
   2597             LoadedWidgetState loadedWidget = loadedWidgets.remove(i);
   2598             Widget widget = loadedWidget.widget;
   2599 
   2600             widget.provider = findProviderByTag(loadedWidget.providerTag);
   2601             if (widget.provider == null) {
   2602                 // This provider is gone. We just let the host figure out
   2603                 // that this happened when it fails to load it.
   2604                 continue;
   2605             }
   2606 
   2607             widget.host = findHostByTag(loadedWidget.hostTag);
   2608             if (widget.host == null) {
   2609                 // This host is gone.
   2610                 continue;
   2611             }
   2612 
   2613             widget.provider.widgets.add(widget);
   2614             widget.host.widgets.add(widget);
   2615             addWidgetLocked(widget);
   2616         }
   2617     }
   2618 
   2619     private Provider findProviderByTag(int tag) {
   2620         if (tag < 0) {
   2621             return null;
   2622         }
   2623         final int providerCount = mProviders.size();
   2624         for (int i = 0; i < providerCount; i++) {
   2625             Provider provider = mProviders.get(i);
   2626             if (provider.tag == tag) {
   2627                 return provider;
   2628             }
   2629         }
   2630         return null;
   2631     }
   2632 
   2633     private Host findHostByTag(int tag) {
   2634         if (tag < 0) {
   2635             return null;
   2636         }
   2637         final int hostCount = mHosts.size();
   2638         for (int i = 0; i < hostCount; i++) {
   2639             Host host = mHosts.get(i);
   2640             if (host.tag == tag) {
   2641                 return host;
   2642             }
   2643         }
   2644         return null;
   2645     }
   2646 
   2647     /**
   2648      * Adds the widget to mWidgets and tracks the package name in mWidgetPackages.
   2649      */
   2650     void addWidgetLocked(Widget widget) {
   2651         mWidgets.add(widget);
   2652 
   2653         onWidgetProviderAddedOrChangedLocked(widget);
   2654     }
   2655 
   2656     /**
   2657      * Checks if the provider is assigned and updates the mWidgetPackages to track packages
   2658      * that have bound widgets.
   2659      */
   2660     void onWidgetProviderAddedOrChangedLocked(Widget widget) {
   2661         if (widget.provider == null) return;
   2662 
   2663         int userId = widget.provider.getUserId();
   2664         ArraySet<String> packages = mWidgetPackages.get(userId);
   2665         if (packages == null) {
   2666             mWidgetPackages.put(userId, packages = new ArraySet<String>());
   2667         }
   2668         packages.add(widget.provider.info.provider.getPackageName());
   2669 
   2670         // If we are adding a widget it might be for a provider that
   2671         // is currently masked, if so mask the widget.
   2672         if (widget.provider.isMaskedLocked()) {
   2673             maskWidgetsViewsLocked(widget.provider, widget);
   2674         } else {
   2675             widget.clearMaskedViewsLocked();
   2676         }
   2677     }
   2678 
   2679     /**
   2680      * Removes a widget from mWidgets and updates the cache of bound widget provider packages.
   2681      * If there are other widgets with the same package, leaves it in the cache, otherwise it
   2682      * removes the associated package from the cache.
   2683      */
   2684     void removeWidgetLocked(Widget widget) {
   2685         mWidgets.remove(widget);
   2686 
   2687         onWidgetRemovedLocked(widget);
   2688     }
   2689 
   2690     private void onWidgetRemovedLocked(Widget widget) {
   2691         if (widget.provider == null) return;
   2692 
   2693         final int userId = widget.provider.getUserId();
   2694         final String packageName = widget.provider.info.provider.getPackageName();
   2695         ArraySet<String> packages = mWidgetPackages.get(userId);
   2696         if (packages == null) {
   2697             return;
   2698         }
   2699         // Check if there is any other widget with the same package name.
   2700         // Remove packageName if none.
   2701         final int N = mWidgets.size();
   2702         for (int i = 0; i < N; i++) {
   2703             Widget w = mWidgets.get(i);
   2704             if (w.provider == null) continue;
   2705             if (w.provider.getUserId() == userId
   2706                     && packageName.equals(w.provider.info.provider.getPackageName())) {
   2707                 return;
   2708             }
   2709         }
   2710         packages.remove(packageName);
   2711     }
   2712 
   2713     /**
   2714      * Clears all widgets and associated cache of packages with bound widgets.
   2715      */
   2716     void clearWidgetsLocked() {
   2717         mWidgets.clear();
   2718 
   2719         onWidgetsClearedLocked();
   2720     }
   2721 
   2722     private void onWidgetsClearedLocked() {
   2723         mWidgetPackages.clear();
   2724     }
   2725 
   2726     @Override
   2727     public boolean isBoundWidgetPackage(String packageName, int userId) {
   2728         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
   2729             throw new SecurityException("Only the system process can call this");
   2730         }
   2731         synchronized (mLock) {
   2732             final ArraySet<String> packages = mWidgetPackages.get(userId);
   2733             if (packages != null) {
   2734                 return packages.contains(packageName);
   2735             }
   2736         }
   2737         return false;
   2738     }
   2739 
   2740     private void saveStateLocked(int userId) {
   2741         tagProvidersAndHosts();
   2742 
   2743         final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
   2744 
   2745         final int profileCount = profileIds.length;
   2746         for (int i = 0; i < profileCount; i++) {
   2747             final int profileId = profileIds[i];
   2748 
   2749             AtomicFile file = getSavedStateFile(profileId);
   2750             FileOutputStream stream;
   2751             try {
   2752                 stream = file.startWrite();
   2753                 if (writeProfileStateToFileLocked(stream, profileId)) {
   2754                     file.finishWrite(stream);
   2755                 } else {
   2756                     file.failWrite(stream);
   2757                     Slog.w(TAG, "Failed to save state, restoring backup.");
   2758                 }
   2759             } catch (IOException e) {
   2760                 Slog.w(TAG, "Failed open state file for write: " + e);
   2761             }
   2762         }
   2763     }
   2764 
   2765     private void tagProvidersAndHosts() {
   2766         final int providerCount = mProviders.size();
   2767         for (int i = 0; i < providerCount; i++) {
   2768             Provider provider = mProviders.get(i);
   2769             provider.tag = i;
   2770         }
   2771 
   2772         final int hostCount = mHosts.size();
   2773         for (int i = 0; i < hostCount; i++) {
   2774             Host host = mHosts.get(i);
   2775             host.tag = i;
   2776         }
   2777     }
   2778 
   2779     private void clearProvidersAndHostsTagsLocked() {
   2780         final int providerCount = mProviders.size();
   2781         for (int i = 0; i < providerCount; i++) {
   2782             Provider provider = mProviders.get(i);
   2783             provider.tag = TAG_UNDEFINED;
   2784         }
   2785 
   2786         final int hostCount = mHosts.size();
   2787         for (int i = 0; i < hostCount; i++) {
   2788             Host host = mHosts.get(i);
   2789             host.tag = TAG_UNDEFINED;
   2790         }
   2791     }
   2792 
   2793     private boolean writeProfileStateToFileLocked(FileOutputStream stream, int userId) {
   2794         int N;
   2795 
   2796         try {
   2797             XmlSerializer out = new FastXmlSerializer();
   2798             out.setOutput(stream, StandardCharsets.UTF_8.name());
   2799             out.startDocument(null, true);
   2800             out.startTag(null, "gs");
   2801             out.attribute(null, "version", String.valueOf(CURRENT_VERSION));
   2802 
   2803             N = mProviders.size();
   2804             for (int i = 0; i < N; i++) {
   2805                 Provider provider = mProviders.get(i);
   2806                 // Save only providers for the user.
   2807                 if (provider.getUserId() != userId) {
   2808                     continue;
   2809                 }
   2810                 if (provider.widgets.size() > 0) {
   2811                     serializeProvider(out, provider);
   2812                 }
   2813             }
   2814 
   2815             N = mHosts.size();
   2816             for (int i = 0; i < N; i++) {
   2817                 Host host = mHosts.get(i);
   2818                 // Save only hosts for the user.
   2819                 if (host.getUserId() != userId) {
   2820                     continue;
   2821                 }
   2822                 serializeHost(out, host);
   2823             }
   2824 
   2825             N = mWidgets.size();
   2826             for (int i = 0; i < N; i++) {
   2827                 Widget widget = mWidgets.get(i);
   2828                 // Save only widgets hosted by the user.
   2829                 if (widget.host.getUserId() != userId) {
   2830                     continue;
   2831                 }
   2832                 serializeAppWidget(out, widget);
   2833             }
   2834 
   2835             Iterator<Pair<Integer, String>> it = mPackagesWithBindWidgetPermission.iterator();
   2836             while (it.hasNext()) {
   2837                 Pair<Integer, String> binding = it.next();
   2838                 // Save only white listings for the user.
   2839                 if (binding.first != userId) {
   2840                     continue;
   2841                 }
   2842                 out.startTag(null, "b");
   2843                 out.attribute(null, "packageName", binding.second);
   2844                 out.endTag(null, "b");
   2845             }
   2846 
   2847             out.endTag(null, "gs");
   2848             out.endDocument();
   2849             return true;
   2850         } catch (IOException e) {
   2851             Slog.w(TAG, "Failed to write state: " + e);
   2852             return false;
   2853         }
   2854     }
   2855 
   2856     private int readProfileStateFromFileLocked(FileInputStream stream, int userId,
   2857             List<LoadedWidgetState> outLoadedWidgets) {
   2858         int version = -1;
   2859         try {
   2860             XmlPullParser parser = Xml.newPullParser();
   2861             parser.setInput(stream, StandardCharsets.UTF_8.name());
   2862 
   2863             int legacyProviderIndex = -1;
   2864             int legacyHostIndex = -1;
   2865             int type;
   2866             do {
   2867                 type = parser.next();
   2868                 if (type == XmlPullParser.START_TAG) {
   2869                     String tag = parser.getName();
   2870                     if ("gs".equals(tag)) {
   2871                         String attributeValue = parser.getAttributeValue(null, "version");
   2872                         try {
   2873                             version = Integer.parseInt(attributeValue);
   2874                         } catch (NumberFormatException e) {
   2875                             version = 0;
   2876                         }
   2877                     } else if ("p".equals(tag)) {
   2878                         legacyProviderIndex++;
   2879                         // TODO: do we need to check that this package has the same signature
   2880                         // as before?
   2881                         String pkg = parser.getAttributeValue(null, "pkg");
   2882                         String cl = parser.getAttributeValue(null, "cl");
   2883 
   2884                         pkg = getCanonicalPackageName(pkg, cl, userId);
   2885                         if (pkg == null) {
   2886                             continue;
   2887                         }
   2888 
   2889                         final int uid = getUidForPackage(pkg, userId);
   2890                         if (uid < 0) {
   2891                             continue;
   2892                         }
   2893 
   2894                         ComponentName componentName = new ComponentName(pkg, cl);
   2895 
   2896                         ActivityInfo providerInfo = getProviderInfo(componentName, userId);
   2897                         if (providerInfo == null) {
   2898                             continue;
   2899                         }
   2900 
   2901                         ProviderId providerId = new ProviderId(uid, componentName);
   2902                         Provider provider = lookupProviderLocked(providerId);
   2903 
   2904                         if (provider == null && mSafeMode) {
   2905                             // if we're in safe mode, make a temporary one
   2906                             provider = new Provider();
   2907                             provider.info = new AppWidgetProviderInfo();
   2908                             provider.info.provider = providerId.componentName;
   2909                             provider.info.providerInfo = providerInfo;
   2910                             provider.zombie = true;
   2911                             provider.id = providerId;
   2912                             mProviders.add(provider);
   2913                         }
   2914 
   2915                         String tagAttribute = parser.getAttributeValue(null, "tag");
   2916                         final int providerTag = !TextUtils.isEmpty(tagAttribute)
   2917                                 ? Integer.parseInt(tagAttribute, 16) : legacyProviderIndex;
   2918                         provider.tag = providerTag;
   2919                     } else if ("h".equals(tag)) {
   2920                         legacyHostIndex++;
   2921                         Host host = new Host();
   2922                         // TODO: do we need to check that this package has the same signature
   2923                         // as before?
   2924                         String pkg = parser.getAttributeValue(null, "pkg");
   2925 
   2926                         final int uid = getUidForPackage(pkg, userId);
   2927                         if (uid < 0) {
   2928                             host.zombie = true;
   2929                         }
   2930 
   2931                         if (!host.zombie || mSafeMode) {
   2932                             // In safe mode, we don't discard the hosts we don't recognize
   2933                             // so that they're not pruned from our list. Otherwise, we do.
   2934                             final int hostId = Integer.parseInt(parser.getAttributeValue(
   2935                                     null, "id"), 16);
   2936 
   2937                             String tagAttribute = parser.getAttributeValue(null, "tag");
   2938                             final int hostTag = !TextUtils.isEmpty(tagAttribute)
   2939                                     ? Integer.parseInt(tagAttribute, 16) : legacyHostIndex;
   2940 
   2941                             host.tag = hostTag;
   2942                             host.id = new HostId(uid, hostId, pkg);
   2943                             mHosts.add(host);
   2944                         }
   2945                     } else if ("b".equals(tag)) {
   2946                         String packageName = parser.getAttributeValue(null, "packageName");
   2947                         final int uid = getUidForPackage(packageName, userId);
   2948                         if (uid >= 0) {
   2949                             Pair<Integer, String> packageId = Pair.create(userId, packageName);
   2950                             mPackagesWithBindWidgetPermission.add(packageId);
   2951                         }
   2952                     } else if ("g".equals(tag)) {
   2953                         Widget widget = new Widget();
   2954                         widget.appWidgetId = Integer.parseInt(parser.getAttributeValue(
   2955                                 null, "id"), 16);
   2956                         setMinAppWidgetIdLocked(userId, widget.appWidgetId + 1);
   2957 
   2958                         // restored ID is allowed to be absent
   2959                         String restoredIdString = parser.getAttributeValue(null, "rid");
   2960                         widget.restoredId = (restoredIdString == null) ? 0
   2961                                 : Integer.parseInt(restoredIdString, 16);
   2962 
   2963                         Bundle options = new Bundle();
   2964                         String minWidthString = parser.getAttributeValue(null, "min_width");
   2965                         if (minWidthString != null) {
   2966                             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
   2967                                     Integer.parseInt(minWidthString, 16));
   2968                         }
   2969                         String minHeightString = parser.getAttributeValue(null, "min_height");
   2970                         if (minHeightString != null) {
   2971                             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
   2972                                     Integer.parseInt(minHeightString, 16));
   2973                         }
   2974                         String maxWidthString = parser.getAttributeValue(null, "max_width");
   2975                         if (maxWidthString != null) {
   2976                             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
   2977                                     Integer.parseInt(maxWidthString, 16));
   2978                         }
   2979                         String maxHeightString = parser.getAttributeValue(null, "max_height");
   2980                         if (maxHeightString != null) {
   2981                             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
   2982                                     Integer.parseInt(maxHeightString, 16));
   2983                         }
   2984                         String categoryString = parser.getAttributeValue(null, "host_category");
   2985                         if (categoryString != null) {
   2986                             options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
   2987                                     Integer.parseInt(categoryString, 16));
   2988                         }
   2989                         widget.options = options;
   2990 
   2991                         final int hostTag = Integer.parseInt(parser.getAttributeValue(
   2992                                 null, "h"), 16);
   2993                         String providerString = parser.getAttributeValue(null, "p");
   2994                         final int providerTag = (providerString != null) ? Integer.parseInt(
   2995                                 parser.getAttributeValue(null, "p"), 16) : TAG_UNDEFINED;
   2996 
   2997                         // We can match widgets with hosts and providers only after hosts
   2998                         // and providers for all users have been loaded since the widget
   2999                         // host and provider can be in different user profiles.
   3000                         LoadedWidgetState loadedWidgets = new LoadedWidgetState(widget,
   3001                                 hostTag, providerTag);
   3002                         outLoadedWidgets.add(loadedWidgets);
   3003                     }
   3004                 }
   3005             } while (type != XmlPullParser.END_DOCUMENT);
   3006         } catch (NullPointerException
   3007                 | NumberFormatException
   3008                 | XmlPullParserException
   3009                 | IOException
   3010                 | IndexOutOfBoundsException e) {
   3011             Slog.w(TAG, "failed parsing " + e);
   3012             return -1;
   3013         }
   3014 
   3015         return version;
   3016     }
   3017 
   3018     private void performUpgradeLocked(int fromVersion) {
   3019         if (fromVersion < CURRENT_VERSION) {
   3020             Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to "
   3021                     + CURRENT_VERSION);
   3022         }
   3023 
   3024         int version = fromVersion;
   3025 
   3026         // Update 1: keyguard moved from package "android" to "com.android.keyguard"
   3027         if (version == 0) {
   3028             HostId oldHostId = new HostId(Process.myUid(),
   3029                     KEYGUARD_HOST_ID, OLD_KEYGUARD_HOST_PACKAGE);
   3030 
   3031             Host host = lookupHostLocked(oldHostId);
   3032             if (host != null) {
   3033                 final int uid = getUidForPackage(NEW_KEYGUARD_HOST_PACKAGE,
   3034                         UserHandle.USER_SYSTEM);
   3035                 if (uid >= 0) {
   3036                     host.id = new HostId(uid, KEYGUARD_HOST_ID, NEW_KEYGUARD_HOST_PACKAGE);
   3037                 }
   3038             }
   3039 
   3040             version = 1;
   3041         }
   3042 
   3043         if (version != CURRENT_VERSION) {
   3044             throw new IllegalStateException("Failed to upgrade widget database");
   3045         }
   3046     }
   3047 
   3048     private static File getStateFile(int userId) {
   3049         return new File(Environment.getUserSystemDirectory(userId), STATE_FILENAME);
   3050     }
   3051 
   3052     private static AtomicFile getSavedStateFile(int userId) {
   3053         File dir = Environment.getUserSystemDirectory(userId);
   3054         File settingsFile = getStateFile(userId);
   3055         if (!settingsFile.exists() && userId == UserHandle.USER_SYSTEM) {
   3056             if (!dir.exists()) {
   3057                 dir.mkdirs();
   3058             }
   3059             // Migrate old data
   3060             File oldFile = new File("/data/system/" + STATE_FILENAME);
   3061             // Method doesn't throw an exception on failure. Ignore any errors
   3062             // in moving the file (like non-existence)
   3063             oldFile.renameTo(settingsFile);
   3064         }
   3065         return new AtomicFile(settingsFile);
   3066     }
   3067 
   3068     void onUserStopped(int userId) {
   3069         synchronized (mLock) {
   3070             boolean crossProfileWidgetsChanged = false;
   3071 
   3072             // Remove widgets that have both host and provider in the user.
   3073             final int widgetCount = mWidgets.size();
   3074             for (int i = widgetCount - 1; i >= 0; i--) {
   3075                 Widget widget = mWidgets.get(i);
   3076 
   3077                 final boolean hostInUser = widget.host.getUserId() == userId;
   3078                 final boolean hasProvider = widget.provider != null;
   3079                 final boolean providerInUser = hasProvider && widget.provider.getUserId() == userId;
   3080 
   3081                 // If both host and provider are in the user, just drop the widgets
   3082                 // as we do not want to make host callbacks and provider broadcasts
   3083                 // as the host and the provider will be killed.
   3084                 if (hostInUser && (!hasProvider || providerInUser)) {
   3085                     removeWidgetLocked(widget);
   3086                     widget.host.widgets.remove(widget);
   3087                     widget.host = null;
   3088                     if (hasProvider) {
   3089                         widget.provider.widgets.remove(widget);
   3090                         widget.provider = null;
   3091                     }
   3092                 }
   3093             }
   3094 
   3095             // Remove hosts and notify providers in other profiles.
   3096             final int hostCount = mHosts.size();
   3097             for (int i = hostCount - 1; i >= 0; i--) {
   3098                 Host host = mHosts.get(i);
   3099                 if (host.getUserId() == userId) {
   3100                     crossProfileWidgetsChanged |= !host.widgets.isEmpty();
   3101                     deleteHostLocked(host);
   3102                 }
   3103             }
   3104 
   3105             // Leave the providers present as hosts will show the widgets
   3106             // masked while the user is stopped.
   3107 
   3108             // Remove grants for this user.
   3109             final int grantCount = mPackagesWithBindWidgetPermission.size();
   3110             for (int i = grantCount - 1; i >= 0; i--) {
   3111                 Pair<Integer, String> packageId = mPackagesWithBindWidgetPermission.valueAt(i);
   3112                 if (packageId.first == userId) {
   3113                     mPackagesWithBindWidgetPermission.removeAt(i);
   3114                 }
   3115             }
   3116 
   3117             // Take a note we no longer have state for this user.
   3118             final int userIndex = mLoadedUserIds.indexOfKey(userId);
   3119             if (userIndex >= 0) {
   3120                 mLoadedUserIds.removeAt(userIndex);
   3121             }
   3122 
   3123             // Remove the widget id counter.
   3124             final int nextIdIndex = mNextAppWidgetIds.indexOfKey(userId);
   3125             if (nextIdIndex >= 0) {
   3126                 mNextAppWidgetIds.removeAt(nextIdIndex);
   3127             }
   3128 
   3129             // Save state if removing a profile changed the group state.
   3130             // Nothing will be saved if the group parent was removed.
   3131             if (crossProfileWidgetsChanged) {
   3132                 saveGroupStateAsync(userId);
   3133             }
   3134         }
   3135     }
   3136 
   3137     /**
   3138      * Updates all providers with the specified package names, and records any providers that were
   3139      * pruned.
   3140      *
   3141      * @return whether any providers were updated
   3142      */
   3143     private boolean updateProvidersForPackageLocked(String packageName, int userId,
   3144             Set<ProviderId> removedProviders) {
   3145         boolean providersUpdated = false;
   3146 
   3147         HashSet<ProviderId> keep = new HashSet<>();
   3148         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
   3149         intent.setPackage(packageName);
   3150         List<ResolveInfo> broadcastReceivers = queryIntentReceivers(intent, userId);
   3151 
   3152         // add the missing ones and collect which ones to keep
   3153         int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
   3154         for (int i = 0; i < N; i++) {
   3155             ResolveInfo ri = broadcastReceivers.get(i);
   3156             ActivityInfo ai = ri.activityInfo;
   3157 
   3158             if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
   3159                 continue;
   3160             }
   3161 
   3162             if (packageName.equals(ai.packageName)) {
   3163                 ProviderId providerId = new ProviderId(ai.applicationInfo.uid,
   3164                         new ComponentName(ai.packageName, ai.name));
   3165 
   3166                 Provider provider = lookupProviderLocked(providerId);
   3167                 if (provider == null) {
   3168                     if (addProviderLocked(ri)) {
   3169                         keep.add(providerId);
   3170                         providersUpdated = true;
   3171                     }
   3172                 } else {
   3173                     Provider parsed = parseProviderInfoXml(providerId, ri);
   3174                     if (parsed != null) {
   3175                         keep.add(providerId);
   3176                         // Use the new AppWidgetProviderInfo.
   3177                         provider.info = parsed.info;
   3178                         // If it's enabled
   3179                         final int M = provider.widgets.size();
   3180                         if (M > 0) {
   3181                             int[] appWidgetIds = getWidgetIds(provider.widgets);
   3182                             // Reschedule for the new updatePeriodMillis (don't worry about handling
   3183                             // it specially if updatePeriodMillis didn't change because we just sent
   3184                             // an update, and the next one will be updatePeriodMillis from now).
   3185                             cancelBroadcasts(provider);
   3186                             registerForBroadcastsLocked(provider, appWidgetIds);
   3187                             // If it's currently showing, call back with the new
   3188                             // AppWidgetProviderInfo.
   3189                             for (int j = 0; j < M; j++) {
   3190                                 Widget widget = provider.widgets.get(j);
   3191                                 widget.views = null;
   3192                                 scheduleNotifyProviderChangedLocked(widget);
   3193                             }
   3194                             // Now that we've told the host, push out an update.
   3195                             sendUpdateIntentLocked(provider, appWidgetIds);
   3196                         }
   3197                     }
   3198                     providersUpdated = true;
   3199                 }
   3200             }
   3201         }
   3202 
   3203         // prune the ones we don't want to keep
   3204         N = mProviders.size();
   3205         for (int i = N - 1; i >= 0; i--) {
   3206             Provider provider = mProviders.get(i);
   3207             if (packageName.equals(provider.info.provider.getPackageName())
   3208                     && provider.getUserId() == userId
   3209                     && !keep.contains(provider.id)) {
   3210                 if (removedProviders != null) {
   3211                     removedProviders.add(provider.id);
   3212                 }
   3213                 deleteProviderLocked(provider);
   3214                 providersUpdated = true;
   3215             }
   3216         }
   3217 
   3218         return providersUpdated;
   3219     }
   3220 
   3221     // Remove widgets for provider in userId that are hosted in parentUserId
   3222     private void removeWidgetsForPackageLocked(String pkgName, int userId, int parentUserId) {
   3223         final int N = mProviders.size();
   3224         for (int i = 0; i < N; ++i) {
   3225             Provider provider = mProviders.get(i);
   3226             if (pkgName.equals(provider.info.provider.getPackageName())
   3227                     && provider.getUserId() == userId
   3228                     && provider.widgets.size() > 0) {
   3229                 deleteWidgetsLocked(provider, parentUserId);
   3230             }
   3231         }
   3232     }
   3233 
   3234     private boolean removeProvidersForPackageLocked(String pkgName, int userId) {
   3235         boolean removed = false;
   3236 
   3237         final int N = mProviders.size();
   3238         for (int i = N - 1; i >= 0; i--) {
   3239             Provider provider = mProviders.get(i);
   3240             if (pkgName.equals(provider.info.provider.getPackageName())
   3241                     && provider.getUserId() == userId) {
   3242                 deleteProviderLocked(provider);
   3243                 removed = true;
   3244             }
   3245         }
   3246         return removed;
   3247     }
   3248 
   3249     private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) {
   3250         boolean removed = removeProvidersForPackageLocked(pkgName, userId);
   3251 
   3252         // Delete the hosts for this package too
   3253         // By now, we have removed any AppWidgets that were in any hosts here,
   3254         // so we don't need to worry about sending DISABLE broadcasts to them.
   3255         final int N = mHosts.size();
   3256         for (int i = N - 1; i >= 0; i--) {
   3257             Host host = mHosts.get(i);
   3258             if (pkgName.equals(host.id.packageName)
   3259                     && host.getUserId() == userId) {
   3260                 deleteHostLocked(host);
   3261                 removed = true;
   3262             }
   3263         }
   3264 
   3265         return removed;
   3266     }
   3267 
   3268     private String getCanonicalPackageName(String packageName, String className, int userId) {
   3269         final long identity = Binder.clearCallingIdentity();
   3270         try {
   3271             try {
   3272                 AppGlobals.getPackageManager().getReceiverInfo(new ComponentName(packageName,
   3273                         className), 0, userId);
   3274                 return packageName;
   3275             } catch (RemoteException re) {
   3276                 String[] packageNames = mContext.getPackageManager()
   3277                         .currentToCanonicalPackageNames(new String[]{packageName});
   3278                 if (packageNames != null && packageNames.length > 0) {
   3279                     return packageNames[0];
   3280                 }
   3281             }
   3282         } finally {
   3283             Binder.restoreCallingIdentity(identity);
   3284         }
   3285         return null;
   3286     }
   3287 
   3288     private void sendBroadcastAsUser(Intent intent, UserHandle userHandle) {
   3289         final long identity = Binder.clearCallingIdentity();
   3290         try {
   3291             mContext.sendBroadcastAsUser(intent, userHandle);
   3292         } finally {
   3293             Binder.restoreCallingIdentity(identity);
   3294         }
   3295     }
   3296 
   3297     private void bindService(Intent intent, ServiceConnection connection,
   3298             UserHandle userHandle) {
   3299         final long token = Binder.clearCallingIdentity();
   3300         try {
   3301             mContext.bindServiceAsUser(intent, connection,
   3302                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
   3303                     userHandle);
   3304         } finally {
   3305             Binder.restoreCallingIdentity(token);
   3306         }
   3307     }
   3308 
   3309     private void unbindService(ServiceConnection connection) {
   3310         final long token = Binder.clearCallingIdentity();
   3311         try {
   3312             mContext.unbindService(connection);
   3313         } finally {
   3314             Binder.restoreCallingIdentity(token);
   3315         }
   3316     }
   3317 
   3318     @Override
   3319     public void onCrossProfileWidgetProvidersChanged(int userId, List<String> packages) {
   3320         final int parentId = mSecurityPolicy.getProfileParent(userId);
   3321         // We care only if the white-listed package is in a profile of
   3322         // the group parent as only the parent can add widgets from the
   3323         // profile and not the other way around.
   3324         if (parentId != userId) {
   3325             synchronized (mLock) {
   3326                 boolean providersChanged = false;
   3327 
   3328                 ArraySet<String> previousPackages = new ArraySet<String>();
   3329                 final int providerCount = mProviders.size();
   3330                 for (int i = 0; i < providerCount; ++i) {
   3331                     Provider provider = mProviders.get(i);
   3332                     if (provider.getUserId() == userId) {
   3333                         previousPackages.add(provider.id.componentName.getPackageName());
   3334                     }
   3335                 }
   3336 
   3337                 final int packageCount = packages.size();
   3338                 for (int i = 0; i < packageCount; i++) {
   3339                     String packageName = packages.get(i);
   3340                     previousPackages.remove(packageName);
   3341                     providersChanged |= updateProvidersForPackageLocked(packageName,
   3342                             userId, null);
   3343                 }
   3344 
   3345                 // Remove widgets from hosts in parent user for packages not in the whitelist
   3346                 final int removedCount = previousPackages.size();
   3347                 for (int i = 0; i < removedCount; ++i) {
   3348                     removeWidgetsForPackageLocked(previousPackages.valueAt(i),
   3349                             userId, parentId);
   3350                 }
   3351 
   3352                 if (providersChanged || removedCount > 0) {
   3353                     saveGroupStateAsync(userId);
   3354                     scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
   3355                 }
   3356             }
   3357         }
   3358     }
   3359 
   3360     private boolean isProfileWithLockedParent(int userId) {
   3361         long token = Binder.clearCallingIdentity();
   3362         try {
   3363             UserInfo userInfo = mUserManager.getUserInfo(userId);
   3364             if (userInfo != null && userInfo.isManagedProfile()) {
   3365                 UserInfo parentInfo = mUserManager.getProfileParent(userId);
   3366                 if (parentInfo != null
   3367                         && !isUserRunningAndUnlocked(parentInfo.getUserHandle().getIdentifier())) {
   3368                     return true;
   3369                 }
   3370             }
   3371         } finally {
   3372             Binder.restoreCallingIdentity(token);
   3373         }
   3374         return false;
   3375     }
   3376 
   3377     private boolean isProfileWithUnlockedParent(int userId) {
   3378         UserInfo userInfo = mUserManager.getUserInfo(userId);
   3379         if (userInfo != null && userInfo.isManagedProfile()) {
   3380             UserInfo parentInfo = mUserManager.getProfileParent(userId);
   3381             if (parentInfo != null
   3382                     && mUserManager.isUserUnlockingOrUnlocked(parentInfo.getUserHandle())) {
   3383                 return true;
   3384             }
   3385         }
   3386         return false;
   3387     }
   3388 
   3389     private final class CallbackHandler extends Handler {
   3390         public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
   3391         public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
   3392         public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3;
   3393         public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4;
   3394 
   3395         public CallbackHandler(Looper looper) {
   3396             super(looper, null, false);
   3397         }
   3398 
   3399         @Override
   3400         public void handleMessage(Message message) {
   3401             switch (message.what) {
   3402                 case MSG_NOTIFY_UPDATE_APP_WIDGET: {
   3403                     SomeArgs args = (SomeArgs) message.obj;
   3404                     Host host = (Host) args.arg1;
   3405                     IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
   3406                     RemoteViews views = (RemoteViews) args.arg3;
   3407                     long requestTime = (Long) args.arg4;
   3408                     final int appWidgetId = args.argi1;
   3409                     args.recycle();
   3410 
   3411                     handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
   3412                 } break;
   3413 
   3414                 case MSG_NOTIFY_PROVIDER_CHANGED: {
   3415                     SomeArgs args = (SomeArgs) message.obj;
   3416                     Host host = (Host) args.arg1;
   3417                     IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
   3418                     AppWidgetProviderInfo info = (AppWidgetProviderInfo)args.arg3;
   3419                     final int appWidgetId = args.argi1;
   3420                     args.recycle();
   3421 
   3422                     handleNotifyProviderChanged(host, callbacks, appWidgetId, info);
   3423                 } break;
   3424 
   3425                 case MSG_NOTIFY_PROVIDERS_CHANGED: {
   3426                     SomeArgs args = (SomeArgs) message.obj;
   3427                     Host host = (Host) args.arg1;
   3428                     IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
   3429                     args.recycle();
   3430 
   3431                     handleNotifyProvidersChanged(host, callbacks);
   3432                 } break;
   3433 
   3434                 case MSG_NOTIFY_VIEW_DATA_CHANGED: {
   3435                     SomeArgs args = (SomeArgs) message.obj;
   3436                     Host host = (Host) args.arg1;
   3437                     IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
   3438                     final int appWidgetId = args.argi1;
   3439                     final int viewId = args.argi2;
   3440                     args.recycle();
   3441 
   3442                     handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId);
   3443                 } break;
   3444             }
   3445         }
   3446     }
   3447 
   3448     private final class SecurityPolicy {
   3449 
   3450         public boolean isEnabledGroupProfile(int profileId) {
   3451             final int parentId = UserHandle.getCallingUserId();
   3452             return isParentOrProfile(parentId, profileId) && isProfileEnabled(profileId);
   3453         }
   3454 
   3455         public int[] getEnabledGroupProfileIds(int userId) {
   3456             final int parentId = getGroupParent(userId);
   3457 
   3458             final long identity = Binder.clearCallingIdentity();
   3459             try {
   3460                 return mUserManager.getEnabledProfileIds(parentId);
   3461             } finally {
   3462                 Binder.restoreCallingIdentity(identity);
   3463             }
   3464         }
   3465 
   3466         public void enforceServiceExistsAndRequiresBindRemoteViewsPermission(
   3467                 ComponentName componentName, int userId) {
   3468             final long identity = Binder.clearCallingIdentity();
   3469             try {
   3470                 ServiceInfo serviceInfo = mPackageManager.getServiceInfo(componentName,
   3471                         PackageManager.GET_PERMISSIONS, userId);
   3472                 if (serviceInfo == null) {
   3473                     throw new SecurityException("Service " + componentName
   3474                             + " not installed for user " + userId);
   3475                 }
   3476                 if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(serviceInfo.permission)) {
   3477                     throw new SecurityException("Service " + componentName
   3478                             + " in user " + userId + "does not require "
   3479                             + android.Manifest.permission.BIND_REMOTEVIEWS);
   3480                 }
   3481             } catch (RemoteException re) {
   3482                 // Local call - shouldn't happen.
   3483             } finally {
   3484                 Binder.restoreCallingIdentity(identity);
   3485             }
   3486         }
   3487 
   3488         public void enforceModifyAppWidgetBindPermissions(String packageName) {
   3489             mContext.enforceCallingPermission(
   3490                     android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
   3491                     "hasBindAppWidgetPermission packageName=" + packageName);
   3492         }
   3493 
   3494         public void enforceCallFromPackage(String packageName) {
   3495             mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
   3496         }
   3497 
   3498         public boolean hasCallerBindPermissionOrBindWhiteListedLocked(String packageName) {
   3499             try {
   3500                 mContext.enforceCallingOrSelfPermission(
   3501                         android.Manifest.permission.BIND_APPWIDGET, null);
   3502             } catch (SecurityException se) {
   3503                 if (!isCallerBindAppWidgetWhiteListedLocked(packageName)) {
   3504                     return false;
   3505                 }
   3506             }
   3507             return true;
   3508         }
   3509 
   3510         private boolean isCallerBindAppWidgetWhiteListedLocked(String packageName) {
   3511             final int userId = UserHandle.getCallingUserId();
   3512             final int packageUid = getUidForPackage(packageName, userId);
   3513             if (packageUid < 0) {
   3514                 throw new IllegalArgumentException("No package " + packageName
   3515                         + " for user " + userId);
   3516             }
   3517             synchronized (mLock) {
   3518                 ensureGroupStateLoadedLocked(userId);
   3519 
   3520                 Pair<Integer, String> packageId = Pair.create(userId, packageName);
   3521                 if (mPackagesWithBindWidgetPermission.contains(packageId)) {
   3522                     return true;
   3523                 }
   3524             }
   3525 
   3526             return false;
   3527         }
   3528 
   3529         public boolean canAccessAppWidget(Widget widget, int uid, String packageName) {
   3530             if (isHostInPackageForUid(widget.host, uid, packageName)) {
   3531                 // Apps hosting the AppWidget have access to it.
   3532                 return true;
   3533             }
   3534             if (isProviderInPackageForUid(widget.provider, uid, packageName)) {
   3535                 // Apps providing the AppWidget have access to it.
   3536                 return true;
   3537             }
   3538             if (isHostAccessingProvider(widget.host, widget.provider, uid, packageName)) {
   3539                 // Apps hosting the AppWidget get to bind to a remote view service in the provider.
   3540                 return true;
   3541             }
   3542             final int userId = UserHandle.getUserId(uid);
   3543             if ((widget.host.getUserId() == userId || (widget.provider != null
   3544                     && widget.provider.getUserId() == userId))
   3545                 && mContext.checkCallingPermission(android.Manifest.permission.BIND_APPWIDGET)
   3546                     == PackageManager.PERMISSION_GRANTED) {
   3547                 // Apps that run in the same user as either the host or the provider and
   3548                 // have the bind widget permission have access to the widget.
   3549                 return true;
   3550             }
   3551             return false;
   3552         }
   3553 
   3554         private boolean isParentOrProfile(int parentId, int profileId) {
   3555             if (parentId == profileId) {
   3556                 return true;
   3557             }
   3558             return getProfileParent(profileId) == parentId;
   3559         }
   3560 
   3561         public boolean isProviderInCallerOrInProfileAndWhitelListed(String packageName,
   3562                 int profileId) {
   3563             final int callerId = UserHandle.getCallingUserId();
   3564             if (profileId == callerId) {
   3565                 return true;
   3566             }
   3567             final int parentId = getProfileParent(profileId);
   3568             if (parentId != callerId) {
   3569                 return false;
   3570             }
   3571             return isProviderWhiteListed(packageName, profileId);
   3572         }
   3573 
   3574         public boolean isProviderWhiteListed(String packageName, int profileId) {
   3575             // If the policy manager is not available on the device we deny it all.
   3576             if (mDevicePolicyManagerInternal == null) {
   3577                 return false;
   3578             }
   3579 
   3580             List<String> crossProfilePackages = mDevicePolicyManagerInternal
   3581                     .getCrossProfileWidgetProviders(profileId);
   3582 
   3583             return crossProfilePackages.contains(packageName);
   3584         }
   3585 
   3586         public int getProfileParent(int profileId) {
   3587             final long identity = Binder.clearCallingIdentity();
   3588             try {
   3589                 UserInfo parent = mUserManager.getProfileParent(profileId);
   3590                 if (parent != null) {
   3591                     return parent.getUserHandle().getIdentifier();
   3592                 }
   3593             } finally {
   3594                 Binder.restoreCallingIdentity(identity);
   3595             }
   3596             return UNKNOWN_USER_ID;
   3597         }
   3598 
   3599         public int getGroupParent(int profileId) {
   3600             final int parentId = mSecurityPolicy.getProfileParent(profileId);
   3601             return (parentId != UNKNOWN_USER_ID) ? parentId : profileId;
   3602         }
   3603 
   3604         public boolean isHostInPackageForUid(Host host, int uid, String packageName) {
   3605             return host.id.uid == uid && host.id.packageName.equals(packageName);
   3606         }
   3607 
   3608         public boolean isProviderInPackageForUid(Provider provider, int uid,
   3609                 String packageName) {
   3610             // Packages providing the AppWidget have access to it.
   3611             return provider != null && provider.id.uid == uid
   3612                     && provider.id.componentName.getPackageName().equals(packageName);
   3613         }
   3614 
   3615         public boolean isHostAccessingProvider(Host host, Provider provider, int uid,
   3616                 String packageName) {
   3617             // The host creates a package context to bind to remote views service in the provider.
   3618             return host.id.uid == uid && provider != null
   3619                     && provider.id.componentName.getPackageName().equals(packageName);
   3620         }
   3621 
   3622         private boolean isProfileEnabled(int profileId) {
   3623             final long identity = Binder.clearCallingIdentity();
   3624             try {
   3625                 UserInfo userInfo = mUserManager.getUserInfo(profileId);
   3626                 if (userInfo == null || !userInfo.isEnabled()) {
   3627                     return false;
   3628                 }
   3629             } finally {
   3630                 Binder.restoreCallingIdentity(identity);
   3631             }
   3632             return true;
   3633         }
   3634     }
   3635 
   3636     private static final class Provider {
   3637         ProviderId id;
   3638         AppWidgetProviderInfo info;
   3639         ArrayList<Widget> widgets = new ArrayList<>();
   3640         PendingIntent broadcast;
   3641         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
   3642 
   3643         boolean maskedByLockedProfile;
   3644         boolean maskedByQuietProfile;
   3645         boolean maskedBySuspendedPackage;
   3646 
   3647         int tag = TAG_UNDEFINED; // for use while saving state (the index)
   3648 
   3649         public int getUserId() {
   3650             return UserHandle.getUserId(id.uid);
   3651         }
   3652 
   3653         public boolean isInPackageForUser(String packageName, int userId) {
   3654             return getUserId() == userId
   3655                     && id.componentName.getPackageName().equals(packageName);
   3656         }
   3657 
   3658         // is there an instance of this provider hosted by the given app?
   3659         public boolean hostedByPackageForUser(String packageName, int userId) {
   3660             final int N = widgets.size();
   3661             for (int i = 0; i < N; i++) {
   3662                 Widget widget = widgets.get(i);
   3663                 if (packageName.equals(widget.host.id.packageName)
   3664                         && widget.host.getUserId() == userId) {
   3665                     return true;
   3666                 }
   3667             }
   3668             return false;
   3669         }
   3670 
   3671         @Override
   3672         public String toString() {
   3673             return "Provider{" + id + (zombie ? " Z" : "") + '}';
   3674         }
   3675 
   3676         // returns true if it's different from previous state.
   3677         public boolean setMaskedByQuietProfileLocked(boolean masked) {
   3678             boolean oldState = maskedByQuietProfile;
   3679             maskedByQuietProfile = masked;
   3680             return masked != oldState;
   3681         }
   3682 
   3683         // returns true if it's different from previous state.
   3684         public boolean setMaskedByLockedProfileLocked(boolean masked) {
   3685             boolean oldState = maskedByLockedProfile;
   3686             maskedByLockedProfile = masked;
   3687             return masked != oldState;
   3688         }
   3689 
   3690         // returns true if it's different from previous state.
   3691         public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
   3692             boolean oldState = maskedBySuspendedPackage;
   3693             maskedBySuspendedPackage = masked;
   3694             return masked != oldState;
   3695         }
   3696 
   3697         public boolean isMaskedLocked() {
   3698             return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
   3699         }
   3700     }
   3701 
   3702     private static final class ProviderId {
   3703         final int uid;
   3704         final ComponentName componentName;
   3705 
   3706         private ProviderId(int uid, ComponentName componentName) {
   3707             this.uid = uid;
   3708             this.componentName = componentName;
   3709         }
   3710 
   3711         @Override
   3712         public boolean equals(Object obj) {
   3713             if (this == obj) {
   3714                 return true;
   3715             }
   3716             if (obj == null) {
   3717                 return false;
   3718             }
   3719             if (getClass() != obj.getClass()) {
   3720                 return false;
   3721             }
   3722             ProviderId other = (ProviderId) obj;
   3723             if (uid != other.uid)  {
   3724                 return false;
   3725             }
   3726             if (componentName == null) {
   3727                 if (other.componentName != null) {
   3728                     return false;
   3729                 }
   3730             } else if (!componentName.equals(other.componentName)) {
   3731                 return false;
   3732             }
   3733             return true;
   3734         }
   3735 
   3736         @Override
   3737         public int hashCode() {
   3738             int result = uid;
   3739             result = 31 * result + ((componentName != null)
   3740                     ? componentName.hashCode() : 0);
   3741             return result;
   3742         }
   3743 
   3744         @Override
   3745         public String toString() {
   3746             return "ProviderId{user:" + UserHandle.getUserId(uid) + ", app:"
   3747                     + UserHandle.getAppId(uid) + ", cmp:" + componentName + '}';
   3748         }
   3749     }
   3750 
   3751     private static final class Host {
   3752         HostId id;
   3753         ArrayList<Widget> widgets = new ArrayList<>();
   3754         IAppWidgetHost callbacks;
   3755         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
   3756 
   3757         int tag = TAG_UNDEFINED; // for use while saving state (the index)
   3758         long lastWidgetUpdateTime; // last time we were successfully able to send an update.
   3759 
   3760         public int getUserId() {
   3761             return UserHandle.getUserId(id.uid);
   3762         }
   3763 
   3764         public boolean isInPackageForUser(String packageName, int userId) {
   3765             return getUserId() == userId && id.packageName.equals(packageName);
   3766         }
   3767 
   3768         private boolean hostsPackageForUser(String pkg, int userId) {
   3769             final int N = widgets.size();
   3770             for (int i = 0; i < N; i++) {
   3771                 Provider provider = widgets.get(i).provider;
   3772                 if (provider != null && provider.getUserId() == userId && provider.info != null
   3773                         && pkg.equals(provider.info.provider.getPackageName())) {
   3774                     return true;
   3775                 }
   3776             }
   3777             return false;
   3778         }
   3779 
   3780         /**
   3781          * Returns the RemoveViews for the provided widget id if an update is pending
   3782          * for that widget.
   3783          */
   3784         public RemoteViews getPendingViewsForId(int appWidgetId) {
   3785             long updateTime = lastWidgetUpdateTime;
   3786             int N = widgets.size();
   3787             for (int i = 0; i < N; i++) {
   3788                 Widget widget = widgets.get(i);
   3789                 if (widget.appWidgetId == appWidgetId
   3790                         && widget.lastUpdateTime > updateTime) {
   3791                     return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
   3792                 }
   3793             }
   3794             return null;
   3795         }
   3796 
   3797         @Override
   3798         public String toString() {
   3799             return "Host{" + id + (zombie ? " Z" : "") + '}';
   3800         }
   3801     }
   3802 
   3803     private static final class HostId {
   3804         final int uid;
   3805         final int hostId;
   3806         final String packageName;
   3807 
   3808         public HostId(int uid, int hostId, String packageName) {
   3809             this.uid = uid;
   3810             this.hostId = hostId;
   3811             this.packageName = packageName;
   3812         }
   3813 
   3814         @Override
   3815         public boolean equals(Object obj) {
   3816             if (this == obj) {
   3817                 return true;
   3818             }
   3819             if (obj == null) {
   3820                 return false;
   3821             }
   3822             if (getClass() != obj.getClass()) {
   3823                 return false;
   3824             }
   3825             HostId other = (HostId) obj;
   3826             if (uid != other.uid)  {
   3827                 return false;
   3828             }
   3829             if (hostId != other.hostId) {
   3830                 return false;
   3831             }
   3832             if (packageName == null) {
   3833                 if (other.packageName != null) {
   3834                     return false;
   3835                 }
   3836             } else if (!packageName.equals(other.packageName)) {
   3837                 return false;
   3838             }
   3839             return true;
   3840         }
   3841 
   3842         @Override
   3843         public int hashCode() {
   3844             int result = uid;
   3845             result = 31 * result + hostId;
   3846             result = 31 * result + ((packageName != null)
   3847                     ? packageName.hashCode() : 0);
   3848             return result;
   3849         }
   3850 
   3851         @Override
   3852         public String toString() {
   3853             return "HostId{user:" + UserHandle.getUserId(uid) + ", app:"
   3854                     + UserHandle.getAppId(uid) + ", hostId:" + hostId
   3855                     + ", pkg:" + packageName + '}';
   3856         }
   3857     }
   3858 
   3859     private static final class Widget {
   3860         int appWidgetId;
   3861         int restoredId;  // tracking & remapping any restored state
   3862         Provider provider;
   3863         RemoteViews views;
   3864         RemoteViews maskedViews;
   3865         Bundle options;
   3866         Host host;
   3867         long lastUpdateTime;
   3868 
   3869         @Override
   3870         public String toString() {
   3871             return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
   3872         }
   3873 
   3874         private boolean replaceWithMaskedViewsLocked(RemoteViews views) {
   3875             maskedViews = views;
   3876             return true;
   3877         }
   3878 
   3879         private boolean clearMaskedViewsLocked() {
   3880             if (maskedViews != null) {
   3881                 maskedViews = null;
   3882                 return true;
   3883             } else {
   3884                 return false;
   3885             }
   3886         }
   3887 
   3888         public RemoteViews getEffectiveViewsLocked() {
   3889             return maskedViews != null ? maskedViews : views;
   3890         }
   3891     }
   3892 
   3893     /**
   3894      * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection. This
   3895      * needs to be a static inner class since a reference to the ServiceConnection is held globally
   3896      * and may lead us to leak AppWidgetService instances (if there were more than one).
   3897      */
   3898     private static final class ServiceConnectionProxy implements ServiceConnection {
   3899         private final IRemoteViewsAdapterConnection mConnectionCb;
   3900 
   3901         ServiceConnectionProxy(IBinder connectionCb) {
   3902             mConnectionCb = IRemoteViewsAdapterConnection.Stub
   3903                     .asInterface(connectionCb);
   3904         }
   3905 
   3906         public void onServiceConnected(ComponentName name, IBinder service) {
   3907             try {
   3908                 mConnectionCb.onServiceConnected(service);
   3909             } catch (RemoteException re) {
   3910                 Slog.e(TAG, "Error passing service interface", re);
   3911             }
   3912         }
   3913 
   3914         public void onServiceDisconnected(ComponentName name) {
   3915             disconnect();
   3916         }
   3917 
   3918         public void disconnect() {
   3919             try {
   3920                 mConnectionCb.onServiceDisconnected();
   3921             } catch (RemoteException re) {
   3922                 Slog.e(TAG, "Error clearing service interface", re);
   3923             }
   3924         }
   3925     }
   3926 
   3927     private class LoadedWidgetState {
   3928         final Widget widget;
   3929         final int hostTag;
   3930         final int providerTag;
   3931 
   3932         public LoadedWidgetState(Widget widget, int hostTag, int providerTag) {
   3933             this.widget = widget;
   3934             this.hostTag = hostTag;
   3935             this.providerTag = providerTag;
   3936         }
   3937     }
   3938 
   3939     private final class SaveStateRunnable implements Runnable {
   3940         final int mUserId;
   3941 
   3942         public SaveStateRunnable(int userId) {
   3943             mUserId = userId;
   3944         }
   3945 
   3946         @Override
   3947         public void run() {
   3948             synchronized (mLock) {
   3949                 // No need to enforce unlocked state when there is no caller. User can be in the
   3950                 // stopping state or removed by the time the message is processed
   3951                 ensureGroupStateLoadedLocked(mUserId, false /* enforceUserUnlockingOrUnlocked */ );
   3952                 saveStateLocked(mUserId);
   3953             }
   3954         }
   3955     }
   3956 
   3957     /**
   3958      * This class encapsulates the backup and restore logic for a user group state.
   3959      */
   3960     private final class BackupRestoreController {
   3961         private static final String TAG = "BackupRestoreController";
   3962 
   3963         private static final boolean DEBUG = true;
   3964 
   3965         // Version of backed-up widget state.
   3966         private static final int WIDGET_STATE_VERSION = 2;
   3967 
   3968         // We need to make sure to wipe the pre-restore widget state only once for
   3969         // a given package.  Keep track of what we've done so far here; the list is
   3970         // cleared at the start of every system restore pass, but preserved through
   3971         // any install-time restore operations.
   3972         private final HashSet<String> mPrunedApps = new HashSet<>();
   3973 
   3974         private final HashMap<Provider, ArrayList<RestoreUpdateRecord>> mUpdatesByProvider =
   3975                 new HashMap<>();
   3976         private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
   3977                 new HashMap<>();
   3978 
   3979         public List<String> getWidgetParticipants(int userId) {
   3980             if (DEBUG) {
   3981                 Slog.i(TAG, "Getting widget participants for user: " + userId);
   3982             }
   3983 
   3984             HashSet<String> packages = new HashSet<>();
   3985             synchronized (mLock) {
   3986                 final int N = mWidgets.size();
   3987                 for (int i = 0; i < N; i++) {
   3988                     Widget widget = mWidgets.get(i);
   3989 
   3990                     // Skip cross-user widgets.
   3991                     if (!isProviderAndHostInUser(widget, userId)) {
   3992                         continue;
   3993                     }
   3994 
   3995                     packages.add(widget.host.id.packageName);
   3996                     Provider provider = widget.provider;
   3997                     if (provider != null) {
   3998                         packages.add(provider.id.componentName.getPackageName());
   3999                     }
   4000                 }
   4001             }
   4002             return new ArrayList<>(packages);
   4003         }
   4004 
   4005         public byte[] getWidgetState(String backedupPackage, int userId) {
   4006             if (DEBUG) {
   4007                 Slog.i(TAG, "Getting widget state for user: " + userId);
   4008             }
   4009 
   4010             ByteArrayOutputStream stream = new ByteArrayOutputStream();
   4011             synchronized (mLock) {
   4012                 // Preflight: if this app neither hosts nor provides any live widgets
   4013                 // we have no work to do.
   4014                 if (!packageNeedsWidgetBackupLocked(backedupPackage, userId)) {
   4015                     return null;
   4016                 }
   4017 
   4018                 try {
   4019                     XmlSerializer out = new FastXmlSerializer();
   4020                     out.setOutput(stream, StandardCharsets.UTF_8.name());
   4021                     out.startDocument(null, true);
   4022                     out.startTag(null, "ws");      // widget state
   4023                     out.attribute(null, "version", String.valueOf(WIDGET_STATE_VERSION));
   4024                     out.attribute(null, "pkg", backedupPackage);
   4025 
   4026                     // Remember all the providers that are currently hosted or published
   4027                     // by this package: that is, all of the entities related to this app
   4028                     // which will need to be told about id remapping.
   4029                     int index = 0;
   4030                     int N = mProviders.size();
   4031                     for (int i = 0; i < N; i++) {
   4032                         Provider provider = mProviders.get(i);
   4033 
   4034                         if (!provider.widgets.isEmpty()
   4035                                 && (provider.isInPackageForUser(backedupPackage, userId)
   4036                                 || provider.hostedByPackageForUser(backedupPackage, userId))) {
   4037                             provider.tag = index;
   4038                             serializeProvider(out, provider);
   4039                             index++;
   4040                         }
   4041                     }
   4042 
   4043                     N = mHosts.size();
   4044                     index = 0;
   4045                     for (int i = 0; i < N; i++) {
   4046                         Host host = mHosts.get(i);
   4047 
   4048                         if (!host.widgets.isEmpty()
   4049                                 && (host.isInPackageForUser(backedupPackage, userId)
   4050                                 || host.hostsPackageForUser(backedupPackage, userId))) {
   4051                             host.tag = index;
   4052                             serializeHost(out, host);
   4053                             index++;
   4054                         }
   4055                     }
   4056 
   4057                     // All widget instances involving this package,
   4058                     // either as host or as provider
   4059                     N = mWidgets.size();
   4060                     for (int i = 0; i < N; i++) {
   4061                         Widget widget = mWidgets.get(i);
   4062 
   4063                         Provider provider = widget.provider;
   4064                         if (widget.host.isInPackageForUser(backedupPackage, userId)
   4065                                 || (provider != null
   4066                                 &&  provider.isInPackageForUser(backedupPackage, userId))) {
   4067                             serializeAppWidget(out, widget);
   4068                         }
   4069                     }
   4070 
   4071                     out.endTag(null, "ws");
   4072                     out.endDocument();
   4073                 } catch (IOException e) {
   4074                     Slog.w(TAG, "Unable to save widget state for " + backedupPackage);
   4075                     return null;
   4076                 }
   4077             }
   4078 
   4079             return stream.toByteArray();
   4080         }
   4081 
   4082         public void restoreStarting(int userId) {
   4083             if (DEBUG) {
   4084                 Slog.i(TAG, "Restore starting for user: " + userId);
   4085             }
   4086 
   4087             synchronized (mLock) {
   4088                 // We're starting a new "system" restore operation, so any widget restore
   4089                 // state that we see from here on is intended to replace the current
   4090                 // widget configuration of any/all of the affected apps.
   4091                 mPrunedApps.clear();
   4092                 mUpdatesByProvider.clear();
   4093                 mUpdatesByHost.clear();
   4094             }
   4095         }
   4096 
   4097         public void restoreWidgetState(String packageName, byte[] restoredState, int userId) {
   4098             if (DEBUG) {
   4099                 Slog.i(TAG, "Restoring widget state for user:" + userId
   4100                         + " package: " + packageName);
   4101             }
   4102 
   4103             ByteArrayInputStream stream = new ByteArrayInputStream(restoredState);
   4104             try {
   4105                 // Providers mentioned in the widget dataset by ordinal
   4106                 ArrayList<Provider> restoredProviders = new ArrayList<>();
   4107 
   4108                 // Hosts mentioned in the widget dataset by ordinal
   4109                 ArrayList<Host> restoredHosts = new ArrayList<>();
   4110 
   4111                 XmlPullParser parser = Xml.newPullParser();
   4112                 parser.setInput(stream, StandardCharsets.UTF_8.name());
   4113 
   4114                 synchronized (mLock) {
   4115                     int type;
   4116                     do {
   4117                         type = parser.next();
   4118                         if (type == XmlPullParser.START_TAG) {
   4119                             final String tag = parser.getName();
   4120                             if ("ws".equals(tag)) {
   4121                                 String version = parser.getAttributeValue(null, "version");
   4122 
   4123                                 final int versionNumber = Integer.parseInt(version);
   4124                                 if (versionNumber > WIDGET_STATE_VERSION) {
   4125                                     Slog.w(TAG, "Unable to process state version " + version);
   4126                                     return;
   4127                                 }
   4128 
   4129                                 // TODO: fix up w.r.t. canonical vs current package names
   4130                                 String pkg = parser.getAttributeValue(null, "pkg");
   4131                                 if (!packageName.equals(pkg)) {
   4132                                     Slog.w(TAG, "Package mismatch in ws");
   4133                                     return;
   4134                                 }
   4135                             } else if ("p".equals(tag)) {
   4136                                 String pkg = parser.getAttributeValue(null, "pkg");
   4137                                 String cl = parser.getAttributeValue(null, "cl");
   4138 
   4139                                 // hostedProviders index will match 'p' attribute in widget's
   4140                                 // entry in the xml file being restored
   4141                                 // If there's no live entry for this provider, add an inactive one
   4142                                 // so that widget IDs referring to them can be properly allocated
   4143 
   4144                                 // Backup and resotre only for the parent profile.
   4145                                 ComponentName componentName = new ComponentName(pkg, cl);
   4146 
   4147                                 Provider p = findProviderLocked(componentName, userId);
   4148                                 if (p == null) {
   4149                                     p = new Provider();
   4150                                     p.id = new ProviderId(UNKNOWN_UID, componentName);
   4151                                     p.info = new AppWidgetProviderInfo();
   4152                                     p.info.provider = componentName;
   4153                                     p.zombie = true;
   4154                                     mProviders.add(p);
   4155                                 }
   4156                                 if (DEBUG) {
   4157                                     Slog.i(TAG, "   provider " + p.id);
   4158                                 }
   4159                                 restoredProviders.add(p);
   4160                             } else if ("h".equals(tag)) {
   4161                                 // The host app may not yet exist on the device.  If it's here we
   4162                                 // just use the existing Host entry, otherwise we create a
   4163                                 // placeholder whose uid will be fixed up at PACKAGE_ADDED time.
   4164                                 String pkg = parser.getAttributeValue(null, "pkg");
   4165 
   4166                                 final int uid = getUidForPackage(pkg, userId);
   4167                                 final int hostId = Integer.parseInt(
   4168                                         parser.getAttributeValue(null, "id"), 16);
   4169 
   4170                                 HostId id = new HostId(uid, hostId, pkg);
   4171                                 Host h = lookupOrAddHostLocked(id);
   4172                                 restoredHosts.add(h);
   4173 
   4174                                 if (DEBUG) {
   4175                                     Slog.i(TAG, "   host[" + restoredHosts.size()
   4176                                             + "]: {" + h.id + "}");
   4177                                 }
   4178                             } else if ("g".equals(tag)) {
   4179                                 int restoredId = Integer.parseInt(
   4180                                         parser.getAttributeValue(null, "id"), 16);
   4181                                 int hostIndex = Integer.parseInt(
   4182                                         parser.getAttributeValue(null, "h"), 16);
   4183                                 Host host = restoredHosts.get(hostIndex);
   4184                                 Provider p = null;
   4185                                 String prov = parser.getAttributeValue(null, "p");
   4186                                 if (prov != null) {
   4187                                     // could have been null if the app had allocated an id
   4188                                     // but not yet established a binding under that id
   4189                                     int which = Integer.parseInt(prov, 16);
   4190                                     p = restoredProviders.get(which);
   4191                                 }
   4192 
   4193                                 // We'll be restoring widget state for both the host and
   4194                                 // provider sides of this widget ID, so make sure we are
   4195                                 // beginning from a clean slate on both fronts.
   4196                                 pruneWidgetStateLocked(host.id.packageName, userId);
   4197                                 if (p != null) {
   4198                                     pruneWidgetStateLocked(p.id.componentName.getPackageName(),
   4199                                             userId);
   4200                                 }
   4201 
   4202                                 // Have we heard about this ancestral widget instance before?
   4203                                 Widget id = findRestoredWidgetLocked(restoredId, host, p);
   4204                                 if (id == null) {
   4205                                     id = new Widget();
   4206                                     id.appWidgetId = incrementAndGetAppWidgetIdLocked(userId);
   4207                                     id.restoredId = restoredId;
   4208                                     id.options = parseWidgetIdOptions(parser);
   4209                                     id.host = host;
   4210                                     id.host.widgets.add(id);
   4211                                     id.provider = p;
   4212                                     if (id.provider != null) {
   4213                                         id.provider.widgets.add(id);
   4214                                     }
   4215                                     if (DEBUG) {
   4216                                         Slog.i(TAG, "New restored id " + restoredId
   4217                                                 + " now " + id);
   4218                                     }
   4219                                     addWidgetLocked(id);
   4220                                 }
   4221                                 if (id.provider.info != null) {
   4222                                     stashProviderRestoreUpdateLocked(id.provider,
   4223                                             restoredId, id.appWidgetId);
   4224                                 } else {
   4225                                     Slog.w(TAG, "Missing provider for restored widget " + id);
   4226                                 }
   4227                                 stashHostRestoreUpdateLocked(id.host, restoredId, id.appWidgetId);
   4228 
   4229                                 if (DEBUG) {
   4230                                     Slog.i(TAG, "   instance: " + restoredId
   4231                                             + " -> " + id.appWidgetId
   4232                                             + " :: p=" + id.provider);
   4233                                 }
   4234                             }
   4235                         }
   4236                     } while (type != XmlPullParser.END_DOCUMENT);
   4237 
   4238                     // We've updated our own bookkeeping.  We'll need to notify the hosts and
   4239                     // providers about the changes, but we can't do that yet because the restore
   4240                     // target is not necessarily fully live at this moment.  Set aside the
   4241                     // information for now; the backup manager will call us once more at the
   4242                     // end of the process when all of the targets are in a known state, and we
   4243                     // will update at that point.
   4244                 }
   4245             } catch (XmlPullParserException | IOException e) {
   4246                 Slog.w(TAG, "Unable to restore widget state for " + packageName);
   4247             } finally {
   4248                 saveGroupStateAsync(userId);
   4249             }
   4250         }
   4251 
   4252         // Called once following the conclusion of a restore operation.  This is when we
   4253         // send out updates to apps involved in widget-state restore telling them about
   4254         // the new widget ID space.
   4255         public void restoreFinished(int userId) {
   4256             if (DEBUG) {
   4257                 Slog.i(TAG, "restoreFinished for " + userId);
   4258             }
   4259 
   4260             final UserHandle userHandle = new UserHandle(userId);
   4261             synchronized (mLock) {
   4262                 // Build the providers' broadcasts and send them off
   4263                 Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
   4264                         = mUpdatesByProvider.entrySet();
   4265                 for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
   4266                     // For each provider there's a list of affected IDs
   4267                     Provider provider = e.getKey();
   4268                     ArrayList<RestoreUpdateRecord> updates = e.getValue();
   4269                     final int pending = countPendingUpdates(updates);
   4270                     if (DEBUG) {
   4271                         Slog.i(TAG, "Provider " + provider + " pending: " + pending);
   4272                     }
   4273                     if (pending > 0) {
   4274                         int[] oldIds = new int[pending];
   4275                         int[] newIds = new int[pending];
   4276                         final int N = updates.size();
   4277                         int nextPending = 0;
   4278                         for (int i = 0; i < N; i++) {
   4279                             RestoreUpdateRecord r = updates.get(i);
   4280                             if (!r.notified) {
   4281                                 r.notified = true;
   4282                                 oldIds[nextPending] = r.oldId;
   4283                                 newIds[nextPending] = r.newId;
   4284                                 nextPending++;
   4285                                 if (DEBUG) {
   4286                                     Slog.i(TAG, "   " + r.oldId + " => " + r.newId);
   4287                                 }
   4288                             }
   4289                         }
   4290                         sendWidgetRestoreBroadcastLocked(
   4291                                 AppWidgetManager.ACTION_APPWIDGET_RESTORED,
   4292                                 provider, null, oldIds, newIds, userHandle);
   4293                     }
   4294                 }
   4295 
   4296                 // same thing per host
   4297                 Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries
   4298                         = mUpdatesByHost.entrySet();
   4299                 for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) {
   4300                     Host host = e.getKey();
   4301                     if (host.id.uid != UNKNOWN_UID) {
   4302                         ArrayList<RestoreUpdateRecord> updates = e.getValue();
   4303                         final int pending = countPendingUpdates(updates);
   4304                         if (DEBUG) {
   4305                             Slog.i(TAG, "Host " + host + " pending: " + pending);
   4306                         }
   4307                         if (pending > 0) {
   4308                             int[] oldIds = new int[pending];
   4309                             int[] newIds = new int[pending];
   4310                             final int N = updates.size();
   4311                             int nextPending = 0;
   4312                             for (int i = 0; i < N; i++) {
   4313                                 RestoreUpdateRecord r = updates.get(i);
   4314                                 if (!r.notified) {
   4315                                     r.notified = true;
   4316                                     oldIds[nextPending] = r.oldId;
   4317                                     newIds[nextPending] = r.newId;
   4318                                     nextPending++;
   4319                                     if (DEBUG) {
   4320                                         Slog.i(TAG, "   " + r.oldId + " => " + r.newId);
   4321                                     }
   4322                                 }
   4323                             }
   4324                             sendWidgetRestoreBroadcastLocked(
   4325                                     AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED,
   4326                                     null, host, oldIds, newIds, userHandle);
   4327                         }
   4328                     }
   4329                 }
   4330             }
   4331         }
   4332 
   4333         private Provider findProviderLocked(ComponentName componentName, int userId) {
   4334             final int providerCount = mProviders.size();
   4335             for (int i = 0; i < providerCount; i++) {
   4336                 Provider provider = mProviders.get(i);
   4337                 if (provider.getUserId() == userId
   4338                         && provider.id.componentName.equals(componentName)) {
   4339                     return provider;
   4340                 }
   4341             }
   4342             return null;
   4343         }
   4344 
   4345         private Widget findRestoredWidgetLocked(int restoredId, Host host, Provider p) {
   4346             if (DEBUG) {
   4347                 Slog.i(TAG, "Find restored widget: id=" + restoredId
   4348                         + " host=" + host + " provider=" + p);
   4349             }
   4350 
   4351             if (p == null || host == null) {
   4352                 return null;
   4353             }
   4354 
   4355             final int N = mWidgets.size();
   4356             for (int i = 0; i < N; i++) {
   4357                 Widget widget = mWidgets.get(i);
   4358                 if (widget.restoredId == restoredId
   4359                         && widget.host.id.equals(host.id)
   4360                         && widget.provider.id.equals(p.id)) {
   4361                     if (DEBUG) {
   4362                         Slog.i(TAG, "   Found at " + i + " : " + widget);
   4363                     }
   4364                     return widget;
   4365                 }
   4366             }
   4367             return null;
   4368         }
   4369 
   4370         private boolean packageNeedsWidgetBackupLocked(String packageName, int userId) {
   4371             int N = mWidgets.size();
   4372             for (int i = 0; i < N; i++) {
   4373                 Widget widget = mWidgets.get(i);
   4374 
   4375                 // Skip cross-user widgets.
   4376                 if (!isProviderAndHostInUser(widget, userId)) {
   4377                     continue;
   4378                 }
   4379 
   4380                 if (widget.host.isInPackageForUser(packageName, userId)) {
   4381                     // this package is hosting widgets, so it knows widget IDs.
   4382                     return true;
   4383                 }
   4384 
   4385                 Provider provider = widget.provider;
   4386                 if (provider != null && provider.isInPackageForUser(packageName, userId)) {
   4387                     // someone is hosting this app's widgets, so it knows widget IDs.
   4388                     return true;
   4389                 }
   4390             }
   4391             return false;
   4392         }
   4393 
   4394         private void stashProviderRestoreUpdateLocked(Provider provider, int oldId, int newId) {
   4395             ArrayList<RestoreUpdateRecord> r = mUpdatesByProvider.get(provider);
   4396             if (r == null) {
   4397                 r = new ArrayList<>();
   4398                 mUpdatesByProvider.put(provider, r);
   4399             } else {
   4400                 // don't duplicate
   4401                 if (alreadyStashed(r, oldId, newId)) {
   4402                     if (DEBUG) {
   4403                         Slog.i(TAG, "ID remap " + oldId + " -> " + newId
   4404                                 + " already stashed for " + provider);
   4405                     }
   4406                     return;
   4407                 }
   4408             }
   4409             r.add(new RestoreUpdateRecord(oldId, newId));
   4410         }
   4411 
   4412         private boolean alreadyStashed(ArrayList<RestoreUpdateRecord> stash,
   4413                 final int oldId, final int newId) {
   4414             final int N = stash.size();
   4415             for (int i = 0; i < N; i++) {
   4416                 RestoreUpdateRecord r = stash.get(i);
   4417                 if (r.oldId == oldId && r.newId == newId) {
   4418                     return true;
   4419                 }
   4420             }
   4421             return false;
   4422         }
   4423 
   4424         private void stashHostRestoreUpdateLocked(Host host, int oldId, int newId) {
   4425             ArrayList<RestoreUpdateRecord> r = mUpdatesByHost.get(host);
   4426             if (r == null) {
   4427                 r = new ArrayList<>();
   4428                 mUpdatesByHost.put(host, r);
   4429             } else {
   4430                 if (alreadyStashed(r, oldId, newId)) {
   4431                     if (DEBUG) {
   4432                         Slog.i(TAG, "ID remap " + oldId + " -> " + newId
   4433                                 + " already stashed for " + host);
   4434                     }
   4435                     return;
   4436                 }
   4437             }
   4438             r.add(new RestoreUpdateRecord(oldId, newId));
   4439         }
   4440 
   4441         private void sendWidgetRestoreBroadcastLocked(String action, Provider provider,
   4442                 Host host, int[] oldIds, int[] newIds, UserHandle userHandle) {
   4443             Intent intent = new Intent(action);
   4444             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds);
   4445             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds);
   4446             if (provider != null) {
   4447                 intent.setComponent(provider.info.provider);
   4448                 sendBroadcastAsUser(intent, userHandle);
   4449             }
   4450             if (host != null) {
   4451                 intent.setComponent(null);
   4452                 intent.setPackage(host.id.packageName);
   4453                 intent.putExtra(AppWidgetManager.EXTRA_HOST_ID, host.id.hostId);
   4454                 sendBroadcastAsUser(intent, userHandle);
   4455             }
   4456         }
   4457 
   4458         // We're restoring widget state for 'pkg', so we start by wiping (a) all widget
   4459         // instances that are hosted by that app, and (b) all instances in other hosts
   4460         // for which 'pkg' is the provider.  We assume that we'll be restoring all of
   4461         // these hosts & providers, so will be reconstructing a correct live state.
   4462         private void pruneWidgetStateLocked(String pkg, int userId) {
   4463             if (!mPrunedApps.contains(pkg)) {
   4464                 if (DEBUG) {
   4465                     Slog.i(TAG, "pruning widget state for restoring package " + pkg);
   4466                 }
   4467                 for (int i = mWidgets.size() - 1; i >= 0; i--) {
   4468                     Widget widget = mWidgets.get(i);
   4469 
   4470                     Host host = widget.host;
   4471                     Provider provider = widget.provider;
   4472 
   4473                     if (host.hostsPackageForUser(pkg, userId)
   4474                             || (provider != null && provider.isInPackageForUser(pkg, userId))) {
   4475                         // 'pkg' is either the host or the provider for this instances,
   4476                         // so we tear it down in anticipation of it (possibly) being
   4477                         // reconstructed due to the restore
   4478                         host.widgets.remove(widget);
   4479                         provider.widgets.remove(widget);
   4480                         unbindAppWidgetRemoteViewsServicesLocked(widget);
   4481                         removeWidgetLocked(widget);
   4482                     }
   4483                 }
   4484                 mPrunedApps.add(pkg);
   4485             } else {
   4486                 if (DEBUG) {
   4487                     Slog.i(TAG, "already pruned " + pkg + ", continuing normally");
   4488                 }
   4489             }
   4490         }
   4491 
   4492         private boolean isProviderAndHostInUser(Widget widget, int userId) {
   4493             // Backup only widgets hosted or provided by the owner profile.
   4494             return widget.host.getUserId() == userId && (widget.provider == null
   4495                     || widget.provider.getUserId() == userId);
   4496         }
   4497 
   4498         private Bundle parseWidgetIdOptions(XmlPullParser parser) {
   4499             Bundle options = new Bundle();
   4500             String minWidthString = parser.getAttributeValue(null, "min_width");
   4501             if (minWidthString != null) {
   4502                 options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
   4503                         Integer.parseInt(minWidthString, 16));
   4504             }
   4505             String minHeightString = parser.getAttributeValue(null, "min_height");
   4506             if (minHeightString != null) {
   4507                 options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
   4508                         Integer.parseInt(minHeightString, 16));
   4509             }
   4510             String maxWidthString = parser.getAttributeValue(null, "max_width");
   4511             if (maxWidthString != null) {
   4512                 options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
   4513                         Integer.parseInt(maxWidthString, 16));
   4514             }
   4515             String maxHeightString = parser.getAttributeValue(null, "max_height");
   4516             if (maxHeightString != null) {
   4517                 options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
   4518                         Integer.parseInt(maxHeightString, 16));
   4519             }
   4520             String categoryString = parser.getAttributeValue(null, "host_category");
   4521             if (categoryString != null) {
   4522                 options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
   4523                         Integer.parseInt(categoryString, 16));
   4524             }
   4525             return options;
   4526         }
   4527 
   4528         private int countPendingUpdates(ArrayList<RestoreUpdateRecord> updates) {
   4529             int pending = 0;
   4530             final int N = updates.size();
   4531             for (int i = 0; i < N; i++) {
   4532                 RestoreUpdateRecord r = updates.get(i);
   4533                 if (!r.notified) {
   4534                     pending++;
   4535                 }
   4536             }
   4537             return pending;
   4538         }
   4539 
   4540         // Accumulate a list of updates that affect the given provider for a final
   4541         // coalesced notification broadcast once restore is over.
   4542         private class RestoreUpdateRecord {
   4543             public int oldId;
   4544             public int newId;
   4545             public boolean notified;
   4546 
   4547             public RestoreUpdateRecord(int theOldId, int theNewId) {
   4548                 oldId = theOldId;
   4549                 newId = theNewId;
   4550                 notified = false;
   4551             }
   4552         }
   4553     }
   4554 }
   4555