Merge "Dump usb as DualDump"
diff --git a/core/java/android/hardware/usb/AccessoryFilter.java b/core/java/android/hardware/usb/AccessoryFilter.java
index d9b7c5b..00070fe 100644
--- a/core/java/android/hardware/usb/AccessoryFilter.java
+++ b/core/java/android/hardware/usb/AccessoryFilter.java
@@ -16,6 +16,11 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.service.usb.UsbAccessoryFilterProto;
+
+import com.android.internal.util.dump.DualDumpOutputStream;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -142,4 +147,17 @@
                 "\", mModel=\"" + mModel +
                 "\", mVersion=\"" + mVersion + "\"]";
     }
+
+    /**
+     * Write a description of the filter to a dump stream.
+     */
+    public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("manufacturer", UsbAccessoryFilterProto.MANUFACTURER, mManufacturer);
+        dump.write("model", UsbAccessoryFilterProto.MODEL, mModel);
+        dump.write("version", UsbAccessoryFilterProto.VERSION, mVersion);
+
+        dump.end(token);
+    }
 }
diff --git a/core/java/android/hardware/usb/DeviceFilter.java b/core/java/android/hardware/usb/DeviceFilter.java
index 439c629..6f1aff7 100644
--- a/core/java/android/hardware/usb/DeviceFilter.java
+++ b/core/java/android/hardware/usb/DeviceFilter.java
@@ -16,8 +16,12 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.service.usb.UsbDeviceFilterProto;
 import android.util.Slog;
 
+import com.android.internal.util.dump.DualDumpOutputStream;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -310,4 +314,22 @@
                 ",mProductName=" + mProductName + ",mSerialNumber=" + mSerialNumber +
                 "]";
     }
+
+    /**
+     * Write a description of the filter to a dump stream.
+     */
+    public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("vendor_id", UsbDeviceFilterProto.VENDOR_ID, mVendorId);
+        dump.write("product_id", UsbDeviceFilterProto.PRODUCT_ID, mProductId);
+        dump.write("class", UsbDeviceFilterProto.CLASS, mClass);
+        dump.write("subclass", UsbDeviceFilterProto.SUBCLASS, mSubclass);
+        dump.write("protocol", UsbDeviceFilterProto.PROTOCOL, mProtocol);
+        dump.write("manufacturer_name", UsbDeviceFilterProto.MANUFACTURER_NAME, mManufacturerName);
+        dump.write("product_name", UsbDeviceFilterProto.PRODUCT_NAME, mProductName);
+        dump.write("serial_number", UsbDeviceFilterProto.SERIAL_NUMBER, mSerialNumber);
+
+        dump.end(token);
+    }
 }
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index a171570..6ce4201 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+
 import com.android.internal.util.Preconditions;
 
 /**
@@ -106,6 +107,17 @@
     }
 
     /**
+     * Returns the attributes of this configuration
+     *
+     * @return the configuration's attributes
+     *
+     * @hide
+     */
+    public int getAttributes() {
+        return mAttributes;
+    }
+
+    /**
      * Returns the configuration's max power consumption, in milliamps.
      *
      * @return the configuration's max power
diff --git a/core/java/android/hardware/usb/UsbConstants.java b/core/java/android/hardware/usb/UsbConstants.java
index 0e8d47c..215e9d5 100644
--- a/core/java/android/hardware/usb/UsbConstants.java
+++ b/core/java/android/hardware/usb/UsbConstants.java
@@ -16,6 +16,8 @@
 
 package android.hardware.usb;
 
+import android.service.ServiceProtoEnums;
+
 /**
  * Contains constants for the USB protocol.
  * These constants correspond to definitions in linux/usb/ch9.h in the linux kernel.
@@ -35,12 +37,12 @@
      * Used to signify direction of data for a {@link UsbEndpoint} is OUT (host to device)
      * @see UsbEndpoint#getDirection
      */
-    public static final int USB_DIR_OUT = 0;
+    public static final int USB_DIR_OUT = ServiceProtoEnums.USB_ENDPOINT_DIR_OUT; // 0
     /**
      * Used to signify direction of data for a {@link UsbEndpoint} is IN (device to host)
      * @see UsbEndpoint#getDirection
      */
-    public static final int USB_DIR_IN = 0x80;
+    public static final int USB_DIR_IN = ServiceProtoEnums.USB_ENDPOINT_DIR_IN; // 0x80
 
     /**
      * Bitmask used for extracting the {@link UsbEndpoint} number its address field.
@@ -63,22 +65,26 @@
      * Control endpoint type (endpoint zero)
      * @see UsbEndpoint#getType
      */
-    public static final int USB_ENDPOINT_XFER_CONTROL = 0;
+    public static final int USB_ENDPOINT_XFER_CONTROL =
+            ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_CONTROL; // 0
     /**
      * Isochronous endpoint type (currently not supported)
      * @see UsbEndpoint#getType
      */
-    public static final int USB_ENDPOINT_XFER_ISOC = 1;
+    public static final int USB_ENDPOINT_XFER_ISOC =
+            ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_ISOC; // 1
     /**
      * Bulk endpoint type
      * @see UsbEndpoint#getType
      */
-    public static final int USB_ENDPOINT_XFER_BULK = 2;
+    public static final int USB_ENDPOINT_XFER_BULK =
+            ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_BULK; // 2
     /**
      * Interrupt endpoint type
      * @see UsbEndpoint#getType
      */
