1 /* 2 * Copyright (C) 2015 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 android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED; 20 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED; 21 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED; 22 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED; 23 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE; 24 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST; 25 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE; 26 import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY; 27 import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY; 28 import static android.hardware.usb.UsbPortStatus.MODE_DFP; 29 import static android.hardware.usb.UsbPortStatus.MODE_DUAL; 30 import static android.hardware.usb.UsbPortStatus.MODE_NONE; 31 import static android.hardware.usb.UsbPortStatus.MODE_UFP; 32 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE; 33 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK; 34 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE; 35 36 import android.Manifest; 37 import android.annotation.NonNull; 38 import android.annotation.Nullable; 39 import android.annotation.RequiresPermission; 40 import android.annotation.SystemApi; 41 import android.hardware.usb.V1_0.Constants; 42 43 import com.android.internal.util.Preconditions; 44 45 /** 46 * Represents a physical USB port and describes its characteristics. 47 * 48 * @hide 49 */ 50 @SystemApi 51 public final class UsbPort { 52 private final String mId; 53 private final int mSupportedModes; 54 private final UsbManager mUsbManager; 55 private final int mSupportedContaminantProtectionModes; 56 private final boolean mSupportsEnableContaminantPresenceProtection; 57 private final boolean mSupportsEnableContaminantPresenceDetection; 58 59 private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; 60 /** 61 * Points to the first power role in the IUsb HAL. 62 */ 63 private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE; 64 65 /** @hide */ UsbPort(@onNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection)66 public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, 67 int supportedContaminantProtectionModes, 68 boolean supportsEnableContaminantPresenceProtection, 69 boolean supportsEnableContaminantPresenceDetection) { 70 Preconditions.checkNotNull(id); 71 Preconditions.checkFlagsArgument(supportedModes, 72 MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY); 73 74 mUsbManager = usbManager; 75 mId = id; 76 mSupportedModes = supportedModes; 77 mSupportedContaminantProtectionModes = supportedContaminantProtectionModes; 78 mSupportsEnableContaminantPresenceProtection = 79 supportsEnableContaminantPresenceProtection; 80 mSupportsEnableContaminantPresenceDetection = 81 supportsEnableContaminantPresenceDetection; 82 } 83 84 /** 85 * Gets the unique id of the port. 86 * 87 * @return The unique id of the port; not intended for display. 88 * 89 * @hide 90 */ getId()91 public String getId() { 92 return mId; 93 } 94 95 /** 96 * Gets the supported modes of the port. 97 * <p> 98 * The actual mode of the port may vary depending on what is plugged into it. 99 * </p> 100 * 101 * @return The supported modes: one of {@link UsbPortStatus#MODE_DFP}, 102 * {@link UsbPortStatus#MODE_UFP}, or {@link UsbPortStatus#MODE_DUAL}. 103 * 104 * @hide 105 */ getSupportedModes()106 public int getSupportedModes() { 107 return mSupportedModes; 108 } 109 110 /** 111 * Gets the supported port proctection modes when the port is contaminated. 112 * <p> 113 * The actual mode of the port is decided by the hardware 114 * </p> 115 * 116 * @hide 117 */ getSupportedContaminantProtectionModes()118 public int getSupportedContaminantProtectionModes() { 119 return mSupportedContaminantProtectionModes; 120 } 121 122 /** 123 * Tells if UsbService can enable/disable contaminant presence protection. 124 * 125 * @hide 126 */ supportsEnableContaminantPresenceProtection()127 public boolean supportsEnableContaminantPresenceProtection() { 128 return mSupportsEnableContaminantPresenceProtection; 129 } 130 131 /** 132 * Tells if UsbService can enable/disable contaminant presence detection. 133 * 134 * @hide 135 */ supportsEnableContaminantPresenceDetection()136 public boolean supportsEnableContaminantPresenceDetection() { 137 return mSupportsEnableContaminantPresenceDetection; 138 } 139 140 /** 141 * Gets the status of this USB port. 142 * 143 * @return The status of the this port, or {@code null} if port is unknown. 144 */ 145 @RequiresPermission(Manifest.permission.MANAGE_USB) getStatus()146 public @Nullable UsbPortStatus getStatus() { 147 return mUsbManager.getPortStatus(this); 148 } 149 150 /** 151 * Sets the desired role combination of the port. 152 * <p> 153 * The supported role combinations depend on what is connected to the port and may be 154 * determined by consulting 155 * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}. 156 * </p><p> 157 * Note: This function is asynchronous and may fail silently without applying 158 * the requested changes. If this function does cause a status change to occur then 159 * a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent. 160 * </p> 161 * 162 * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} or 163 * {@link UsbPortStatus#POWER_ROLE_SINK}, or 164 * {@link UsbPortStatus#POWER_ROLE_NONE} if no power role. 165 * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} or 166 * {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 167 * {@link UsbPortStatus#DATA_ROLE_NONE} if no data role. 168 */ 169 @RequiresPermission(Manifest.permission.MANAGE_USB) setRoles(@sbPortStatus.UsbPowerRole int powerRole, @UsbPortStatus.UsbDataRole int dataRole)170 public void setRoles(@UsbPortStatus.UsbPowerRole int powerRole, 171 @UsbPortStatus.UsbDataRole int dataRole) { 172 UsbPort.checkRoles(powerRole, dataRole); 173 174 mUsbManager.setPortRoles(this, powerRole, dataRole); 175 } 176 177 /** 178 * @hide 179 **/ enableContaminantDetection(boolean enable)180 public void enableContaminantDetection(boolean enable) { 181 mUsbManager.enableContaminantDetection(this, enable); 182 } 183 /** 184 * Combines one power and one data role together into a unique value with 185 * exactly one bit set. This can be used to efficiently determine whether 186 * a combination of roles is supported by testing whether that bit is present 187 * in a bit-field. 188 * 189 * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} 190 * or {@link UsbPortStatus#POWER_ROLE_SINK}, or 0 if no power role. 191 * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} 192 * or {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 0 if no data role. 193 * @hide 194 */ combineRolesAsBit(int powerRole, int dataRole)195 public static int combineRolesAsBit(int powerRole, int dataRole) { 196 checkRoles(powerRole, dataRole); 197 final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole; 198 return 1 << index; 199 } 200 201 /** @hide */ modeToString(int mode)202 public static String modeToString(int mode) { 203 StringBuilder modeString = new StringBuilder(); 204 if (mode == MODE_NONE) { 205 return "none"; 206 } 207 208 if ((mode & MODE_DUAL) == MODE_DUAL) { 209 modeString.append("dual, "); 210 } else { 211 if ((mode & MODE_DFP) == MODE_DFP) { 212 modeString.append("dfp, "); 213 } else if ((mode & MODE_UFP) == MODE_UFP) { 214 modeString.append("ufp, "); 215 } 216 } 217 if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) { 218 modeString.append("audio_acc, "); 219 } 220 if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) { 221 modeString.append("debug_acc, "); 222 } 223 224 if (modeString.length() == 0) { 225 return Integer.toString(mode); 226 } 227 return modeString.substring(0, modeString.length() - 2); 228 } 229 230 /** @hide */ powerRoleToString(int role)231 public static String powerRoleToString(int role) { 232 switch (role) { 233 case POWER_ROLE_NONE: 234 return "no-power"; 235 case POWER_ROLE_SOURCE: 236 return "source"; 237 case POWER_ROLE_SINK: 238 return "sink"; 239 default: 240 return Integer.toString(role); 241 } 242 } 243 244 /** @hide */ dataRoleToString(int role)245 public static String dataRoleToString(int role) { 246 switch (role) { 247 case DATA_ROLE_NONE: 248 return "no-data"; 249 case DATA_ROLE_HOST: 250 return "host"; 251 case DATA_ROLE_DEVICE: 252 return "device"; 253 default: 254 return Integer.toString(role); 255 } 256 } 257 258 /** @hide */ contaminantPresenceStatusToString(int contaminantPresenceStatus)259 public static String contaminantPresenceStatusToString(int contaminantPresenceStatus) { 260 switch (contaminantPresenceStatus) { 261 case CONTAMINANT_DETECTION_NOT_SUPPORTED: 262 return "not-supported"; 263 case CONTAMINANT_DETECTION_DISABLED: 264 return "disabled"; 265 case CONTAMINANT_DETECTION_DETECTED: 266 return "detected"; 267 case CONTAMINANT_DETECTION_NOT_DETECTED: 268 return "not detected"; 269 default: 270 return Integer.toString(contaminantPresenceStatus); 271 } 272 } 273 274 /** @hide */ roleCombinationsToString(int combo)275 public static String roleCombinationsToString(int combo) { 276 StringBuilder result = new StringBuilder(); 277 result.append("["); 278 279 boolean first = true; 280 while (combo != 0) { 281 final int index = Integer.numberOfTrailingZeros(combo); 282 combo &= ~(1 << index); 283 final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET); 284 final int dataRole = index % NUM_DATA_ROLES; 285 if (first) { 286 first = false; 287 } else { 288 result.append(", "); 289 } 290 result.append(powerRoleToString(powerRole)); 291 result.append(':'); 292 result.append(dataRoleToString(dataRole)); 293 } 294 295 result.append("]"); 296 return result.toString(); 297 } 298 299 /** @hide */ checkMode(int powerRole)300 public static void checkMode(int powerRole) { 301 Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE, 302 Constants.PortMode.NUM_MODES - 1, "portMode"); 303 } 304 305 /** @hide */ checkPowerRole(int dataRole)306 public static void checkPowerRole(int dataRole) { 307 Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE, 308 Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole"); 309 } 310 311 /** @hide */ checkDataRole(int mode)312 public static void checkDataRole(int mode) { 313 Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE, 314 Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole"); 315 } 316 317 /** @hide */ checkRoles(int powerRole, int dataRole)318 public static void checkRoles(int powerRole, int dataRole) { 319 Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK, 320 "powerRole"); 321 Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole"); 322 } 323 324 /** @hide */ isModeSupported(int mode)325 public boolean isModeSupported(int mode) { 326 if ((mSupportedModes & mode) == mode) return true; 327 return false; 328 } 329 330 @NonNull 331 @Override toString()332 public String toString() { 333 return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) 334 + "supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes 335 + "supportsEnableContaminantPresenceProtection=" 336 + mSupportsEnableContaminantPresenceProtection 337 + "supportsEnableContaminantPresenceDetection=" 338 + mSupportsEnableContaminantPresenceDetection; 339 } 340 } 341