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