blob: 2a00a442542d17b77d9224fbd15d1ea3a3e61bd0 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static com.android.server.pm.KnownPackages.LAST_KNOWN_PACKAGE;
import static com.android.server.pm.PackageManagerServiceUtils.dumpCriticalInfo;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.incremental.PerUidReadTimeouts;
import android.service.pm.PackageServiceDumpProto;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.resolution.ComponentResolverApi;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
import dalvik.annotation.optimization.NeverCompile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Dumps PackageManagerService internal states.
*/
final class DumpHelper {
private final PermissionManagerServiceInternal mPermissionManager;
private final StorageEventHelper mStorageEventHelper;
private final DomainVerificationManagerInternal mDomainVerificationManager;
private final PackageInstallerService mInstallerService;
private final String[] mRequiredVerifierPackages;
private final KnownPackages mKnownPackages;
private final ChangedPackagesTracker mChangedPackagesTracker;
private final ArrayMap<String, FeatureInfo> mAvailableFeatures;
private final ArraySet<String> mProtectedBroadcasts;
private final PerUidReadTimeouts[] mPerUidReadTimeouts;
private final SnapshotStatistics mSnapshotStatistics;
DumpHelper(
PermissionManagerServiceInternal permissionManager,
StorageEventHelper storageEventHelper,
DomainVerificationManagerInternal domainVerificationManager,
PackageInstallerService installerService, String[] requiredVerifierPackages,
KnownPackages knownPackages,
ChangedPackagesTracker changedPackagesTracker,
ArrayMap<String, FeatureInfo> availableFeatures,
ArraySet<String> protectedBroadcasts,
PerUidReadTimeouts[] perUidReadTimeouts,
SnapshotStatistics snapshotStatistics) {
mPermissionManager = permissionManager;
mStorageEventHelper = storageEventHelper;
mDomainVerificationManager = domainVerificationManager;
mInstallerService = installerService;
mRequiredVerifierPackages = requiredVerifierPackages;
mKnownPackages = knownPackages;
mChangedPackagesTracker = changedPackagesTracker;
mAvailableFeatures = availableFeatures;
mProtectedBroadcasts = protectedBroadcasts;
mPerUidReadTimeouts = perUidReadTimeouts;
mSnapshotStatistics = snapshotStatistics;
}
@NeverCompile // Avoid size overhead of debugging code.
public void doDump(Computer snapshot, FileDescriptor fd, PrintWriter pw, String[] args) {
DumpState dumpState = new DumpState();
ArraySet<String> permissionNames = null;
int opti = 0;
while (opti < args.length) {
String opt = args[opti];
if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
break;
}
opti++;
if ("-a".equals(opt)) {
// Right now we only know how to print all.
} else if ("-h".equals(opt)) {
printHelp(pw);
return;
} else if ("--checkin".equals(opt)) {
dumpState.setCheckIn(true);
} else if ("--all-components".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_DUMP_ALL_COMPONENTS);
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
} else if ("--include-apex".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_INCLUDE_APEX);
} else if ("--proto".equals(opt)) {
dumpProto(snapshot, fd);
return;
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
}
}
// Is the caller requesting to dump a particular piece of data?
if (opti < args.length) {
String cmd = args[opti];
opti++;
// Is this a package name?
if ("android".equals(cmd) || cmd.contains(".")) {
dumpState.setTargetPackageName(cmd);
// When dumping a single package, we always dump all of its
// filter information since the amount of data will be reasonable.
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
} else if ("check-permission".equals(cmd)) {
if (opti >= args.length) {
pw.println("Error: check-permission missing permission argument");
return;
}
String perm = args[opti];
opti++;
if (opti >= args.length) {
pw.println("Error: check-permission missing package argument");
return;
}
String pkg = args[opti];
opti++;
int user = UserHandle.getUserId(Binder.getCallingUid());
if (opti < args.length) {
try {
user = Integer.parseInt(args[opti]);
} catch (NumberFormatException e) {
pw.println("Error: check-permission user argument is not a number: "
+ args[opti]);
return;
}
}
// Normalize package name to handle renamed packages and static libs
pkg = snapshot.resolveInternalPackageName(pkg,
PackageManager.VERSION_CODE_HIGHEST);
pw.println(mPermissionManager.checkPermission(
pkg, perm, Context.DEVICE_ID_DEFAULT, user));
return;
} else if ("l".equals(cmd) || "libraries".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_LIBS);
} else if ("f".equals(cmd) || "features".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_FEATURES);
} else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
if (opti >= args.length) {
dumpState.setDump(DumpState.DUMP_ACTIVITY_RESOLVERS
| DumpState.DUMP_SERVICE_RESOLVERS
| DumpState.DUMP_RECEIVER_RESOLVERS
| DumpState.DUMP_CONTENT_RESOLVERS);
} else {
while (opti < args.length) {
String name = args[opti];
if ("a".equals(name) || "activity".equals(name)) {
dumpState.setDump(DumpState.DUMP_ACTIVITY_RESOLVERS);
} else if ("s".equals(name) || "service".equals(name)) {
dumpState.setDump(DumpState.DUMP_SERVICE_RESOLVERS);
} else if ("r".equals(name) || "receiver".equals(name)) {
dumpState.setDump(DumpState.DUMP_RECEIVER_RESOLVERS);
} else if ("c".equals(name) || "content".equals(name)) {
dumpState.setDump(DumpState.DUMP_CONTENT_RESOLVERS);
} else {
pw.println("Error: unknown resolver table type: " + name);
return;
}
opti++;
}
}
} else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PERMISSIONS);
} else if ("permission".equals(cmd)) {
if (opti >= args.length) {
pw.println("Error: permission requires permission name");
return;
}
permissionNames = new ArraySet<>();
while (opti < args.length) {
permissionNames.add(args[opti]);
opti++;
}
dumpState.setDump(DumpState.DUMP_PERMISSIONS
| DumpState.DUMP_PACKAGES | DumpState.DUMP_SHARED_USERS);
} else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PREFERRED);
} else if ("preferred-xml".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
if (opti < args.length && "--full".equals(args[opti])) {
dumpState.setFullPreferred(true);
opti++;
}
} else if ("d".equals(cmd) || "domain-preferred-apps".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_DOMAIN_PREFERRED);
} else if ("p".equals(cmd) || "packages".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PACKAGES);
} else if ("q".equals(cmd) || "queries".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_QUERIES);
} else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_SHARED_USERS);
if (opti < args.length && "noperm".equals(args[opti])) {
dumpState.setOptionEnabled(DumpState.OPTION_SKIP_PERMISSIONS);
}
} else if ("prov".equals(cmd) || "providers".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PROVIDERS);
} else if ("m".equals(cmd) || "messages".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_MESSAGES);
} else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_VERIFIERS);
} else if ("dv".equals(cmd) || "domain-verifier".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_DOMAIN_VERIFIER);
} else if ("version".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_VERSION);
} else if ("k".equals(cmd) || "keysets".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_KEYSETS);
} else if ("installs".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_INSTALLS);
} else if ("frozen".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_FROZEN);
} else if ("volumes".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_VOLUMES);
} else if ("dexopt".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_DEXOPT);
} else if ("compiler-stats".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_COMPILER_STATS);
} else if ("changes".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_CHANGES);
} else if ("service-permissions".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_SERVICE_PERMISSIONS);
} else if ("known-packages".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_KNOWN_PACKAGES);
} else if ("t".equals(cmd) || "timeouts".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PER_UID_READ_TIMEOUTS);
} else if ("snapshot".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_SNAPSHOT_STATISTICS);
if (opti < args.length) {
if ("--full".equals(args[opti])) {
dumpState.setBrief(false);
opti++;
} else if ("--brief".equals(args[opti])) {
dumpState.setBrief(true);
opti++;
}
}
} else if ("protected-broadcasts".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PROTECTED_BROADCASTS);
}
}
final String packageName = dumpState.getTargetPackageName();
final boolean checkin = dumpState.isCheckIn();
// Return if the package doesn't exist.
if (packageName != null
&& snapshot.getPackageStateInternal(packageName) == null
&& !snapshot.isApexPackage(packageName)) {
pw.println("Unable to find package: " + packageName);
return;
}
if (checkin) {
pw.println("vers,1");
}
// reader
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_VERSION)
&& packageName == null) {
snapshot.dump(DumpState.DUMP_VERSION, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_KNOWN_PACKAGES)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println("Known Packages:");
ipw.increaseIndent();
for (int i = 0; i <= LAST_KNOWN_PACKAGE; i++) {
final String knownPackage = KnownPackages.knownPackageToString(i);
ipw.print(knownPackage);
ipw.println(":");
final String[] pkgNames = mKnownPackages.getKnownPackageNames(snapshot,
i, UserHandle.USER_SYSTEM);
ipw.increaseIndent();
if (ArrayUtils.isEmpty(pkgNames)) {
ipw.println("none");
} else {
for (String name : pkgNames) {
ipw.println(name);
}
}
ipw.decreaseIndent();
}
ipw.decreaseIndent();
}
if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
if (!checkin && mRequiredVerifierPackages.length > 0) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Verifiers:");
}
for (String requiredVerifierPackage : mRequiredVerifierPackages) {
if (!checkin) {
pw.print(" Required: ");
pw.print(requiredVerifierPackage);
pw.print(" (uid=");
pw.print(snapshot.getPackageUid(requiredVerifierPackage,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
pw.println(")");
} else {
pw.print("vrfy,");
pw.print(requiredVerifierPackage);
pw.print(",");
pw.println(snapshot.getPackageUid(requiredVerifierPackage,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
}
}
}
if (dumpState.isDumping(DumpState.DUMP_DOMAIN_VERIFIER)
&& packageName == null) {
final DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
final ComponentName verifierComponent = proxy.getComponentName();
if (verifierComponent != null) {
String verifierPackageName = verifierComponent.getPackageName();
if (!checkin) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Domain Verifier:");
pw.print(" Using: ");
pw.print(verifierPackageName);
pw.print(" (uid=");
pw.print(snapshot.getPackageUid(verifierPackageName,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
pw.println(")");
} else if (verifierPackageName != null) {
pw.print("dv,");
pw.print(verifierPackageName);
pw.print(",");
pw.println(snapshot.getPackageUid(verifierPackageName,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
}
} else {
pw.println();
pw.println("No Domain Verifier available!");
}
}
if (dumpState.isDumping(DumpState.DUMP_LIBS)
&& packageName == null) {
snapshot.dump(DumpState.DUMP_LIBS, fd, pw, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_FEATURES)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
if (!checkin) {
pw.println("Features:");
}
for (FeatureInfo feat : mAvailableFeatures.values()) {
if (!checkin) {
pw.print(" ");
pw.print(feat.name);
if (feat.version > 0) {
pw.print(" version=");
pw.print(feat.version);
}
pw.println();
} else {
pw.print("feat,");
pw.print(feat.name);
pw.print(",");
pw.println(feat.version);
}
}
}
final ComponentResolverApi componentResolver = snapshot.getComponentResolver();
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
componentResolver.dumpActivityResolvers(pw, dumpState, packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
componentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
componentResolver.dumpServiceResolvers(pw, dumpState, packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
componentResolver.dumpProviderResolvers(pw, dumpState, packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
snapshot.dump(DumpState.DUMP_PREFERRED, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PREFERRED_XML) && packageName == null) {
snapshot.dump(DumpState.DUMP_PREFERRED_XML, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
snapshot.dump(DumpState.DUMP_DOMAIN_PREFERRED, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
snapshot.dumpPermissions(pw, packageName, permissionNames, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
componentResolver.dumpContentProviders(snapshot, pw, dumpState,
packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
snapshot.dumpKeySet(pw, packageName, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
snapshot.dumpPackages(pw, packageName, permissionNames, dumpState, checkin);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_QUERIES)) {
snapshot.dump(DumpState.DUMP_QUERIES, fd, pw, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
snapshot.dumpSharedUsers(pw, packageName, permissionNames, dumpState,
checkin);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_CHANGES)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Package Changes:");
mChangedPackagesTracker.iterateAll((sequenceNumber, values) -> {
pw.print(" Sequence number=");
pw.println(sequenceNumber);
final int numChangedPackages = values.size();
for (int i = 0; i < numChangedPackages; i++) {
final SparseArray<String> changes = values.valueAt(i);
pw.print(" User ");
pw.print(values.keyAt(i));
pw.println(":");
final int numChanges = changes.size();
if (numChanges == 0) {
pw.print(" ");
pw.println("No packages changed");
} else {
for (int j = 0; j < numChanges; j++) {
final String pkgName = changes.valueAt(j);
final int userSequenceNumber = changes.keyAt(j);
pw.print(" ");
pw.print("seq=");
pw.print(userSequenceNumber);
pw.print(", package=");
pw.println(pkgName);
}
}
}
});
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_FROZEN)
&& packageName == null) {
snapshot.dump(DumpState.DUMP_FROZEN, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_VOLUMES)
&& packageName == null) {
mStorageEventHelper.dumpLoadedVolumes(pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
&& packageName == null) {
componentResolver.dumpServicePermissions(pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
snapshot.dump(DumpState.DUMP_DEXOPT, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_COMPILER_STATS)) {
snapshot.dump(DumpState.DUMP_COMPILER_STATS, fd, pw, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_MESSAGES)
&& packageName == null) {
if (!checkin) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
snapshot.dump(DumpState.DUMP_MESSAGES, fd, pw, dumpState);
pw.println();
pw.println("Package warning messages:");
dumpCriticalInfo(pw, null);
} else {
dumpCriticalInfo(pw, "msg,");
}
}
// PackageInstaller should be called outside of mPackages lock
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_INSTALLS)
&& packageName == null) {
// XXX should handle packageName != null by dumping only install data that
// the given package is involved with.
if (dumpState.onTitlePrinted()) {
pw.println();
}
mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_APEX)) {
snapshot.dump(DumpState.DUMP_APEX, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PER_UID_READ_TIMEOUTS)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Per UID read timeouts:");
pw.println(" Default timeouts flag: " + PackageManagerService.getDefaultTimeouts());
pw.println(" Known digesters list flag: "
+ PackageManagerService.getKnownDigestersList());
pw.println(" Timeouts (" + mPerUidReadTimeouts.length + "):");
for (PerUidReadTimeouts item : mPerUidReadTimeouts) {
pw.print(" (");
pw.print("uid=" + item.uid + ", ");
pw.print("minTimeUs=" + item.minTimeUs + ", ");
pw.print("minPendingTimeUs=" + item.minPendingTimeUs + ", ");
pw.print("maxPendingTimeUs=" + item.maxPendingTimeUs);
pw.println(")");
}
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_SNAPSHOT_STATISTICS)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Snapshot statistics:");
mSnapshotStatistics.dump(pw, " " /* indent */, SystemClock.currentTimeMicro(),
snapshot.getUsed(), dumpState.isBrief());
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_PROTECTED_BROADCASTS)
&& packageName == null) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Protected broadcast actions:");
for (int i = 0; i < mProtectedBroadcasts.size(); i++) {
pw.print(" ");
pw.println(mProtectedBroadcasts.valueAt(i));
}
}
}
private void printHelp(PrintWriter pw) {
pw.println("Package manager dump options:");
pw.println(" [-h] [-f] [--checkin] [--all-components] [cmd] ...");
pw.println(" --checkin: dump for a checkin");
pw.println(" -f: print details of intent filters");
pw.println(" -h: print this help");
pw.println(" --proto: dump data to proto");
pw.println(" --all-components: include all component names in package dump");
pw.println(" --include-apex: includes the apex packages in package dump");
pw.println(" cmd may be one of:");
pw.println(" apex: list active APEXes and APEX session state");
pw.println(" l[ibraries]: list known shared libraries");
pw.println(" f[eatures]: list device features");
pw.println(" k[eysets]: print known keysets");
pw.println(" r[esolvers] [activity|service|receiver|content]: dump intent resolvers");
pw.println(" perm[issions]: dump permissions");
pw.println(" permission [name ...]: dump declaration and use of given permission");
pw.println(" pref[erred]: print preferred package settings");
pw.println(" preferred-xml [--full]: print preferred package settings as xml");
pw.println(" prov[iders]: dump content providers");
pw.println(" p[ackages]: dump installed packages");
pw.println(" q[ueries]: dump app queryability calculations");
pw.println(" s[hared-users] [noperm]: dump shared user IDs");
pw.println(" m[essages]: print collected runtime messages");
pw.println(" v[erifiers]: print package verifier info");
pw.println(" d[omain-preferred-apps]: print domains preferred apps");
pw.println(" i[ntent-filter-verifiers]|ifv: print intent filter verifier info");
pw.println(" t[imeouts]: print read timeouts for known digesters");
pw.println(" version: print database version info");
pw.println(" write: write current settings now");
pw.println(" installs: details about install sessions");
pw.println(" check-permission <permission> <package> [<user>]: does pkg hold perm?");
pw.println(" dexopt: dump dexopt state");
pw.println(" compiler-stats: dump compiler statistics");
pw.println(" service-permissions: dump permissions required by services");
pw.println(" snapshot [--full|--brief]: dump snapshot statistics");
pw.println(" protected-broadcasts: print list of protected broadcast actions");
pw.println(" known-packages: dump known packages");
pw.println(" changes: dump the packages that have been changed");
pw.println(" frozen: dump the frozen packages");
pw.println(" volumes: dump the loaded volumes");
pw.println(" <package.name>: info about given package");
}
private void dumpProto(Computer snapshot, FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
for (String requiredVerifierPackage : mRequiredVerifierPackages) {
final long requiredVerifierPackageToken =
proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
requiredVerifierPackage);
proto.write(
PackageServiceDumpProto.PackageShortProto.UID,
snapshot.getPackageUid(
requiredVerifierPackage,
MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.USER_SYSTEM));
proto.end(requiredVerifierPackageToken);
}
DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
ComponentName verifierComponent = proxy.getComponentName();
if (verifierComponent != null) {
String verifierPackageName = verifierComponent.getPackageName();
final long verifierPackageToken =
proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
proto.write(
PackageServiceDumpProto.PackageShortProto.UID,
snapshot.getPackageUid(
verifierPackageName,
MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.USER_SYSTEM));
proto.end(verifierPackageToken);
}
snapshot.dumpSharedLibrariesProto(proto);
dumpAvailableFeaturesProto(proto);
snapshot.dumpPackagesProto(proto);
snapshot.dumpSharedUsersProto(proto);
dumpCriticalInfo(proto);
proto.flush();
}
private void dumpAvailableFeaturesProto(@NonNull ProtoOutputStream proto) {
final int count = mAvailableFeatures.size();
for (int i = 0; i < count; i++) {
mAvailableFeatures.valueAt(i).dumpDebug(proto, PackageServiceDumpProto.FEATURES);
}
}
}