-    public static final int USB_ENDPOINT_XFER_INT = 3;
+    public static final int USB_ENDPOINT_XFER_INT =
+            ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_INT; // 3
 
 
     /**
diff --git a/core/java/com/android/internal/print/DumpUtils.java b/core/java/com/android/internal/print/DumpUtils.java
index 3192d5c..1916c11 100644
--- a/core/java/com/android/internal/print/DumpUtils.java
+++ b/core/java/com/android/internal/print/DumpUtils.java
@@ -16,10 +16,9 @@
 
 package com.android.internal.print;
 
+import static com.android.internal.util.dump.DumpUtils.writeComponentName;
+
 import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.ComponentNameProto;
 import android.content.Context;
 import android.print.PageRange;
 import android.print.PrintAttributes;
@@ -40,42 +39,13 @@
 import android.service.print.PrinterInfoProto;
 import android.service.print.ResolutionProto;
 
+import com.android.internal.util.dump.DualDumpOutputStream;
+
 /**
  * Utilities for dumping print related proto buffer
  */
 public class DumpUtils {
     /**
-     * Write a string to a proto if the string is not {@code null}.
-     *
-     * @param proto The proto to write to
-     * @param idName Clear text name of the proto-id
-     * @param id The proto-id of the string
-     * @param string The string to write
-     */
-    public static void writeStringIfNotNull(@NonNull DualDumpOutputStream proto, String idName,
-            long id, @Nullable String string) {
-        if (string != null) {
-            proto.write(idName, id, string);
-        }
-    }
-
-    /**
-     * Write a {@link ComponentName} to a proto.
-     *
-     * @param proto The proto to write to
-     * @param idName Clear text name of the proto-id
-     * @param id The proto-id of the component name
-     * @param component The component name to write
-     */
-    public static void writeComponentName(@NonNull DualDumpOutputStream proto, String idName,
-            long id, @NonNull ComponentName component) {
-        long token = proto.start(idName, id);
-        proto.write("package_name", ComponentNameProto.PACKAGE_NAME, component.getPackageName());
-        proto.write("class_name", ComponentNameProto.CLASS_NAME, component.getClassName());
-        proto.end(token);
-    }
-
-    /**
      * Write a {@link PrinterId} to a proto.
      *
      * @param proto The proto to write to
diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java
new file mode 100644
index 0000000..cac2265
--- /dev/null
+++ b/core/java/com/android/internal/usb/DumpUtils.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2018 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.internal.usb;
+
+import static android.hardware.usb.UsbPort.MODE_AUDIO_ACCESSORY;
+import static android.hardware.usb.UsbPort.MODE_DEBUG_ACCESSORY;
+import static android.hardware.usb.UsbPort.MODE_DFP;
+import static android.hardware.usb.UsbPort.MODE_DUAL;
+import static android.hardware.usb.UsbPort.MODE_NONE;
+import static android.hardware.usb.UsbPort.MODE_UFP;
+
+import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+
+import android.annotation.NonNull;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbConfiguration;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbEndpoint;
+import android.hardware.usb.UsbInterface;
+import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
+import android.hardware.usb.V1_0.Constants;
+import android.service.usb.UsbAccessoryProto;
+import android.service.usb.UsbConfigurationProto;
+import android.service.usb.UsbDeviceProto;
+import android.service.usb.UsbEndPointProto;
+import android.service.usb.UsbInterfaceProto;
+import android.service.usb.UsbPortProto;
+import android.service.usb.UsbPortStatusProto;
+import android.service.usb.UsbPortStatusRoleCombinationProto;
+
+import com.android.internal.util.dump.DualDumpOutputStream;
+
+/** Dump methods for public USB classes */
+public class DumpUtils {
+    public static void writeAccessory(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbAccessory accessory) {
+        long token = dump.start(idName, id);
+
+        dump.write("manufacturer", UsbAccessoryProto.MANUFACTURER, accessory.getManufacturer());
+        dump.write("model", UsbAccessoryProto.MODEL, accessory.getModel());
+        writeStringIfNotNull(dump, "description", UsbAccessoryProto.DESCRIPTION,
+                accessory.getManufacturer());
+        dump.write("version", UsbAccessoryProto.VERSION, accessory.getVersion());
+        writeStringIfNotNull(dump, "uri", UsbAccessoryProto.URI, accessory.getUri());
+        dump.write("serial", UsbAccessoryProto.SERIAL, accessory.getSerial());
+
+        dump.end(token);
+    }
+
+    public static void writeDevice(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbDevice device) {
+        long token = dump.start(idName, id);
+
+        dump.write("name", UsbDeviceProto.NAME, device.getDeviceName());
+        dump.write("vendor_id", UsbDeviceProto.VENDOR_ID, device.getVendorId());
+        dump.write("product_id", UsbDeviceProto.PRODUCT_ID, device.getProductId());
+        dump.write("class", UsbDeviceProto.CLASS, device.getDeviceClass());
+        dump.write("subclass", UsbDeviceProto.SUBCLASS, device.getDeviceSubclass());
+        dump.write("protocol", UsbDeviceProto.PROTOCOL, device.getDeviceProtocol());
+        dump.write("manufacturer_name", UsbDeviceProto.MANUFACTURER_NAME,
+                device.getManufacturerName());
+        dump.write("product_name", UsbDeviceProto.PRODUCT_NAME, device.getProductName());
+        dump.write("version", UsbDeviceProto.VERSION, device.getVersion());
+        dump.write("serial_number", UsbDeviceProto.SERIAL_NUMBER, device.getSerialNumber());
+
+        int numConfigurations = device.getConfigurationCount();
+        for (int i = 0; i < numConfigurations; i++) {
+            writeConfiguration(dump, "configurations", UsbDeviceProto.CONFIGURATIONS,
+                    device.getConfiguration(i));
+        }
+
+        dump.end(token);
+    }
+
+    private static void writeConfiguration(@NonNull DualDumpOutputStream dump,
+            @NonNull String idName, long id, @NonNull UsbConfiguration configuration) {
+        long token = dump.start(idName, id);
+        dump.write("id", UsbConfigurationProto.ID, configuration.getId());
+        dump.write("name", UsbConfigurationProto.NAME, configuration.getName());
+        dump.write("attributes", UsbConfigurationProto.ATTRIBUTES, configuration.getAttributes());
+        dump.write("max_power", UsbConfigurationProto.MAX_POWER, configuration.getMaxPower());
+
+        int numInterfaces = configuration.getInterfaceCount();
+        for (int i = 0; i < numInterfaces; i++) {
+            writeInterface(dump, "interfaces", UsbConfigurationProto.INTERFACES,
+                    configuration.getInterface(i));
+        }
+        dump.end(token);
+    }
+
+    private static void writeInterface(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbInterface iface) {
+        long token = dump.start(idName, id);
+
+        dump.write("id", UsbInterfaceProto.ID, iface.getId());
+        dump.write("alternate_settings", UsbInterfaceProto.ALTERNATE_SETTINGS,
+                iface.getAlternateSetting());
+        dump.write("name", UsbInterfaceProto.NAME, iface.getName());
+        dump.write("class", UsbInterfaceProto.CLASS, iface.getInterfaceClass());
+        dump.write("subclass", UsbInterfaceProto.SUBCLASS, iface.getInterfaceSubclass());
+        dump.write("protocol", UsbInterfaceProto.PROTOCOL, iface.getInterfaceProtocol());
+
+        int numEndpoints = iface.getEndpointCount();
+        for (int i = 0; i < numEndpoints; i++) {
+            writeEndpoint(dump, "endpoints", UsbInterfaceProto.ENDPOINTS, iface.getEndpoint(i));
+        }
+        dump.end(token);
+    }
+
+    private static void writeEndpoint(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbEndpoint endpoint) {
+        long token = dump.start(idName, id);
+
+        dump.write("endpoint_number", UsbEndPointProto.ENDPOINT_NUMBER,
+                endpoint.getEndpointNumber());
+        dump.write("direction", UsbEndPointProto.DIRECTION, endpoint.getDirection());
+        dump.write("address", UsbEndPointProto.ADDRESS, endpoint.getAddress());
+        dump.write("type", UsbEndPointProto.TYPE, endpoint.getType());
+        dump.write("attributes", UsbEndPointProto.ATTRIBUTES,
+                endpoint.getAttributes());
+        dump.write("max_packet_size", UsbEndPointProto.MAX_PACKET_SIZE,
+                endpoint.getMaxPacketSize());
+        dump.write("interval", UsbEndPointProto.INTERVAL, endpoint.getInterval());
+
+        dump.end(token);
+    }
+
+    public static void writePort(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbPort port) {
+        long token = dump.start(idName, id);
+
+        dump.write("id", UsbPortProto.ID, port.getId());
+
+        int mode = port.getSupportedModes();
+        if (dump.isProto()) {
+            if (mode == MODE_NONE) {
+                dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_NONE);
+            } else {
+                if ((mode & MODE_DUAL) == MODE_DUAL) {
+                    dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DUAL);
+                } else {
+                    if ((mode & MODE_DFP) == MODE_DFP) {
+                        dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DFP);
+                    } else if ((mode & MODE_UFP) == MODE_UFP) {
+                        dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_UFP);
+                    }
+                }
+
+                if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) {
+                    dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES,
+                            MODE_AUDIO_ACCESSORY);
+                }
+
+                if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) {
+                    dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES,
+                            MODE_DEBUG_ACCESSORY);
+                }
+            }
+        } else {
+            dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, UsbPort.modeToString(mode));
+        }
+
+        dump.end(token);
+    }
+
+    private static void writePowerRole(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, int powerRole) {
+        if (dump.isProto()) {
+            dump.write(idName, id, powerRole);
+        } else {
+            dump.write(idName, id, UsbPort.powerRoleToString(powerRole));
+        }
+    }
+
+    private static void writeDataRole(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, int dataRole) {
+        if (dump.isProto()) {
+            dump.write(idName, id, dataRole);
+        } else {
+            dump.write(idName, id, UsbPort.dataRoleToString(dataRole));
+        }
+    }
+
+
+    public static void writePortStatus(@NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id, @NonNull UsbPortStatus status) {
+        long token = dump.start(idName, id);
+
+        dump.write("connected", UsbPortStatusProto.CONNECTED, status.isConnected());
+
+        if (dump.isProto()) {
+            dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE, status.getCurrentMode());
+        } else {
+            dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE,
+                    UsbPort.modeToString(status.getCurrentMode()));
+        }
+
+        writePowerRole(dump, "power_role", UsbPortStatusProto.POWER_ROLE,
+                status.getCurrentPowerRole());
+        writeDataRole(dump, "data_role", UsbPortStatusProto.DATA_ROLE, status.getCurrentDataRole());
+
+        int undumpedCombinations = status.getSupportedRoleCombinations();
+        while (undumpedCombinations != 0) {
+            int index = Integer.numberOfTrailingZeros(undumpedCombinations);
+            undumpedCombinations &= ~(1 << index);
+
+            int powerRole = (index / Constants.PortDataRole.NUM_DATA_ROLES
+                    + Constants.PortPowerRole.NONE);
+            int dataRole = index % Constants.PortDataRole.NUM_DATA_ROLES;
+
+            long roleCombinationToken = dump.start("role_combinations",
+                    UsbPortStatusProto.ROLE_COMBINATIONS);
+            writePowerRole(dump, "power_role", UsbPortStatusRoleCombinationProto.POWER_ROLE,
+                    powerRole);
+            writeDataRole(dump, "data_role", UsbPortStatusRoleCombinationProto.DATA_ROLE,
+                    dataRole);
+            dump.end(roleCombinationToken);
+        }
+
+        dump.end(token);
+    }
+}
diff --git a/core/java/com/android/internal/print/DualDumpOutputStream.java b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java
similarity index 92%
rename from core/java/com/android/internal/print/DualDumpOutputStream.java
rename to core/java/com/android/internal/util/dump/DualDumpOutputStream.java
index 4b10ef2..3ac38ed 100644
--- a/core/java/com/android/internal/print/DualDumpOutputStream.java
+++ b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.print;
+package com.android.internal.util.dump;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -131,27 +131,27 @@
         }
     }
 
