import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.util.ArrayMap;
+import android.util.Log;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
* <p>This mirrors the interface of {@link ProtoOutputStream}.
*/
public class DualDumpOutputStream {
+ private static final String LOG_TAG = DualDumpOutputStream.class.getSimpleName();
+
// When writing to a proto, the proto
private final @Nullable ProtoOutputStream mProtoStream;
// Temporary storage of data when printing to mIpw
private final LinkedList<DumpObject> mDumpObjects = new LinkedList<>();
- private static abstract class DumpAble {
+ private static abstract class Dumpable {
final String name;
- private DumpAble(String name) {
+ private Dumpable(String name) {
this.name = name;
}
abstract void print(IndentingPrintWriter ipw, boolean printName);
}
- private static class DumpObject extends DumpAble {
- private final LinkedHashMap<String, ArrayList<DumpAble>> mSubObjects = new LinkedHashMap<>();
+ private static class DumpObject extends Dumpable {
+ private final LinkedHashMap<String, ArrayList<Dumpable>> mSubObjects = new LinkedHashMap<>();
private DumpObject(String name) {
super(name);
}
ipw.increaseIndent();
- for (ArrayList<DumpAble> subObject: mSubObjects.values()) {
+ for (ArrayList<Dumpable> subObject: mSubObjects.values()) {
int numDumpables = subObject.size();
if (numDumpables == 1) {
* @param fieldName name of the field added
* @param d The dumpable to add
*/
- public void add(String fieldName, DumpAble d) {
- ArrayList<DumpAble> l = mSubObjects.get(fieldName);
+ public void add(String fieldName, Dumpable d) {
+ ArrayList<Dumpable> l = mSubObjects.get(fieldName);
if (l == null) {
l = new ArrayList<>(1);
}
}
- private static class DumpField extends DumpAble {
+ private static class DumpField extends Dumpable {
private final String mValue;
private DumpField(String name, String value) {
*/
public DualDumpOutputStream(@Nullable ProtoOutputStream proto,
@Nullable IndentingPrintWriter ipw) {
- Preconditions.checkArgument((proto == null) != (ipw == null));
+ if ((proto == null) == (ipw == null)) {
+ Log.e(LOG_TAG, "Cannot dump to clear text and proto at once. Ignoring proto");
+ proto = null;
+ }
mProtoStream = proto;
mIpw = ipw;
DumpObject d = new DumpObject(fieldName);
mDumpObjects.getLast().add(fieldName, d);
mDumpObjects.addLast(d);
- return 0;
+ return System.identityHashCode(d);
}
}
if (mProtoStream != null) {
mProtoStream.end(token);
} else {
+ if (System.identityHashCode(mDumpObjects.getLast()) != token) {
+ Log.w(LOG_TAG, "Unexpected token for ending " + mDumpObjects.getLast().name
+ + " at " + Arrays.toString(Thread.currentThread().getStackTrace()));
+ }
mDumpObjects.removeLast();
}
}
* @param nestedState The state of the dump
*/
public void writeNested(@NonNull String fieldName, byte[] nestedState) {
- Preconditions.checkNotNull(mIpw);
+ if (mIpw == null) {
+ Log.w(LOG_TAG, "writeNested does not work for proto logging");
+ return;
+ }
mDumpObjects.getLast().add(fieldName,
new DumpField(fieldName, (new String(nestedState, StandardCharsets.UTF_8)).trim()));
mDestroyed = true;
}
- public void dump(@NonNull DualDumpOutputStream proto) {
+ public void dump(@NonNull DualDumpOutputStream dumpStream) {
synchronized (mLock) {
- proto.write("user_id", PrintUserStateProto.USER_ID, mUserId);
+ dumpStream.write("user_id", PrintUserStateProto.USER_ID, mUserId);
final int installedServiceCount = mInstalledServices.size();
for (int i = 0; i < installedServiceCount; i++) {
- long token = proto.start("installed_services",
+ long token = dumpStream.start("installed_services",
PrintUserStateProto.INSTALLED_SERVICES);
PrintServiceInfo installedService = mInstalledServices.get(i);
ResolveInfo resolveInfo = installedService.getResolveInfo();
- writeComponentName(proto, "component_name",
+ writeComponentName(dumpStream, "component_name",
InstalledPrintServiceProto.COMPONENT_NAME,
new ComponentName(resolveInfo.serviceInfo.packageName,
resolveInfo.serviceInfo.name));
- writeStringIfNotNull(proto, "settings_activity",
+ writeStringIfNotNull(dumpStream, "settings_activity",
InstalledPrintServiceProto.SETTINGS_ACTIVITY,
installedService.getSettingsActivityName());
- writeStringIfNotNull(proto, "add_printers_activity",
+ writeStringIfNotNull(dumpStream, "add_printers_activity",
InstalledPrintServiceProto.ADD_PRINTERS_ACTIVITY,
installedService.getAddPrintersActivityName());
- writeStringIfNotNull(proto, "advanced_options_activity",
+ writeStringIfNotNull(dumpStream, "advanced_options_activity",
InstalledPrintServiceProto.ADVANCED_OPTIONS_ACTIVITY,
installedService.getAdvancedOptionsActivityName());
- proto.end(token);
+ dumpStream.end(token);
}
for (ComponentName disabledService : mDisabledServices) {
- writeComponentName(proto, "disabled_services",
+ writeComponentName(dumpStream, "disabled_services",
PrintUserStateProto.DISABLED_SERVICES, disabledService);
}
final int activeServiceCount = mActiveServices.size();
for (int i = 0; i < activeServiceCount; i++) {
- long token = proto.start("actives_services", PrintUserStateProto.ACTIVE_SERVICES);
- mActiveServices.valueAt(i).dump(proto);
- proto.end(token);
+ long token = dumpStream.start("actives_services",
+ PrintUserStateProto.ACTIVE_SERVICES);
+ mActiveServices.valueAt(i).dump(dumpStream);
+ dumpStream.end(token);
}
- mPrintJobForAppCache.dumpLocked(proto);
+ mPrintJobForAppCache.dumpLocked(dumpStream);
if (mPrinterDiscoverySession != null) {
- long token = proto.start("discovery_service",
+ long token = dumpStream.start("discovery_service",
PrintUserStateProto.DISCOVERY_SESSIONS);
- mPrinterDiscoverySession.dumpLocked(proto);
- proto.end(token);
+ mPrinterDiscoverySession.dumpLocked(dumpStream);
+ dumpStream.end(token);
}
}
- long token = proto.start("print_spooler_state", PrintUserStateProto.PRINT_SPOOLER_STATE);
- mSpooler.dump(proto);
- proto.end(token);
+ long token = dumpStream.start("print_spooler_state",
+ PrintUserStateProto.PRINT_SPOOLER_STATE);
+ mSpooler.dump(dumpStream);
+ dumpStream.end(token);
}
private void readConfigurationLocked() {
}
}
- public void dumpLocked(@NonNull DualDumpOutputStream proto) {
- proto.write("is_destroyed", PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
- proto.write("is_printer_discovery_in_progress",
+ public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
+ dumpStream.write("is_destroyed", PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
+ dumpStream.write("is_printer_discovery_in_progress",
PrinterDiscoverySessionProto.IS_PRINTER_DISCOVERY_IN_PROGRESS,
!mStartedPrinterDiscoveryTokens.isEmpty());
final int observerCount = mDiscoveryObservers.beginBroadcast();
for (int i = 0; i < observerCount; i++) {
IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
- proto.write("printer_discovery_observers",
+ dumpStream.write("printer_discovery_observers",
PrinterDiscoverySessionProto.PRINTER_DISCOVERY_OBSERVERS,
observer.toString());
}
final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
for (int i = 0; i < tokenCount; i++) {
IBinder token = mStartedPrinterDiscoveryTokens.get(i);
- proto.write("discovery_requests",
+ dumpStream.write("discovery_requests",
PrinterDiscoverySessionProto.DISCOVERY_REQUESTS, token.toString());
}
final int trackedPrinters = mStateTrackedPrinters.size();
for (int i = 0; i < trackedPrinters; i++) {
PrinterId printer = mStateTrackedPrinters.get(i);
- writePrinterId(proto, "tracked_printer_requests",
+ writePrinterId(dumpStream, "tracked_printer_requests",
PrinterDiscoverySessionProto.TRACKED_PRINTER_REQUESTS, printer);
}
final int printerCount = mPrinters.size();
for (int i = 0; i < printerCount; i++) {
PrinterInfo printer = mPrinters.valueAt(i);
- writePrinterInfo(mContext, proto, "printer",
+ writePrinterInfo(mContext, dumpStream, "printer",
PrinterDiscoverySessionProto.PRINTER, printer);
}
}
}
}
- public void dumpLocked(@NonNull DualDumpOutputStream proto) {
+ public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
final int bucketCount = mPrintJobsForRunningApp.size();
for (int i = 0; i < bucketCount; i++) {
final int appId = mPrintJobsForRunningApp.keyAt(i);
List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
final int printJobCount = bucket.size();
for (int j = 0; j < printJobCount; j++) {
- long token = proto.start("cached_print_jobs",
+ long token = dumpStream.start("cached_print_jobs",
PrintUserStateProto.CACHED_PRINT_JOBS);
- proto.write("app_id", CachedPrintJobProto.APP_ID, appId);
+ dumpStream.write("app_id", CachedPrintJobProto.APP_ID, appId);
- writePrintJobInfo(mContext, proto, "print_job", CachedPrintJobProto.PRINT_JOB,
- bucket.get(j));
+ writePrintJobInfo(mContext, dumpStream, "print_job",
+ CachedPrintJobProto.PRINT_JOB, bucket.get(j));
- proto.end(token);
+ dumpStream.end(token);
}
}
}