1 /*
2  * Copyright (C) 2021 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.pm;
18 
19 import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
20 import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
21 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
22 import static android.os.Process.SYSTEM_UID;
23 import static android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED;
24 
25 import static com.android.server.pm.PackageManagerService.DEBUG_BACKUP;
26 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
27 import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
28 import static com.android.server.pm.PackageManagerService.PACKAGE_SCHEME;
29 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
30 import static com.android.server.pm.PackageManagerService.TAG;
31 
32 import android.Manifest;
33 import android.annotation.AppIdInt;
34 import android.annotation.NonNull;
35 import android.annotation.Nullable;
36 import android.annotation.SuppressLint;
37 import android.app.ActivityManager;
38 import android.app.ActivityManagerInternal;
39 import android.app.BroadcastOptions;
40 import android.app.IActivityManager;
41 import android.content.ComponentName;
42 import android.content.Context;
43 import android.content.IIntentReceiver;
44 import android.content.Intent;
45 import android.content.pm.PackageInstaller;
46 import android.content.pm.PackageManager;
47 import android.content.pm.UserInfo;
48 import android.content.pm.UserProperties;
49 import android.multiuser.Flags;
50 import android.net.Uri;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.PowerExemptionManager;
54 import android.os.Process;
55 import android.os.RemoteException;
56 import android.os.UserHandle;
57 import android.os.storage.StorageManager;
58 import android.os.storage.VolumeInfo;
59 import android.provider.DeviceConfig;
60 import android.stats.storage.StorageEnums;
61 import android.util.IntArray;
62 import android.util.Log;
63 import android.util.Pair;
64 import android.util.Slog;
65 import android.util.SparseArray;
66 
67 import com.android.internal.util.ArrayUtils;
68 import com.android.internal.util.FrameworkStatsLog;
69 import com.android.server.pm.pkg.AndroidPackage;
70 import com.android.server.pm.pkg.PackageStateInternal;
71 import com.android.server.pm.pkg.PackageUserStateInternal;
72 
73 import java.util.ArrayList;
74 import java.util.Arrays;
75 import java.util.Collections;
76 import java.util.function.BiFunction;
77 
78 /**
79  * Helper class to send broadcasts for various situations.
80  */
81 public final class BroadcastHelper {
82     private static final boolean DEBUG_BROADCASTS = false;
83     /**
84      * Permissions required in order to receive instant application lifecycle broadcasts.
85      */
86     private static final String[] INSTANT_APP_BROADCAST_PERMISSION =
87             new String[]{android.Manifest.permission.ACCESS_INSTANT_APPS};
88 
89     private final UserManagerInternal mUmInternal;
90     private final ActivityManagerInternal mAmInternal;
91     private final Context mContext;
92     private final Handler mHandler;
93     private final PackageMonitorCallbackHelper mPackageMonitorCallbackHelper;
94     private final AppsFilterSnapshot mAppsFilter;
95 
BroadcastHelper(PackageManagerServiceInjector injector)96     BroadcastHelper(PackageManagerServiceInjector injector) {
97         mUmInternal = injector.getUserManagerInternal();
98         mAmInternal = injector.getActivityManagerInternal();
99         mContext = injector.getContext();
100         mHandler = injector.getHandler();
101         mPackageMonitorCallbackHelper = injector.getPackageMonitorCallbackHelper();
102         mAppsFilter = injector.getAppsFilter();
103     }
104 
105     /**
106      * Sends a broadcast to registered clients on userId for the given Intent.
107      */
sendPackageBroadcastWithIntent(Intent intent, int userId, boolean isInstantApp, @Intent.Flags int flags, int[] visibilityAllowList, final IIntentReceiver finishedReceiver, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @Nullable Bundle bOptions)108     void sendPackageBroadcastWithIntent(Intent intent, int userId, boolean isInstantApp,
109             @Intent.Flags int flags,
110             int[] visibilityAllowList,
111             final IIntentReceiver finishedReceiver,
112             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
113             @Nullable Bundle bOptions) {
114         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | flags);
115         SparseArray<int[]> broadcastAllowList = new SparseArray<>();
116         broadcastAllowList.put(userId, visibilityAllowList);
117         broadcastIntent(intent, finishedReceiver, isInstantApp, userId, broadcastAllowList,
118                 filterExtrasForReceiver, bOptions);
119     }
120 
sendPackageBroadcast(final String action, final String pkg, final Bundle extras, final int flags, final String targetPkg, final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @Nullable Bundle bOptions)121     void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
122             final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
123             final int[] userIds, int[] instantUserIds,
124             @Nullable SparseArray<int[]> broadcastAllowList,
125             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
126             @Nullable Bundle bOptions) {
127         try {
128             final IActivityManager am = ActivityManager.getService();
129             if (am == null) return;
130             final int[] resolvedUserIds;
131             if (userIds == null) {
132                 resolvedUserIds = am.getRunningUserIds();
133             } else {
134                 resolvedUserIds = userIds;
135             }
136 
137             if (ArrayUtils.isEmpty(instantUserIds)) {
138                 doSendBroadcast(action, pkg, extras, flags, targetPkg, finishedReceiver,
139                         resolvedUserIds, false /* isInstantApp */, broadcastAllowList,
140                         filterExtrasForReceiver, bOptions);
141             } else {
142                 // send restricted broadcasts for instant apps
143                 doSendBroadcast(action, pkg, extras, flags, targetPkg, finishedReceiver,
144                         instantUserIds, true /* isInstantApp */, null,
145                         null /* filterExtrasForReceiver */, bOptions);
146             }
147         } catch (RemoteException ex) {
148         }
149     }
150 
151     /**
152      * Sends a broadcast for the given action.
153      * <p>If {@code isInstantApp} is {@code true}, then the broadcast is protected with
154      * the {@link android.Manifest.permission#ACCESS_INSTANT_APPS} permission. This allows
155      * the system and applications allowed to see instant applications to receive package
156      * lifecycle events for instant applications.
157      */
doSendBroadcast( @onNull String action, @Nullable String pkg, @Nullable Bundle extras, int flags, @Nullable String targetPkg, @Nullable IIntentReceiver finishedReceiver, @NonNull int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @Nullable Bundle bOptions)158     private void doSendBroadcast(
159             @NonNull String action,
160             @Nullable String pkg,
161             @Nullable Bundle extras,
162             int flags,
163             @Nullable String targetPkg,
164             @Nullable IIntentReceiver finishedReceiver,
165             @NonNull int[] userIds,
166             boolean isInstantApp,
167             @Nullable SparseArray<int[]> broadcastAllowList,
168             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
169             @Nullable Bundle bOptions) {
170         for (int userId : userIds) {
171             final Intent intent = new Intent(action,
172                     pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);
173             if (extras != null) {
174                 intent.putExtras(extras);
175             }
176             if (targetPkg != null) {
177                 intent.setPackage(targetPkg);
178             }
179             // Modify the UID when posting to other users
180             int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
181             if (uid >= 0 && UserHandle.getUserId(uid) != userId) {
182                 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
183                 intent.putExtra(Intent.EXTRA_UID, uid);
184             }
185             if (broadcastAllowList != null && PLATFORM_PACKAGE_NAME.equals(targetPkg)) {
186                 intent.putExtra(Intent.EXTRA_VISIBILITY_ALLOW_LIST,
187                          broadcastAllowList.get(userId));
188             }
189             intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
190             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | flags);
191             broadcastIntent(intent, finishedReceiver, isInstantApp, userId, broadcastAllowList,
192                     filterExtrasForReceiver, bOptions);
193         }
194     }
195 
196 
broadcastIntent(Intent intent, IIntentReceiver finishedReceiver, boolean isInstantApp, int userId, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @Nullable Bundle bOptions)197     private void broadcastIntent(Intent intent, IIntentReceiver finishedReceiver,
198             boolean isInstantApp, int userId, @Nullable SparseArray<int[]> broadcastAllowList,
199             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
200             @Nullable Bundle bOptions) {
201         final String[] requiredPermissions =
202                 isInstantApp ? INSTANT_APP_BROADCAST_PERMISSION : null;
203         if (DEBUG_BROADCASTS) {
204             RuntimeException here = new RuntimeException("here");
205             here.fillInStackTrace();
206             Slog.d(TAG, "Sending to user " + userId + ": "
207                     + intent.toShortString(false, true, false, false)
208                     + " " + intent.getExtras(), here);
209         }
210         mAmInternal.broadcastIntentWithCallback(
211                 intent, finishedReceiver, requiredPermissions, userId,
212                 broadcastAllowList == null ? null : broadcastAllowList.get(userId),
213                 filterExtrasForReceiver, bOptions);
214     }
215 
sendResourcesChangedBroadcast(@onNull Computer snapshot, boolean mediaStatus, boolean replacing, @NonNull String[] pkgNames, @NonNull int[] uids)216     void sendResourcesChangedBroadcast(@NonNull Computer snapshot,
217                                        boolean mediaStatus,
218                                        boolean replacing,
219                                        @NonNull String[] pkgNames,
220                                        @NonNull int[] uids) {
221         if (ArrayUtils.isEmpty(pkgNames) || ArrayUtils.isEmpty(uids)) {
222             return;
223         }
224         Bundle extras = new Bundle();
225         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgNames);
226         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids);
227         if (replacing) {
228             extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
229         }
230         String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
231                 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
232         sendPackageBroadcast(action, null /* pkg */, extras, 0 /* flags */,
233                 null /* targetPkg */, null /* finishedReceiver */, null /* userIds */,
234                 null /* instantUserIds */, null /* broadcastAllowList */,
235                 (callingUid, intentExtras) -> filterExtrasChangedPackageList(
236                         snapshot, callingUid, intentExtras),
237                 null /* bOptions */);
238     }
239 
240     /**
241      * The just-installed/enabled app is bundled on the system, so presumed to be able to run
242      * automatically without needing an explicit launch.
243      * Send it a LOCKED_BOOT_COMPLETED/BOOT_COMPLETED if it would ordinarily have gotten ones.
244      */
sendBootCompletedBroadcastToSystemApp(@onNull String packageName, boolean includeStopped, int userId)245     private void sendBootCompletedBroadcastToSystemApp(@NonNull String packageName,
246                                                        boolean includeStopped,
247                                                        int userId) {
248         // If user is not running, the app didn't miss any broadcast
249         if (!mUmInternal.isUserRunning(userId)) {
250             return;
251         }
252         final IActivityManager am = ActivityManager.getService();
253         try {
254             // Deliver LOCKED_BOOT_COMPLETED first
255             Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
256                     .setPackage(packageName);
257             lockedBcIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
258             if (includeStopped) {
259                 lockedBcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
260             }
261             final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
262             final BroadcastOptions bOptions = getTemporaryAppAllowlistBroadcastOptions(
263                     REASON_LOCKED_BOOT_COMPLETED);
264             am.broadcastIntentWithFeature(null, null, lockedBcIntent, null, null, 0, null, null,
265                     requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE,
266                     bOptions.toBundle(), false, false, userId);
267 
268             // Deliver BOOT_COMPLETED only if user is unlocked
269             if (mUmInternal.isUserUnlockingOrUnlocked(userId)) {
270                 Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName);
271                 bcIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
272                 if (includeStopped) {
273                     bcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
274                 }
275                 am.broadcastIntentWithFeature(null, null, bcIntent, null, null, 0, null, null,
276                         requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE,
277                         bOptions.toBundle(), false, false, userId);
278             }
279         } catch (RemoteException e) {
280             throw e.rethrowFromSystemServer();
281         }
282     }
283 
getTemporaryAppAllowlistBroadcastOptions( @owerExemptionManager.ReasonCode int reasonCode)284     private @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
285             @PowerExemptionManager.ReasonCode int reasonCode) {
286         long duration = 10_000;
287         if (mAmInternal != null) {
288             duration = mAmInternal.getBootTimeTempAllowListDuration();
289         }
290         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
291         bOptions.setTemporaryAppAllowlist(duration,
292                 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
293                 reasonCode, "");
294         return bOptions;
295     }
296 
sendPackageChangedBroadcast(@onNull String packageName, boolean dontKillApp, @NonNull ArrayList<String> componentNames, int packageUid, @Nullable String reason, @Nullable int[] userIds, @Nullable int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList)297     private void sendPackageChangedBroadcast(@NonNull String packageName,
298                                              boolean dontKillApp,
299                                              @NonNull ArrayList<String> componentNames,
300                                              int packageUid,
301                                              @Nullable String reason,
302                                              @Nullable int[] userIds,
303                                              @Nullable int[] instantUserIds,
304                                              @Nullable SparseArray<int[]> broadcastAllowList) {
305         if (DEBUG_INSTALL) {
306             Log.v(TAG, "Sending package changed: package=" + packageName + " components="
307                     + componentNames);
308         }
309         Bundle extras = new Bundle(4);
310         extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
311         String[] nameList = new String[componentNames.size()];
312         componentNames.toArray(nameList);
313         extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
314         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, dontKillApp);
315         extras.putInt(Intent.EXTRA_UID, packageUid);
316         if (reason != null) {
317             extras.putString(Intent.EXTRA_REASON, reason);
318         }
319         // If this is not reporting a change of the overall package, then only send it
320         // to registered receivers.  We don't want to launch a swath of apps for every
321         // little component state change.
322         final int flags = !componentNames.contains(packageName)
323                 ? Intent.FLAG_RECEIVER_REGISTERED_ONLY : 0;
324         sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
325                 userIds, instantUserIds, broadcastAllowList, null /* filterExtrasForReceiver */,
326                 null /* bOptions */);
327     }
328 
sendDeviceCustomizationReadyBroadcast()329     static void sendDeviceCustomizationReadyBroadcast() {
330         final Intent intent = new Intent(Intent.ACTION_DEVICE_CUSTOMIZATION_READY);
331         intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
332         final IActivityManager am = ActivityManager.getService();
333         final String[] requiredPermissions = {
334                 Manifest.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY,
335         };
336         try {
337             am.broadcastIntentWithFeature(null, null, intent, null, null, 0, null, null,
338                     requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, null, false,
339                     false, UserHandle.USER_ALL);
340         } catch (RemoteException e) {
341             throw e.rethrowFromSystemServer();
342         }
343     }
344 
sendSessionCommitBroadcast(@onNull Computer snapshot, @NonNull PackageInstaller.SessionInfo sessionInfo, int userId, @Nullable String appPredictionServicePackage)345     void sendSessionCommitBroadcast(@NonNull Computer snapshot,
346                                     @NonNull PackageInstaller.SessionInfo sessionInfo,
347                                     int userId,
348                                     @Nullable String appPredictionServicePackage) {
349         UserManagerService ums = UserManagerService.getInstance();
350         if (ums == null || sessionInfo.isStaged()) {
351             return;
352         }
353         final UserInfo parent = ums.getProfileParent(userId);
354         final int launcherUserId = (parent != null) ? parent.id : userId;
355         final ComponentName launcherComponent = snapshot.getDefaultHomeActivity(launcherUserId);
356         if (launcherComponent != null && canLauncherAccessProfile(launcherComponent, userId)) {
357             Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
358                     .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
359                     .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
360                     .setPackage(launcherComponent.getPackageName());
361             mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUserId));
362         }
363         if (appPredictionServicePackage != null) {
364             Intent predictorIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
365                     .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
366                     .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
367                     .setPackage(appPredictionServicePackage);
368             mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUserId));
369         }
370     }
371 
372     /**
373      * A Profile is accessible to launcher in question if:
374      * - It's not hidden for API visibility.
375      * - Hidden, but launcher application has either
376      *      {@link Manifest.permission.ACCESS_HIDDEN_PROFILES_FULL} or
377      *      {@link Manifest.permission.ACCESS_HIDDEN_PROFILES}
378      *   granted.
379      */
canLauncherAccessProfile(ComponentName launcherComponent, int userId)380     boolean canLauncherAccessProfile(ComponentName launcherComponent, int userId) {
381         if (android.os.Flags.allowPrivateProfile()
382                 && Flags.enablePermissionToAccessHiddenProfiles()
383                 && Flags.enablePrivateSpaceFeatures()) {
384             if (mUmInternal.getUserProperties(userId).getProfileApiVisibility()
385                     != UserProperties.PROFILE_API_VISIBILITY_HIDDEN) {
386                 return true;
387             }
388             if (mContext.getPackageManager().checkPermission(
389                             Manifest.permission.ACCESS_HIDDEN_PROFILES_FULL,
390                             launcherComponent.getPackageName())
391                     == PackageManager.PERMISSION_GRANTED) {
392                 return true;
393             }
394             // TODO(b/122900055) Change/Remove this and replace with new permission role.
395             return mContext.getPackageManager().checkPermission(
396                             Manifest.permission.ACCESS_HIDDEN_PROFILES,
397                             launcherComponent.getPackageName())
398                         == PackageManager.PERMISSION_GRANTED;
399         }
400         return true;
401     }
402 
sendPreferredActivityChangedBroadcast(int userId)403     void sendPreferredActivityChangedBroadcast(int userId) {
404         mHandler.post(() -> {
405             final IActivityManager am = ActivityManager.getService();
406             if (am == null) {
407                 return;
408             }
409 
410             final Intent intent = new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
411             intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
412             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
413             try {
414                 am.broadcastIntentWithFeature(null, null, intent, null, null,
415                         0, null, null, null, null, null, android.app.AppOpsManager.OP_NONE,
416                         null, false, false, userId);
417             } catch (RemoteException e) {
418             }
419         });
420     }
421 
sendPostInstallBroadcasts(@onNull Computer snapshot, @NonNull InstallRequest request, @NonNull String packageName, @NonNull String requiredPermissionControllerPackage, @NonNull String[] requiredVerifierPackages, @NonNull String requiredInstallerPackage, @NonNull PackageSender packageSender, boolean isLaunchedForRestore, boolean isKillApp, boolean isUpdate, boolean isArchived)422     void sendPostInstallBroadcasts(@NonNull Computer snapshot,
423                                    @NonNull InstallRequest request,
424                                    @NonNull String packageName,
425                                    @NonNull String requiredPermissionControllerPackage,
426                                    @NonNull String[] requiredVerifierPackages,
427                                    @NonNull String requiredInstallerPackage,
428                                    @NonNull PackageSender packageSender,
429                                    boolean isLaunchedForRestore,
430                                    boolean isKillApp,
431                                    boolean isUpdate,
432                                    boolean isArchived) {
433         // Send the removed broadcasts
434         if (request.getRemovedInfo() != null) {
435             if (request.getRemovedInfo().mIsExternal) {
436                 if (DEBUG_INSTALL) {
437                     Slog.i(TAG, "upgrading pkg " + request.getRemovedInfo().mRemovedPackage
438                             + " is ASEC-hosted -> UNAVAILABLE");
439                 }
440                 final String[] pkgNames = new String[]{
441                         request.getRemovedInfo().mRemovedPackage};
442                 final int[] uids = new int[]{request.getRemovedInfo().mUid};
443                 notifyResourcesChanged(
444                         false /* mediaStatus */, true /* replacing */, pkgNames, uids);
445                 sendResourcesChangedBroadcast(
446                         snapshot, false /* mediaStatus */, true /* replacing */, pkgNames, uids);
447             }
448             sendPackageRemovedBroadcasts(
449                     request.getRemovedInfo(), packageSender, isKillApp, false /*removedBySystem*/,
450                     false /*isArchived*/);
451         }
452 
453         final int[] firstUserIds = request.getFirstTimeBroadcastUserIds();
454         final int[] firstInstantUserIds = request.getFirstTimeBroadcastInstantUserIds();
455         final int[] updateUserIds = request.getUpdateBroadcastUserIds();
456         final int[] instantUserIds = request.getUpdateBroadcastInstantUserIds();
457 
458         final String installerPackageName =
459                 request.getInstallerPackageName() != null
460                         ? request.getInstallerPackageName()
461                         : request.getRemovedInfo() != null
462                         ? request.getRemovedInfo().mInstallerPackageName
463                         : null;
464 
465         Bundle extras = new Bundle();
466         extras.putInt(Intent.EXTRA_UID, request.getAppId());
467         if (isUpdate) {
468             extras.putBoolean(Intent.EXTRA_REPLACING, true);
469         }
470         if (isArchived) {
471             extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
472         }
473         extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, request.getDataLoaderType());
474 
475         final String staticSharedLibraryName = request.getPkg().getStaticSharedLibraryName();
476         // If a package is a static shared library, then only the installer of the package
477         // should get the broadcast.
478         if (installerPackageName != null && staticSharedLibraryName != null) {
479             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
480                     extras, 0 /*flags*/,
481                     installerPackageName, null /*finishedReceiver*/,
482                     request.getNewUsers(), null /* instantUserIds*/,
483                     null /* broadcastAllowList */, null);
484         }
485 
486         // Send installed broadcasts if the package is not a static shared lib.
487         if (staticSharedLibraryName == null) {
488             // Send PACKAGE_ADDED broadcast for users that see the package for the first time
489             // sendPackageAddedForNewUsers also deals with system apps
490             final int appId = UserHandle.getAppId(request.getAppId());
491             final boolean isSystem = request.isInstallSystem();
492             final boolean isVirtualPreload =
493                     ((request.getInstallFlags() & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
494             sendPackageAddedForNewUsers(snapshot, packageName,
495                     isSystem || isVirtualPreload,
496                     isVirtualPreload /*startReceiver*/, appId,
497                     firstUserIds, firstInstantUserIds, isArchived, request.getDataLoaderType());
498 
499             // Send PACKAGE_ADDED broadcast for users that don't see
500             // the package for the first time
501 
502             // Send to all running apps.
503             final SparseArray<int[]> newBroadcastAllowList =
504                     mAppsFilter.getVisibilityAllowList(snapshot,
505                             snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
506                             updateUserIds, snapshot.getPackageStates());
507             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
508                     extras, 0 /*flags*/,
509                     null /*targetPackage*/, null /*finishedReceiver*/,
510                     updateUserIds, instantUserIds, newBroadcastAllowList, null);
511             // Send to the installer, even if it's not running.
512             if (installerPackageName != null) {
513                 sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
514                         extras, 0 /*flags*/,
515                         installerPackageName, null /*finishedReceiver*/,
516                         updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
517             }
518             // Send to PermissionController for all update users, even if it may not be running
519             // for some users
520             if (isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
521                 sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
522                         extras, 0 /*flags*/,
523                         requiredPermissionControllerPackage, null /*finishedReceiver*/,
524                         updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
525             }
526             // Notify required verifier(s) that are not the installer of record for the package.
527             for (String verifierPackageName : requiredVerifierPackages) {
528                 if (verifierPackageName != null && !verifierPackageName.equals(
529                         installerPackageName)) {
530                     sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED,
531                             packageName,
532                             extras, 0 /*flags*/,
533                             verifierPackageName, null /*finishedReceiver*/,
534                             updateUserIds, instantUserIds, null /* broadcastAllowList */,
535                             null);
536                 }
537             }
538             // If package installer is defined, notify package installer about new
539             // app installed
540             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, packageName,
541                     extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
542                     requiredInstallerPackage, null /*finishedReceiver*/,
543                     firstUserIds, instantUserIds, null /* broadcastAllowList */, null);
544 
545             // Send replaced for users that don't see the package for the first time
546             if (isUpdate) {
547                 sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
548                         packageName, extras, 0 /*flags*/,
549                         null /*targetPackage*/, null /*finishedReceiver*/,
550                         updateUserIds, instantUserIds,
551                         request.getRemovedInfo().mBroadcastAllowList, null);
552                 if (installerPackageName != null) {
553                     sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED, packageName,
554                             extras, 0 /*flags*/,
555                             installerPackageName, null /*finishedReceiver*/,
556                             updateUserIds, instantUserIds, null /*broadcastAllowList*/,
557                             null);
558                 }
559                 for (String verifierPackageName : requiredVerifierPackages) {
560                     if (verifierPackageName != null && !verifierPackageName.equals(
561                             installerPackageName)) {
562                         sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
563                                 packageName, extras, 0 /*flags*/, verifierPackageName,
564                                 null /*finishedReceiver*/, updateUserIds, instantUserIds,
565                                 null /*broadcastAllowList*/, null);
566                     }
567                 }
568                 sendPackageBroadcastAndNotify(Intent.ACTION_MY_PACKAGE_REPLACED,
569                         null /*package*/, null /*extras*/, 0 /*flags*/,
570                         packageName /*targetPackage*/,
571                         null /*finishedReceiver*/, updateUserIds, instantUserIds,
572                         null /*broadcastAllowList*/,
573                         getTemporaryAppAllowlistBroadcastOptions(
574                                 REASON_PACKAGE_REPLACED).toBundle());
575             } else if (isLaunchedForRestore && !request.isInstallSystem()) {
576                 // First-install and we did a restore, so we're responsible for the
577                 // first-launch broadcast.
578                 if (DEBUG_BACKUP) {
579                     Slog.i(TAG, "Post-restore of " + packageName
580                             + " sending FIRST_LAUNCH in " + Arrays.toString(firstUserIds));
581                 }
582                 sendFirstLaunchBroadcast(packageName, installerPackageName,
583                         firstUserIds, firstInstantUserIds);
584             }
585 
586             // Send broadcast package appeared if external for all users
587             if (request.getPkg().isExternalStorage()) {
588                 if (!isUpdate) {
589                     final StorageManager storage = mContext.getSystemService(StorageManager.class);
590                     VolumeInfo volume =
591                             storage.findVolumeByUuid(
592                                     StorageManager.convert(
593                                             request.getPkg().getVolumeUuid()).toString());
594                     int packageExternalStorageType =
595                             PackageManagerServiceUtils.getPackageExternalStorageType(volume,
596                                     /* isExternalStorage */ true);
597                     // If the package was installed externally, log it.
598                     if (packageExternalStorageType != StorageEnums.UNKNOWN) {
599                         FrameworkStatsLog.write(
600                                 FrameworkStatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
601                                 packageExternalStorageType, packageName);
602                     }
603                 }
604                 if (DEBUG_INSTALL) {
605                     Slog.i(TAG, "upgrading pkg " + packageName + " is external");
606                 }
607                 if (!isArchived) {
608                     final String[] pkgNames = new String[]{packageName};
609                     final int[] uids = new int[]{request.getPkg().getUid()};
610                     sendResourcesChangedBroadcast(snapshot,
611                             true /* mediaStatus */, true /* replacing */, pkgNames, uids);
612                     notifyResourcesChanged(true /* mediaStatus */,
613                             true /* replacing */, pkgNames, uids);
614                 }
615             }
616         } else { // if static shared lib
617             final ArrayList<AndroidPackage> libraryConsumers = request.getLibraryConsumers();
618             if (!ArrayUtils.isEmpty(libraryConsumers)) {
619                 // No need to kill consumers if it's installation of new version static shared lib.
620                 final boolean dontKillApp = !isUpdate;
621                 for (int i = 0; i < libraryConsumers.size(); i++) {
622                     AndroidPackage pkg = libraryConsumers.get(i);
623                     // send broadcast that all consumers of the static shared library have changed
624                     sendPackageChangedBroadcast(snapshot, pkg.getPackageName(),
625                             dontKillApp,
626                             new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
627                             pkg.getUid(), null);
628                 }
629             }
630         }
631     }
632 
sendPackageAddedForNewUsers(@onNull Computer snapshot, @NonNull String packageName, boolean sendBootCompleted, boolean includeStopped, @AppIdInt int appId, int[] userIds, int[] instantUserIds, boolean isArchived, int dataLoaderType)633     private void sendPackageAddedForNewUsers(@NonNull Computer snapshot,
634                                              @NonNull String packageName,
635                                              boolean sendBootCompleted,
636                                              boolean includeStopped,
637                                              @AppIdInt int appId,
638                                              int[] userIds,
639                                              int[] instantUserIds,
640                                              boolean isArchived,
641                                              int dataLoaderType) {
642         if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) {
643             return;
644         }
645         SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(snapshot,
646                 snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
647                 userIds, snapshot.getPackageStates());
648         mHandler.post(
649                 () -> sendPackageAddedForNewUsers(packageName, appId, userIds,
650                         instantUserIds, isArchived, dataLoaderType, broadcastAllowList));
651         mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(packageName, appId, userIds,
652                 instantUserIds, isArchived, dataLoaderType, broadcastAllowList, mHandler);
653         if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
654             mHandler.post(() -> {
655                         for (int userId : userIds) {
656                             sendBootCompletedBroadcastToSystemApp(
657                                     packageName, includeStopped, userId);
658                         }
659                     }
660             );
661         }
662     }
663 
sendPackageAddedForNewUsers(@onNull String packageName, @AppIdInt int appId, int[] userIds, int[] instantUserIds, boolean isArchived, int dataLoaderType, @NonNull SparseArray<int[]> broadcastAllowlist)664     private void sendPackageAddedForNewUsers(@NonNull String packageName,
665                                              @AppIdInt int appId,
666                                              int[] userIds,
667                                              int[] instantUserIds,
668                                              boolean isArchived,
669                                              int dataLoaderType,
670                                              @NonNull SparseArray<int[]> broadcastAllowlist) {
671         Bundle extras = new Bundle(1);
672         // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
673         final int uid = UserHandle.getUid(
674                 (ArrayUtils.isEmpty(userIds) ? instantUserIds[0] : userIds[0]), appId);
675         extras.putInt(Intent.EXTRA_UID, uid);
676         if (isArchived) {
677             extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
678         }
679         extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
680 
681         sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
682                 packageName, extras, 0, null, null, userIds, instantUserIds,
683                 broadcastAllowlist, null /* filterExtrasForReceiver */, null);
684         // Send to PermissionController for all new users, even if it may not be running for some
685         // users
686         if (isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
687             sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
688                     packageName, extras, 0,
689                     mContext.getPackageManager().getPermissionControllerPackageName(),
690                     null, userIds, instantUserIds,
691                     broadcastAllowlist, null /* filterExtrasForReceiver */, null);
692         }
693     }
694 
sendPackageAddedForUser(@onNull Computer snapshot, @NonNull String packageName, @NonNull PackageStateInternal packageState, int userId, boolean isArchived, int dataLoaderType, @Nullable String appPredictionServicePackage)695     void sendPackageAddedForUser(@NonNull Computer snapshot,
696                                  @NonNull String packageName,
697                                  @NonNull PackageStateInternal packageState,
698                                  int userId,
699                                  boolean isArchived,
700                                  int dataLoaderType,
701                                  @Nullable String appPredictionServicePackage) {
702         final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
703         final boolean isSystem = packageState.isSystem();
704         final boolean isInstantApp = userState.isInstantApp();
705         final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
706         final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
707         sendPackageAddedForNewUsers(snapshot, packageName, isSystem /*sendBootCompleted*/,
708                 false /*startReceiver*/, packageState.getAppId(), userIds, instantUserIds,
709                 isArchived, dataLoaderType);
710 
711         // Send a session commit broadcast
712         final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
713         info.installReason = userState.getInstallReason();
714         info.appPackageName = packageName;
715         sendSessionCommitBroadcast(snapshot, info, userId, appPredictionServicePackage);
716     }
717 
sendFirstLaunchBroadcast(String pkgName, String installerPkg, int[] userIds, int[] instantUserIds)718     void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
719             int[] userIds, int[] instantUserIds) {
720         sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
721                 installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */,
722                 null /* filterExtrasForReceiver */, null);
723     }
724 
725     /**
726      * Filter package names for the intent extras {@link Intent#EXTRA_CHANGED_PACKAGE_LIST} and
727      * {@link Intent#EXTRA_CHANGED_UID_LIST} by using the rules of the package visibility.
728      *
729      * @param callingUid The uid that is going to access the intent extras.
730      * @param extras The intent extras to filter
731      * @return An extras that have been filtered, or {@code null} if the given uid is unable to
732      * access all the packages in the extras.
733      */
734     @Nullable
filterExtrasChangedPackageList(@onNull Computer snapshot, int callingUid, @NonNull Bundle extras)735     private static Bundle filterExtrasChangedPackageList(@NonNull Computer snapshot, int callingUid,
736             @NonNull Bundle extras) {
737         if (UserHandle.isCore(callingUid)) {
738             // see all
739             return extras;
740         }
741         final String[] pkgs = extras.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST);
742         if (ArrayUtils.isEmpty(pkgs)) {
743             return extras;
744         }
745         final int userId = extras.getInt(
746                 Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(callingUid));
747         final int[] uids = extras.getIntArray(Intent.EXTRA_CHANGED_UID_LIST);
748         final Pair<String[], int[]> filteredPkgs =
749                 filterPackages(snapshot, pkgs, uids, callingUid, userId);
750         if (ArrayUtils.isEmpty(filteredPkgs.first)) {
751             // caller is unable to access this intent
752             return null;
753         }
754         final Bundle filteredExtras = new Bundle(extras);
755         filteredExtras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, filteredPkgs.first);
756         filteredExtras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, filteredPkgs.second);
757         return filteredExtras;
758     }
759 
760     /** Returns whether the Safety Label Change notification, a privacy feature, is enabled. */
isPrivacySafetyLabelChangeNotificationsEnabled(Context context)761     private static boolean isPrivacySafetyLabelChangeNotificationsEnabled(Context context) {
762         PackageManager packageManager = context.getPackageManager();
763         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
764                 SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, true)
765             && !packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
766             && !packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
767             && !packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
768     }
769 
770     @NonNull
filterPackages(@onNull Computer snapshot, @NonNull String[] pkgs, @Nullable int[] uids, int callingUid, int userId)771     private static Pair<String[], int[]> filterPackages(@NonNull Computer snapshot,
772             @NonNull String[] pkgs, @Nullable int[] uids, int callingUid, int userId) {
773         final int pkgSize = pkgs.length;
774         final int uidSize = !ArrayUtils.isEmpty(uids) ? uids.length : 0;
775 
776         final ArrayList<String> pkgList = new ArrayList<>(pkgSize);
777         final IntArray uidList = uidSize > 0 ? new IntArray(uidSize) : null;
778         for (int i = 0; i < pkgSize; i++) {
779             final String packageName = pkgs[i];
780             if (snapshot.shouldFilterApplication(
781                     snapshot.getPackageStateInternal(packageName), callingUid, userId)) {
782                 continue;
783             }
784             pkgList.add(packageName);
785             if (uidList != null && i < uidSize) {
786                 uidList.add(uids[i]);
787             }
788         }
789         return new Pair<>(
790                 pkgList.size() > 0 ? pkgList.toArray(new String[pkgList.size()]) : null,
791                 uidList != null && uidList.size() > 0 ? uidList.toArray() : null);
792     }
793 
sendApplicationHiddenForUser(@onNull String packageName, @NonNull PackageStateInternal packageState, int userId, @NonNull PackageSender packageSender)794     void sendApplicationHiddenForUser(@NonNull String packageName,
795                                       @NonNull PackageStateInternal packageState,
796                                       int userId,
797                                       @NonNull PackageSender packageSender) {
798         final PackageRemovedInfo info = new PackageRemovedInfo();
799         info.mRemovedPackage = packageName;
800         info.mInstallerPackageName = packageState.getInstallSource().mInstallerPackageName;
801         info.mRemovedUsers = new int[] {userId};
802         info.mBroadcastUsers = new int[] {userId};
803         info.mUid = UserHandle.getUid(userId, packageState.getAppId());
804         info.mRemovedPackageVersionCode = packageState.getVersionCode();
805         sendPackageRemovedBroadcasts(info, packageSender, true /*killApp*/,
806                 false /*removedBySystem*/, false /*isArchived*/);
807     }
808 
sendPackageChangedBroadcast(@onNull Computer snapshot, @NonNull String packageName, boolean dontKillApp, @NonNull ArrayList<String> componentNames, int packageUid, @NonNull String reason)809     void sendPackageChangedBroadcast(@NonNull Computer snapshot,
810                                      @NonNull String packageName,
811                                      boolean dontKillApp,
812                                      @NonNull ArrayList<String> componentNames,
813                                      int packageUid,
814                                      @NonNull String reason) {
815         PackageStateInternal setting = snapshot.getPackageStateInternal(packageName,
816                 Process.SYSTEM_UID);
817         if (setting == null) {
818             return;
819         }
820         final int userId = UserHandle.getUserId(packageUid);
821         final boolean isInstantApp =
822                 snapshot.isInstantAppInternal(packageName, userId, Process.SYSTEM_UID);
823         final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
824         final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
825         final SparseArray<int[]> broadcastAllowList =
826                 isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds);
827         mHandler.post(() -> sendPackageChangedBroadcast(
828                 packageName, dontKillApp, componentNames, packageUid, reason, userIds,
829                 instantUserIds, broadcastAllowList));
830         mPackageMonitorCallbackHelper.notifyPackageChanged(packageName, dontKillApp, componentNames,
831                 packageUid, reason, userIds, instantUserIds, broadcastAllowList, mHandler);
832     }
833 
sendPackageBroadcastAndNotify(@onNull String action, @NonNull String pkg, @NonNull Bundle extras, int flags, @Nullable String targetPkg, @Nullable IIntentReceiver finishedReceiver, @NonNull int[] userIds, @NonNull int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable Bundle bOptions)834     private void sendPackageBroadcastAndNotify(@NonNull String action,
835                                                @NonNull  String pkg,
836                                                @NonNull  Bundle extras,
837                                                int flags,
838                                                @Nullable String targetPkg,
839                                                @Nullable IIntentReceiver finishedReceiver,
840                                                @NonNull int[] userIds,
841                                                @NonNull int[] instantUserIds,
842                                                @Nullable SparseArray<int[]> broadcastAllowList,
843                                                @Nullable Bundle bOptions) {
844         mHandler.post(() -> sendPackageBroadcast(action, pkg, extras, flags,
845                 targetPkg, finishedReceiver, userIds, instantUserIds, broadcastAllowList,
846                 null /* filterExtrasForReceiver */, bOptions));
847         if (targetPkg == null) {
848             // For some broadcast action, e.g. ACTION_PACKAGE_ADDED, this method will be called
849             // many times to different targets, e.g. installer app, permission controller, other
850             // registered apps. We should filter it to avoid calling back many times for the same
851             // action. When the targetPkg is set, it sends the broadcast to specific app, e.g.
852             // installer app or null for registered apps. The callback only need to send back to the
853             // registered apps so we check the null condition here.
854             notifyPackageMonitor(action, pkg, extras, userIds, instantUserIds, broadcastAllowList,
855                     null /* filterExtras */);
856         }
857     }
858 
sendSystemPackageUpdatedBroadcasts(@onNull PackageRemovedInfo packageRemovedInfo)859     void sendSystemPackageUpdatedBroadcasts(@NonNull PackageRemovedInfo packageRemovedInfo) {
860         if (!packageRemovedInfo.mIsRemovedPackageSystemUpdate) {
861             return;
862         }
863 
864         final String removedPackage = packageRemovedInfo.mRemovedPackage;
865         final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
866         final SparseArray<int[]> broadcastAllowList = packageRemovedInfo.mBroadcastAllowList;
867 
868         Bundle extras = new Bundle(2);
869         extras.putInt(Intent.EXTRA_UID, packageRemovedInfo.mUid);
870         extras.putBoolean(Intent.EXTRA_REPLACING, true);
871         sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
872                 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
873 
874         if (installerPackageName != null) {
875             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED,
876                     removedPackage, extras, 0 /*flags*/,
877                     installerPackageName, null, null, null, null /* broadcastAllowList */,
878                     null);
879             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED,
880                     removedPackage, extras, 0 /*flags*/,
881                     installerPackageName, null, null, null, null /* broadcastAllowList */,
882                     null);
883         }
884         sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
885                 extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
886         sendPackageBroadcastAndNotify(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
887                 removedPackage, null, null, null, null /* broadcastAllowList */,
888                 getTemporaryBroadcastOptionsForSystemPackageUpdate(REASON_PACKAGE_REPLACED)
889                         .toBundle());
890     }
891 
892     @SuppressLint("AndroidFrameworkRequiresPermission")
getTemporaryBroadcastOptionsForSystemPackageUpdate( @owerExemptionManager.ReasonCode int reasonCode)893     private @NonNull BroadcastOptions getTemporaryBroadcastOptionsForSystemPackageUpdate(
894             @PowerExemptionManager.ReasonCode int reasonCode) {
895         long duration = 10_000;
896         if (mAmInternal != null) {
897             duration = mAmInternal.getBootTimeTempAllowListDuration();
898         }
899         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
900         bOptions.setTemporaryAppAllowlist(duration,
901                 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
902                 reasonCode, "");
903         return bOptions;
904     }
905 
906 
sendPackageRemovedBroadcasts( @onNull PackageRemovedInfo packageRemovedInfo, @NonNull PackageSender packageSender, boolean killApp, boolean removedBySystem, boolean isArchived)907     void sendPackageRemovedBroadcasts(
908             @NonNull PackageRemovedInfo packageRemovedInfo,
909             @NonNull PackageSender packageSender,
910             boolean killApp,
911             boolean removedBySystem,
912             boolean isArchived) {
913         final String removedPackage = packageRemovedInfo.mRemovedPackage;
914         final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
915         final int[] broadcastUserIds = packageRemovedInfo.mBroadcastUsers;
916         final int[] instantUserIds = packageRemovedInfo.mInstantUserIds;
917         final SparseArray<int[]> broadcastAllowList = packageRemovedInfo.mBroadcastAllowList;
918         final boolean dataRemoved = packageRemovedInfo.mDataRemoved;
919         final boolean isUpdate = packageRemovedInfo.mIsUpdate;
920         final boolean isRemovedPackageSystemUpdate =
921                 packageRemovedInfo.mIsRemovedPackageSystemUpdate;
922         final boolean isRemovedForAllUsers = packageRemovedInfo.mRemovedForAllUsers;
923         final boolean isStaticSharedLib = packageRemovedInfo.mIsStaticSharedLib;
924 
925         Bundle extras = new Bundle();
926         extras.putInt(Intent.EXTRA_UID, packageRemovedInfo.mUid);
927         extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
928         extras.putBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, isRemovedPackageSystemUpdate);
929         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
930         extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
931         final boolean isReplace = isUpdate || isRemovedPackageSystemUpdate;
932         if (isReplace || isArchived) {
933             extras.putBoolean(Intent.EXTRA_REPLACING, true);
934         }
935         if (isArchived) {
936             extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
937         }
938         extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, isRemovedForAllUsers);
939 
940         // Send PACKAGE_REMOVED broadcast to the respective installer.
941         if (removedPackage != null && installerPackageName != null) {
942             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED,
943                     removedPackage, extras, 0 /*flags*/,
944                     installerPackageName, null, broadcastUserIds, instantUserIds, null, null);
945         }
946         if (isStaticSharedLib) {
947             // When uninstalling static shared libraries, only the package's installer needs to be
948             // sent a PACKAGE_REMOVED broadcast. There are no other intended recipients.
949             return;
950         }
951         if (removedPackage != null) {
952             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED,
953                     removedPackage, extras, 0, null /*targetPackage*/, null,
954                     broadcastUserIds, instantUserIds, broadcastAllowList, null);
955             sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_REMOVED_INTERNAL,
956                     removedPackage, extras, 0 /*flags*/, PLATFORM_PACKAGE_NAME,
957                     null /*finishedReceiver*/, broadcastUserIds, instantUserIds,
958                     broadcastAllowList, null /*bOptions*/);
959             if (dataRemoved && !isRemovedPackageSystemUpdate) {
960                 sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_FULLY_REMOVED,
961                         removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
962                         null, broadcastUserIds, instantUserIds, broadcastAllowList, null);
963                 packageSender.notifyPackageRemoved(removedPackage, packageRemovedInfo.mUid);
964             }
965         }
966         if (packageRemovedInfo.mIsAppIdRemoved) {
967             // If a system app's updates are uninstalled the UID is not actually removed. Some
968             // services need to know the package name affected.
969             //
970             // When setting Intent.EXTRA_REPLACING is true for isReplace or isArchived above,
971             // the system triggers AppOpsService#resetAllModes in
972             // ActivityManagerService#broadcastIntentLockedTraced when the action is
973             // ACTION_UID_REMOVED. Add Intent.EXTRA_PACKAGE_NAME for isReplace or isArchived too.
974             // Because AppOpsService#resetAllModes needs the packageName to define which uid to be
975             // reset. If there is no package name, it resets the all appOps for all uids.
976             if (isReplace || isArchived) {
977                 extras.putString(Intent.EXTRA_PACKAGE_NAME, removedPackage);
978             }
979 
980             sendPackageBroadcastAndNotify(Intent.ACTION_UID_REMOVED,
981                     null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
982                     null, null, broadcastUserIds, instantUserIds, broadcastAllowList, null);
983         }
984     }
985 
986     /**
987      * Send broadcast intents for packages suspension changes.
988      *
989      * @param intent The action name of the suspension intent.
990      * @param pkgList The names of packages which have suspension changes.
991      * @param uidList The uids of packages which have suspension changes.
992      * @param userId The user where packages reside.
993      */
sendPackagesSuspendedOrUnsuspendedForUser(@onNull Computer snapshot, @NonNull String intent, @NonNull String[] pkgList, @NonNull int[] uidList, boolean quarantined, int userId)994     void sendPackagesSuspendedOrUnsuspendedForUser(@NonNull Computer snapshot,
995                                                    @NonNull String intent,
996                                                    @NonNull String[] pkgList,
997                                                    @NonNull int[] uidList,
998                                                    boolean quarantined,
999                                                    int userId) {
1000         final Bundle extras = new Bundle(3);
1001         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
1002         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
1003         if (quarantined) {
1004             extras.putBoolean(Intent.EXTRA_QUARANTINED, true);
1005         }
1006         final int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND;
1007         final Bundle options = new BroadcastOptions()
1008                 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
1009                 .toBundle();
1010         BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver =
1011                 (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
1012                         snapshot, callingUid, intentExtras);
1013         mHandler.post(() -> sendPackageBroadcast(intent, null /* pkg */,
1014                 extras, flags, null /* targetPkg */, null /* finishedReceiver */,
1015                 new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */,
1016                 filterExtrasForReceiver,
1017                 options));
1018         notifyPackageMonitor(intent, null /* pkg */, extras, new int[]{userId},
1019                 null /* instantUserIds */, null /* broadcastAllowList */, filterExtrasForReceiver);
1020     }
1021 
sendMyPackageSuspendedOrUnsuspended(@onNull Computer snapshot, @NonNull String[] affectedPackages, boolean suspended, int userId)1022     void sendMyPackageSuspendedOrUnsuspended(@NonNull Computer snapshot,
1023                                              @NonNull String[] affectedPackages,
1024                                              boolean suspended,
1025                                              int userId) {
1026         final String action = suspended
1027                 ? Intent.ACTION_MY_PACKAGE_SUSPENDED
1028                 : Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
1029         mHandler.post(() -> {
1030             final IActivityManager am = ActivityManager.getService();
1031             if (am == null) {
1032                 Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
1033                         + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
1034                 return;
1035             }
1036             final int[] targetUserIds = new int[] {userId};
1037             for (String packageName : affectedPackages) {
1038                 final Bundle appExtras = suspended
1039                         ? SuspendPackageHelper.getSuspendedPackageAppExtras(
1040                                 snapshot, packageName, userId, SYSTEM_UID)
1041                         : null;
1042                 final Bundle intentExtras;
1043                 if (appExtras != null) {
1044                     intentExtras = new Bundle(1);
1045                     intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
1046                 } else {
1047                     intentExtras = null;
1048                 }
1049                 doSendBroadcast(action, null, intentExtras,
1050                         Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
1051                         targetUserIds, false, null, null, null);
1052             }
1053         });
1054     }
1055 
1056     /**
1057      * Send broadcast intents for packages distracting changes.
1058      *
1059      * @param pkgList The names of packages which have suspension changes.
1060      * @param uidList The uids of packages which have suspension changes.
1061      * @param userId The user where packages reside.
1062      */
sendDistractingPackagesChanged(@onNull Computer snapshot, @NonNull String[] pkgList, @NonNull int[] uidList, int userId, int distractionFlags)1063     void sendDistractingPackagesChanged(@NonNull Computer snapshot,
1064                                         @NonNull String[] pkgList,
1065                                         @NonNull int[] uidList,
1066                                         int userId,
1067                                         int distractionFlags) {
1068         final Bundle extras = new Bundle();
1069         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
1070         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
1071         extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
1072 
1073         mHandler.post(() -> sendPackageBroadcast(
1074                 Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */,
1075                 extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */,
1076                 null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */,
1077                 null /* broadcastAllowList */,
1078                 (callingUid, intentExtras) -> filterExtrasChangedPackageList(
1079                         snapshot, callingUid, intentExtras),
1080                 null /* bOptions */));
1081     }
1082 
sendResourcesChangedBroadcastAndNotify(@onNull Computer snapshot, boolean mediaStatus, boolean replacing, @NonNull ArrayList<AndroidPackage> packages)1083     void sendResourcesChangedBroadcastAndNotify(@NonNull Computer snapshot,
1084                                                 boolean mediaStatus,
1085                                                 boolean replacing,
1086                                                 @NonNull ArrayList<AndroidPackage> packages) {
1087         final int size = packages.size();
1088         final String[] packageNames = new String[size];
1089         final int[] packageUids = new int[size];
1090         for (int i = 0; i < size; i++) {
1091             final AndroidPackage pkg = packages.get(i);
1092             packageNames[i] = pkg.getPackageName();
1093             packageUids[i] = pkg.getUid();
1094         }
1095         sendResourcesChangedBroadcast(snapshot, mediaStatus,
1096                 replacing, packageNames, packageUids);
1097         notifyResourcesChanged(mediaStatus, replacing, packageNames, packageUids);
1098     }
1099 
notifyPackageMonitor(@onNull String action, @NonNull String pkg, @Nullable Bundle extras, @NonNull int[] userIds, @NonNull int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtras)1100     private void notifyPackageMonitor(@NonNull String action,
1101                                       @NonNull String pkg,
1102                                       @Nullable Bundle extras,
1103                                       @NonNull int[] userIds,
1104                                       @NonNull int[] instantUserIds,
1105                                       @Nullable SparseArray<int[]> broadcastAllowList,
1106                                       @Nullable BiFunction<Integer, Bundle, Bundle> filterExtras) {
1107         mPackageMonitorCallbackHelper.notifyPackageMonitor(action, pkg, extras, userIds,
1108                 instantUserIds, broadcastAllowList, mHandler, filterExtras);
1109     }
1110 
notifyResourcesChanged(boolean mediaStatus, boolean replacing, @NonNull String[] pkgNames, @NonNull int[] uids)1111     private void notifyResourcesChanged(boolean mediaStatus,
1112                                 boolean replacing,
1113                                 @NonNull String[] pkgNames,
1114                                 @NonNull int[] uids) {
1115         mPackageMonitorCallbackHelper.notifyResourcesChanged(mediaStatus, replacing, pkgNames,
1116                 uids, mHandler);
1117     }
1118 }
1119