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