Loading services/core/java/com/android/server/pm/UserManagerService.java +25 −11 Original line number Original line Diff line number Diff line Loading @@ -4516,8 +4516,8 @@ public class UserManagerService extends IUserManager.Stub { switch(cmd) { switch(cmd) { case "list": case "list": return runList(pw, shell); return runList(pw, shell); case "list-missing-system-packages": case "report-system-user-package-whitelist-problems": return runListMissingSystemPackages(pw, shell); return runReportPackageWhitelistProblems(pw, shell); default: default: return shell.handleDefaultCommands(cmd); return shell.handleDefaultCommands(cmd); } } Loading Loading @@ -4584,17 +4584,22 @@ public class UserManagerService extends IUserManager.Stub { } } } } private int runListMissingSystemPackages(PrintWriter pw, Shell shell) { private int runReportPackageWhitelistProblems(PrintWriter pw, Shell shell) { boolean verbose = false; boolean verbose = false; boolean force = false; boolean criticalOnly = false; int mode = UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_NONE; String opt; String opt; while ((opt = shell.getNextOption()) != null) { while ((opt = shell.getNextOption()) != null) { switch (opt) { switch (opt) { case "-v": case "-v": case "--verbose": verbose = true; verbose = true; break; break; case "--force": case "--critical-only": force = true; criticalOnly = true; break; case "--mode": mode = Integer.parseInt(shell.getNextArgRequired()); break; break; default: default: pw.println("Invalid option: " + opt); pw.println("Invalid option: " + opt); Loading @@ -4602,8 +4607,12 @@ public class UserManagerService extends IUserManager.Stub { } } } } Slog.d(LOG_TAG, "runReportPackageWhitelistProblems(): verbose=" + verbose + ", criticalOnly=" + criticalOnly + ", mode=" + UserSystemPackageInstaller.modeToString(mode)); try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) { try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) { mSystemPackageInstaller.dumpMissingSystemPackages(ipw, force, verbose); mSystemPackageInstaller.dumpPackageWhitelistProblems(ipw, mode, verbose, criticalOnly); } } return 0; return 0; } } Loading Loading @@ -5176,13 +5185,18 @@ public class UserManagerService extends IUserManager.Stub { final PrintWriter pw = getOutPrintWriter(); final PrintWriter pw = getOutPrintWriter(); pw.println("User manager (user) commands:"); pw.println("User manager (user) commands:"); pw.println(" help"); pw.println(" help"); pw.println(" Print this help text."); pw.println(" Prints this help text."); pw.println(""); pw.println(""); pw.println(" list [-v] [-all]"); pw.println(" list [-v] [-all]"); pw.println(" Prints all users on the system."); pw.println(" Prints all users on the system."); pw.println(" list-missing-system-packages [-v] [--force]"); pw.println(" report-system-user-package-whitelist-problems [-v | --verbose] " pw.println(" Prints all system packages that were not explicitly configured to be " + "[--critical-only] [--mode MODE]"); + "installed."); pw.println(" Reports all issues on user-type package whitelist XML files. Options:"); pw.println(" -v | --verbose : shows extra info, like number of issues"); pw.println(" --critical-only: show only critical issues, excluding warnings"); pw.println(" --mode MODE: shows what errors would be if device used mode MODE (where" + " MODE is the whitelist mode integer as defined by " + "config_userTypePackageWhitelistMode)"); } } } } Loading services/core/java/com/android/server/pm/UserSystemPackageInstaller.java +109 −62 Original line number Original line Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.Pair; import android.util.DebugUtils; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; Loading @@ -41,6 +41,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; Loading Loading @@ -111,14 +112,20 @@ class UserSystemPackageInstaller { * frameworks/base/core/res/res/values/config.xml * frameworks/base/core/res/res/values/config.xml */ */ static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode"; static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode"; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01; // NOTE: flags below are public so they can used by DebugUtils.flagsToString. And this class static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02; // itself is package-protected, so it doesn't matter... static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1; // Used by Shell command only static final int USER_TYPE_PACKAGE_WHITELIST_MODE_NONE = -1000; @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = { @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = { USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE, USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE, USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE, USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE, Loading Loading @@ -266,58 +273,56 @@ class UserSystemPackageInstaller { if (!isLogMode(mode) && !isEnforceMode(mode)) { if (!isLogMode(mode) && !isEnforceMode(mode)) { return; return; } } final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode); Slog.v(TAG, "Checking that all system packages are whitelisted."); final int size = warnings.size(); if (size == 0) { // Check whether all whitelisted packages are indeed on the system. Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): no warnings"); final List<String> warnings = getPackagesWhitelistWarnings(); return; final int numberWarnings = warnings.size(); if (numberWarnings == 0) { Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has no warnings"); } else { Slog.w(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has " + numberWarnings + " warnings:"); for (int i = 0; i < numberWarnings; i++) { Slog.w(TAG, warnings.get(i)); } } } // Check whether all system packages are indeed whitelisted. if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) { if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) { // Only shows whether all whitelisted packages are indeed on the system. return; for (int i = 0; i < size; i++) { final Pair<Boolean, String> pair = warnings.get(i); final boolean isSevere = pair.first; if (!isSevere) { final String msg = pair.second; Slog.w(TAG, msg); } } } final List<String> errors = getPackagesWhitelistErrors(mode); final int numberErrors = errors.size(); if (numberErrors == 0) { Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has no errors"); return; return; } } Slog.e(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has " + numberErrors + " errors:"); Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): " + size + " warnings"); boolean doWtf = !isImplicitWhitelistMode(mode); boolean doWtf = !isImplicitWhitelistMode(mode); for (int i = 0; i < size; i++) { for (int i = 0; i < numberWarnings; i++) { final Pair<Boolean, String> pair = warnings.get(i); final String msg = errors.get(i); final boolean isSevere = pair.first; final String msg = pair.second; if (isSevere) { if (doWtf) { if (doWtf) { Slog.wtf(TAG, msg); Slog.wtf(TAG, msg); } else { } else { Slog.e(TAG, msg); Slog.e(TAG, msg); } } } else { Slog.w(TAG, msg); } } } } } // TODO: method below was created to refactor the one-time logging logic so it can be used on // dump / cmd as well. It could to be further refactored (for example, creating a new // structure for the warnings so it doesn't need a Pair). /** /** * Gets warnings for system user whitelisting. * Gets packages that are listed in the whitelist XML but are not present on the system image. * * @return list of warnings, where {@code Pair.first} is the severity ({@code true} for WTF, * {@code false} for WARN) and {@code Pair.second} the message. */ */ @NonNull @NonNull private List<Pair<Boolean, String>> checkSystemPackagesWhitelistWarnings( private List<String> getPackagesWhitelistWarnings() { @PackageWhitelistMode int mode) { final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final List<Pair<Boolean, String>> warnings = new ArrayList<>(); final List<String> warnings = new ArrayList<>(); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); // Check whether all whitelisted packages are indeed on the system. // Check whether all whitelisted packages are indeed on the system. Loading @@ -326,25 +331,39 @@ class UserSystemPackageInstaller { for (String pkgName : allWhitelistedPackages) { for (String pkgName : allWhitelistedPackages) { final AndroidPackage pkg = pmInt.getPackage(pkgName); final AndroidPackage pkg = pmInt.getPackage(pkgName); if (pkg == null) { if (pkg == null) { warnings.add(new Pair<>(false, String.format(notPresentFmt, pkgName))); warnings.add(String.format(notPresentFmt, pkgName)); } else if (!pkg.isSystem()) { } else if (!pkg.isSystem()) { warnings.add(new Pair<>(false, String.format(notSystemFmt, pkgName))); warnings.add(String.format(notSystemFmt, pkgName)); } } return warnings; } } /** * Gets packages that are not listed in the whitelist XMLs when they should be. */ @NonNull private List<String> getPackagesWhitelistErrors(@PackageWhitelistMode int mode) { if ((!isEnforceMode(mode) || isImplicitWhitelistMode(mode)) && !isLogMode(mode)) { return Collections.emptyList(); } } final List<String> errors = new ArrayList<>(); final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); // Check whether all system packages are indeed whitelisted. // Check whether all system packages are indeed whitelisted. final String logMessageFmt = "System package %s is not whitelisted using " final String logMessageFmt = "System package %s is not whitelisted using " + "'install-in-user-type' in SystemConfig for any user types!"; + "'install-in-user-type' in SystemConfig for any user types!"; final boolean isSevere = isEnforceMode(mode); pmInt.forEachPackage(pkg -> { pmInt.forEachPackage(pkg -> { if (!pkg.isSystem()) return; if (!pkg.isSystem()) return; final String pkgName = pkg.getManifestPackageName(); final String pkgName = pkg.getManifestPackageName(); if (!allWhitelistedPackages.contains(pkgName)) { if (!allWhitelistedPackages.contains(pkgName)) { warnings.add(new Pair<>(isSevere, String.format(logMessageFmt, pkgName))); errors.add(String.format(logMessageFmt, pkgName)); } } }); }); return warnings; return errors; } } /** Whether to only install system packages in new users for which they are whitelisted. */ /** Whether to only install system packages in new users for which they are whitelisted. */ Loading Loading @@ -420,10 +439,28 @@ class UserSystemPackageInstaller { if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { return runtimeMode; return runtimeMode; } } return getDeviceDefaultWhitelistMode(); } /** Gets the PackageWhitelistMode as defined by {@code config_userTypePackageWhitelistMode}. */ private @PackageWhitelistMode int getDeviceDefaultWhitelistMode() { return Resources.getSystem() return Resources.getSystem() .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode); .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode); } } static @NonNull String modeToString(@PackageWhitelistMode int mode) { // Must handle some types separately because they're not bitwise flags switch (mode) { case USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT: return "DEVICE_DEFAULT"; case USER_TYPE_PACKAGE_WHITELIST_MODE_NONE: return "NONE"; default: return DebugUtils.flagsToString(UserSystemPackageInstaller.class, "USER_TYPE_PACKAGE_WHITELIST_MODE_", mode); } } /** /** * Gets the system packages names that should be installed on the given user. * Gets the system packages names that should be installed on the given user. * See {@link #getInstallablePackagesForUserType(String)}. * See {@link #getInstallablePackagesForUserType(String)}. Loading Loading @@ -703,34 +740,44 @@ class UserSystemPackageInstaller { pw.decreaseIndent(); pw.decreaseIndent(); pw.decreaseIndent(); pw.decreaseIndent(); pw.increaseIndent(); pw.increaseIndent(); dumpMissingSystemPackages(pw, /* force= */ true, /* verbose= */ true); dumpPackageWhitelistProblems(pw, mode, /* verbose= */ true, /* criticalOnly= */ false); pw.decreaseIndent(); pw.decreaseIndent(); } } void dumpMissingSystemPackages(IndentingPrintWriter pw, boolean force, boolean verbose) { void dumpPackageWhitelistProblems(IndentingPrintWriter pw, @PackageWhitelistMode int mode, final int mode = getWhitelistMode(); boolean verbose, boolean criticalOnly) { final boolean show = force || (isEnforceMode(mode) && !isImplicitWhitelistMode(mode)); // Handle special cases first if (!show) return; if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_NONE) { mode = getWhitelistMode(); } else if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { mode = getDeviceDefaultWhitelistMode(); } Slog.v(TAG, "dumpPackageWhitelistProblems(): using mode " + modeToString(mode)); final List<String> errors = getPackagesWhitelistErrors(mode); showIssues(pw, verbose, errors, "errors"); final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode); if (criticalOnly) return; final int size = warnings.size(); final List<String> warnings = getPackagesWhitelistWarnings(); showIssues(pw, verbose, warnings, "warnings"); } private static void showIssues(IndentingPrintWriter pw, boolean verbose, List<String> issues, String issueType) { final int size = issues.size(); if (size == 0) { if (size == 0) { if (verbose) { if (verbose) { pw.println("All system packages are accounted for"); pw.print("No "); pw.println(issueType); } } return; return; } } if (verbose) { if (verbose) { pw.print(size); pw.println(" warnings for system user:"); pw.print(size); pw.print(' '); pw.println(issueType); pw.increaseIndent(); pw.increaseIndent(); } } for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { final Pair<Boolean, String> pair = warnings.get(i); pw.println(issues.get(i)); final String lvl = pair.first ? "WTF" : "WARN"; final String msg = pair.second; pw.print(lvl); pw.print(": "); pw.println(msg); } } if (verbose) { if (verbose) { pw.decreaseIndent(); pw.decreaseIndent(); Loading Loading
services/core/java/com/android/server/pm/UserManagerService.java +25 −11 Original line number Original line Diff line number Diff line Loading @@ -4516,8 +4516,8 @@ public class UserManagerService extends IUserManager.Stub { switch(cmd) { switch(cmd) { case "list": case "list": return runList(pw, shell); return runList(pw, shell); case "list-missing-system-packages": case "report-system-user-package-whitelist-problems": return runListMissingSystemPackages(pw, shell); return runReportPackageWhitelistProblems(pw, shell); default: default: return shell.handleDefaultCommands(cmd); return shell.handleDefaultCommands(cmd); } } Loading Loading @@ -4584,17 +4584,22 @@ public class UserManagerService extends IUserManager.Stub { } } } } private int runListMissingSystemPackages(PrintWriter pw, Shell shell) { private int runReportPackageWhitelistProblems(PrintWriter pw, Shell shell) { boolean verbose = false; boolean verbose = false; boolean force = false; boolean criticalOnly = false; int mode = UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_NONE; String opt; String opt; while ((opt = shell.getNextOption()) != null) { while ((opt = shell.getNextOption()) != null) { switch (opt) { switch (opt) { case "-v": case "-v": case "--verbose": verbose = true; verbose = true; break; break; case "--force": case "--critical-only": force = true; criticalOnly = true; break; case "--mode": mode = Integer.parseInt(shell.getNextArgRequired()); break; break; default: default: pw.println("Invalid option: " + opt); pw.println("Invalid option: " + opt); Loading @@ -4602,8 +4607,12 @@ public class UserManagerService extends IUserManager.Stub { } } } } Slog.d(LOG_TAG, "runReportPackageWhitelistProblems(): verbose=" + verbose + ", criticalOnly=" + criticalOnly + ", mode=" + UserSystemPackageInstaller.modeToString(mode)); try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) { try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) { mSystemPackageInstaller.dumpMissingSystemPackages(ipw, force, verbose); mSystemPackageInstaller.dumpPackageWhitelistProblems(ipw, mode, verbose, criticalOnly); } } return 0; return 0; } } Loading Loading @@ -5176,13 +5185,18 @@ public class UserManagerService extends IUserManager.Stub { final PrintWriter pw = getOutPrintWriter(); final PrintWriter pw = getOutPrintWriter(); pw.println("User manager (user) commands:"); pw.println("User manager (user) commands:"); pw.println(" help"); pw.println(" help"); pw.println(" Print this help text."); pw.println(" Prints this help text."); pw.println(""); pw.println(""); pw.println(" list [-v] [-all]"); pw.println(" list [-v] [-all]"); pw.println(" Prints all users on the system."); pw.println(" Prints all users on the system."); pw.println(" list-missing-system-packages [-v] [--force]"); pw.println(" report-system-user-package-whitelist-problems [-v | --verbose] " pw.println(" Prints all system packages that were not explicitly configured to be " + "[--critical-only] [--mode MODE]"); + "installed."); pw.println(" Reports all issues on user-type package whitelist XML files. Options:"); pw.println(" -v | --verbose : shows extra info, like number of issues"); pw.println(" --critical-only: show only critical issues, excluding warnings"); pw.println(" --mode MODE: shows what errors would be if device used mode MODE (where" + " MODE is the whitelist mode integer as defined by " + "config_userTypePackageWhitelistMode)"); } } } } Loading
services/core/java/com/android/server/pm/UserSystemPackageInstaller.java +109 −62 Original line number Original line Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.Pair; import android.util.DebugUtils; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; Loading @@ -41,6 +41,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; Loading Loading @@ -111,14 +112,20 @@ class UserSystemPackageInstaller { * frameworks/base/core/res/res/values/config.xml * frameworks/base/core/res/res/values/config.xml */ */ static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode"; static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode"; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01; // NOTE: flags below are public so they can used by DebugUtils.flagsToString. And this class static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02; // itself is package-protected, so it doesn't matter... static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08; public static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1; static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1; // Used by Shell command only static final int USER_TYPE_PACKAGE_WHITELIST_MODE_NONE = -1000; @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = { @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = { USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE, USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE, USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE, USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE, Loading Loading @@ -266,58 +273,56 @@ class UserSystemPackageInstaller { if (!isLogMode(mode) && !isEnforceMode(mode)) { if (!isLogMode(mode) && !isEnforceMode(mode)) { return; return; } } final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode); Slog.v(TAG, "Checking that all system packages are whitelisted."); final int size = warnings.size(); if (size == 0) { // Check whether all whitelisted packages are indeed on the system. Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): no warnings"); final List<String> warnings = getPackagesWhitelistWarnings(); return; final int numberWarnings = warnings.size(); if (numberWarnings == 0) { Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has no warnings"); } else { Slog.w(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has " + numberWarnings + " warnings:"); for (int i = 0; i < numberWarnings; i++) { Slog.w(TAG, warnings.get(i)); } } } // Check whether all system packages are indeed whitelisted. if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) { if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) { // Only shows whether all whitelisted packages are indeed on the system. return; for (int i = 0; i < size; i++) { final Pair<Boolean, String> pair = warnings.get(i); final boolean isSevere = pair.first; if (!isSevere) { final String msg = pair.second; Slog.w(TAG, msg); } } } final List<String> errors = getPackagesWhitelistErrors(mode); final int numberErrors = errors.size(); if (numberErrors == 0) { Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has no errors"); return; return; } } Slog.e(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has " + numberErrors + " errors:"); Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): " + size + " warnings"); boolean doWtf = !isImplicitWhitelistMode(mode); boolean doWtf = !isImplicitWhitelistMode(mode); for (int i = 0; i < size; i++) { for (int i = 0; i < numberWarnings; i++) { final Pair<Boolean, String> pair = warnings.get(i); final String msg = errors.get(i); final boolean isSevere = pair.first; final String msg = pair.second; if (isSevere) { if (doWtf) { if (doWtf) { Slog.wtf(TAG, msg); Slog.wtf(TAG, msg); } else { } else { Slog.e(TAG, msg); Slog.e(TAG, msg); } } } else { Slog.w(TAG, msg); } } } } } // TODO: method below was created to refactor the one-time logging logic so it can be used on // dump / cmd as well. It could to be further refactored (for example, creating a new // structure for the warnings so it doesn't need a Pair). /** /** * Gets warnings for system user whitelisting. * Gets packages that are listed in the whitelist XML but are not present on the system image. * * @return list of warnings, where {@code Pair.first} is the severity ({@code true} for WTF, * {@code false} for WARN) and {@code Pair.second} the message. */ */ @NonNull @NonNull private List<Pair<Boolean, String>> checkSystemPackagesWhitelistWarnings( private List<String> getPackagesWhitelistWarnings() { @PackageWhitelistMode int mode) { final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final List<Pair<Boolean, String>> warnings = new ArrayList<>(); final List<String> warnings = new ArrayList<>(); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); // Check whether all whitelisted packages are indeed on the system. // Check whether all whitelisted packages are indeed on the system. Loading @@ -326,25 +331,39 @@ class UserSystemPackageInstaller { for (String pkgName : allWhitelistedPackages) { for (String pkgName : allWhitelistedPackages) { final AndroidPackage pkg = pmInt.getPackage(pkgName); final AndroidPackage pkg = pmInt.getPackage(pkgName); if (pkg == null) { if (pkg == null) { warnings.add(new Pair<>(false, String.format(notPresentFmt, pkgName))); warnings.add(String.format(notPresentFmt, pkgName)); } else if (!pkg.isSystem()) { } else if (!pkg.isSystem()) { warnings.add(new Pair<>(false, String.format(notSystemFmt, pkgName))); warnings.add(String.format(notSystemFmt, pkgName)); } } return warnings; } } /** * Gets packages that are not listed in the whitelist XMLs when they should be. */ @NonNull private List<String> getPackagesWhitelistErrors(@PackageWhitelistMode int mode) { if ((!isEnforceMode(mode) || isImplicitWhitelistMode(mode)) && !isLogMode(mode)) { return Collections.emptyList(); } } final List<String> errors = new ArrayList<>(); final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages(); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); // Check whether all system packages are indeed whitelisted. // Check whether all system packages are indeed whitelisted. final String logMessageFmt = "System package %s is not whitelisted using " final String logMessageFmt = "System package %s is not whitelisted using " + "'install-in-user-type' in SystemConfig for any user types!"; + "'install-in-user-type' in SystemConfig for any user types!"; final boolean isSevere = isEnforceMode(mode); pmInt.forEachPackage(pkg -> { pmInt.forEachPackage(pkg -> { if (!pkg.isSystem()) return; if (!pkg.isSystem()) return; final String pkgName = pkg.getManifestPackageName(); final String pkgName = pkg.getManifestPackageName(); if (!allWhitelistedPackages.contains(pkgName)) { if (!allWhitelistedPackages.contains(pkgName)) { warnings.add(new Pair<>(isSevere, String.format(logMessageFmt, pkgName))); errors.add(String.format(logMessageFmt, pkgName)); } } }); }); return warnings; return errors; } } /** Whether to only install system packages in new users for which they are whitelisted. */ /** Whether to only install system packages in new users for which they are whitelisted. */ Loading Loading @@ -420,10 +439,28 @@ class UserSystemPackageInstaller { if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { return runtimeMode; return runtimeMode; } } return getDeviceDefaultWhitelistMode(); } /** Gets the PackageWhitelistMode as defined by {@code config_userTypePackageWhitelistMode}. */ private @PackageWhitelistMode int getDeviceDefaultWhitelistMode() { return Resources.getSystem() return Resources.getSystem() .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode); .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode); } } static @NonNull String modeToString(@PackageWhitelistMode int mode) { // Must handle some types separately because they're not bitwise flags switch (mode) { case USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT: return "DEVICE_DEFAULT"; case USER_TYPE_PACKAGE_WHITELIST_MODE_NONE: return "NONE"; default: return DebugUtils.flagsToString(UserSystemPackageInstaller.class, "USER_TYPE_PACKAGE_WHITELIST_MODE_", mode); } } /** /** * Gets the system packages names that should be installed on the given user. * Gets the system packages names that should be installed on the given user. * See {@link #getInstallablePackagesForUserType(String)}. * See {@link #getInstallablePackagesForUserType(String)}. Loading Loading @@ -703,34 +740,44 @@ class UserSystemPackageInstaller { pw.decreaseIndent(); pw.decreaseIndent(); pw.decreaseIndent(); pw.decreaseIndent(); pw.increaseIndent(); pw.increaseIndent(); dumpMissingSystemPackages(pw, /* force= */ true, /* verbose= */ true); dumpPackageWhitelistProblems(pw, mode, /* verbose= */ true, /* criticalOnly= */ false); pw.decreaseIndent(); pw.decreaseIndent(); } } void dumpMissingSystemPackages(IndentingPrintWriter pw, boolean force, boolean verbose) { void dumpPackageWhitelistProblems(IndentingPrintWriter pw, @PackageWhitelistMode int mode, final int mode = getWhitelistMode(); boolean verbose, boolean criticalOnly) { final boolean show = force || (isEnforceMode(mode) && !isImplicitWhitelistMode(mode)); // Handle special cases first if (!show) return; if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_NONE) { mode = getWhitelistMode(); } else if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) { mode = getDeviceDefaultWhitelistMode(); } Slog.v(TAG, "dumpPackageWhitelistProblems(): using mode " + modeToString(mode)); final List<String> errors = getPackagesWhitelistErrors(mode); showIssues(pw, verbose, errors, "errors"); final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode); if (criticalOnly) return; final int size = warnings.size(); final List<String> warnings = getPackagesWhitelistWarnings(); showIssues(pw, verbose, warnings, "warnings"); } private static void showIssues(IndentingPrintWriter pw, boolean verbose, List<String> issues, String issueType) { final int size = issues.size(); if (size == 0) { if (size == 0) { if (verbose) { if (verbose) { pw.println("All system packages are accounted for"); pw.print("No "); pw.println(issueType); } } return; return; } } if (verbose) { if (verbose) { pw.print(size); pw.println(" warnings for system user:"); pw.print(size); pw.print(' '); pw.println(issueType); pw.increaseIndent(); pw.increaseIndent(); } } for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { final Pair<Boolean, String> pair = warnings.get(i); pw.println(issues.get(i)); final String lvl = pair.first ? "WTF" : "WARN"; final String msg = pair.second; pw.print(lvl); pw.print(": "); pw.println(msg); } } if (verbose) { if (verbose) { pw.decreaseIndent(); pw.decreaseIndent(); Loading