1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.M; 4 import static android.os.Build.VERSION_CODES.N; 5 import static android.os.Build.VERSION_CODES.N_MR1; 6 import static android.os.Build.VERSION_CODES.O; 7 import static android.os.Build.VERSION_CODES.P; 8 import static android.os.Build.VERSION_CODES.Q; 9 import static com.google.common.truth.Truth.assertThat; 10 import static org.mockito.Mockito.when; 11 import static org.robolectric.Shadows.shadowOf; 12 import static org.robolectric.util.ReflectionHelpers.getStaticField; 13 import static org.robolectric.util.reflector.Reflector.reflector; 14 15 import android.app.Activity; 16 import android.content.Context; 17 import android.hardware.usb.UsbAccessory; 18 import android.hardware.usb.UsbDevice; 19 import android.hardware.usb.UsbDeviceConnection; 20 import android.hardware.usb.UsbManager; 21 import android.hardware.usb.UsbPort; 22 import android.hardware.usb.UsbPortStatus; 23 import android.os.Build; 24 import android.os.ParcelFileDescriptor; 25 import androidx.test.core.app.ApplicationProvider; 26 import androidx.test.ext.junit.runners.AndroidJUnit4; 27 import java.util.Arrays; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.stream.Collectors; 31 import org.junit.Before; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.mockito.Mock; 35 import org.mockito.MockitoAnnotations; 36 import org.robolectric.Robolectric; 37 import org.robolectric.RuntimeEnvironment; 38 import org.robolectric.annotation.Config; 39 import org.robolectric.shadows.ShadowUsbManager._UsbManagerQ_; 40 import org.robolectric.shadows.ShadowUsbManager._UsbManager_; 41 42 /** Unit tests for {@link ShadowUsbManager}. */ 43 @RunWith(AndroidJUnit4.class) 44 public class ShadowUsbManagerTest { 45 private static final String DEVICE_NAME_1 = "usb1"; 46 private static final String DEVICE_NAME_2 = "usb2"; 47 48 private UsbManager usbManager; 49 50 @Mock UsbDevice usbDevice1; 51 @Mock UsbDevice usbDevice2; 52 @Mock UsbAccessory usbAccessory; 53 54 @Before setUp()55 public void setUp() { 56 MockitoAnnotations.initMocks(this); 57 usbManager = 58 (UsbManager) 59 ApplicationProvider.getApplicationContext().getSystemService(Context.USB_SERVICE); 60 61 when(usbDevice1.getDeviceName()).thenReturn(DEVICE_NAME_1); 62 when(usbDevice2.getDeviceName()).thenReturn(DEVICE_NAME_2); 63 } 64 65 @Test getDeviceList()66 public void getDeviceList() { 67 assertThat(usbManager.getDeviceList()).isEmpty(); 68 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice1, true); 69 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice2, true); 70 assertThat(usbManager.getDeviceList().values()).containsExactly(usbDevice1, usbDevice2); 71 } 72 73 @Test hasPermission_device()74 public void hasPermission_device() { 75 assertThat(usbManager.hasPermission(usbDevice1)).isFalse(); 76 77 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice1, false); 78 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice2, false); 79 80 assertThat(usbManager.hasPermission(usbDevice1)).isFalse(); 81 assertThat(usbManager.hasPermission(usbDevice2)).isFalse(); 82 83 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice1, true); 84 85 assertThat(usbManager.hasPermission(usbDevice1)).isTrue(); 86 assertThat(usbManager.hasPermission(usbDevice2)).isFalse(); 87 } 88 89 @Test hasPermission_accessory()90 public void hasPermission_accessory() { 91 assertThat(usbManager.hasPermission(usbAccessory)).isFalse(); 92 shadowOf(usbManager).setAttachedUsbAccessory(usbAccessory); 93 assertThat(usbManager.hasPermission(usbAccessory)).isFalse(); 94 shadowOf(usbManager).grantPermission(usbAccessory); 95 assertThat(usbManager.hasPermission(usbAccessory)).isTrue(); 96 shadowOf(usbManager) 97 .revokePermission(usbAccessory, RuntimeEnvironment.getApplication().getPackageName()); 98 assertThat(usbManager.hasPermission(usbAccessory)).isFalse(); 99 } 100 101 @Test 102 @Config(minSdk = N) grantPermission_selfPackage_shouldHavePermission()103 public void grantPermission_selfPackage_shouldHavePermission() { 104 usbManager.grantPermission(usbDevice1); 105 106 assertThat(usbManager.hasPermission(usbDevice1)).isTrue(); 107 } 108 109 @Test 110 @Config(minSdk = N_MR1) grantPermission_differentPackage_shouldHavePermission()111 public void grantPermission_differentPackage_shouldHavePermission() { 112 usbManager.grantPermission(usbDevice1, "foo.bar"); 113 114 assertThat(shadowOf(usbManager).hasPermissionForPackage(usbDevice1, "foo.bar")).isTrue(); 115 } 116 117 @Test 118 @Config(minSdk = N_MR1) revokePermission_shouldNotHavePermission()119 public void revokePermission_shouldNotHavePermission() { 120 usbManager.grantPermission(usbDevice1, "foo.bar"); 121 assertThat(shadowOf(usbManager).hasPermissionForPackage(usbDevice1, "foo.bar")).isTrue(); 122 123 shadowOf(usbManager).revokePermission(usbDevice1, "foo.bar"); 124 125 assertThat(shadowOf(usbManager).hasPermissionForPackage(usbDevice1, "foo.bar")).isFalse(); 126 } 127 128 @Test 129 @Config(minSdk = M, maxSdk = P) getPorts_shouldReturnAddedPorts()130 public void getPorts_shouldReturnAddedPorts() { 131 shadowOf(usbManager).addPort("port1"); 132 shadowOf(usbManager).addPort("port2"); 133 shadowOf(usbManager).addPort("port3"); 134 135 List<UsbPort> usbPorts = getUsbPorts(); 136 assertThat(usbPorts).hasSize(3); 137 assertThat(usbPorts.stream().map(UsbPort::getId).collect(Collectors.toList())) 138 .containsExactly("port1", "port2", "port3"); 139 } 140 141 @Test 142 @Config(minSdk = Q) getPortStatus_shouldReturnStatusForCorrespondingPort()143 public void getPortStatus_shouldReturnStatusForCorrespondingPort() { 144 shadowOf(usbManager).addPort("port1"); 145 shadowOf(usbManager).addPort("port2"); 146 shadowOf(usbManager) 147 .addPort( 148 "port3", 149 UsbPortStatus.MODE_DUAL, 150 UsbPortStatus.POWER_ROLE_SINK, 151 UsbPortStatus.DATA_ROLE_DEVICE, 152 /* statusSupportedRoleCombinations= */ 0); 153 154 UsbPortStatus portStatus = (UsbPortStatus) shadowOf(usbManager).getPortStatus("port3"); 155 assertThat(portStatus.getCurrentMode()).isEqualTo(UsbPortStatus.MODE_DUAL); 156 assertThat(portStatus.getCurrentPowerRole()).isEqualTo(UsbPortStatus.POWER_ROLE_SINK); 157 assertThat(portStatus.getCurrentDataRole()).isEqualTo(UsbPortStatus.DATA_ROLE_DEVICE); 158 assertThat(portStatus.getSupportedRoleCombinations()).isEqualTo(0); 159 } 160 161 @Test 162 @Config(minSdk = M) clearPorts_shouldRemoveAllPorts()163 public void clearPorts_shouldRemoveAllPorts() { 164 shadowOf(usbManager).addPort("port1"); 165 shadowOf(usbManager).clearPorts(); 166 167 List<UsbPort> usbPorts = getUsbPorts(); 168 assertThat(usbPorts).isEmpty(); 169 } 170 171 @Test 172 @Config(minSdk = M, maxSdk = P) setPortRoles_sinkHost_shouldSetPortStatus()173 public void setPortRoles_sinkHost_shouldSetPortStatus() { 174 final int powerRoleSink = getStaticField(UsbPort.class, "POWER_ROLE_SINK"); 175 final int dataRoleHost = getStaticField(UsbPort.class, "DATA_ROLE_HOST"); 176 177 shadowOf(usbManager).addPort("port1"); 178 179 List<UsbPort> usbPorts = getUsbPorts(); 180 181 _usbManager_().setPortRoles(usbPorts.get(0), powerRoleSink, dataRoleHost); 182 183 UsbPortStatus usbPortStatus = _usbManager_().getPortStatus(usbPorts.get(0)); 184 assertThat(usbPortStatus.getCurrentPowerRole()).isEqualTo(powerRoleSink); 185 assertThat(usbPortStatus.getCurrentDataRole()).isEqualTo(dataRoleHost); 186 } 187 188 @Test 189 @Config(minSdk = Q) setPortRoles_sinkHost_shouldSetPortStatus_Q()190 public void setPortRoles_sinkHost_shouldSetPortStatus_Q() { 191 shadowOf(usbManager).addPort("port1"); 192 193 List<UsbPort> usbPorts = getUsbPorts(); 194 _usbManager_() 195 .setPortRoles(usbPorts.get(0), UsbPortStatus.POWER_ROLE_SINK, UsbPortStatus.DATA_ROLE_HOST); 196 197 UsbPortStatus usbPortStatus = _usbManager_().getPortStatus(usbPorts.get(0)); 198 assertThat(usbPortStatus.getCurrentPowerRole()).isEqualTo(UsbPortStatus.POWER_ROLE_SINK); 199 assertThat(usbPortStatus.getCurrentDataRole()).isEqualTo(UsbPortStatus.DATA_ROLE_HOST); 200 } 201 202 @Test removeDevice()203 public void removeDevice() { 204 assertThat(usbManager.getDeviceList()).isEmpty(); 205 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice1, false); 206 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice2, false); 207 208 assertThat(usbManager.getDeviceList().values()).containsExactly(usbDevice1, usbDevice2); 209 210 shadowOf(usbManager).removeUsbDevice(usbDevice1); 211 assertThat(usbManager.getDeviceList().values()).containsExactly(usbDevice2); 212 } 213 214 @Test openDevice()215 public void openDevice() throws Exception { 216 shadowOf(usbManager).addOrUpdateUsbDevice(usbDevice1, true); 217 UsbDeviceConnection connection = usbManager.openDevice(usbDevice1); 218 assertThat(connection).isNotNull(); 219 } 220 221 @Test openAccessory()222 public void openAccessory() throws Exception { 223 try (ParcelFileDescriptor pfd = usbManager.openAccessory(usbAccessory)) { 224 assertThat(pfd).isNotNull(); 225 } 226 } 227 228 @Test setAccessory()229 public void setAccessory() { 230 assertThat(usbManager.getAccessoryList()).isNull(); 231 shadowOf(usbManager).setAttachedUsbAccessory(usbAccessory); 232 assertThat(usbManager.getAccessoryList()).hasLength(1); 233 assertThat(usbManager.getAccessoryList()[0]).isEqualTo(usbAccessory); 234 } 235 236 ///////////////////////// 237 getUsbPorts()238 private List<UsbPort> getUsbPorts() { 239 // return type changed from UsbPort[] to List<UsbPort> in Q... 240 if (RuntimeEnvironment.getApiLevel() >= Build.VERSION_CODES.Q) { 241 return reflector(_UsbManagerQ_.class, usbManager).getPorts(); 242 } 243 return Arrays.asList(_usbManager_().getPorts()); 244 } 245 _usbManager_()246 private _UsbManager_ _usbManager_() { 247 return reflector(_UsbManager_.class, usbManager); 248 } 249 250 @Test 251 @Config(minSdk = O) usbManager_activityContextEnabled_differentInstancesRetrieveSameUsbDevices()252 public void usbManager_activityContextEnabled_differentInstancesRetrieveSameUsbDevices() { 253 String originalProperty = System.getProperty("robolectric.createActivityContexts", ""); 254 System.setProperty("robolectric.createActivityContexts", "true"); 255 Activity activity = null; 256 try { 257 UsbManager applicationUsbManager = 258 ApplicationProvider.getApplicationContext().getSystemService(UsbManager.class); 259 activity = Robolectric.setupActivity(Activity.class); 260 UsbManager activityUsbManager = activity.getSystemService(UsbManager.class); 261 262 assertThat(applicationUsbManager).isNotSameInstanceAs(activityUsbManager); 263 264 HashMap<String, UsbDevice> applicationDevices = applicationUsbManager.getDeviceList(); 265 HashMap<String, UsbDevice> activityDevices = activityUsbManager.getDeviceList(); 266 267 assertThat(activityDevices).isEqualTo(applicationDevices); 268 } finally { 269 if (activity != null) { 270 activity.finish(); 271 } 272 System.setProperty("robolectric.createActivityContexts", originalProperty); 273 } 274 } 275 } 276