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