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.server.usb; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import android.content.Context; 25 import android.content.res.Resources; 26 import android.content.res.Resources.NotFoundException; 27 28 import androidx.test.InstrumentationRegistry; 29 import androidx.test.filters.SmallTest; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.server.usb.descriptors.UsbDescriptorParser; 33 34 import com.google.common.io.ByteStreams; 35 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.io.IOException; 40 import java.io.InputStream; 41 42 /** 43 * Tests for {@link com.android.server.usb.descriptors.UsbDescriptorParser} 44 */ 45 @RunWith(AndroidJUnit4.class) 46 public class UsbDescriptorParserTests { 47 loadParser(int resource)48 public UsbDescriptorParser loadParser(int resource) { 49 Context c = InstrumentationRegistry.getContext(); 50 Resources res = c.getResources(); 51 InputStream is = null; 52 try { 53 is = res.openRawResource(resource); 54 } catch (NotFoundException e) { 55 fail("Failed to load resource."); 56 } 57 58 byte[] descriptors = null; 59 try { 60 descriptors = ByteStreams.toByteArray(is); 61 } catch (IOException e) { 62 fail("Failed to convert descriptor strema to bytearray."); 63 } 64 65 // Testing same codepath as UsbHostManager.java:usbDeviceAdded 66 UsbDescriptorParser parser = new UsbDescriptorParser("test-usb-addr", descriptors); 67 return parser; 68 } 69 70 /** A Headset has a microphone and a speaker and is a headset. 71 * Descriptors for this example show up on lsusb -v with: 72 * bcdDevice 22.80 73 * and a UAC1 audio device with the following control interface: 74 * bInterfaceClass 1 Audio 75 * ... 76 * bDescriptorSubtype 2 (INPUT_TERMINAL) 77 * bTerminalID 1 78 * wTerminalType 0x0201 Microphone 79 * ... 80 * bDescriptorSubtype 3 (OUTPUT_TERMINAL) 81 * bTerminalID 15 82 * wTerminalType 0x0302 Headphones 83 */ 84 @Test 85 @SmallTest testHeadsetDescriptorParser()86 public void testHeadsetDescriptorParser() { 87 UsbDescriptorParser parser = loadParser(R.raw.usbdescriptors_headset); 88 assertTrue(parser.hasInput()); 89 assertTrue(parser.hasOutput()); 90 assertTrue(parser.isInputHeadset()); 91 assertTrue(parser.isOutputHeadset()); 92 93 assertTrue(parser.hasAudioInterface()); 94 assertTrue(parser.hasHIDInterface()); 95 assertFalse(parser.hasStorageInterface()); 96 97 assertEquals(parser.getDeviceDescriptor().getDeviceReleaseString(), "22.80"); 98 } 99 100 /** Headphones have no microphones but are considered a headset. 101 * Descriptors for this example show up on lsusb -v with: 102 * bcdDevice 22.80 103 * and a UAC1 audio device with the following control interface: 104 * bInterfaceClass 1 Audio 105 * ... 106 * bDescriptorSubtype 3 (OUTPUT_TERMINAL) 107 * bTerminalID 15 108 * wTerminalType 0x0302 Headphones 109 */ 110 @Test 111 @SmallTest testHeadphoneDescriptorParser()112 public void testHeadphoneDescriptorParser() { 113 UsbDescriptorParser parser = loadParser(R.raw.usbdescriptors_headphones); 114 assertFalse(parser.hasInput()); 115 assertTrue(parser.hasOutput()); 116 assertFalse(parser.isInputHeadset()); 117 assertTrue(parser.isOutputHeadset()); 118 119 assertTrue(parser.hasAudioInterface()); 120 assertTrue(parser.hasHIDInterface()); 121 assertFalse(parser.hasStorageInterface()); 122 123 assertEquals(parser.getDeviceDescriptor().getDeviceReleaseString(), "22.80"); 124 } 125 126 /** Line out with no microphones aren't considered a headset. 127 * Descriptors for this example show up on lsusb -v with: 128 * bcdDevice 22.80 129 * and the following UAC1 audio control interface 130 * bInterfaceClass 1 Audio 131 * ... 132 * bDescriptorSubtype 3 (OUTPUT_TERMINAL) 133 * bTerminalID 15 134 * wTerminalType 0x0603 Line Connector 135 */ 136 @Test 137 @SmallTest testLineoutDescriptorParser()138 public void testLineoutDescriptorParser() { 139 UsbDescriptorParser parser = loadParser(R.raw.usbdescriptors_lineout); 140 assertFalse(parser.hasInput()); 141 assertTrue(parser.hasOutput()); 142 assertFalse(parser.isInputHeadset()); 143 assertFalse(parser.isOutputHeadset()); 144 145 assertTrue(parser.hasAudioInterface()); 146 assertTrue(parser.hasHIDInterface()); 147 assertFalse(parser.hasStorageInterface()); 148 149 assertEquals(parser.getDeviceDescriptor().getDeviceReleaseString(), "22.80"); 150 } 151 152 /** An HID-only device shouldn't be considered anything at all. 153 /* Descriptors show up on lsusb -v with: 154 * bcdDevice 22.80 155 * and a single HID interface, 156 * bInterfaceClass 3 Human Interface Device 157 */ 158 @Test 159 @SmallTest testNothingDescriptorParser()160 public void testNothingDescriptorParser() { 161 UsbDescriptorParser parser = loadParser(R.raw.usbdescriptors_nothing); 162 assertFalse(parser.hasInput()); 163 assertFalse(parser.hasOutput()); 164 assertFalse(parser.isInputHeadset()); 165 assertFalse(parser.isOutputHeadset()); 166 167 assertFalse(parser.hasAudioInterface()); 168 assertTrue(parser.hasHIDInterface()); 169 assertFalse(parser.hasStorageInterface()); 170 171 assertEquals(parser.getDeviceDescriptor().getDeviceReleaseString(), "22.80"); 172 } 173 174 /** A USB mass-storage device. 175 * Shows up on lsusb -v with: 176 * bcdDevice 2.08 177 * and a single interface descriptor, 178 * bInterfaceClass 8 Mass Storage 179 */ 180 @Test 181 @SmallTest testMassStorageDescriptorParser()182 public void testMassStorageDescriptorParser() { 183 UsbDescriptorParser parser = loadParser(R.raw.usbdescriptors_massstorage); 184 assertFalse(parser.hasInput()); 185 assertFalse(parser.hasOutput()); 186 assertFalse(parser.isInputHeadset()); 187 assertFalse(parser.isOutputHeadset()); 188 189 assertFalse(parser.hasAudioInterface()); 190 assertFalse(parser.hasHIDInterface()); 191 assertTrue(parser.hasStorageInterface()); 192 193 assertEquals(parser.getDeviceDescriptor().getDeviceReleaseString(), "2.08"); 194 } 195 196 } 197