Merge "Added Shell command to list system packages that were not configured for exclusion." into rvc-dev am: 9a17241735
Change-Id: I3876c8782c0faf313daaed36083c0a4de80d68e0
This commit is contained in:
@@ -104,6 +104,7 @@ import com.android.internal.os.BackgroundThread;
|
|||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
import com.android.internal.util.FastXmlSerializer;
|
||||||
import com.android.internal.util.FrameworkStatsLog;
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
@@ -4516,6 +4517,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":
|
||||||
|
return runListMissingSystemPackages(pw, shell);
|
||||||
default:
|
default:
|
||||||
return shell.handleDefaultCommands(cmd);
|
return shell.handleDefaultCommands(cmd);
|
||||||
}
|
}
|
||||||
@@ -4582,6 +4585,30 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int runListMissingSystemPackages(PrintWriter pw, Shell shell) {
|
||||||
|
boolean verbose = false;
|
||||||
|
boolean force = false;
|
||||||
|
String opt;
|
||||||
|
while ((opt = shell.getNextOption()) != null) {
|
||||||
|
switch (opt) {
|
||||||
|
case "-v":
|
||||||
|
verbose = true;
|
||||||
|
break;
|
||||||
|
case "--force":
|
||||||
|
force = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pw.println("Invalid option: " + opt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) {
|
||||||
|
mSystemPackageInstaller.dumpMissingSystemPackages(ipw, force, verbose);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
|
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
|
||||||
@@ -5154,6 +5181,9 @@ public class UserManagerService extends IUserManager.Stub {
|
|||||||
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(" Prints all system packages that were not explicitly configured to be "
|
||||||
|
+ "installed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,15 +22,16 @@ import android.annotation.Nullable;
|
|||||||
import android.annotation.UserIdInt;
|
import android.annotation.UserIdInt;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManagerInternal;
|
import android.content.pm.PackageManagerInternal;
|
||||||
import android.content.pm.PackageParser;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.SystemProperties;
|
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.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemConfig;
|
import com.android.server.SystemConfig;
|
||||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||||
@@ -38,7 +39,9 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -263,37 +266,85 @@ class UserSystemPackageInstaller {
|
|||||||
if (!isLogMode(mode) && !isEnforceMode(mode)) {
|
if (!isLogMode(mode) && !isEnforceMode(mode)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Slog.v(TAG, "Checking that all system packages are whitelisted.");
|
final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode);
|
||||||
final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages();
|
final int size = warnings.size();
|
||||||
PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
|
if (size == 0) {
|
||||||
|
Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): no warnings");
|
||||||
// Check whether all whitelisted packages are indeed on the system.
|
|
||||||
for (String pkgName : allWhitelistedPackages) {
|
|
||||||
AndroidPackage pkg = pmInt.getPackage(pkgName);
|
|
||||||
if (pkg == null) {
|
|
||||||
Slog.w(TAG, pkgName + " is whitelisted but not present.");
|
|
||||||
} else if (!pkg.isSystem()) {
|
|
||||||
Slog.w(TAG, pkgName + " is whitelisted and present but not a system package.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether all system packages are indeed whitelisted.
|
|
||||||
if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean doWtf = isEnforceMode(mode);
|
|
||||||
pmInt.forEachPackage(pkg -> {
|
if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) {
|
||||||
if (pkg.isSystem() && !allWhitelistedPackages.contains(pkg.getManifestPackageName())) {
|
// Only shows whether all whitelisted packages are indeed on the system.
|
||||||
final String msg = "System package " + pkg.getManifestPackageName()
|
for (int i = 0; i < size; i++) {
|
||||||
+ " is not whitelisted using 'install-in-user-type' in SystemConfig "
|
final Pair<Boolean, String> pair = warnings.get(i);
|
||||||
+ "for any user types!";
|
final boolean isSevere = pair.first;
|
||||||
|
if (!isSevere) {
|
||||||
|
final String msg = pair.second;
|
||||||
|
Slog.w(TAG, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slog.v(TAG, "checkWhitelistedSystemPackages(mode=" + mode + "): " + size + " warnings");
|
||||||
|
boolean doWtf = !isImplicitWhitelistMode(mode);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final Pair<Boolean, String> pair = warnings.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.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
private List<Pair<Boolean, String>> checkSystemPackagesWhitelistWarnings(
|
||||||
|
@PackageWhitelistMode int mode) {
|
||||||
|
final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages();
|
||||||
|
final List<Pair<Boolean, String>> warnings = new ArrayList<>();
|
||||||
|
final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
|
||||||
|
|
||||||
|
// Check whether all whitelisted packages are indeed on the system.
|
||||||
|
final String notPresentFmt = "%s is whitelisted but not present.";
|
||||||
|
final String notSystemFmt = "%s is whitelisted and present but not a system package.";
|
||||||
|
for (String pkgName : allWhitelistedPackages) {
|
||||||
|
final AndroidPackage pkg = pmInt.getPackage(pkgName);
|
||||||
|
if (pkg == null) {
|
||||||
|
warnings.add(new Pair<>(false, String.format(notPresentFmt, pkgName)));
|
||||||
|
} else if (!pkg.isSystem()) {
|
||||||
|
warnings.add(new Pair<>(false, String.format(notSystemFmt, pkgName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether all system packages are indeed whitelisted.
|
||||||
|
final String logMessageFmt = "System package %s is not whitelisted using "
|
||||||
|
+ "'install-in-user-type' in SystemConfig for any user types!";
|
||||||
|
final boolean isSevere = isEnforceMode(mode);
|
||||||
|
pmInt.forEachPackage(pkg -> {
|
||||||
|
if (!pkg.isSystem()) return;
|
||||||
|
final String pkgName = pkg.getManifestPackageName();
|
||||||
|
if (!allWhitelistedPackages.contains(pkgName)) {
|
||||||
|
warnings.add(new Pair<>(isSevere, String.format(logMessageFmt, pkgName)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return warnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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. */
|
||||||
@@ -602,32 +653,45 @@ class UserSystemPackageInstaller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dump(PrintWriter pw) {
|
void dump(PrintWriter pw) {
|
||||||
final String prefix = " ";
|
try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) {
|
||||||
final String prefix2 = prefix + prefix;
|
dumpIndented(ipw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dumpIndented(IndentingPrintWriter pw) {
|
||||||
final int mode = getWhitelistMode();
|
final int mode = getWhitelistMode();
|
||||||
pw.println("Whitelisted packages per user type");
|
pw.println("Whitelisted packages per user type");
|
||||||
pw.print(prefix); pw.print("Mode: ");
|
|
||||||
|
pw.increaseIndent();
|
||||||
|
pw.print("Mode: ");
|
||||||
pw.print(mode);
|
pw.print(mode);
|
||||||
pw.print(isEnforceMode(mode) ? " (enforced)" : "");
|
pw.print(isEnforceMode(mode) ? " (enforced)" : "");
|
||||||
pw.print(isLogMode(mode) ? " (logged)" : "");
|
pw.print(isLogMode(mode) ? " (logged)" : "");
|
||||||
pw.print(isImplicitWhitelistMode(mode) ? " (implicit)" : "");
|
pw.print(isImplicitWhitelistMode(mode) ? " (implicit)" : "");
|
||||||
pw.print(isIgnoreOtaMode(mode) ? " (ignore OTAs)" : "");
|
pw.print(isIgnoreOtaMode(mode) ? " (ignore OTAs)" : "");
|
||||||
pw.println();
|
pw.println();
|
||||||
|
pw.decreaseIndent();
|
||||||
|
|
||||||
pw.print(prefix); pw.println("Legend");
|
pw.increaseIndent();
|
||||||
|
pw.println("Legend");
|
||||||
|
pw.increaseIndent();
|
||||||
for (int idx = 0; idx < mUserTypes.length; idx++) {
|
for (int idx = 0; idx < mUserTypes.length; idx++) {
|
||||||
pw.print(prefix2); pw.println(idx + " -> " + mUserTypes[idx]);
|
pw.println(idx + " -> " + mUserTypes[idx]);
|
||||||
}
|
}
|
||||||
|
pw.decreaseIndent(); pw.decreaseIndent();
|
||||||
|
|
||||||
|
pw.increaseIndent();
|
||||||
final int size = mWhitelistedPackagesForUserTypes.size();
|
final int size = mWhitelistedPackagesForUserTypes.size();
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
pw.print(prefix); pw.println("No packages");
|
pw.println("No packages");
|
||||||
|
pw.decreaseIndent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pw.print(prefix); pw.print(size); pw.println(" packages:");
|
pw.print(size); pw.println(" packages:");
|
||||||
|
pw.increaseIndent();
|
||||||
for (int pkgIdx = 0; pkgIdx < size; pkgIdx++) {
|
for (int pkgIdx = 0; pkgIdx < size; pkgIdx++) {
|
||||||
final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(pkgIdx);
|
final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(pkgIdx);
|
||||||
pw.print(prefix2); pw.print(pkgName); pw.print(": ");
|
pw.print(pkgName); pw.print(": ");
|
||||||
final long userTypesBitSet = mWhitelistedPackagesForUserTypes.valueAt(pkgIdx);
|
final long userTypesBitSet = mWhitelistedPackagesForUserTypes.valueAt(pkgIdx);
|
||||||
for (int idx = 0; idx < mUserTypes.length; idx++) {
|
for (int idx = 0; idx < mUserTypes.length; idx++) {
|
||||||
if ((userTypesBitSet & (1 << idx)) != 0) {
|
if ((userTypesBitSet & (1 << idx)) != 0) {
|
||||||
@@ -636,5 +700,40 @@ class UserSystemPackageInstaller {
|
|||||||
}
|
}
|
||||||
pw.println();
|
pw.println();
|
||||||
}
|
}
|
||||||
|
pw.decreaseIndent(); pw.decreaseIndent();
|
||||||
|
|
||||||
|
pw.increaseIndent();
|
||||||
|
dumpMissingSystemPackages(pw, /* force= */ true, /* verbose= */ true);
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpMissingSystemPackages(IndentingPrintWriter pw, boolean force, boolean verbose) {
|
||||||
|
final int mode = getWhitelistMode();
|
||||||
|
final boolean show = force || (isEnforceMode(mode) && !isImplicitWhitelistMode(mode));
|
||||||
|
if (!show) return;
|
||||||
|
|
||||||
|
final List<Pair<Boolean, String>> warnings = checkSystemPackagesWhitelistWarnings(mode);
|
||||||
|
final int size = warnings.size();
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
if (verbose) {
|
||||||
|
pw.println("All system packages are accounted for");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
pw.print(size); pw.println(" warnings for system user:");
|
||||||
|
pw.increaseIndent();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final Pair<Boolean, String> pair = warnings.get(i);
|
||||||
|
final String lvl = pair.first ? "WTF" : "WARN";
|
||||||
|
final String msg = pair.second;
|
||||||
|
pw.print(lvl); pw.print(": "); pw.println(msg);
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user