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