+    /**
+     * Create a new DualDumpOutputStream.
+     *
+     * @param proto the {@link ProtoOutputStream}
+     */
+    public DualDumpOutputStream(@NonNull ProtoOutputStream proto) {
+        mProtoStream = proto;
+        mIpw = null;
+    }
 
     /**
-     * Create a new DualDumpOutputStream. Only one output should be set.
+     * Create a new DualDumpOutputStream.
      *
-     * @param proto If dumping to proto the {@link ProtoOutputStream}
-     * @param ipw If dumping to a print writer, the {@link IndentingPrintWriter}
+     * @param ipw the {@link IndentingPrintWriter}
      */
-    public DualDumpOutputStream(@Nullable ProtoOutputStream proto,
-            @Nullable IndentingPrintWriter ipw) {
-        if ((proto == null) == (ipw == null)) {
-            Log.e(LOG_TAG, "Cannot dump to clear text and proto at once. Ignoring proto");
-            proto = null;
-        }
-
-        mProtoStream = proto;
+    public DualDumpOutputStream(@NonNull IndentingPrintWriter ipw) {
+        mProtoStream = null;
         mIpw = ipw;
 
-        if (!isProto()) {
-            // Add root object
-            mDumpObjects.add(new DumpObject(null));
-        }
+        // Add root object
+        mDumpObjects.add(new DumpObject(null));
     }
 
     public void write(@NonNull String fieldName, long fieldId, double val) {
diff --git a/core/java/com/android/internal/util/dump/DumpUtils.java b/core/java/com/android/internal/util/dump/DumpUtils.java
new file mode 100644
index 0000000..0ee204e
--- /dev/null
+++ b/core/java/com/android/internal/util/dump/DumpUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.internal.util.dump;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+
+public class DumpUtils {
+    /**
+     * Write a string to a proto if the string is not {@code null}.
+     *
+     * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
+     * @param id The proto-id of the string
+     * @param string The string to write
+     */
+    public static void writeStringIfNotNull(@NonNull DualDumpOutputStream proto, String idName,
+            long id, @Nullable String string) {
+        if (string != null) {
+            proto.write(idName, id, string);
+        }
+    }
+
+    /**
+     * Write a {@link ComponentName} to a proto.
+     *
+     * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
+     * @param id The proto-id of the component name
+     * @param component The component name to write
+     */
+    public static void writeComponentName(@NonNull DualDumpOutputStream proto, String idName,
+            long id, @NonNull ComponentName component) {
+        long token = proto.start(idName, id);
+        proto.write("package_name", ComponentNameProto.PACKAGE_NAME, component.getPackageName());
+        proto.write("class_name", ComponentNameProto.CLASS_NAME, component.getClassName());
+        proto.end(token);
+    }
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 8a04bf7..0b0ed83 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -42,6 +42,7 @@
 import "frameworks/base/core/proto/android/service/package.proto";
 import "frameworks/base/core/proto/android/service/print.proto";
 import "frameworks/base/core/proto/android/service/procstats.proto";
+import "frameworks/base/core/proto/android/service/usb.proto";
 import "frameworks/base/core/proto/android/util/event_log_tags.proto";
 import "frameworks/base/core/proto/android/util/log.proto";
 import "frameworks/base/libs/incident/proto/android/os/header.proto";
@@ -254,4 +255,9 @@
         (section).type = SECTION_DUMPSYS,
         (section).args = "jobscheduler --proto"
     ];
+
+    optional android.service.usb.UsbServiceDumpProto usb = 3021 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "usb --proto"
+    ];
 }
