1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.usb;
18 
19 import static android.hardware.usb.UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT;
20 import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY;
21 import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY;
22 import static android.hardware.usb.UsbPortStatus.MODE_DFP;
23 import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
24 import static android.hardware.usb.UsbPortStatus.MODE_NONE;
25 import static android.hardware.usb.UsbPortStatus.MODE_UFP;
26 
27 import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
28 
29 import android.annotation.NonNull;
30 import android.hardware.usb.DisplayPortAltModeInfo;
31 import android.hardware.usb.UsbAccessory;
32 import android.hardware.usb.UsbConfiguration;
33 import android.hardware.usb.UsbDevice;
34 import android.hardware.usb.UsbEndpoint;
35 import android.hardware.usb.UsbInterface;
36 import android.hardware.usb.UsbPort;
37 import android.hardware.usb.UsbPortStatus;
38 import android.hardware.usb.V1_0.Constants;
39 import android.service.usb.UsbAccessoryProto;
40 import android.service.usb.UsbConfigurationProto;
41 import android.service.usb.UsbDeviceProto;
42 import android.service.usb.UsbEndPointProto;
43 import android.service.usb.UsbInterfaceProto;
44 import android.service.usb.UsbPortProto;
45 import android.service.usb.UsbPortStatusProto;
46 import android.service.usb.UsbPortStatusRoleCombinationProto;
47 
48 import com.android.internal.util.dump.DualDumpOutputStream;
49 
50 /** Dump methods for public USB classes */
51 public class DumpUtils {
writeAccessory(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbAccessory accessory)52     public static void writeAccessory(@NonNull DualDumpOutputStream dump, @NonNull String idName,
53             long id, @NonNull UsbAccessory accessory) {
54         long token = dump.start(idName, id);
55 
56         dump.write("manufacturer", UsbAccessoryProto.MANUFACTURER, accessory.getManufacturer());
57         dump.write("model", UsbAccessoryProto.MODEL, accessory.getModel());
58         writeStringIfNotNull(dump, "description", UsbAccessoryProto.DESCRIPTION,
59                 accessory.getManufacturer());
60         dump.write("version", UsbAccessoryProto.VERSION, accessory.getVersion());
61         writeStringIfNotNull(dump, "uri", UsbAccessoryProto.URI, accessory.getUri());
62         dump.write("serial", UsbAccessoryProto.SERIAL, accessory.getSerial());
63 
64         dump.end(token);
65     }
66 
writeDevice(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbDevice device)67     public static void writeDevice(@NonNull DualDumpOutputStream dump, @NonNull String idName,
68             long id, @NonNull UsbDevice device) {
69         long token = dump.start(idName, id);
70 
71         dump.write("name", UsbDeviceProto.NAME, device.getDeviceName());
72         dump.write("vendor_id", UsbDeviceProto.VENDOR_ID, device.getVendorId());
73         dump.write("product_id", UsbDeviceProto.PRODUCT_ID, device.getProductId());
74         dump.write("class", UsbDeviceProto.CLASS, device.getDeviceClass());
75         dump.write("subclass", UsbDeviceProto.SUBCLASS, device.getDeviceSubclass());
76         dump.write("protocol", UsbDeviceProto.PROTOCOL, device.getDeviceProtocol());
77         dump.write("manufacturer_name", UsbDeviceProto.MANUFACTURER_NAME,
78                 device.getManufacturerName());
79         dump.write("product_name", UsbDeviceProto.PRODUCT_NAME, device.getProductName());
80         dump.write("version", UsbDeviceProto.VERSION, device.getVersion());
81         dump.write("serial_number", UsbDeviceProto.SERIAL_NUMBER, device.getSerialNumber());
82 
83         int numConfigurations = device.getConfigurationCount();
84         for (int i = 0; i < numConfigurations; i++) {
85             writeConfiguration(dump, "configurations", UsbDeviceProto.CONFIGURATIONS,
86                     device.getConfiguration(i));
87         }
88 
89         dump.end(token);
90     }
91 
writeConfiguration(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbConfiguration configuration)92     private static void writeConfiguration(@NonNull DualDumpOutputStream dump,
93             @NonNull String idName, long id, @NonNull UsbConfiguration configuration) {
94         long token = dump.start(idName, id);
95         dump.write("id", UsbConfigurationProto.ID, configuration.getId());
96         dump.write("name", UsbConfigurationProto.NAME, configuration.getName());
97         dump.write("attributes", UsbConfigurationProto.ATTRIBUTES, configuration.getAttributes());
98         dump.write("max_power", UsbConfigurationProto.MAX_POWER, configuration.getMaxPower());
99 
100         int numInterfaces = configuration.getInterfaceCount();
101         for (int i = 0; i < numInterfaces; i++) {
102             writeInterface(dump, "interfaces", UsbConfigurationProto.INTERFACES,
103                     configuration.getInterface(i));
104         }
105         dump.end(token);
106     }
107 
writeInterface(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbInterface iface)108     private static void writeInterface(@NonNull DualDumpOutputStream dump, @NonNull String idName,
109             long id, @NonNull UsbInterface iface) {
110         long token = dump.start(idName, id);
111 
112         dump.write("id", UsbInterfaceProto.ID, iface.getId());
113         dump.write("alternate_settings", UsbInterfaceProto.ALTERNATE_SETTINGS,
114                 iface.getAlternateSetting());
115         dump.write("name", UsbInterfaceProto.NAME, iface.getName());
116         dump.write("class", UsbInterfaceProto.CLASS, iface.getInterfaceClass());
117         dump.write("subclass", UsbInterfaceProto.SUBCLASS, iface.getInterfaceSubclass());
118         dump.write("protocol", UsbInterfaceProto.PROTOCOL, iface.getInterfaceProtocol());
119 
120         int numEndpoints = iface.getEndpointCount();
121         for (int i = 0; i < numEndpoints; i++) {
122             writeEndpoint(dump, "endpoints", UsbInterfaceProto.ENDPOINTS, iface.getEndpoint(i));
123         }
124         dump.end(token);
125     }
126 
writeEndpoint(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbEndpoint endpoint)127     private static void writeEndpoint(@NonNull DualDumpOutputStream dump, @NonNull String idName,
128             long id, @NonNull UsbEndpoint endpoint) {
129         long token = dump.start(idName, id);
130 
131         dump.write("endpoint_number", UsbEndPointProto.ENDPOINT_NUMBER,
132                 endpoint.getEndpointNumber());
133         dump.write("direction", UsbEndPointProto.DIRECTION, endpoint.getDirection());
134         dump.write("address", UsbEndPointProto.ADDRESS, endpoint.getAddress());
135         dump.write("type", UsbEndPointProto.TYPE, endpoint.getType());
136         dump.write("attributes", UsbEndPointProto.ATTRIBUTES,
137                 endpoint.getAttributes());
138         dump.write("max_packet_size", UsbEndPointProto.MAX_PACKET_SIZE,
139                 endpoint.getMaxPacketSize());
140         dump.write("interval", UsbEndPointProto.INTERVAL, endpoint.getInterval());
141 
142         dump.end(token);
143     }
144 
writePort(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbPort port)145     public static void writePort(@NonNull DualDumpOutputStream dump, @NonNull String idName,
146             long id, @NonNull UsbPort port) {
147         long token = dump.start(idName, id);
148 
149         dump.write("id", UsbPortProto.ID, port.getId());
150 
151         int mode = port.getSupportedModes();
152         if (dump.isProto()) {
153             if (mode == MODE_NONE) {
154                 dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_NONE);
155             } else {
156                 if ((mode & MODE_DUAL) == MODE_DUAL) {
157                     dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DUAL);
158                 } else {
159                     if ((mode & MODE_DFP) == MODE_DFP) {
160                         dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DFP);
161                     } else if ((mode & MODE_UFP) == MODE_UFP) {
162                         dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_UFP);
163                     }
164                 }
165 
166                 if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) {
167                     dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES,
168                             MODE_AUDIO_ACCESSORY);
169                 }
170 
171                 if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) {
172                     dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES,
173                             MODE_DEBUG_ACCESSORY);
174                 }
175             }
176         } else {
177             dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, UsbPort.modeToString(mode));
178         }
179         dump.write("supports_compliance_warnings",
180                 UsbPortProto.SUPPORTS_COMPLIANCE_WARNINGS,
181                 port.supportsComplianceWarnings());
182         if (port.isAltModeSupported(FLAG_ALT_MODE_TYPE_DISPLAYPORT)) {
183             dump.write("supported_alt_modes", UsbPortProto.SUPPORTED_ALT_MODES,
184                     FLAG_ALT_MODE_TYPE_DISPLAYPORT);
185         }
186 
187         dump.end(token);
188     }
189 
writePowerRole(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, int powerRole)190     private static void writePowerRole(@NonNull DualDumpOutputStream dump, @NonNull String idName,
191             long id, int powerRole) {
192         if (dump.isProto()) {
193             dump.write(idName, id, powerRole);
194         } else {
195             dump.write(idName, id, UsbPort.powerRoleToString(powerRole));
196         }
197     }
198 
writeDataRole(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, int dataRole)199     private static void writeDataRole(@NonNull DualDumpOutputStream dump, @NonNull String idName,
200             long id, int dataRole) {
201         if (dump.isProto()) {
202             dump.write(idName, id, dataRole);
203         } else {
204             dump.write(idName, id, UsbPort.dataRoleToString(dataRole));
205         }
206     }
207 
writeContaminantPresenceStatus(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, int contaminantPresenceStatus)208     private static void writeContaminantPresenceStatus(@NonNull DualDumpOutputStream dump,
209             @NonNull String idName, long id, int contaminantPresenceStatus) {
210         if (dump.isProto()) {
211             dump.write(idName, id, contaminantPresenceStatus);
212         } else {
213             dump.write(idName, id,
214                     UsbPort.contaminantPresenceStatusToString(contaminantPresenceStatus));
215         }
216     }
217 
writePortStatus(@onNull DualDumpOutputStream dump, @NonNull String idName, long id, @NonNull UsbPortStatus status)218     public static void writePortStatus(@NonNull DualDumpOutputStream dump, @NonNull String idName,
219             long id, @NonNull UsbPortStatus status) {
220         long token = dump.start(idName, id);
221 
222         dump.write("connected", UsbPortStatusProto.CONNECTED, status.isConnected());
223 
224         if (dump.isProto()) {
225             dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE, status.getCurrentMode());
226         } else {
227             dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE,
228                     UsbPort.modeToString(status.getCurrentMode()));
229         }
230 
231         writePowerRole(dump, "power_role", UsbPortStatusProto.POWER_ROLE,
232                 status.getCurrentPowerRole());
233         writeDataRole(dump, "data_role", UsbPortStatusProto.DATA_ROLE, status.getCurrentDataRole());
234 
235         int undumpedCombinations = status.getSupportedRoleCombinations();
236         while (undumpedCombinations != 0) {
237             int index = Integer.numberOfTrailingZeros(undumpedCombinations);
238             undumpedCombinations &= ~(1 << index);
239 
240             int powerRole = (index / Constants.PortDataRole.NUM_DATA_ROLES
241                     + Constants.PortPowerRole.NONE);
242             int dataRole = index % Constants.PortDataRole.NUM_DATA_ROLES;
243 
244             long roleCombinationToken = dump.start("role_combinations",
245                     UsbPortStatusProto.ROLE_COMBINATIONS);
246             writePowerRole(dump, "power_role", UsbPortStatusRoleCombinationProto.POWER_ROLE,
247                     powerRole);
248             writeDataRole(dump, "data_role", UsbPortStatusRoleCombinationProto.DATA_ROLE,
249                     dataRole);
250             dump.end(roleCombinationToken);
251         }
252 
253         writeContaminantPresenceStatus(dump, "contaminant_presence_status",
254                 UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
255                 status.getContaminantDetectionStatus());
256         dump.write("usb_data_status", UsbPortStatusProto.USB_DATA_STATUS,
257                 UsbPort.usbDataStatusToString(status.getUsbDataStatus()));
258         dump.write("is_power_transfer_limited", UsbPortStatusProto.IS_POWER_TRANSFER_LIMITED,
259                 status.isPowerTransferLimited());
260         dump.write("usb_power_brick_status", UsbPortStatusProto.USB_POWER_BRICK_STATUS,
261                 UsbPort.powerBrickConnectionStatusToString(status.getPowerBrickConnectionStatus()));
262         dump.write("compliance_warning_status", UsbPortStatusProto.COMPLIANCE_WARNINGS_STRING,
263                 UsbPort.complianceWarningsToString(status.getComplianceWarnings()));
264         DisplayPortAltModeInfo displayPortAltModeInfo = status.getDisplayPortAltModeInfo();
265         if (displayPortAltModeInfo != null) {
266             dump.write("displayport_alt_mode_status",
267                     UsbPortStatusProto.DISPLAYPORT_ALT_MODE_STATUS,
268                     status.getDisplayPortAltModeInfo().toString());
269         }
270         dump.end(token);
271     }
272 }
273