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_PACKAGE_REPLACED; 20 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 21 22 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 23 24 import android.annotation.NonNull; 25 import android.app.ActivityManagerInternal; 26 import android.app.BroadcastOptions; 27 import android.content.Intent; 28 import android.os.Bundle; 29 import android.os.PowerExemptionManager; 30 import android.util.SparseArray; 31 32 import com.android.internal.util.ArrayUtils; 33 import com.android.server.LocalServices; 34 35 final class PackageRemovedInfo { 36 final PackageSender mPackageSender; 37 String mRemovedPackage; 38 String mInstallerPackageName; 39 int mUid = -1; 40 int mRemovedAppId = -1; 41 int[] mOrigUsers; 42 int[] mRemovedUsers = null; 43 int[] mBroadcastUsers = null; 44 int[] mInstantUserIds = null; 45 SparseArray<Integer> mInstallReasons; 46 SparseArray<Integer> mUninstallReasons; 47 boolean mIsRemovedPackageSystemUpdate = false; 48 boolean mIsUpdate; 49 boolean mDataRemoved; 50 boolean mRemovedForAllUsers; 51 boolean mIsStaticSharedLib; 52 boolean mIsExternal; 53 // a two dimensional array mapping userId to the set of appIds that can receive notice 54 // of package changes 55 SparseArray<int[]> mBroadcastAllowList; 56 // Clean up resources deleted packages. 57 InstallArgs mArgs = null; 58 private static final int[] EMPTY_INT_ARRAY = new int[0]; 59 PackageRemovedInfo(PackageSender packageSender)60 PackageRemovedInfo(PackageSender packageSender) { 61 mPackageSender = packageSender; 62 } 63 sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem)64 void sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem) { 65 sendPackageRemovedBroadcastInternal(killApp, removedBySystem); 66 } 67 sendSystemPackageUpdatedBroadcasts()68 void sendSystemPackageUpdatedBroadcasts() { 69 if (mIsRemovedPackageSystemUpdate) { 70 sendSystemPackageUpdatedBroadcastsInternal(); 71 } 72 } 73 sendSystemPackageUpdatedBroadcastsInternal()74 private void sendSystemPackageUpdatedBroadcastsInternal() { 75 Bundle extras = new Bundle(2); 76 extras.putInt(Intent.EXTRA_UID, mRemovedAppId >= 0 ? mRemovedAppId : mUid); 77 extras.putBoolean(Intent.EXTRA_REPLACING, true); 78 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, mRemovedPackage, extras, 79 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null); 80 if (mInstallerPackageName != null) { 81 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, 82 mRemovedPackage, extras, 0 /*flags*/, 83 mInstallerPackageName, null, null, null, null /* broadcastAllowList */, 84 null); 85 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, 86 mRemovedPackage, extras, 0 /*flags*/, 87 mInstallerPackageName, null, null, null, null /* broadcastAllowList */, 88 null); 89 } 90 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, mRemovedPackage, 91 extras, 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null); 92 mPackageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0, 93 mRemovedPackage, null, null, null, null /* broadcastAllowList */, 94 getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle()); 95 } 96 getTemporaryAppAllowlistBroadcastOptions( @owerExemptionManager.ReasonCode int reasonCode)97 private static @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions( 98 @PowerExemptionManager.ReasonCode int reasonCode) { 99 long duration = 10_000; 100 final ActivityManagerInternal amInternal = 101 LocalServices.getService(ActivityManagerInternal.class); 102 if (amInternal != null) { 103 duration = amInternal.getBootTimeTempAllowListDuration(); 104 } 105 final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); 106 bOptions.setTemporaryAppAllowlist(duration, 107 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 108 reasonCode, ""); 109 return bOptions; 110 } 111 sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem)112 private void sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem) { 113 // Don't send static shared library removal broadcasts as these 114 // libs are visible only the apps that depend on them an one 115 // cannot remove the library if it has a dependency. 116 if (mIsStaticSharedLib) { 117 return; 118 } 119 Bundle extras = new Bundle(); 120 final int removedUid = mRemovedAppId >= 0 ? mRemovedAppId : mUid; 121 extras.putInt(Intent.EXTRA_UID, removedUid); 122 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, mDataRemoved); 123 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp); 124 extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem); 125 final boolean isReplace = mIsUpdate || mIsRemovedPackageSystemUpdate; 126 if (isReplace) { 127 extras.putBoolean(Intent.EXTRA_REPLACING, true); 128 } 129 extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, mRemovedForAllUsers); 130 if (mRemovedPackage != null) { 131 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, 132 mRemovedPackage, extras, 0, null /*targetPackage*/, null, 133 mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null); 134 if (mInstallerPackageName != null) { 135 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, 136 mRemovedPackage, extras, 0 /*flags*/, 137 mInstallerPackageName, null, mBroadcastUsers, mInstantUserIds, null, null); 138 } 139 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED_INTERNAL, 140 mRemovedPackage, extras, 0 /*flags*/, PLATFORM_PACKAGE_NAME, 141 null /*finishedReceiver*/, mBroadcastUsers, mInstantUserIds, 142 mBroadcastAllowList, null /*bOptions*/); 143 if (mDataRemoved && !mIsRemovedPackageSystemUpdate) { 144 mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, 145 mRemovedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, 146 null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null); 147 mPackageSender.notifyPackageRemoved(mRemovedPackage, removedUid); 148 } 149 } 150 if (mRemovedAppId >= 0) { 151 // If a system app's updates are uninstalled the UID is not actually removed. Some 152 // services need to know the package name affected. 153 if (isReplace) { 154 extras.putString(Intent.EXTRA_PACKAGE_NAME, mRemovedPackage); 155 } 156 157 mPackageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED, 158 null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, 159 null, null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null); 160 } 161 } 162 populateUsers(int[] userIds, PackageSetting deletedPackageSetting)163 public void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) { 164 mRemovedUsers = userIds; 165 if (mRemovedUsers == null) { 166 mBroadcastUsers = null; 167 return; 168 } 169 170 mBroadcastUsers = EMPTY_INT_ARRAY; 171 mInstantUserIds = EMPTY_INT_ARRAY; 172 for (int i = userIds.length - 1; i >= 0; --i) { 173 final int userId = userIds[i]; 174 if (deletedPackageSetting.getInstantApp(userId)) { 175 mInstantUserIds = ArrayUtils.appendInt(mInstantUserIds, userId); 176 } else { 177 mBroadcastUsers = ArrayUtils.appendInt(mBroadcastUsers, userId); 178 } 179 } 180 } 181 } 182