diff --git a/core/proto/android/service/enums.proto b/core/proto/android/service/enums.proto
new file mode 100644
index 0000000..b64e685
--- /dev/null
+++ b/core/proto/android/service/enums.proto
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+package android.service;
+
+option java_outer_classname = "ServiceProtoEnums";
+option java_multiple_files = true;
+
+enum UsbEndPointType {
+    USB_ENDPOINT_TYPE_XFER_CONTROL = 0;
+    USB_ENDPOINT_TYPE_XFER_ISOC = 1;
+    USB_ENDPOINT_TYPE_XFER_BULK = 2;
+    USB_ENDPOINT_TYPE_XFER_INT = 3;
+}
+
+enum UsbEndPointDirection {
+    USB_ENDPOINT_DIR_OUT = 0;
+    USB_ENDPOINT_DIR_IN = 0x80;
+}
+
+enum UsbConnectionRecordMode {
+    USB_CONNECTION_RECORD_MODE_CONNECT = 0;
+    USB_CONNECTION_RECORD_MODE_CONNECT_BADPARSE = 1;
+    USB_CONNECTION_RECORD_MODE_CONNECT_BADDEVICE = 2;
+    USB_CONNECTION_RECORD_MODE_DISCONNECT = -1;
+}
\ No newline at end of file
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
new file mode 100644
index 0000000..b60c569
--- /dev/null
+++ b/core/proto/android/service/usb.proto
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+package android.service.usb;
+
+option java_multiple_files = true;
+option java_outer_classname = "UsbServiceProto";
+
+import "frameworks/base/core/proto/android/content/component_name.proto";
+import "frameworks/base/core/proto/android/service/enums.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+message UsbServiceDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbDeviceManagerProto device_manager = 1;
+    optional UsbHostManagerProto host_manager = 2;
+    optional UsbPortManagerProto port_manager = 3;
+    optional UsbAlsaManagerProto alsa_manager = 4;
+    optional UsbSettingsManagerProto settings_manager = 5;
+}
+
+message UsbDeviceManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbHandlerProto handler = 1;
+    optional UsbDebuggingManagerProto debugging_manager = 2;
+}
+
+message UsbHandlerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */
+    enum Function {
+        FUNCTION_ADB = 1;
+        FUNCTION_ACCESSORY = 2;
+        FUNCTION_MTP = 4;
+        FUNCTION_MIDI = 8;
+        FUNCTION_PTP = 16;
+        FUNCTION_RNDIS = 32;
+        FUNCTION_AUDIO_SOURCE = 64;
+    }
+
+    repeated Function current_functions = 1;
+    optional bool current_functions_applied = 2;
+    repeated Function screen_unlocked_functions = 3;
+    optional bool screen_locked = 4;
+    optional bool connected = 5;
+    optional bool configured = 6;
+    optional UsbAccessoryProto current_accessory = 7;
+    optional bool host_connected = 8;
+    optional bool source_power = 9;
+    optional bool sink_power = 10;
+    optional bool usb_charging = 11;
+    optional bool hide_usb_notification = 12;
+    optional bool audio_accessory_connected = 13;
+    optional bool adb_enabled = 14;
+    optional string kernel_state = 15;
+    optional string kernel_function_list = 16;
+}
+
+message UsbAccessoryProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string manufacturer = 1;
+    optional string model = 2;
+    optional string description = 3;
+    optional string version = 4;
+    optional string uri = 5;
+    optional string serial = 6 [ (android.privacy).dest = DEST_EXPLICIT ];
+}
+
+message UsbDebuggingManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional bool connected_to_adb = 1;
+    optional string last_key_recevied = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
+    optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ];
+    optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ];
+}
+
+message UsbHostManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional android.content.ComponentNameProto default_usb_host_connection_handler = 1;
+    repeated UsbDeviceProto devices = 2;
+    optional int32 num_connects = 3;
+    repeated UsbConnectionRecordProto connections = 4;
+}
+
+message UsbDeviceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string name = 1;
+    optional int32 vendor_id = 2;
+    optional int32 product_id = 3;
+    optional int32 class = 4;
+    optional int32 subclass = 5;
+    optional int32 protocol = 6;
+    optional string manufacturer_name = 7;
+    optional string product_name = 8;
+    optional string version = 9;
+    optional string serial_number = 10 [ (android.privacy).dest = DEST_EXPLICIT ];
+    repeated UsbConfigurationProto configurations = 11;
+}
+
+message UsbConfigurationProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 id = 1;
+    optional string name = 2;
+    optional uint32 attributes = 3;
+    optional int32 max_power = 4;
+    repeated UsbInterfaceProto interfaces = 5;
+}
+
+message UsbInterfaceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 id = 1;
+    optional int32 alternate_settings = 2;
+    optional string name = 3;
+    optional int32 class = 4;
+    optional int32 subclass = 5;
+    optional int32 protocol = 6;
+    repeated UsbEndPointProto endpoints = 7;
+}
+
+message UsbEndPointProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 endpoint_number = 1;
+    optional android.service.UsbEndPointDirection direction = 2;
+    optional int32 address = 3;
+    optional android.service.UsbEndPointType type = 4;
+    optional uint32 attributes = 5;
+    optional int32 max_packet_size = 6;
+    optional int32 interval = 7;
+}
+
+message UsbConnectionRecordProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string device_address = 1;
+    optional android.service.UsbConnectionRecordMode mode = 2;
+    optional int64 timestamp = 3;
+    optional int32 manufacturer = 4;
+    optional int32 product = 5;
+    optional UsbIsHeadsetProto is_headset = 6;
+}
+
+message UsbIsHeadsetProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional bool in = 1;
+    optional bool out = 2;
+}
+
+message UsbPortManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional bool is_simulation_active = 1;
+    repeated UsbPortInfoProto usb_ports = 2;
+}
+
+message UsbPortInfoProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbPortProto port = 1;
+    optional UsbPortStatusProto status = 2;
+    optional bool can_change_mode = 3;
+    optional bool can_change_power_role = 4;
+    optional bool can_change_data_role = 5;
+}
+
+message UsbPortProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    /* Same as android.hardware.usb.V1_1.Constants.PortMode_1_1 */
+    enum Mode {
+        MODE_NONE = 0;
+        MODE_UFP = 1;
+        MODE_DFP = 2;
+        MODE_DRP = 3;
+        MODE_AUDIO_ACCESSORY = 4;
+        MODE_DEBUG_ACCESSORY = 8;
+    }
+
+    optional string id = 1;
+    repeated Mode supported_modes = 2;
+}
+
+message UsbPortStatusProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    /* Same as android.hardware.usb.V1_0.Constants.PortPowerRole */
+    enum PowerRole {
+        POWER_ROLE_NONE = 0;
+        POWER_ROLE_SOURCE = 1;
+        POWER_ROLE_SINK = 2;
+    }
+
+    /* Same as android.hardware.usb.V1_0.Constants.PortDataRole */
+    enum DataRole {
+        DATA_ROLE_NONE = 0;
+        DATA_ROLE_HOST = 1;
+        DATA_ROLE_DEVICE = 2;
+    }
+
+    optional bool connected = 1;
+    optional UsbPortProto.Mode current_mode = 2;
+    optional PowerRole power_role = 3;
+    optional DataRole data_role = 4;
+    repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
+}
+
+message UsbPortStatusRoleCombinationProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbPortStatusProto.PowerRole power_role = 1;
+    optional UsbPortStatusProto.DataRole data_role = 2;
+}
+
+message UsbAlsaManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 cards_parser = 1;
+    repeated UsbAlsaDeviceProto alsa_devices = 2;
+    repeated UsbMidiDeviceProto midi_devices = 3;
+}
+
+message UsbAlsaDeviceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 card = 1;
+    optional int32 device = 2;
+    optional string name = 3;
+    optional bool has_playback = 4;
+    optional bool has_capture = 5;
+    optional string address = 6;
+}
+
+message UsbMidiDeviceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 card = 1;
+    optional int32 device = 2;
+    optional string device_address = 3;
+}
+
+message UsbSettingsManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    repeated UsbUserSettingsManagerProto user_settings = 1;
+    repeated UsbProfileGroupSettingsManagerProto profile_group_settings = 2;
+}
+
+message UsbUserSettingsManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 user_id = 1;
+    repeated UsbSettingsDevicePermissionProto device_permissions = 2;
+    repeated UsbSettingsAccessoryPermissionProto accessory_permissions = 3;
+}
+
+message UsbSettingsDevicePermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string device_name = 1;
+    repeated int32 uids = 2;
+}
+
+message UsbSettingsAccessoryPermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string accessory_description = 1;
+    repeated int32 uids = 2;
+}
+
+message UsbProfileGroupSettingsManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 parent_user_id = 1;
+    repeated UsbSettingsDevicePreferenceProto device_preferences = 2;
+    repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3;
+}
+
+message UsbSettingsDevicePreferenceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbDeviceFilterProto filter = 1;
+    optional UserPackageProto user_package = 2;
+}
+
+message UsbDeviceFilterProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 vendor_id = 1;
+    optional int32 product_id = 2;
+    optional int32 class = 3;
+    optional int32 subclass = 4;
+    optional int32 protocol = 5;
+    optional string manufacturer_name = 6;
+    optional string product_name = 7;
+    optional string serial_number = 8 [ (android.privacy).dest = DEST_EXPLICIT ];
+}
+
+message UserPackageProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 user_id = 1;
+    optional string package_name =2;
+}
+
+message UsbSettingsAccessoryPreferenceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbAccessoryFilterProto filter = 1;
+    optional UserPackageProto user_package = 2;
+}
+
+message UsbAccessoryFilterProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string manufacturer = 1;
+    optional string model = 2;
+    optional string version = 3;
+}
\ No newline at end of file
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index f6a259d..53e8813 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -16,8 +16,8 @@
 
 package com.android.printspooler.model;
 
-import static com.android.internal.print.DumpUtils.writeComponentName;
 import static com.android.internal.print.DumpUtils.writePrintJobInfo;
+import static com.android.internal.util.dump.DumpUtils.writeComponentName;
 
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
@@ -59,10 +59,10 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.HandlerCaller;
-import com.android.internal.print.DualDumpOutputStream;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.printspooler.R;
 import com.android.printspooler.util.ApprovedPrintServices;
 
