• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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