Merge "Improved 'cmd user list-missing-system-packages'." into rvc-dev am: 5ae8bbd6f7
Change-Id: Ia7d2672b296ceb0e07ae6ff56d991bf0ac4d6aae
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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,
|
||||||
@@ -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) {
|
|
||||||
Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): no warnings");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) {
|
// Check whether all whitelisted packages are indeed on the system.
|
||||||
// Only shows whether all whitelisted packages are indeed on the system.
|
final List<String> warnings = getPackagesWhitelistWarnings();
|
||||||
for (int i = 0; i < size; i++) {
|
final int numberWarnings = warnings.size();
|
||||||
final Pair<Boolean, String> pair = warnings.get(i);
|
if (numberWarnings == 0) {
|
||||||
final boolean isSevere = pair.first;
|
Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode)
|
||||||
if (!isSevere) {
|
+ ") has no warnings");
|
||||||
final String msg = pair.second;
|
} else {
|
||||||
Slog.w(TAG, msg);
|
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)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): " + size + " warnings");
|
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;
|
||||||
|
}
|
||||||
|
Slog.e(TAG, "checkWhitelistedSystemPackages(mode=" + modeToString(mode) + ") has "
|
||||||
|
+ numberErrors + " errors:");
|
||||||
|
|
||||||
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;
|
if (doWtf) {
|
||||||
final String msg = pair.second;
|
Slog.wtf(TAG, msg);
|
||||||
if (isSevere) {
|
|
||||||
if (doWtf) {
|
|
||||||
Slog.wtf(TAG, msg);
|
|
||||||
} else {
|
|
||||||
Slog.e(TAG, msg);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Slog.w(TAG, msg);
|
Slog.e(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.
|
||||||
@@ -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. */
|
||||||
@@ -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)}.
|
||||||
@@ -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<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode);
|
final List<String> errors = getPackagesWhitelistErrors(mode);
|
||||||
final int size = warnings.size();
|
showIssues(pw, verbose, errors, "errors");
|
||||||
|
|
||||||
|
if (criticalOnly) return;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|||||||
Reference in New Issue
Block a user