@@ -214,12 +214,11 @@
         try {
             synchronized (mLock) {
                 if (dumpAsProto) {
-                    dumpLocked(new DualDumpOutputStream(new ProtoOutputStream(fd), null));
+                    dumpLocked(new DualDumpOutputStream(new ProtoOutputStream(fd)));
                 } else {
                     try (FileOutputStream out = new FileOutputStream(fd)) {
                         try (PrintWriter w = new PrintWriter(out)) {
-                            dumpLocked(new DualDumpOutputStream(null, new IndentingPrintWriter(w,
-                                    "  ")));
+                            dumpLocked(new DualDumpOutputStream(new IndentingPrintWriter(w, "  ")));
                         }
                     } catch (IOException ignored) {
                     }
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index d6cc805..e1c1eb2 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -61,10 +61,10 @@
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
-import com.android.internal.print.DualDumpOutputStream;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
@@ -708,12 +708,12 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 if (dumpAsProto) {
-                    dump(new DualDumpOutputStream(new ProtoOutputStream(fd), null),
+                    dump(new DualDumpOutputStream(new ProtoOutputStream(fd)),
                             userStatesToDump);
                 } else {
                     pw.println("PRINT MANAGER STATE (dumpsys print)");
 
-                    dump(new DualDumpOutputStream(null, new IndentingPrintWriter(pw, "  ")),
+                    dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
                             userStatesToDump);
                 }
             } finally {
diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
index 80b97cf..f72d8ee 100644
--- a/services/print/java/com/android/server/print/RemotePrintService.java
+++ b/services/print/java/com/android/server/print/RemotePrintService.java
@@ -16,8 +16,8 @@
 
 package com.android.server.print;
 
-import static com.android.internal.print.DumpUtils.writeComponentName;
 import static com.android.internal.print.DumpUtils.writePrinterId;
+import static com.android.internal.util.dump.DumpUtils.writeComponentName;
 
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
@@ -49,7 +49,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.print.DualDumpOutputStream;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index a69baa1..ba5dde0 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -46,7 +46,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.TransferPipe;
-import com.android.internal.print.DualDumpOutputStream;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 import libcore.io.IoUtils;
 
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index e2808e8..84c1bb2 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -20,11 +20,11 @@
 import static android.content.pm.PackageManager.GET_SERVICES;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 
-import static com.android.internal.print.DumpUtils.writeComponentName;
 import static com.android.internal.print.DumpUtils.writePrintJobInfo;
 import static com.android.internal.print.DumpUtils.writePrinterId;
 import static com.android.internal.print.DumpUtils.writePrinterInfo;
-import static com.android.internal.print.DumpUtils.writeStringIfNotNull;
+import static com.android.internal.util.dump.DumpUtils.writeComponentName;
+import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.NonNull;
@@ -81,7 +81,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BackgroundThread;
-import com.android.internal.print.DualDumpOutputStream;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
 import com.android.server.print.RemotePrintServiceRecommendationService
         .RemotePrintServiceRecommendationServiceCallbacks;
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
index 74280ff..7480e56 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
@@ -16,6 +16,11 @@
 
 package com.android.server.usb;
 
+import android.annotation.NonNull;
+import android.service.usb.UsbAlsaDeviceProto;
+
+import com.android.internal.util.dump.DualDumpOutputStream;
+
 /**
  * Represents the ALSA specification, and attributes of an ALSA device.
  */
@@ -109,6 +114,22 @@
             + ", hasCapture: " + mHasCapture + "]";
     }
 
+    /**
+     * Write a description of the device to a dump stream.
+     */
+    public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("card", UsbAlsaDeviceProto.CARD, mCardNum);
+        dump.write("device", UsbAlsaDeviceProto.DEVICE, mDeviceNum);
+        dump.write("name", UsbAlsaDeviceProto.NAME, mDeviceName);
+        dump.write("has_playback", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasPlayback);
+        dump.write("has_capture", UsbAlsaDeviceProto.HAS_CAPTURE, mHasCapture);
+        dump.write("address", UsbAlsaDeviceProto.ADDRESS, mDeviceAddress);
+
+        dump.end(token);
+    }
+
     // called by logDevices
     String toShortString() {
         return "[card:" + mCardNum + " device:" + mDeviceNum + " " + mDeviceName + "]";
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 0a94828..0c5f8f1 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -27,10 +27,11 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
+import android.service.usb.UsbAlsaManagerProto;
 import android.util.Slog;
 
 import com.android.internal.alsa.AlsaCardsParser;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.audio.AudioService;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 
@@ -304,22 +305,38 @@
    }
 
     //
-    // Logging
+    // Devices List
     //
-    // called by UsbService.dump
-    public void dump(IndentingPrintWriter pw) {
-        pw.println("Parsers Scan Status:");
-        pw.println("  Cards Parser: " + mCardsParser.getScanStatus());
-//        pw.println("  Devices Parser: " + mDevicesParser.getScanStatus());
-        pw.println("USB Audio Devices:");
+/*
+    //import java.util.ArrayList;
+    public ArrayList<UsbAudioDevice> getConnectedDevices() {
+        ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
+        for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
+            devices.add(entry.getValue());
+        }
+        return devices;
+    }
+*/
+
+    /**
+     * Dump the USB alsa state.
+     */
+    public void dump(DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("cards_parser", UsbAlsaManagerProto.CARDS_PARSER, mCardsParser.getScanStatus());
+
         for (UsbAlsaDevice usbAlsaDevice : mAlsaDevices) {
-            pw.println("  " + usbAlsaDevice.getDeviceAddress() + ": " + usbAlsaDevice);
+            usbAlsaDevice.dump(dump, "alsa_devices", UsbAlsaManagerProto.ALSA_DEVICES);
         }
-        pw.println("USB MIDI Devices:");
+
         for (String deviceAddr : mMidiDevices.keySet()) {
-            UsbMidiDevice midiDevice = mMidiDevices.get(deviceAddr);
-            pw.println("  " + deviceAddr + ": " + midiDevice);
+            // A UsbMidiDevice does not have a handle to the UsbDevice anymore
+            mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "midi_devices",
+                    UsbAlsaManagerProto.MIDI_DEVICES);
         }
+
+        dump.end(token);
     }
 
 /*
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index 703f1a1..74d8e12 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -16,6 +16,8 @@
 
 package com.android.server.usb;
 
+import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+
 import android.app.ActivityManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -35,11 +37,12 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.service.usb.UsbDebuggingManagerProto;
 import android.util.Base64;
 import android.util.Slog;
 
 import com.android.internal.R;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.FgThread;
 
 import java.io.File;
@@ -451,21 +454,30 @@
         mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_CLEAR);
     }
 
-    public void dump(IndentingPrintWriter pw) {
-        pw.println("USB Debugging State:");
-        pw.println("  Connected to adbd: " + (mThread != null));
-        pw.println("  Last key received: " + mFingerprints);
-        pw.println("  User keys:");
+    /**
+     * Dump the USB debugging state.
+     */
+    public void dump(DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("connected_to_adb", UsbDebuggingManagerProto.CONNECTED_TO_ADB, mThread != null);
+        writeStringIfNotNull(dump, "last_key_received", UsbDebuggingManagerProto.LAST_KEY_RECEVIED,
+                mFingerprints);
+
         try {
-            pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
+            dump.write("user_keys", UsbDebuggingManagerProto.USER_KEYS,
+                    FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
         } catch (IOException e) {
-            pw.println("IOException: " + e);
+            Slog.e(TAG, "Cannot read user keys", e);
         }
-        pw.println("  System keys:");
+
         try {
-            pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
+            dump.write("system_keys", UsbDebuggingManagerProto.SYSTEM_KEYS,
+                    FileUtils.readTextFile(new File("/adb_keys"), 0, null));
         } catch (IOException e) {
-            pw.println("IOException: " + e);
+            Slog.e(TAG, "Cannot read system keys", e);
         }
+
+        dump.end(token);
     }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a67e7f3..e5f50de 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,6 +16,9 @@
 
 package com.android.server.usb;
 
+import static com.android.internal.usb.DumpUtils.writeAccessory;
+import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.KeyguardManager;
@@ -41,6 +44,7 @@
 import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbPort;
 import android.hardware.usb.UsbPortStatus;
+import android.hardware.usb.gadget.V1_0.GadgetFunction;
 import android.hardware.usb.gadget.V1_0.IUsbGadget;
 import android.hardware.usb.gadget.V1_0.IUsbGadgetCallback;
 import android.hardware.usb.gadget.V1_0.Status;
@@ -63,6 +67,8 @@
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
 import android.provider.Settings;
+import android.service.usb.UsbDeviceManagerProto;
+import android.service.usb.UsbHandlerProto;
 import android.util.Pair;
 import android.util.Slog;
 
@@ -72,7 +78,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 
@@ -1244,32 +1250,66 @@
             return mScreenUnlockedFunctions;
         }
 
+        /**
+         * Dump a functions mask either as proto-enums (if dumping to proto) or a string (if dumping
+         * to a print writer)
+         */
+        private void dumpFunctions(DualDumpOutputStream dump, String idName, long id,
+                long functions) {
+            // UsbHandlerProto.UsbFunction matches GadgetFunction
+            for (int i = 0; i < 63; i++) {
+                if ((functions & (1L << i)) != 0) {
+                    if (dump.isProto()) {
+                        dump.write(idName, id, 1L << i);
+                    } else {
+                        dump.write(idName, id, GadgetFunction.toString(1L << i));
+                    }
+                }
+            }
+        }
 
-        public void dump(IndentingPrintWriter pw) {
-            pw.println("USB Device State:");
-            pw.println("  mCurrentFunctions: " + mCurrentFunctions);
-            pw.println("  mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
-            pw.println("  mScreenUnlockedFunctions: " + mScreenUnlockedFunctions);
-            pw.println("  mScreenLocked: " + mScreenLocked);
-            pw.println("  mConnected: " + mConnected);
-            pw.println("  mConfigured: " + mConfigured);
-            pw.println("  mCurrentAccessory: " + mCurrentAccessory);
-            pw.println("  mHostConnected: " + mHostConnected);
-            pw.println("  mSourcePower: " + mSourcePower);
-            pw.println("  mSinkPower: " + mSinkPower);
-            pw.println("  mUsbCharging: " + mUsbCharging);
-            pw.println("  mHideUsbNotification: " + mHideUsbNotification);
-            pw.println("  mAudioAccessoryConnected: " + mAudioAccessoryConnected);
-            pw.println("  mAdbEnabled: " + mAdbEnabled);
+        public void dump(DualDumpOutputStream dump, String idName, long id) {
+            long token = dump.start(idName, id);
+
+            dumpFunctions(dump, "current_functions", UsbHandlerProto.CURRENT_FUNCTIONS,
+                    mCurrentFunctions);
+            dump.write("current_functions_applied", UsbHandlerProto.CURRENT_FUNCTIONS_APPLIED,
+                    mCurrentFunctionsApplied);
+            dumpFunctions(dump, "screen_unlocked_functions",
+                    UsbHandlerProto.SCREEN_UNLOCKED_FUNCTIONS, mScreenUnlockedFunctions);
+            dump.write("screen_locked", UsbHandlerProto.SCREEN_LOCKED, mScreenLocked);
+            dump.write("connected", UsbHandlerProto.CONNECTED, mConnected);
+            dump.write("configured", UsbHandlerProto.CONFIGURED, mConfigured);
+            if (mCurrentAccessory != null) {
+                writeAccessory(dump, "current_accessory", UsbHandlerProto.CURRENT_ACCESSORY,
+                        mCurrentAccessory);
+            }
+            dump.write("host_connected", UsbHandlerProto.HOST_CONNECTED, mHostConnected);
+            dump.write("source_power", UsbHandlerProto.SOURCE_POWER, mSourcePower);
+            dump.write("sink_power", UsbHandlerProto.SINK_POWER, mSinkPower);
+            dump.write("usb_charging", UsbHandlerProto.USB_CHARGING, mUsbCharging);
+            dump.write("hide_usb_notification", UsbHandlerProto.HIDE_USB_NOTIFICATION,
+                    mHideUsbNotification);
+            dump.write("audio_accessory_connected", UsbHandlerProto.AUDIO_ACCESSORY_CONNECTED,
+                    mAudioAccessoryConnected);
+            dump.write("adb_enabled", UsbHandlerProto.ADB_ENABLED, mAdbEnabled);
 
             try {
-                pw.println("  Kernel state: "
-                        + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
-                pw.println("  Kernel function list: "
-                        + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
-            } catch (IOException e) {
-                pw.println("IOException: " + e);
+                writeStringIfNotNull(dump, "kernel_state", UsbHandlerProto.KERNEL_STATE,
+                        FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
+            } catch (Exception e) {
+                Slog.e(TAG, "Could not read kernel state", e);
             }
+
+            try {
+                writeStringIfNotNull(dump, "kernel_function_list",
+                        UsbHandlerProto.KERNEL_FUNCTION_LIST,
+                        FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
+            } catch (Exception e) {
+                Slog.e(TAG, "Could not read kernel function list", e);
+            }
+
+            dump.end(token);
         }
 
         /**
@@ -2000,13 +2040,21 @@
         }
     }
 
-    public void dump(IndentingPrintWriter pw) {
+    /**
+     * Write the state to a dump stream.
+     */
+    public void dump(DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
         if (mHandler != null) {
-            mHandler.dump(pw);
+            mHandler.dump(dump, "handler", UsbDeviceManagerProto.HANDLER);
         }
         if (mDebuggingManager != null) {
-            mDebuggingManager.dump(pw);
+            mDebuggingManager.dump(dump, "debugging_manager",
+                    UsbDeviceManagerProto.DEBUGGING_MANAGER);
         }
+
+        dump.end(token);
     }
 
     private native String[] nativeGetAccessoryStrings();
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 58f91477..0fcd075 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -16,6 +16,10 @@
 
 package com.android.server.usb;
 
+import static com.android.internal.usb.DumpUtils.writeDevice;
+import static com.android.internal.util.dump.DumpUtils.writeComponentName;
+
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
@@ -23,11 +27,16 @@
 import android.hardware.usb.UsbDevice;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.service.ServiceProtoEnums;
+import android.service.usb.UsbConnectionRecordProto;
+import android.service.usb.UsbHostManagerProto;
+import android.service.usb.UsbIsHeadsetProto;
 import android.text.TextUtils;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.usb.descriptors.UsbDescriptor;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 import com.android.server.usb.descriptors.UsbDeviceDescriptor;
@@ -84,10 +93,13 @@
         long mTimestamp;        // Same time-base as system log.
         String mDeviceAddress;
 
-        static final int CONNECT = 0;
-        static final int CONNECT_BADPARSE = 1;
-        static final int CONNECT_BADDEVICE = 2;
-        static final int DISCONNECT = -1;
+        static final int CONNECT = ServiceProtoEnums.USB_CONNECTION_RECORD_MODE_CONNECT; // 0
+        static final int CONNECT_BADPARSE =
+                ServiceProtoEnums.USB_CONNECTION_RECORD_MODE_CONNECT_BADPARSE; // 1
+        static final int CONNECT_BADDEVICE =
+                ServiceProtoEnums.USB_CONNECTION_RECORD_MODE_CONNECT_BADDEVICE; // 2
+        static final int DISCONNECT =
+                ServiceProtoEnums.USB_CONNECTION_RECORD_MODE_DISCONNECT; // -1
 
         final int mMode;
         final byte[] mDescriptors;
@@ -103,6 +115,31 @@
             return (new StringBuilder(sFormat.format(new Date(mTimestamp)))).toString();
         }
 
+        void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+            long token = dump.start(idName, id);
+
+            dump.write("device_address", UsbConnectionRecordProto.DEVICE_ADDRESS, mDeviceAddress);
+            dump.write("mode", UsbConnectionRecordProto.MODE, mMode);
+            dump.write("timestamp", UsbConnectionRecordProto.TIMESTAMP, mTimestamp);
+
+            if (mMode != DISCONNECT) {
+                UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
+
+                UsbDeviceDescriptor deviceDescriptor = parser.getDeviceDescriptor();
+
+                dump.write("manufacturer", UsbConnectionRecordProto.MANUFACTURER,
+                        deviceDescriptor.getVendorID());
+                dump.write("product", UsbConnectionRecordProto.PRODUCT,
+                        deviceDescriptor.getProductID());
+                long isHeadSetToken = dump.start("is_headset", UsbConnectionRecordProto.IS_HEADSET);
+                dump.write("in", UsbIsHeadsetProto.IN, parser.isInputHeadset());
+                dump.write("out", UsbIsHeadsetProto.OUT, parser.isOutputHeadset());
+                dump.end(isHeadSetToken);
+            }
+
+            dump.end(token);
+        }
+
         void dumpShort(IndentingPrintWriter pw) {
             if (mMode != DISCONNECT) {
                 pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
@@ -394,30 +431,30 @@
 
     /**
      * Dump out various information about the state of USB device connections.
-     *
      */
-    public void dump(IndentingPrintWriter pw, String[] args) {
-        pw.println("USB Host State:");
+    public void dump(DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
         synchronized (mHandlerLock) {
             if (mUsbDeviceConnectionHandler != null) {
-                pw.println("Default USB Host Connection handler: " + mUsbDeviceConnectionHandler);
+                writeComponentName(dump, "default_usb_host_connection_handler",
+                        UsbHostManagerProto.DEFAULT_USB_HOST_CONNECTION_HANDLER,
+                        mUsbDeviceConnectionHandler);
             }
         }
         synchronized (mLock) {
             for (String name : mDevices.keySet()) {
-                pw.println("  " + name + ": " + mDevices.get(name));
+                writeDevice(dump, "devices", UsbHostManagerProto.DEVICES, mDevices.get(name));
             }
 
-            // Connections
-            pw.println("" + mNumConnects + " total connects/disconnects");
-            pw.println("Last " + mConnections.size() + " connections/disconnections");
+            dump.write("num_connects", UsbHostManagerProto.NUM_CONNECTS, mNumConnects);
+
             for (ConnectionRecord rec : mConnections) {
-                rec.dumpShort(pw);
+                rec.dump(dump, "connections", UsbHostManagerProto.CONNECTIONS);
             }
-
         }
 
-        mUsbAlsaManager.dump(pw);
+        dump.end(token);
     }
 
     /**
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index cd19795..f47636e 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -16,14 +16,15 @@
 
 package com.android.server.usb;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.media.midi.MidiDeviceInfo;
 import android.media.midi.MidiDeviceServer;
 import android.media.midi.MidiDeviceStatus;
 import android.media.midi.MidiManager;
 import android.media.midi.MidiReceiver;
-import android.media.midi.MidiSender;
 import android.os.Bundle;
+import android.service.usb.UsbMidiDeviceProto;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -32,6 +33,7 @@
 
 import com.android.internal.midi.MidiEventScheduler;
 import com.android.internal.midi.MidiEventScheduler.MidiEvent;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 import libcore.io.IoUtils;
 
@@ -338,6 +340,20 @@
         mIsOpen = false;
     }
 
+    /**
+     * Write a description of the device to a dump stream.
+     */
+    public void dump(String deviceAddr, @NonNull DualDumpOutputStream dump, @NonNull String idName,
+            long id) {
+        long token = dump.start(idName, id);
+
+        dump.write("device_address", UsbMidiDeviceProto.DEVICE_ADDRESS, deviceAddr);
+        dump.write("card", UsbMidiDeviceProto.CARD, mAlsaCard);
+        dump.write("device", UsbMidiDeviceProto.DEVICE, mAlsaDevice);
+
+        dump.end(token);
+    }
+
     private static native int nativeGetSubdeviceCount(int card, int device);
     private native FileDescriptor[] nativeOpen(int card, int device, int subdeviceCount);
     private native void nativeClose(FileDescriptor[] fileDescriptors);
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index e28513a..ddb4f04 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -16,6 +16,10 @@
 
 package com.android.server.usb;
 
+import static com.android.internal.usb.DumpUtils.writePort;
+import static com.android.internal.usb.DumpUtils.writePortStatus;
+
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.usb.UsbManager;
@@ -38,12 +42,15 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.service.usb.UsbPortInfoProto;
+import android.service.usb.UsbPortManagerProto;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.FgThread;
 
 import java.util.ArrayList;
@@ -390,22 +397,22 @@
         }
     }
 
-    public void dump(IndentingPrintWriter pw) {
-        synchronized (mLock) {
-            pw.print("USB Port State:");
-            if (!mSimulatedPorts.isEmpty()) {
-                pw.print(" (simulation active; end with 'dumpsys usb reset')");
-            }
-            pw.println();
+    /**
+     * Dump the USB port state.
+     */
+    public void dump(DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
 
-            if (mPorts.isEmpty()) {
-                pw.println("  <no ports>");
-            } else {
-                for (PortInfo portInfo : mPorts.values()) {
-                    pw.println("  " + portInfo.mUsbPort.getId() + ": " + portInfo);
-                }
+        synchronized (mLock) {
+            dump.write("is_simulation_active", UsbPortManagerProto.IS_SIMULATION_ACTIVE,
+                    !mSimulatedPorts.isEmpty());
+
+            for (PortInfo portInfo : mPorts.values()) {
+                portInfo.dump(dump, "usb_ports", UsbPortManagerProto.USB_PORTS);
             }
         }
+
+        dump.end(token);
     }
 
     private static class HALCallback extends IUsbCallback.Stub {
@@ -765,6 +772,20 @@
             return false;
         }
 
+        void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
+            long token = dump.start(idName, id);
+
+            writePort(dump, "port", UsbPortInfoProto.PORT, mUsbPort);
+            writePortStatus(dump, "status", UsbPortInfoProto.STATUS, mUsbPortStatus);
+            dump.write("can_change_mode", UsbPortInfoProto.CAN_CHANGE_MODE, mCanChangeMode);
+            dump.write("can_change_power_role", UsbPortInfoProto.CAN_CHANGE_POWER_ROLE,
+                    mCanChangePowerRole);
+            dump.write("can_change_data_role", UsbPortInfoProto.CAN_CHANGE_DATA_ROLE,
+                    mCanChangeDataRole);
+
+            dump.end(token);
+        }
+
         @Override
         public String toString() {
             return "port=" + mUsbPort + ", status=" + mUsbPortStatus
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 5f1f5e4..4b2d9b9 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -41,6 +41,10 @@
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.service.usb.UsbProfileGroupSettingsManagerProto;
+import android.service.usb.UsbSettingsAccessoryPreferenceProto;
+import android.service.usb.UsbSettingsDevicePreferenceProto;
+import android.service.usb.UserPackageProto;
 import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
@@ -52,8 +56,8 @@
 import com.android.internal.annotations.Immutable;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 import libcore.io.IoUtils;
 
@@ -154,6 +158,15 @@
         public String toString() {
             return user.getIdentifier() + "/" + packageName;
         }
+
+        public void dump(DualDumpOutputStream dump, String idName, long id) {
+            long token = dump.start(idName, id);
+
+            dump.write("user_id", UserPackageProto.USER_ID, user.getIdentifier());
+            dump.write("package_name", UserPackageProto.PACKAGE_NAME, packageName);
+
+            dump.end(token);
+        }
     }
 
     private class MyPackageMonitor extends PackageMonitor {
@@ -1109,17 +1122,38 @@
         }
     }
 
-    public void dump(IndentingPrintWriter pw) {
+    public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
+        long token = dump.start(idName, id);
+
         synchronized (mLock) {
-            pw.println("Device preferences:");
+            dump.write("parent_user_id", UsbProfileGroupSettingsManagerProto.PARENT_USER_ID,
+                    mParentUser.getIdentifier());
+
             for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
-                pw.println("  " + filter + ": " + mDevicePreferenceMap.get(filter));
+                long devicePrefToken = dump.start("device_preferences",
+                        UsbProfileGroupSettingsManagerProto.DEVICE_PREFERENCES);
+
+                filter.dump(dump, "filter", UsbSettingsDevicePreferenceProto.FILTER);
+
+                mDevicePreferenceMap.get(filter).dump(dump, "user_package",
+                        UsbSettingsDevicePreferenceProto.USER_PACKAGE);
+
+                dump.end(devicePrefToken);
             }
-            pw.println("Accessory preferences:");
             for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
-                pw.println("  " + filter + ": " + mAccessoryPreferenceMap.get(filter));
+                long accessoryPrefToken = dump.start("accessory_preferences",
+                        UsbProfileGroupSettingsManagerProto.ACCESSORY_PREFERENCES);
+
+                filter.dump(dump, "filter", UsbSettingsAccessoryPreferenceProto.FILTER);
+
+                mAccessoryPreferenceMap.get(filter).dump(dump, "user_package",
+                        UsbSettingsAccessoryPreferenceProto.USER_PACKAGE);
+
+                dump.end(accessoryPrefToken);
             }
         }
+
+        dump.end(token);
     }
 
     private static Intent createDeviceAttachedIntent(UsbDevice device) {
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 2f6e531..1edc469 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -37,17 +37,22 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.service.usb.UsbServiceDumpProto;
+import android.util.ArraySet;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.SystemService;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 
 /**
  * UsbService manages all USB related state, including both host and device support.
@@ -503,21 +508,38 @@
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         final long ident = Binder.clearCallingIdentity();
         try {
-            if (args == null || args.length == 0 || "-a".equals(args[0])) {
-                pw.println("USB Manager State:");
-                pw.increaseIndent();
+            ArraySet<String> argsSet = new ArraySet<>();
+            Collections.addAll(argsSet, args);
+
+            boolean dumpAsProto = false;
+            if (argsSet.contains("--proto")) {
+                dumpAsProto = true;
+            }
+
+            if (args == null || args.length == 0 || args[0].equals("-a") || dumpAsProto) {
+                DualDumpOutputStream dump;
+                if (dumpAsProto) {
+                    dump = new DualDumpOutputStream(new ProtoOutputStream(fd));
+                } else {
+                    pw.println("USB MANAGER STATE (dumpsys usb):");
+
+                    dump = new DualDumpOutputStream(new IndentingPrintWriter(pw, "  "));
+                }
+
                 if (mDeviceManager != null) {
-                    mDeviceManager.dump(pw);
+                    mDeviceManager.dump(dump, "device_manager", UsbServiceDumpProto.DEVICE_MANAGER);
                 }
                 if (mHostManager != null) {
-                    mHostManager.dump(pw, args);
+                    mHostManager.dump(dump, "host_manager", UsbServiceDumpProto.HOST_MANAGER);
                 }
                 if (mPortManager != null) {
-                    mPortManager.dump(pw);
+                    mPortManager.dump(dump, "port_manager", UsbServiceDumpProto.PORT_MANAGER);
                 }
-                mAlsaManager.dump(pw);
+                mAlsaManager.dump(dump, "alsa_manager", UsbServiceDumpProto.ALSA_MANAGER);
 
-                mSettingsManager.dump(pw);
+                mSettingsManager.dump(dump, "settings_manager",
+                        UsbServiceDumpProto.SETTINGS_MANAGER);
+                dump.flush();
             } else if ("set-port-roles".equals(args[0]) && args.length == 4) {
                 final String portId = args[1];
                 final int powerRole;
@@ -558,7 +580,8 @@
                     // during debugging, it might be worth adding a sleep here before
                     // dumping the new state.
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("add-port".equals(args[0]) && args.length == 3) {
                 final String portId = args[1];
@@ -583,7 +606,8 @@
                 if (mPortManager != null) {
                     mPortManager.addSimulatedPort(portId, supportedModes, pw);
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("connect-port".equals(args[0]) && args.length == 5) {
                 final String portId = args[1];
@@ -630,31 +654,36 @@
                     mPortManager.connectSimulatedPort(portId, mode, canChangeMode,
                             powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw);
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("disconnect-port".equals(args[0]) && args.length == 2) {
                 final String portId = args[1];
                 if (mPortManager != null) {
                     mPortManager.disconnectSimulatedPort(portId, pw);
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("remove-port".equals(args[0]) && args.length == 2) {
                 final String portId = args[1];
                 if (mPortManager != null) {
                     mPortManager.removeSimulatedPort(portId, pw);
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("reset".equals(args[0]) && args.length == 1) {
                 if (mPortManager != null) {
                     mPortManager.resetSimulation(pw);
                     pw.println();
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("ports".equals(args[0]) && args.length == 1) {
                 if (mPortManager != null) {
-                    mPortManager.dump(pw);
+                    mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")),
+                            "", 0);
                 }
             } else if ("dump-descriptors".equals(args[0])) {
                 mHostManager.dumpDescriptors(pw, args);
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index c7e5998d..caf05a3 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -26,11 +26,12 @@
 import android.hardware.usb.UsbManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.service.usb.UsbSettingsManagerProto;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 /**
  * Maintains all {@link UsbUserSettingsManager} for all users.
@@ -134,39 +135,27 @@
 
     /**
      * Dump all settings of all users.
-     *
-     * @param pw The writer to dump to
      */
-    void dump(@NonNull IndentingPrintWriter pw) {
+    void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+
         synchronized (mSettingsByUser) {
             int numUsers = mSettingsByUser.size();
             for (int i = 0; i < numUsers; i++) {
-                final int userId = mSettingsByUser.keyAt(i);
-                final UsbUserSettingsManager settings = mSettingsByUser.valueAt(i);
-                pw.println("Settings for user " + userId + ":");
-                pw.increaseIndent();
-                try {
-                    settings.dump(pw);
-                } finally {
-                    pw.decreaseIndent();
-                }
+                mSettingsByUser.valueAt(i).dump(dump, "user_settings",
+                        UsbSettingsManagerProto.USER_SETTINGS);
             }
         }
 
         synchronized (mSettingsByProfileGroup) {
             int numProfileGroups = mSettingsByProfileGroup.size();
             for (int i = 0; i < numProfileGroups; i++) {
-                final int parentUserId = mSettingsByProfileGroup.keyAt(i);
-                final UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.valueAt(i);
-                pw.println("Settings for profile group " + parentUserId + ":");
-                pw.increaseIndent();
-                try {
-                    settings.dump(pw);
-                } finally {
-                    pw.decreaseIndent();
-                }
+                mSettingsByProfileGroup.valueAt(i).dump(dump, "profile_group_settings",
+                        UsbSettingsManagerProto.PROFILE_GROUP_SETTINGS);
             }
         }
+
+        dump.end(token);
     }
 
     /**
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 11e43e3..8409506 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -25,17 +25,20 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbManager;
 import android.os.Binder;
 import android.os.Process;
 import android.os.UserHandle;
+import android.service.usb.UsbSettingsAccessoryPermissionProto;
+import android.service.usb.UsbSettingsDevicePermissionProto;
+import android.service.usb.UsbUserSettingsManagerProto;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.dump.DualDumpOutputStream;
 
 import java.util.HashMap;
 
@@ -302,28 +305,44 @@
         }
     }
 
-    public void dump(IndentingPrintWriter pw) {
+    public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
+        long token = dump.start(idName, id);
+
         synchronized (mLock) {
-            pw.println("Device permissions:");
+            dump.write("user_id", UsbUserSettingsManagerProto.USER_ID, mUser.getIdentifier());
+
             for (String deviceName : mDevicePermissionMap.keySet()) {
-                pw.print("  " + deviceName + ": ");
+                long devicePermissionToken = dump.start("device_permissions",
+                        UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
+
+                dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
+
                 SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
                 int count = uidList.size();
                 for (int i = 0; i < count; i++) {
-                    pw.print(Integer.toString(uidList.keyAt(i)) + " ");
+                    dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
                 }
-                pw.println();
+
+                dump.end(devicePermissionToken);
             }
-            pw.println("Accessory permissions:");
             for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
-                pw.print("  " + accessory + ": ");
+                long accessoryPermissionToken = dump.start("accessory_permissions",
+                        UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
+
+                dump.write("accessory_description",
+                        UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
+                        accessory.getDescription());
+
                 SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
                 int count = uidList.size();
                 for (int i = 0; i < count; i++) {
-                    pw.print(Integer.toString(uidList.keyAt(i)) + " ");
+                    dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
                 }
-                pw.println();
+
+                dump.end(accessoryPermissionToken);
             }
         }
+
+        dump.end(token);
     }
 }