1 /* 2 * Copyright (C) 2024 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 android.hardware.usb; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static junit.framework.Assert.assertFalse; 22 import static junit.framework.Assert.assertTrue; 23 24 import static org.mockito.Mockito.any; 25 import static org.mockito.Mockito.eq; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.hardware.usb.flags.Flags; 31 32 import androidx.test.runner.AndroidJUnit4; 33 34 import com.android.dx.mockito.inline.extended.ExtendedMockito; 35 import com.android.internal.util.XmlUtils; 36 37 import org.junit.After; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.mockito.Mockito; 42 import org.mockito.MockitoSession; 43 import org.mockito.quality.Strictness; 44 import org.xmlpull.v1.XmlPullParser; 45 import org.xmlpull.v1.XmlPullParserFactory; 46 import org.xmlpull.v1.XmlSerializer; 47 48 import java.io.StringReader; 49 50 /** 51 * Unit tests for {@link android.hardware.usb.DeviceFilter}. 52 */ 53 @RunWith(AndroidJUnit4.class) 54 public class DeviceFilterTest { 55 56 private static final int VID = 10; 57 private static final int PID = 11; 58 private static final int CLASS = 12; 59 private static final int SUBCLASS = 13; 60 private static final int PROTOCOL = 14; 61 private static final String MANUFACTURER = "Google"; 62 private static final String PRODUCT = "Test"; 63 private static final String SERIAL_NO = "4AL23"; 64 private static final String INTERFACE_NAME = "MTP"; 65 66 private MockitoSession mStaticMockSession; 67 68 @Before setUp()69 public void setUp() throws Exception { 70 mStaticMockSession = ExtendedMockito.mockitoSession() 71 .mockStatic(Flags.class) 72 .strictness(Strictness.WARN) 73 .startMocking(); 74 75 when(Flags.enableInterfaceNameDeviceFilter()).thenReturn(true); 76 } 77 78 @After tearDown()79 public void tearDown() throws Exception { 80 mStaticMockSession.finishMocking(); 81 } 82 83 @Test testConstructorFromValues_interfaceNameIsInitialized()84 public void testConstructorFromValues_interfaceNameIsInitialized() { 85 DeviceFilter deviceFilter = new DeviceFilter( 86 VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER, 87 PRODUCT, SERIAL_NO, INTERFACE_NAME 88 ); 89 90 verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter); 91 assertThat(deviceFilter.mInterfaceName).isEqualTo(INTERFACE_NAME); 92 } 93 94 @Test testConstructorFromUsbDevice_interfaceNameIsNull()95 public void testConstructorFromUsbDevice_interfaceNameIsNull() { 96 UsbDevice usbDevice = Mockito.mock(UsbDevice.class); 97 when(usbDevice.getVendorId()).thenReturn(VID); 98 when(usbDevice.getProductId()).thenReturn(PID); 99 when(usbDevice.getDeviceClass()).thenReturn(CLASS); 100 when(usbDevice.getDeviceSubclass()).thenReturn(SUBCLASS); 101 when(usbDevice.getDeviceProtocol()).thenReturn(PROTOCOL); 102 when(usbDevice.getManufacturerName()).thenReturn(MANUFACTURER); 103 when(usbDevice.getProductName()).thenReturn(PRODUCT); 104 when(usbDevice.getSerialNumber()).thenReturn(SERIAL_NO); 105 106 DeviceFilter deviceFilter = new DeviceFilter(usbDevice); 107 108 verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter); 109 assertThat(deviceFilter.mInterfaceName).isEqualTo(null); 110 } 111 112 @Test testConstructorFromDeviceFilter_interfaceNameIsInitialized()113 public void testConstructorFromDeviceFilter_interfaceNameIsInitialized() { 114 DeviceFilter originalDeviceFilter = new DeviceFilter( 115 VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER, 116 PRODUCT, SERIAL_NO, INTERFACE_NAME 117 ); 118 119 DeviceFilter deviceFilter = new DeviceFilter(originalDeviceFilter); 120 121 verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter); 122 assertThat(deviceFilter.mInterfaceName).isEqualTo(INTERFACE_NAME); 123 } 124 125 126 @Test testReadFromXml_interfaceNamePresent_propertyIsInitialized()127 public void testReadFromXml_interfaceNamePresent_propertyIsInitialized() throws Exception { 128 DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device interface-name=\"MTP\"/>"); 129 130 assertThat(deviceFilter.mInterfaceName).isEqualTo("MTP"); 131 } 132 133 @Test testReadFromXml_interfaceNameAbsent_propertyIsNull()134 public void testReadFromXml_interfaceNameAbsent_propertyIsNull() throws Exception { 135 DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device vendor-id=\"1\" />"); 136 137 assertThat(deviceFilter.mInterfaceName).isEqualTo(null); 138 } 139 140 @Test testWrite_withInterfaceName()141 public void testWrite_withInterfaceName() throws Exception { 142 DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device interface-name=\"MTP\"/>"); 143 XmlSerializer serializer = Mockito.mock(XmlSerializer.class); 144 145 deviceFilter.write(serializer); 146 147 verify(serializer).attribute(null, "interface-name", "MTP"); 148 } 149 150 @Test testWrite_withoutInterfaceName()151 public void testWrite_withoutInterfaceName() throws Exception { 152 DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device vendor-id=\"1\" />"); 153 XmlSerializer serializer = Mockito.mock(XmlSerializer.class); 154 155 deviceFilter.write(serializer); 156 157 verify(serializer, times(0)).attribute(eq(null), eq("interface-name"), any()); 158 } 159 160 @Test testToString()161 public void testToString() { 162 DeviceFilter deviceFilter = new DeviceFilter( 163 VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER, 164 PRODUCT, SERIAL_NO, INTERFACE_NAME 165 ); 166 167 assertThat(deviceFilter.toString()).isEqualTo( 168 "DeviceFilter[mVendorId=10,mProductId=11,mClass=12,mSubclass=13,mProtocol=14," 169 + "mManufacturerName=Google,mProductName=Test,mSerialNumber=4AL23," 170 + "mInterfaceName=MTP]"); 171 } 172 173 @Test testMatch_interfaceNameMatches_returnTrue()174 public void testMatch_interfaceNameMatches_returnTrue() throws Exception { 175 DeviceFilter deviceFilter = getDeviceFilterFromXml( 176 "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" " 177 + "interface-name=\"MTP\"/>"); 178 UsbDevice usbDevice = Mockito.mock(UsbDevice.class); 179 when(usbDevice.getInterfaceCount()).thenReturn(1); 180 when(usbDevice.getInterface(0)).thenReturn(new UsbInterface( 181 /* id= */ 0, 182 /* alternateSetting= */ 0, 183 /* name= */ "MTP", 184 /* class= */ 255, 185 /* subClass= */ 255, 186 /* protocol= */ 0)); 187 188 assertTrue(deviceFilter.matches(usbDevice)); 189 } 190 191 @Test testMatch_interfaceNameMismatch_returnFalse()192 public void testMatch_interfaceNameMismatch_returnFalse() throws Exception { 193 DeviceFilter deviceFilter = getDeviceFilterFromXml( 194 "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" " 195 + "interface-name=\"MTP\"/>"); 196 UsbDevice usbDevice = Mockito.mock(UsbDevice.class); 197 when(usbDevice.getInterfaceCount()).thenReturn(1); 198 when(usbDevice.getInterface(0)).thenReturn(new UsbInterface( 199 /* id= */ 0, 200 /* alternateSetting= */ 0, 201 /* name= */ "UVC", 202 /* class= */ 255, 203 /* subClass= */ 255, 204 /* protocol= */ 0)); 205 206 assertFalse(deviceFilter.matches(usbDevice)); 207 } 208 209 @Test testMatch_interfaceNameMismatchFlagDisabled_returnTrue()210 public void testMatch_interfaceNameMismatchFlagDisabled_returnTrue() throws Exception { 211 when(Flags.enableInterfaceNameDeviceFilter()).thenReturn(false); 212 DeviceFilter deviceFilter = getDeviceFilterFromXml( 213 "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" " 214 + "interface-name=\"MTP\"/>"); 215 UsbDevice usbDevice = Mockito.mock(UsbDevice.class); 216 when(usbDevice.getInterfaceCount()).thenReturn(1); 217 when(usbDevice.getInterface(0)).thenReturn(new UsbInterface( 218 /* id= */ 0, 219 /* alternateSetting= */ 0, 220 /* name= */ "UVC", 221 /* class= */ 255, 222 /* subClass= */ 255, 223 /* protocol= */ 0)); 224 225 assertTrue(deviceFilter.matches(usbDevice)); 226 } 227 verifyDeviceFilterConfigurationExceptInterfaceName(DeviceFilter deviceFilter)228 private void verifyDeviceFilterConfigurationExceptInterfaceName(DeviceFilter deviceFilter) { 229 assertThat(deviceFilter.mVendorId).isEqualTo(VID); 230 assertThat(deviceFilter.mProductId).isEqualTo(PID); 231 assertThat(deviceFilter.mClass).isEqualTo(CLASS); 232 assertThat(deviceFilter.mSubclass).isEqualTo(SUBCLASS); 233 assertThat(deviceFilter.mProtocol).isEqualTo(PROTOCOL); 234 assertThat(deviceFilter.mManufacturerName).isEqualTo(MANUFACTURER); 235 assertThat(deviceFilter.mProductName).isEqualTo(PRODUCT); 236 assertThat(deviceFilter.mSerialNumber).isEqualTo(SERIAL_NO); 237 } 238 getDeviceFilterFromXml(String xml)239 private DeviceFilter getDeviceFilterFromXml(String xml) throws Exception { 240 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 241 XmlPullParser parser = factory.newPullParser(); 242 parser.setInput(new StringReader(xml)); 243 XmlUtils.nextElement(parser); 244 245 return DeviceFilter.read(parser); 246 } 247 248 } 249