• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManagerInternal;
25 import android.content.res.Resources;
26 import android.os.SystemProperties;
27 import android.os.UserHandle;
28 import android.util.ArrayMap;
29 import android.util.ArraySet;
30 import android.util.DebugUtils;
31 import android.util.IndentingPrintWriter;
32 import android.util.Slog;
33 import android.util.SparseArrayMap;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.server.LocalServices;
37 import com.android.server.SystemConfig;
38 import com.android.server.pm.parsing.pkg.AndroidPackage;
39 import com.android.server.pm.pkg.PackageStateInternal;
40 
41 import java.lang.annotation.Retention;
42 import java.lang.annotation.RetentionPolicy;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49 
50 /**
51  * Responsible for un/installing system packages based on user type.
52  *
53  * <p>Uses the SystemConfig's install-in-user-type allowlist;
54  * see {@link SystemConfig#getAndClearPackageToUserTypeWhitelist} and
55  * {@link SystemConfig#getAndClearPackageToUserTypeBlacklist}.
56  *
57  * <p>If {@link #isEnforceMode()} is false, then all system packages are always installed for all
58  * users. The following applies when it is true.
59  *
60  * <p>Any package can be in one of three states in the {@code SystemConfig} allowlist
61  * <ol>
62  *     <li>Explicitly denylisted for a particular user type</li>
63  *     <li>Explicitly allowlisted for a particular user type</li>
64  *     <li>Not mentioned at all, for any user type (neither allowlisted nor denylisted)</li>
65  * </ol>
66  *
67  * <p>Denylisting always takes precedence - if a package is denylisted for a particular user,
68  * it won't be installed on that type of user (even if it is also allowlisted for that user).
69  * Next comes allowlisting - if it is allowlisted for a particular user, it will be installed on
70  * that type of user (as long as it isn't denylisted).
71  * Finally, if the package is not mentioned at all (i.e. neither allowlisted nor denylisted for
72  * any user types) in the SystemConfig 'install-in-user-type' lists
73  * then:
74  * <ul>
75  *     <li>If {@link #isImplicitWhitelistMode()}, the package is implicitly treated as allowlisted
76  *          for <b>all</b> users</li>
77  *     <li>Otherwise, if {@link #isImplicitWhitelistSystemMode()}, the package is implicitly treated
78  *          as allowlisted for the <b>{@link UserHandle#USER_SYSTEM}</b> user (not other users),
79  *          which is useful for local development purposes</li>
80  *     <li>Otherwise, the package is implicitly treated as denylisted for all users</li>
81  * </ul>
82  *
83  * <p>Packages are only installed/uninstalled by this mechanism when a new user is created or during
84  * an update. In the case of updates:<ul>
85  *     <li>new packages are (un)installed per the allowlist/denylist</li>
86  *     <li>pre-existing installed denylisted packages are never uninstalled</li>
87  *     <li>pre-existing not-installed allowlisted packages are only installed if the reason why they
88  *     had been previously uninstalled was due to UserSystemPackageInstaller</li>
89  * </ul>
90  *
91  * <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
92  * update. So, to verify changes during development, you can emulate the latter by calling:
93  * <pre><code>
94  * adb shell setprop persist.pm.mock-upgrade true
95  * </code></pre>
96  */
97 class UserSystemPackageInstaller {
98     private static final String TAG = UserSystemPackageInstaller.class.getSimpleName();
99 
100     private static final boolean DEBUG = false;
101 
102     /**
103      * System Property whether to only install system packages on a user if they're allowlisted for
104      * that user type. These are flags and can be freely combined.
105      * <ul>
106      * <li> 0  - disable allowlist (install all system packages; no logging)</li>
107      * <li> 1  - enforce (only install system packages if they are allowlisted)</li>
108      * <li> 2  - log (log non-allowlisted packages)</li>
109      * <li> 4  - for all users: implicitly allowlist any package not mentioned in the allowlist</li>
110      * <li> 8  - for SYSTEM: implicitly allowlist any package not mentioned in the allowlist</li>
111      * <li> 16 - ignore OTAs (don't install system packages during OTAs)</li>
112      * <li>-1  - use device default (as defined in res/res/values/config.xml)</li>
113      * </ul>
114      * Note: This list must be kept current with config_userTypePackageWhitelistMode in
115      * frameworks/base/core/res/res/values/config.xml
116      */
117     static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode";
118 
119     // NOTE: flags below are public so they can used by DebugUtils.flagsToString. And this class
120     // itself is package-protected, so it doesn't matter...
121     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00;
122     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01;
123     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02;
124     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04;
125     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08;
126     public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10;
127     static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
128 
129     // Used by Shell command only
130     static final int USER_TYPE_PACKAGE_WHITELIST_MODE_NONE = -1000;
131 
132     @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = {
133             USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE,
134             USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE,
135             USER_TYPE_PACKAGE_WHITELIST_MODE_LOG,
136             USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST,
137             USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA,
138     })
139     @Retention(RetentionPolicy.SOURCE)
140     public @interface PackageWhitelistMode {}
141 
142     /**
143      * Maps system package manifest names to a bitset representing (via {@link #getUserTypeMask})
144      * the user types on which they should be initially installed.
145      * <p>
146      * E.g. if package "pkg1" should be installed on "usertype_d", which is the user type for which
147      * {@link #getUserTypeMask}("usertype_d") returns (1 << 3)
148      * then mWhitelistedPackagesForUserTypes.get("pkg1") will be a Long whose
149      * bit in position 3 will equal 1.
150      * <p>
151      * Packages that are allowlisted, but then denylisted so that they aren't to be installed on
152      * any user, are purposefully still present in this list.
153      */
154     private final ArrayMap<String, Long> mWhitelistedPackagesForUserTypes;
155 
156     private final UserManagerService mUm;
157 
158     /**
159      * Alphabetically sorted list of user types.
160      * Throughout this class, a long (functioning as a bitset) has its ith bit representing
161      * the user type stored in mUserTypes[i].
162      * mUserTypes cannot exceed Long.SIZE (since we are using long for our bitset).
163      */
164     private final String[] mUserTypes;
165 
UserSystemPackageInstaller(UserManagerService um, ArrayMap<String, UserTypeDetails> userTypes)166     UserSystemPackageInstaller(UserManagerService um, ArrayMap<String, UserTypeDetails> userTypes) {
167         mUm = um;
168         mUserTypes = getAndSortKeysFromMap(userTypes);
169         if (mUserTypes.length > Long.SIZE) {
170             throw new IllegalArgumentException("Device contains " + userTypes.size()
171                     + " user types. However, UserSystemPackageInstaller does not work if there are"
172                     + " more than " + Long.SIZE + " user types.");
173             // UserSystemPackageInstaller could use a BitSet instead of Long in this case.
174             // But, currently, 64 user types is far beyond expectations, so we have not done so.
175         }
176         mWhitelistedPackagesForUserTypes =
177                 determineWhitelistedPackagesForUserTypes(SystemConfig.getInstance());
178     }
179 
180     /** Constructor for testing purposes. */
181     @VisibleForTesting
UserSystemPackageInstaller(UserManagerService ums, ArrayMap<String, Long> whitelist, String[] sortedUserTypes)182     UserSystemPackageInstaller(UserManagerService ums, ArrayMap<String, Long> whitelist,
183             String[] sortedUserTypes) {
184         mUm = ums;
185         mUserTypes = sortedUserTypes;
186         mWhitelistedPackagesForUserTypes = whitelist;
187     }
188 
189     /**
190      * During OTAs and first boot, install/uninstall all system packages for all users based on the
191      * user's user type and the SystemConfig allowlist.
192      * We do NOT uninstall packages during an OTA though.
193      *
194      * This is responsible for enforcing the allowlist for pre-existing users (i.e. USER_SYSTEM);
195      * enforcement for new users is done when they are created in UserManagerService.createUser().
196      *
197      * @param preExistingPackages list of packages on the device prior to the upgrade. Cannot be
198      *                            null if isUpgrade is true.
199      */
installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade, @Nullable ArraySet<String> preExistingPackages)200     boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade,
201             @Nullable ArraySet<String> preExistingPackages) {
202         final int mode = getWhitelistMode();
203         checkWhitelistedSystemPackages(mode);
204         final boolean isConsideredUpgrade = isUpgrade && !isIgnoreOtaMode(mode);
205         if (!isConsideredUpgrade && !isFirstBoot) {
206             return false;
207         }
208         if (isFirstBoot && !isEnforceMode(mode)) {
209             // Note that if !isEnforceMode, we nonetheless still install packages if isUpgrade
210             // in order to undo any previous non-installing. isFirstBoot lacks this requirement.
211             return false;
212         }
213         Slog.i(TAG, "Reviewing whitelisted packages due to "
214                 + (isFirstBoot ? "[firstBoot]" : "") + (isConsideredUpgrade ? "[upgrade]" : ""));
215         final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
216 
217         // User ID -> package name -> installed
218         SparseArrayMap<String, Boolean> changesToCommit = new SparseArrayMap<>();
219 
220         // Install/uninstall system packages per user.
221         for (int userId : mUm.getUserIds()) {
222             final Set<String> userAllowlist = getInstallablePackagesForUserId(userId);
223 
224             pmInt.forEachPackageState(packageState -> {
225                 if (packageState.getPkg() == null) {
226                     return;
227                 }
228                 boolean install = (userAllowlist == null
229                                 || userAllowlist.contains(packageState.getPackageName()))
230                         && !packageState.getTransientState().isHiddenUntilInstalled();
231                 if (packageState.getUserStateOrDefault(userId).isInstalled() != install
232                         && shouldChangeInstallationState(packageState, install, userId,
233                         isFirstBoot, isConsideredUpgrade, preExistingPackages)) {
234                     changesToCommit.add(userId, packageState.getPackageName(), install);
235                 }
236             });
237         }
238 
239         pmInt.commitPackageStateMutation(null, packageStateMutator -> {
240             for (int userIndex = 0; userIndex < changesToCommit.numMaps(); userIndex++) {
241                 int userId = changesToCommit.keyAt(userIndex);
242                 int packagesSize = changesToCommit.numElementsForKey(userId);
243                 for (int packageIndex = 0; packageIndex < packagesSize; ++packageIndex) {
244                     String packageName = changesToCommit.keyAt(userIndex, packageIndex);
245                     boolean installed = changesToCommit.valueAt(userIndex, packageIndex);
246                     packageStateMutator.forPackage(packageName)
247                             .userState(userId)
248                             .setInstalled(installed)
249                             .setUninstallReason(installed
250                                     ? PackageManager.UNINSTALL_REASON_UNKNOWN
251                                     : PackageManager.UNINSTALL_REASON_USER_TYPE);
252 
253                     Slog.i(TAG + "CommitDebug", (installed ? "Installed " : "Uninstalled ")
254                             + packageName + " for user " + userId);
255                 }
256             }
257         });
258 
259         return true;
260     }
261 
262     /**
263      * Returns whether to proceed with install/uninstall for the given package.
264      * In particular, do not install a package unless it was only uninstalled due to the user type;
265      * and do not uninstall a package if it previously was installed (prior to the OTA).
266      *
267      * Should be called only within PackageManagerInternal.forEachPackageSetting() since it
268      * requires the LP lock.
269      *
270      * @param preOtaPkgs list of packages on the device prior to the upgrade.
271      *                   Cannot be null if isUpgrade is true.
272      */
shouldChangeInstallationState(PackageStateInternal packageState, boolean install, @UserIdInt int userId, boolean isFirstBoot, boolean isUpgrade, @Nullable ArraySet<String> preOtaPkgs)273     private static boolean shouldChangeInstallationState(PackageStateInternal packageState,
274                                                          boolean install,
275                                                          @UserIdInt int userId,
276                                                          boolean isFirstBoot,
277                                                          boolean isUpgrade,
278                                                          @Nullable ArraySet<String> preOtaPkgs) {
279         if (install) {
280             // Only proceed with install if we are the only reason why it had been uninstalled.
281             return packageState.getUserStateOrDefault(userId).getUninstallReason()
282                     == PackageManager.UNINSTALL_REASON_USER_TYPE;
283         } else {
284             // Only proceed with uninstall if the package is new to the device.
285             return isFirstBoot
286                     || (isUpgrade && !preOtaPkgs.contains(packageState.getPackageName()));
287         }
288     }
289 
290     /**
291      * Checks whether the system packages and the mWhitelistedPackagesForUserTypes allowlist are
292      * in 1-to-1 correspondence.
293      */
checkWhitelistedSystemPackages(@ackageWhitelistMode int mode)294     private void checkWhitelistedSystemPackages(@PackageWhitelistMode int mode) {
295         if (!isLogMode(mode) && !isEnforceMode(mode)) {
296             return;
297         }
298         Slog.v(TAG,  "Checking that all system packages are whitelisted.");
299 
300         // Check whether all allowlisted packages are indeed on the system.
301         final List<String> warnings = getPackagesWhitelistWarnings();
302         final int numberWarnings = warnings.size();
303         if (numberWarnings == 0) {
304             Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode)
305                     + ") has no warnings");
306         } else {
307             Slog.w(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode)
308                     + ") has " + numberWarnings + " warnings:");
309             for (int i = 0; i < numberWarnings; i++) {
310                 Slog.w(TAG, warnings.get(i));
311             }
312         }
313 
314         // Check whether all system packages are indeed allowlisted.
315         if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) {
316             return;
317         }
318 
319         final List<String> errors = getPackagesWhitelistErrors(mode);
320         final int numberErrors = errors.size();
321 
322         if (numberErrors == 0) {
323             Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode)
324                     + ") has no errors");
325             return;
326         }
327         Slog.e(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has "
328                 + numberErrors + " errors:");
329 
330         boolean doWtf = !isImplicitWhitelistMode(mode);
331         for (int i = 0; i < numberErrors; i++) {
332             final String msg = errors.get(i);
333             if (doWtf) {
334                 Slog.wtf(TAG, msg);
335             } else {
336                 Slog.e(TAG, msg);
337             }
338         }
339     }
340 
341     /**
342      * Gets packages that are listed in the allowlist XML but are not present on the system image.
343      */
344     @NonNull
getPackagesWhitelistWarnings()345     private List<String> getPackagesWhitelistWarnings() {
346         final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages();
347         final List<String> warnings = new ArrayList<>();
348         final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
349 
350         // Check whether all allowlisted packages are indeed on the system.
351         final String notPresentFmt = "%s is allowlisted but not present.";
352         final String notSystemFmt = "%s is allowlisted and present but not a system package.";
353         final String overlayFmt = "%s is allowlisted unnecessarily since it's a static overlay.";
354         for (String pkgName : allWhitelistedPackages) {
355             final AndroidPackage pkg = pmInt.getPackage(pkgName);
356             if (pkg == null) {
357                 warnings.add(String.format(notPresentFmt, pkgName));
358             } else if (!pkg.isSystem()) {
359                 warnings.add(String.format(notSystemFmt, pkgName));
360             } else if (shouldUseOverlayTargetName(pkg)) {
361                 warnings.add(String.format(overlayFmt, pkgName));
362             }
363         }
364         return warnings;
365     }
366 
367     /**
368      * Gets packages that are not listed in the allowlist XMLs when they should be.
369      */
370     @NonNull
getPackagesWhitelistErrors(@ackageWhitelistMode int mode)371     private List<String> getPackagesWhitelistErrors(@PackageWhitelistMode int mode) {
372         if ((!isEnforceMode(mode) || isImplicitWhitelistMode(mode)) && !isLogMode(mode)) {
373             return Collections.emptyList();
374         }
375 
376         final List<String> errors = new ArrayList<>();
377         final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages();
378         final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
379 
380         // Check whether all system packages are indeed allowlisted.
381         final String logMessageFmt = "System package %s is not whitelisted using "
382                 + "'install-in-user-type' in SystemConfig for any user types!";
383         pmInt.forEachPackage(pkg -> {
384             if (!pkg.isSystem()) return;
385             final String pkgName = pkg.getManifestPackageName();
386             if (!allWhitelistedPackages.contains(pkgName)
387                     && !shouldUseOverlayTargetName(pmInt.getPackage(pkgName))) {
388                 errors.add(String.format(logMessageFmt, pkgName));
389             }
390         });
391 
392         return errors;
393     }
394 
395     /** Whether to only install system packages in new users for which they are allowlisted. */
isEnforceMode()396     boolean isEnforceMode() {
397         return isEnforceMode(getWhitelistMode());
398     }
399 
400     /**
401      * Whether to ignore OTAs, and therefore not install missing system packages during OTAs.
402      * <p>Note:
403      * If in this mode, old system packages will not be installed on pre-existing users during OTAs.
404      * Any system packages that had not been installed at the time of the user's creation,
405      * due to {@link UserSystemPackageInstaller}'s previous actions, will therefore continue to
406      * remain uninstalled, even if the allowlist (or enforcement mode) now declares that they should
407      * be.
408      */
isIgnoreOtaMode()409     boolean isIgnoreOtaMode() {
410         return isIgnoreOtaMode(getWhitelistMode());
411     }
412 
413     /**
414      * Whether to log a warning concerning potential problems with the user-type package allowlist.
415      */
isLogMode()416     boolean isLogMode() {
417         return isLogMode(getWhitelistMode());
418     }
419 
420     /**
421      * Whether to treat all packages that are not mentioned at all in the allowlist to be implicitly
422      * allowlisted for all users.
423      */
isImplicitWhitelistMode()424     boolean isImplicitWhitelistMode() {
425         return isImplicitWhitelistMode(getWhitelistMode());
426     }
427 
428     /**
429      * Whether to treat all packages that are not mentioned at all in the allowlist to be implicitly
430      * allowlisted for the SYSTEM user.
431      */
isImplicitWhitelistSystemMode()432     boolean isImplicitWhitelistSystemMode() {
433         return isImplicitWhitelistSystemMode(getWhitelistMode());
434     }
435 
436     /**
437      * Returns whether the package is a static overlay, whose installation should depend on the
438      * allowlisting of the overlay's target's package name, rather than of its own package name.
439      *
440      * @param pkg A package (which need not be an overlay)
441      */
shouldUseOverlayTargetName(AndroidPackage pkg)442     private static boolean shouldUseOverlayTargetName(AndroidPackage pkg) {
443         return pkg.isOverlayIsStatic();
444     }
445 
446     /** See {@link #isEnforceMode()}. */
isEnforceMode(int whitelistMode)447     private static boolean isEnforceMode(int whitelistMode) {
448         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
449     }
450 
451     /** See {@link #isIgnoreOtaMode()}. */
isIgnoreOtaMode(int whitelistMode)452     private static boolean isIgnoreOtaMode(int whitelistMode) {
453         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA) != 0;
454     }
455 
456     /** See {@link #isLogMode()}. */
isLogMode(int whitelistMode)457     private static boolean isLogMode(int whitelistMode) {
458         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_LOG) != 0;
459     }
460 
461     /** See {@link #isImplicitWhitelistMode()}. */
isImplicitWhitelistMode(int whitelistMode)462     private static boolean isImplicitWhitelistMode(int whitelistMode) {
463         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
464     }
465 
466     /** See {@link #isImplicitWhitelistSystemMode()}. */
isImplicitWhitelistSystemMode(int whitelistMode)467     private static boolean isImplicitWhitelistSystemMode(int whitelistMode) {
468         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM) != 0;
469     }
470 
471     /** Gets the PackageWhitelistMode for use of {@link #mWhitelistedPackagesForUserTypes}. */
getWhitelistMode()472     private @PackageWhitelistMode int getWhitelistMode() {
473         final int runtimeMode = SystemProperties.getInt(
474                 PACKAGE_WHITELIST_MODE_PROP, USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
475         if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) {
476             return runtimeMode;
477         }
478         return getDeviceDefaultWhitelistMode();
479     }
480 
481     /** Gets the PackageWhitelistMode as defined by {@code config_userTypePackageWhitelistMode}. */
getDeviceDefaultWhitelistMode()482     private @PackageWhitelistMode int getDeviceDefaultWhitelistMode() {
483         return Resources.getSystem()
484                 .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode);
485     }
486 
modeToString(@ackageWhitelistMode int mode)487     static @NonNull String modeToString(@PackageWhitelistMode int mode) {
488         // Must handle some types separately because they're not bitwise flags
489         switch (mode) {
490             case USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT:
491                 return "DEVICE_DEFAULT";
492             case USER_TYPE_PACKAGE_WHITELIST_MODE_NONE:
493                 return "NONE";
494             default:
495                 return DebugUtils.flagsToString(UserSystemPackageInstaller.class,
496                         "USER_TYPE_PACKAGE_WHITELIST_MODE_", mode);
497         }
498     }
499 
500     /**
501      * Gets the system packages names that should be installed on the given user.
502      * See {@link #getInstallablePackagesForUserType(String)}.
503      */
getInstallablePackagesForUserId(@serIdInt int userId)504     private @Nullable Set<String> getInstallablePackagesForUserId(@UserIdInt int userId) {
505         return getInstallablePackagesForUserType(mUm.getUserInfo(userId).userType);
506     }
507 
508     /**
509      * Gets the system package names that should be installed on users of the given user type, as
510      * determined by SystemConfig, the allowlist mode, and the apps actually on the device.
511      * Names are the {@link AndroidPackage#getPackageName()}, not necessarily the manifest names.
512      *
513      * Returns null if all system packages should be installed (due to enforce-mode being off).
514      */
getInstallablePackagesForUserType(String userType)515     @Nullable Set<String> getInstallablePackagesForUserType(String userType) {
516         final int mode = getWhitelistMode();
517         if (!isEnforceMode(mode)) {
518             return null;
519         }
520         final boolean implicitlyWhitelist = isImplicitWhitelistMode(mode)
521                 || (isImplicitWhitelistSystemMode(mode) && mUm.isUserTypeSubtypeOfSystem(userType));
522         final Set<String> whitelistedPackages = getWhitelistedPackagesForUserType(userType);
523 
524         final Set<String> installPackages = new ArraySet<>();
525         final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
526         pmInt.forEachPackage(pkg -> {
527             if (!pkg.isSystem()) {
528                 return;
529             }
530             if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes,
531                     whitelistedPackages, implicitlyWhitelist)) {
532                 // Although the allowlist uses manifest names, this function returns packageNames.
533                 installPackages.add(pkg.getPackageName());
534             }
535         });
536         return installPackages;
537     }
538 
539     /**
540      * Returns whether the given system package should be installed on the given user, based on the
541      * the given allowlist of system packages.
542      *
543      * @param sysPkg the system package. Must be a system package; no verification for this is done.
544      * @param userTypeWhitelist map of package manifest names to user types on which they should be
545      *                          installed. This is only used for overriding the userWhitelist in
546      *                          certain situations (based on its keyset).
547      * @param userWhitelist set of package manifest names that should be installed on this
548      *                      <b>particular</b> user. This must be consistent with userTypeWhitelist,
549      *                      but is passed in separately to avoid repeatedly calculating it from
550      *                      userTypeWhitelist.
551      * @param implicitlyWhitelist whether non-mentioned packages are implicitly allowlisted.
552      */
553     @VisibleForTesting
shouldInstallPackage(AndroidPackage sysPkg, @NonNull ArrayMap<String, Long> userTypeWhitelist, @NonNull Set<String> userWhitelist, boolean implicitlyWhitelist)554     static boolean shouldInstallPackage(AndroidPackage sysPkg,
555             @NonNull ArrayMap<String, Long> userTypeWhitelist,
556             @NonNull Set<String> userWhitelist, boolean implicitlyWhitelist) {
557         final String pkgName = shouldUseOverlayTargetName(sysPkg) ?
558                 sysPkg.getOverlayTarget() : sysPkg.getManifestPackageName();
559         return (implicitlyWhitelist && !userTypeWhitelist.containsKey(pkgName))
560                 || userWhitelist.contains(pkgName);
561     }
562 
563     /**
564      * Gets the package manifest names that are allowlisted for users of the given user type,
565      * as determined by SystemConfig.
566      */
567     @VisibleForTesting
getWhitelistedPackagesForUserType(String userType)568     @NonNull Set<String> getWhitelistedPackagesForUserType(String userType) {
569         final long userTypeMask = getUserTypeMask(userType);
570         final Set<String> installablePkgs = new ArraySet<>(mWhitelistedPackagesForUserTypes.size());
571         for (int i = 0; i < mWhitelistedPackagesForUserTypes.size(); i++) {
572             final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(i);
573             final long whitelistedUserTypes = mWhitelistedPackagesForUserTypes.valueAt(i);
574             if ((userTypeMask & whitelistedUserTypes) != 0) {
575                 installablePkgs.add(pkgName);
576             }
577         }
578         return installablePkgs;
579     }
580 
581     /**
582      * Set of package manifest names that are included anywhere in the package-to-user-type
583      * allowlist, as determined by SystemConfig.
584      *
585      * Packages that are allowlisted, but then denylisted so that they aren't to be installed on
586      * any user, are still present in this list, since that is a valid scenario (e.g. if an OEM
587      * completely blacklists an AOSP app).
588      */
getWhitelistedSystemPackages()589     private Set<String> getWhitelistedSystemPackages() {
590         return mWhitelistedPackagesForUserTypes.keySet();
591     }
592 
593     /**
594      * Returns a map of package manifest names to the bit set representing (via
595      * {@link #getUserTypeMask}) the user types on which they are to be installed.
596      * Also, clears this data from SystemConfig where it was stored inefficiently (and therefore
597      * should be called exactly once, even if the data isn't useful).
598      *
599      * Any system packages not present in this map should not even be on the device at all.
600      * To enforce this:
601      * <ul>
602      *  <li>Illegal user types are ignored.</li>
603      *  <li>Packages that never allowlisted at all (even if they are explicitly denylisted) are
604      *          ignored.</li>
605      *  <li>Packages that are denylisted whenever they are allowlisted will be stored with the
606      *          value 0 (since this is a valid scenario, e.g. if an OEM completely blacklists an
607      *          AOSP app).</li>
608      * </ul>
609      *
610      * @see #mWhitelistedPackagesForUserTypes
611      */
612     @VisibleForTesting
determineWhitelistedPackagesForUserTypes(SystemConfig sysConfig)613     ArrayMap<String, Long> determineWhitelistedPackagesForUserTypes(SystemConfig sysConfig) {
614         // We first get the list of user types that correspond to FULL, SYSTEM, and PROFILE.
615         final Map<String, Long> baseTypeBitSets = getBaseTypeBitSets();
616 
617         final ArrayMap<String, Set<String>> whitelist =
618                 sysConfig.getAndClearPackageToUserTypeWhitelist();
619         // result maps packageName -> userTypes on which the package should be installed.
620         final ArrayMap<String, Long> result = new ArrayMap<>(whitelist.size() + 1);
621         // First, do the allowlisted user types.
622         for (int i = 0; i < whitelist.size(); i++) {
623             final String pkgName = whitelist.keyAt(i).intern();
624             final long typesBitSet = getTypesBitSet(whitelist.valueAt(i), baseTypeBitSets);
625             if (typesBitSet != 0) {
626                 result.put(pkgName, typesBitSet);
627             }
628         }
629         // Then, un-allowlist any denylisted user types.
630         final ArrayMap<String, Set<String>> blacklist =
631                 sysConfig.getAndClearPackageToUserTypeBlacklist();
632         for (int i = 0; i < blacklist.size(); i++) {
633             final String pkgName = blacklist.keyAt(i).intern();
634             final long nonTypesBitSet = getTypesBitSet(blacklist.valueAt(i), baseTypeBitSets);
635             final Long typesBitSet = result.get(pkgName);
636             if (typesBitSet != null) {
637                 result.put(pkgName, typesBitSet & ~nonTypesBitSet);
638             } else if (nonTypesBitSet != 0) {
639                 // Package was never allowlisted but is validly denylisted.
640                 result.put(pkgName, 0L);
641             }
642         }
643         // Regardless of the whitelists/blacklists, ensure mandatory packages.
644         result.put("android", ~0L);
645         return result;
646     }
647 
648     /**
649      * Returns the bitmask (with exactly one 1) corresponding to the given userType.
650      * Returns 0 if no such userType exists.
651      */
652     @VisibleForTesting
getUserTypeMask(String userType)653     long getUserTypeMask(String userType) {
654         final int userTypeIndex = Arrays.binarySearch(mUserTypes, userType);
655         final long userTypeMask = userTypeIndex >= 0 ? (1 << userTypeIndex) : 0;
656         return userTypeMask;
657     }
658 
659     /**
660      * Returns the mapping from the name of each base type to the bitset (as defined by
661      * {@link #getUserTypeMask}) of user types to which it corresponds (i.e. the base's subtypes).
662      * <p>
663      * E.g. if "android.type.ex" is a FULL user type for which getUserTypeMask() returns (1 << 3),
664      * then getBaseTypeBitSets().get("FULL") will contain true (1) in position 3.
665      */
getBaseTypeBitSets()666     private Map<String, Long> getBaseTypeBitSets() {
667         long typesBitSetFull = 0;
668         long typesBitSetSystem = 0;
669         long typesBitSetProfile = 0;
670         for (int idx = 0; idx < mUserTypes.length; idx++) {
671             if (mUm.isUserTypeSubtypeOfFull(mUserTypes[idx])) {
672                 typesBitSetFull |= (1 << idx);
673             }
674             if (mUm.isUserTypeSubtypeOfSystem(mUserTypes[idx])) {
675                 typesBitSetSystem |= (1 << idx);
676             }
677             if (mUm.isUserTypeSubtypeOfProfile(mUserTypes[idx])) {
678                 typesBitSetProfile |= (1 << idx);
679             }
680         }
681 
682         Map<String, Long> result = new ArrayMap<>(3);
683         result.put("FULL", typesBitSetFull);
684         result.put("SYSTEM", typesBitSetSystem);
685         result.put("PROFILE", typesBitSetProfile);
686         return result;
687     }
688 
689     /**
690      * Converts a list of user types and base types, as used in SystemConfig, to a bit set
691      * representing (via {@link #getUserTypeMask}) user types.
692      *
693      * Returns 0 if userTypes does not contain any valid user or base types.
694      *
695      * @param baseTypeBitSets a map from the base types (FULL/SYSTEM/PROFILE) to their subtypes
696      *                        (represented as a bitset, as defined by {@link #getUserTypeMask}).
697      *                        (This can be created by {@link #getBaseTypeBitSets}.)
698      */
getTypesBitSet(Iterable<String> userTypes, Map<String, Long> baseTypeBitSets)699     private long getTypesBitSet(Iterable<String> userTypes, Map<String, Long> baseTypeBitSets) {
700         long resultBitSet = 0;
701         for (String type : userTypes) {
702             // See if userType is a base type, like FULL.
703             final Long baseTypeBitSet = baseTypeBitSets.get(type);
704             if (baseTypeBitSet != null) {
705                 resultBitSet |= baseTypeBitSet;
706                 continue;
707             }
708             // userType wasn't a base type, so it should be the name of a specific user type.
709             final long userTypeBitSet = getUserTypeMask(type);
710             if (userTypeBitSet != 0) {
711                 resultBitSet |= userTypeBitSet;
712                 continue;
713             }
714             Slog.w(TAG, "SystemConfig contained an invalid user type: " + type);
715         }
716         return resultBitSet;
717     }
718 
719     /** Returns a sorted array consisting of the keyset of the provided map. */
getAndSortKeysFromMap(ArrayMap<String, ?> map)720     private static String[] getAndSortKeysFromMap(ArrayMap<String, ?> map) {
721         final String[] userTypeList = new String[map.size()];
722         for (int i = 0; i < map.size(); i++) {
723             userTypeList[i] = map.keyAt(i);
724         }
725         Arrays.sort(userTypeList);
726         return userTypeList;
727     }
728 
dump(IndentingPrintWriter pw)729     void dump(IndentingPrintWriter pw) {
730         final int mode = getWhitelistMode();
731         pw.println("Whitelisted packages per user type");
732 
733         pw.increaseIndent();
734         pw.print("Mode: ");
735         pw.print(mode);
736         pw.print(isEnforceMode(mode) ? " (enforced)" : "");
737         pw.print(isLogMode(mode) ? " (logged)" : "");
738         pw.print(isImplicitWhitelistMode(mode) ? " (implicit)" : "");
739         pw.print(isIgnoreOtaMode(mode) ? " (ignore OTAs)" : "");
740         pw.println();
741         pw.decreaseIndent();
742 
743         pw.increaseIndent();
744         pw.println("Legend");
745         pw.increaseIndent();
746         for (int idx = 0; idx < mUserTypes.length; idx++) {
747             pw.println(idx + " -> " + mUserTypes[idx]);
748         }
749         pw.decreaseIndent(); pw.decreaseIndent();
750 
751         pw.increaseIndent();
752         final int size = mWhitelistedPackagesForUserTypes.size();
753         if (size == 0) {
754             pw.println("No packages");
755             pw.decreaseIndent();
756             return;
757         }
758         pw.print(size); pw.println(" packages:");
759         pw.increaseIndent();
760         for (int pkgIdx = 0; pkgIdx < size; pkgIdx++) {
761             final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(pkgIdx);
762             pw.print(pkgName); pw.print(": ");
763             final long userTypesBitSet = mWhitelistedPackagesForUserTypes.valueAt(pkgIdx);
764             for (int idx = 0; idx < mUserTypes.length; idx++) {
765                 if ((userTypesBitSet & (1 << idx)) != 0) {
766                     pw.print(idx); pw.print(" ");
767                 }
768             }
769             pw.println();
770         }
771         pw.decreaseIndent(); pw.decreaseIndent();
772 
773         pw.increaseIndent();
774         dumpPackageWhitelistProblems(pw, mode, /* verbose= */ true, /* criticalOnly= */ false);
775         pw.decreaseIndent();
776     }
777 
dumpPackageWhitelistProblems(IndentingPrintWriter pw, @PackageWhitelistMode int mode, boolean verbose, boolean criticalOnly)778     void dumpPackageWhitelistProblems(IndentingPrintWriter pw, @PackageWhitelistMode int mode,
779             boolean verbose, boolean criticalOnly) {
780         // Handle special cases first
781         if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_NONE) {
782             mode = getWhitelistMode();
783         } else if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) {
784             mode = getDeviceDefaultWhitelistMode();
785         }
786         if (criticalOnly) {
787             // Ignore log mode (if set) since log-only issues are not critical.
788             mode &= ~USER_TYPE_PACKAGE_WHITELIST_MODE_LOG;
789         }
790         Slog.v(TAG, "dumpPackageWhitelistProblems(): using mode " + modeToString(mode));
791 
792         final List<String> errors = getPackagesWhitelistErrors(mode);
793         showIssues(pw, verbose, errors, "errors");
794 
795         if (criticalOnly) return;
796 
797         final List<String> warnings = getPackagesWhitelistWarnings();
798         showIssues(pw, verbose, warnings, "warnings");
799     }
800 
showIssues(IndentingPrintWriter pw, boolean verbose, List<String> issues, String issueType)801     private static void showIssues(IndentingPrintWriter pw, boolean verbose, List<String> issues,
802             String issueType) {
803         final int size = issues.size();
804         if (size == 0) {
805             if (verbose) {
806                 pw.print("No "); pw.println(issueType);
807             }
808             return;
809         }
810         if (verbose) {
811             pw.print(size); pw.print(' '); pw.println(issueType);
812             pw.increaseIndent();
813         }
814         for (int i = 0; i < size; i++) {
815             pw.println(issues.get(i));
816         }
817         if (verbose) {
818             pw.decreaseIndent();
819         }
820     }
821 }
822