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.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL; 20 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_NOT_SUPPORTED; 21 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_PORT_MISMATCH; 22 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS; 23 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED; 24 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED; 25 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED; 26 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED; 27 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE; 28 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST; 29 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE; 30 import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY; 31 import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY; 32 import static android.hardware.usb.UsbPortStatus.MODE_DFP; 33 import static android.hardware.usb.UsbPortStatus.MODE_DUAL; 34 import static android.hardware.usb.UsbPortStatus.MODE_NONE; 35 import static android.hardware.usb.UsbPortStatus.MODE_UFP; 36 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_DISCONNECTED; 37 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN; 38 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_CONNECTED; 39 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE; 40 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK; 41 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE; 42 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_UNKNOWN; 43 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_ENABLED; 44 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_OVERHEAT; 45 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_CONTAMINANT; 46 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK; 47 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE; 48 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DEBUG; 49 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK_HOST_MODE; 50 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK_DEVICE_MODE; 51 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY; 52 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_BC_1_2; 53 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP; 54 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_OTHER; 55 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED; 56 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES; 57 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL; 58 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION; 59 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO; 60 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; 61 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE; 62 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED; 63 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_ENABLED; 64 65 import android.Manifest; 66 import android.annotation.CallbackExecutor; 67 import android.annotation.CheckResult; 68 import android.annotation.FlaggedApi; 69 import android.annotation.IntDef; 70 import android.annotation.NonNull; 71 import android.annotation.Nullable; 72 import android.annotation.RequiresPermission; 73 import android.annotation.SystemApi; 74 import android.annotation.TestApi; 75 import android.hardware.usb.flags.Flags; 76 import android.hardware.usb.UsbOperationInternal; 77 import android.hardware.usb.V1_0.Constants; 78 import android.os.Binder; 79 import android.util.Log; 80 81 import com.android.internal.util.Preconditions; 82 83 import java.lang.annotation.Retention; 84 import java.lang.annotation.RetentionPolicy; 85 import java.util.Objects; 86 import java.util.concurrent.atomic.AtomicInteger; 87 import java.util.concurrent.Executor; 88 import java.util.function.Consumer; 89 90 /** 91 * Represents a physical USB port and describes its characteristics. 92 * 93 * @hide 94 */ 95 @SystemApi 96 public final class UsbPort { 97 private static final String TAG = "UsbPort"; 98 private final String mId; 99 private final int mSupportedModes; 100 private final UsbManager mUsbManager; 101 private final int mSupportedContaminantProtectionModes; 102 private final boolean mSupportsEnableContaminantPresenceProtection; 103 private final boolean mSupportsEnableContaminantPresenceDetection; 104 private final boolean mSupportsComplianceWarnings; 105 private final @AltModeType int mSupportedAltModes; 106 107 private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; 108 /** 109 * Points to the first power role in the IUsb HAL. 110 */ 111 private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE; 112 113 /** 114 * Counter for tracking UsbOperation operations. 115 */ 116 private static final AtomicInteger sUsbOperationCount = new AtomicInteger(); 117 118 /** 119 * The {@link #enableUsbData} request was successfully completed. 120 */ 121 public static final int ENABLE_USB_DATA_SUCCESS = 0; 122 123 /** 124 * The {@link #enableUsbData} request failed due to internal error. 125 */ 126 public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1; 127 128 /** 129 * The {@link #enableUsbData} request failed as it's not supported. 130 */ 131 public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2; 132 133 /** 134 * The {@link #enableUsbData} request failed as port id mismatched. 135 */ 136 public static final int ENABLE_USB_DATA_ERROR_PORT_MISMATCH = 3; 137 138 /** 139 * The {@link #enableUsbData} request failed due to other reasons. 140 */ 141 public static final int ENABLE_USB_DATA_ERROR_OTHER = 4; 142 143 /** @hide */ 144 @IntDef(prefix = { "ENABLE_USB_DATA_" }, value = { 145 ENABLE_USB_DATA_SUCCESS, 146 ENABLE_USB_DATA_ERROR_INTERNAL, 147 ENABLE_USB_DATA_ERROR_NOT_SUPPORTED, 148 ENABLE_USB_DATA_ERROR_PORT_MISMATCH, 149 ENABLE_USB_DATA_ERROR_OTHER 150 }) 151 @Retention(RetentionPolicy.SOURCE) 152 @interface EnableUsbDataStatus{} 153 154 /** 155 * The {@link #enableLimitPowerTransfer} request was successfully completed. 156 */ 157 public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0; 158 159 /** 160 * The {@link #enableLimitPowerTransfer} request failed due to internal error. 161 */ 162 public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1; 163 164 /** 165 * The {@link #enableLimitPowerTransfer} request failed as it's not supported. 166 */ 167 public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2; 168 169 /** 170 * The {@link #enableLimitPowerTransfer} request failed as port id mismatched. 171 */ 172 public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3; 173 174 /** 175 * The {@link #enableLimitPowerTransfer} request failed due to other reasons. 176 */ 177 public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4; 178 179 /** @hide */ 180 @IntDef(prefix = { "ENABLE_LIMIT_POWER_TRANSFER_" }, value = { 181 ENABLE_LIMIT_POWER_TRANSFER_SUCCESS, 182 ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL, 183 ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED, 184 ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH, 185 ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER 186 }) 187 @Retention(RetentionPolicy.SOURCE) 188 @interface EnableLimitPowerTransferStatus{} 189 190 /** 191 * The {@link #enableUsbDataWhileDocked} request was successfully completed. 192 */ 193 public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0; 194 195 /** 196 * The {@link #enableUsbDataWhileDocked} request failed due to internal error. 197 */ 198 public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL = 1; 199 200 /** 201 * The {@link #enableUsbDataWhileDocked} request failed as it's not supported. 202 */ 203 public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED = 2; 204 205 /** 206 * The {@link #enableUsbDataWhileDocked} request failed as port id mismatched. 207 */ 208 public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3; 209 210 /** 211 * The {@link #enableUsbDataWhileDocked} request failed as data is still enabled. 212 */ 213 public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED = 4; 214 215 /** 216 * The {@link #enableUsbDataWhileDocked} request failed due to other reasons. 217 */ 218 public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; 219 220 /** 221 * The {@link #resetUsbPort} request was successfully completed. 222 */ 223 public static final int RESET_USB_PORT_SUCCESS = 0; 224 225 /** 226 * The {@link #resetUsbPort} request failed due to internal error. 227 */ 228 public static final int RESET_USB_PORT_ERROR_INTERNAL = 1; 229 230 /** 231 * The {@link #resetUsbPort} request failed as it's not supported. 232 */ 233 public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2; 234 235 /** 236 * The {@link #resetUsbPort} request failed as port id mismatched. 237 */ 238 public static final int RESET_USB_PORT_ERROR_PORT_MISMATCH = 3; 239 240 /** 241 * The {@link #resetUsbPort} request failed due to other reasons. 242 */ 243 public static final int RESET_USB_PORT_ERROR_OTHER = 4; 244 245 /** @hide */ 246 @IntDef(prefix = { "RESET_USB_PORT_" }, value = { 247 RESET_USB_PORT_SUCCESS, 248 RESET_USB_PORT_ERROR_INTERNAL, 249 RESET_USB_PORT_ERROR_NOT_SUPPORTED, 250 RESET_USB_PORT_ERROR_PORT_MISMATCH, 251 RESET_USB_PORT_ERROR_OTHER 252 }) 253 @Retention(RetentionPolicy.SOURCE) 254 @interface ResetUsbPortStatus{} 255 256 /** @hide */ 257 @IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = { 258 ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS, 259 ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL, 260 ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED, 261 ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH, 262 ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED, 263 ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER 264 }) 265 @Retention(RetentionPolicy.SOURCE) 266 @interface EnableUsbDataWhileDockedStatus{} 267 268 /** 269 * Indicates that the Alt Mode being described is DisplayPort. 270 */ 271 public static final int FLAG_ALT_MODE_TYPE_DISPLAYPORT = 1 << 0; 272 273 /** @hide */ 274 @IntDef(prefix = { "FLAG_ALT_MODE_TYPE_" }, flag = true, value = { 275 FLAG_ALT_MODE_TYPE_DISPLAYPORT, 276 }) 277 @Retention(RetentionPolicy.SOURCE) 278 public @interface AltModeType {} 279 280 /** @hide */ UsbPort(@onNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection)281 public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, 282 int supportedContaminantProtectionModes, 283 boolean supportsEnableContaminantPresenceProtection, 284 boolean supportsEnableContaminantPresenceDetection) { 285 this(usbManager, id, supportedModes, supportedContaminantProtectionModes, 286 supportsEnableContaminantPresenceProtection, 287 supportsEnableContaminantPresenceDetection, 288 false, 0); 289 } 290 291 /** @hide */ UsbPort(@onNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection, boolean supportsComplianceWarnings, int supportedAltModes)292 public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, 293 int supportedContaminantProtectionModes, 294 boolean supportsEnableContaminantPresenceProtection, 295 boolean supportsEnableContaminantPresenceDetection, 296 boolean supportsComplianceWarnings, 297 int supportedAltModes) { 298 Objects.requireNonNull(id); 299 Preconditions.checkFlagsArgument(supportedModes, 300 MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY); 301 302 mUsbManager = usbManager; 303 mId = id; 304 mSupportedModes = supportedModes; 305 mSupportedContaminantProtectionModes = supportedContaminantProtectionModes; 306 mSupportsEnableContaminantPresenceProtection = 307 supportsEnableContaminantPresenceProtection; 308 mSupportsEnableContaminantPresenceDetection = 309 supportsEnableContaminantPresenceDetection; 310 mSupportsComplianceWarnings = supportsComplianceWarnings; 311 mSupportedAltModes = supportedAltModes; 312 } 313 314 /** 315 * Gets the unique id of the port. 316 * 317 * @return The unique id of the port; not intended for display. 318 * 319 * @hide 320 */ getId()321 public String getId() { 322 return mId; 323 } 324 325 /** 326 * Gets the supported modes of the port. 327 * <p> 328 * The actual mode of the port may vary depending on what is plugged into it. 329 * </p> 330 * 331 * @return The supported modes: one of {@link UsbPortStatus#MODE_DFP}, 332 * {@link UsbPortStatus#MODE_UFP}, or {@link UsbPortStatus#MODE_DUAL}. 333 * 334 * @hide 335 */ getSupportedModes()336 public int getSupportedModes() { 337 return mSupportedModes; 338 } 339 340 /** 341 * Gets the supported port proctection modes when the port is contaminated. 342 * <p> 343 * The actual mode of the port is decided by the hardware 344 * </p> 345 * 346 * @hide 347 */ getSupportedContaminantProtectionModes()348 public int getSupportedContaminantProtectionModes() { 349 return mSupportedContaminantProtectionModes; 350 } 351 352 /** 353 * Tells if UsbService can enable/disable contaminant presence protection. 354 * 355 * @hide 356 */ supportsEnableContaminantPresenceProtection()357 public boolean supportsEnableContaminantPresenceProtection() { 358 return mSupportsEnableContaminantPresenceProtection; 359 } 360 361 /** 362 * Tells if UsbService can enable/disable contaminant presence detection. 363 * 364 * @hide 365 */ supportsEnableContaminantPresenceDetection()366 public boolean supportsEnableContaminantPresenceDetection() { 367 return mSupportsEnableContaminantPresenceDetection; 368 } 369 370 /** 371 * Gets the status of this USB port. 372 * 373 * @return The status of the this port, or {@code null} if port is unknown. 374 */ 375 @RequiresPermission(Manifest.permission.MANAGE_USB) getStatus()376 public @Nullable UsbPortStatus getStatus() { 377 return mUsbManager.getPortStatus(this); 378 } 379 380 /** 381 * Returns whether this USB port supports mode change 382 * 383 * @return true if mode change is supported. 384 * @hide 385 */ 386 @TestApi 387 @RequiresPermission(Manifest.permission.MANAGE_USB) 388 @FlaggedApi(Flags.FLAG_ENABLE_IS_MODE_CHANGE_SUPPORTED_API) isModeChangeSupported()389 public boolean isModeChangeSupported() { 390 return mUsbManager.isModeChangeSupported(this); 391 } 392 393 /** 394 * Queries USB Port to see if the port is capable of identifying 395 * non compliant USB power source/cable/accessory. 396 * 397 * @return true when the UsbPort is capable of identifying 398 * non compliant USB power 399 * source/cable/accessory. 400 * @return false otherwise. 401 */ 402 @CheckResult 403 @RequiresPermission(Manifest.permission.MANAGE_USB) supportsComplianceWarnings()404 public boolean supportsComplianceWarnings() { 405 return mSupportsComplianceWarnings; 406 } 407 408 /** 409 * Returns all Alt Modes supported by the port. 410 * 411 * @hide 412 */ getSupportedAltModesMask()413 public @AltModeType int getSupportedAltModesMask() { 414 return mSupportedAltModes; 415 } 416 417 /** 418 * Returns whether all Alt Mode types in a given mask are supported 419 * by the port. 420 * 421 * @return true if all given Alt Modes are supported, false otherwise. 422 * 423 */ isAltModeSupported(@ltModeType int typeMask)424 public boolean isAltModeSupported(@AltModeType int typeMask) { 425 return (mSupportedAltModes & typeMask) == typeMask; 426 } 427 428 429 /** 430 * Sets the desired role combination of the port. 431 * <p> 432 * The supported role combinations depend on what is connected to the port and may be 433 * determined by consulting 434 * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}. 435 * </p><p> 436 * Note: This function is asynchronous and may fail silently without applying 437 * the operationed changes. If this function does cause a status change to occur then 438 * a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent. 439 * </p> 440 * 441 * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} or 442 * {@link UsbPortStatus#POWER_ROLE_SINK}, or 443 * {@link UsbPortStatus#POWER_ROLE_NONE} if no power role. 444 * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} or 445 * {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 446 * {@link UsbPortStatus#DATA_ROLE_NONE} if no data role. 447 */ 448 @RequiresPermission(Manifest.permission.MANAGE_USB) setRoles(@sbPortStatus.UsbPowerRole int powerRole, @UsbPortStatus.UsbDataRole int dataRole)449 public void setRoles(@UsbPortStatus.UsbPowerRole int powerRole, 450 @UsbPortStatus.UsbDataRole int dataRole) { 451 UsbPort.checkRoles(powerRole, dataRole); 452 453 mUsbManager.setPortRoles(this, powerRole, dataRole); 454 } 455 456 /** 457 * Reset Usb data on the port. 458 * 459 * @param executor Executor for the callback. 460 * @param consumer A consumer that consumes the reset result. 461 * {@link #RESET_USB_PORT_SUCCESS} when request completes 462 * successfully or 463 * {@link #RESET_USB_PORT_ERROR_INTERNAL} when request 464 * fails due to internal error or 465 * {@link RESET_USB_PORT_ERROR_NOT_SUPPORTED} when not 466 * supported or 467 * {@link RESET_USB_PORT_ERROR_PORT_MISMATCH} when request 468 * fails due to port id mismatch or 469 * {@link RESET_USB_PORT_ERROR_OTHER} when fails due to 470 * other reasons. 471 */ 472 @CheckResult 473 @RequiresPermission(Manifest.permission.MANAGE_USB) resetUsbPort(@onNull @allbackExecutor Executor executor, @NonNull @ResetUsbPortStatus Consumer<Integer> consumer)474 public void resetUsbPort(@NonNull @CallbackExecutor Executor executor, 475 @NonNull @ResetUsbPortStatus Consumer<Integer> consumer) { 476 // UID is added To minimize operationID overlap between two different packages. 477 int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); 478 Log.i(TAG, "resetUsbPort opId:" + operationId); 479 UsbOperationInternal opCallback = 480 new UsbOperationInternal(operationId, mId, executor, consumer); 481 mUsbManager.resetUsbPort(this, operationId, opCallback); 482 } 483 484 /** 485 * Enables/Disables Usb data on the port. 486 * 487 * @param enable When true enables USB data if disabled. 488 * When false disables USB data if enabled. 489 * @return {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or 490 * {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal 491 * error or 492 * {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or 493 * {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id 494 * mismatch or 495 * {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons. 496 */ 497 @CheckResult 498 @RequiresPermission(Manifest.permission.MANAGE_USB) enableUsbData(boolean enable)499 public @EnableUsbDataStatus int enableUsbData(boolean enable) { 500 // UID is added To minimize operationID overlap between two different packages. 501 int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); 502 Log.i(TAG, "enableUsbData opId:" + operationId 503 + " callingUid:" + Binder.getCallingUid()); 504 UsbOperationInternal opCallback = 505 new UsbOperationInternal(operationId, mId); 506 if (mUsbManager.enableUsbData(this, enable, operationId, opCallback) == true) { 507 opCallback.waitForOperationComplete(); 508 } 509 510 int result = opCallback.getStatus(); 511 switch (result) { 512 case USB_OPERATION_SUCCESS: 513 return ENABLE_USB_DATA_SUCCESS; 514 case USB_OPERATION_ERROR_INTERNAL: 515 return ENABLE_USB_DATA_ERROR_INTERNAL; 516 case USB_OPERATION_ERROR_NOT_SUPPORTED: 517 return ENABLE_USB_DATA_ERROR_NOT_SUPPORTED; 518 case USB_OPERATION_ERROR_PORT_MISMATCH: 519 return ENABLE_USB_DATA_ERROR_PORT_MISMATCH; 520 default: 521 return ENABLE_USB_DATA_ERROR_OTHER; 522 } 523 } 524 525 /** 526 * Enables Usb data when disabled due to {@link UsbPort#DATA_STATUS_DISABLED_DOCK} 527 * 528 * @return {@link #ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS} when request completes successfully or 529 * {@link #ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL} when request fails due to 530 * internal error or 531 * {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED} when not supported or 532 * {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH} when request fails due to 533 * port id mismatch or 534 * {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED} when request fails as data 535 * is still enabled or 536 * {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER} when fails due to other reasons. 537 */ 538 @CheckResult 539 @RequiresPermission(Manifest.permission.MANAGE_USB) enableUsbDataWhileDocked()540 public @EnableUsbDataWhileDockedStatus int enableUsbDataWhileDocked() { 541 // UID is added To minimize operationID overlap between two different packages. 542 int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); 543 Log.i(TAG, "enableUsbData opId:" + operationId 544 + " callingUid:" + Binder.getCallingUid()); 545 UsbPortStatus portStatus = getStatus(); 546 if (portStatus != null && 547 (portStatus.getUsbDataStatus() & DATA_STATUS_DISABLED_DOCK) != 548 DATA_STATUS_DISABLED_DOCK) { 549 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED; 550 } 551 552 UsbOperationInternal opCallback = 553 new UsbOperationInternal(operationId, mId); 554 mUsbManager.enableUsbDataWhileDocked(this, operationId, opCallback); 555 opCallback.waitForOperationComplete(); 556 int result = opCallback.getStatus(); 557 switch (result) { 558 case USB_OPERATION_SUCCESS: 559 return ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS; 560 case USB_OPERATION_ERROR_INTERNAL: 561 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL; 562 case USB_OPERATION_ERROR_NOT_SUPPORTED: 563 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED; 564 case USB_OPERATION_ERROR_PORT_MISMATCH: 565 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH; 566 default: 567 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER; 568 } 569 } 570 571 /** 572 * Limits power transfer In and out of the port. 573 * <p> 574 * Disables charging and limits sourcing power(when permitted by the USB spec) until 575 * port disconnect event. 576 * </p> 577 * @param enable limits power transfer when true. 578 * @return {@link #ENABLE_LIMIT_POWER_TRANSFER_SUCCESS} when request completes successfully or 579 * {@link #ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL} when request fails due to 580 * internal error or 581 * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED} when not supported or 582 * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH} when request fails due to 583 * port id mismatch or 584 * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER} when fails due to other reasons. 585 */ 586 @CheckResult 587 @RequiresPermission(Manifest.permission.MANAGE_USB) enableLimitPowerTransfer(boolean enable)588 public @EnableLimitPowerTransferStatus int enableLimitPowerTransfer(boolean enable) { 589 // UID is added To minimize operationID overlap between two different packages. 590 int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); 591 Log.i(TAG, "enableLimitPowerTransfer opId:" + operationId 592 + " callingUid:" + Binder.getCallingUid()); 593 UsbOperationInternal opCallback = 594 new UsbOperationInternal(operationId, mId); 595 mUsbManager.enableLimitPowerTransfer(this, enable, operationId, opCallback); 596 opCallback.waitForOperationComplete(); 597 int result = opCallback.getStatus(); 598 switch (result) { 599 case USB_OPERATION_SUCCESS: 600 return ENABLE_LIMIT_POWER_TRANSFER_SUCCESS; 601 case USB_OPERATION_ERROR_INTERNAL: 602 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL; 603 case USB_OPERATION_ERROR_NOT_SUPPORTED: 604 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED; 605 case USB_OPERATION_ERROR_PORT_MISMATCH: 606 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH; 607 default: 608 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER; 609 } 610 } 611 612 /** 613 * @hide 614 **/ enableContaminantDetection(boolean enable)615 public void enableContaminantDetection(boolean enable) { 616 mUsbManager.enableContaminantDetection(this, enable); 617 } 618 /** 619 * Combines one power and one data role together into a unique value with 620 * exactly one bit set. This can be used to efficiently determine whether 621 * a combination of roles is supported by testing whether that bit is present 622 * in a bit-field. 623 * 624 * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} 625 * or {@link UsbPortStatus#POWER_ROLE_SINK}, or 0 if no power role. 626 * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} 627 * or {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 0 if no data role. 628 * @hide 629 */ combineRolesAsBit(int powerRole, int dataRole)630 public static int combineRolesAsBit(int powerRole, int dataRole) { 631 checkRoles(powerRole, dataRole); 632 final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole; 633 return 1 << index; 634 } 635 636 /** @hide */ modeToString(int mode)637 public static String modeToString(int mode) { 638 StringBuilder modeString = new StringBuilder(); 639 if (mode == MODE_NONE) { 640 return "none"; 641 } 642 643 if ((mode & MODE_DUAL) == MODE_DUAL) { 644 modeString.append("dual, "); 645 } else { 646 if ((mode & MODE_DFP) == MODE_DFP) { 647 modeString.append("dfp, "); 648 } else if ((mode & MODE_UFP) == MODE_UFP) { 649 modeString.append("ufp, "); 650 } 651 } 652 if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) { 653 modeString.append("audio_acc, "); 654 } 655 if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) { 656 modeString.append("debug_acc, "); 657 } 658 659 if (modeString.length() == 0) { 660 return Integer.toString(mode); 661 } 662 return modeString.substring(0, modeString.length() - 2); 663 } 664 665 /** @hide */ powerRoleToString(int role)666 public static String powerRoleToString(int role) { 667 switch (role) { 668 case POWER_ROLE_NONE: 669 return "no-power"; 670 case POWER_ROLE_SOURCE: 671 return "source"; 672 case POWER_ROLE_SINK: 673 return "sink"; 674 default: 675 return Integer.toString(role); 676 } 677 } 678 679 /** @hide */ dataRoleToString(int role)680 public static String dataRoleToString(int role) { 681 switch (role) { 682 case DATA_ROLE_NONE: 683 return "no-data"; 684 case DATA_ROLE_HOST: 685 return "host"; 686 case DATA_ROLE_DEVICE: 687 return "device"; 688 default: 689 return Integer.toString(role); 690 } 691 } 692 693 /** @hide */ contaminantPresenceStatusToString(int contaminantPresenceStatus)694 public static String contaminantPresenceStatusToString(int contaminantPresenceStatus) { 695 switch (contaminantPresenceStatus) { 696 case CONTAMINANT_DETECTION_NOT_SUPPORTED: 697 return "not-supported"; 698 case CONTAMINANT_DETECTION_DISABLED: 699 return "disabled"; 700 case CONTAMINANT_DETECTION_DETECTED: 701 return "detected"; 702 case CONTAMINANT_DETECTION_NOT_DETECTED: 703 return "not detected"; 704 default: 705 return Integer.toString(contaminantPresenceStatus); 706 } 707 } 708 709 /** @hide */ usbDataStatusToString(int usbDataStatus)710 public static String usbDataStatusToString(int usbDataStatus) { 711 StringBuilder statusString = new StringBuilder(); 712 713 if (usbDataStatus == DATA_STATUS_UNKNOWN) { 714 return "unknown"; 715 } 716 717 if ((usbDataStatus & DATA_STATUS_ENABLED) == DATA_STATUS_ENABLED) { 718 return "enabled"; 719 } 720 721 if ((usbDataStatus & DATA_STATUS_DISABLED_OVERHEAT) == DATA_STATUS_DISABLED_OVERHEAT) { 722 statusString.append("disabled-overheat, "); 723 } 724 725 if ((usbDataStatus & DATA_STATUS_DISABLED_CONTAMINANT) 726 == DATA_STATUS_DISABLED_CONTAMINANT) { 727 statusString.append("disabled-contaminant, "); 728 } 729 730 if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK) == DATA_STATUS_DISABLED_DOCK) { 731 statusString.append("disabled-dock, "); 732 } 733 734 if ((usbDataStatus & DATA_STATUS_DISABLED_FORCE) == DATA_STATUS_DISABLED_FORCE) { 735 statusString.append("disabled-force, "); 736 } 737 738 if ((usbDataStatus & DATA_STATUS_DISABLED_DEBUG) == DATA_STATUS_DISABLED_DEBUG) { 739 statusString.append("disabled-debug, "); 740 } 741 742 if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK_HOST_MODE) == 743 DATA_STATUS_DISABLED_DOCK_HOST_MODE) { 744 statusString.append("disabled-host-dock, "); 745 } 746 747 if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK_DEVICE_MODE) == 748 DATA_STATUS_DISABLED_DOCK_DEVICE_MODE) { 749 statusString.append("disabled-device-dock, "); 750 } 751 return statusString.toString().replaceAll(", $", ""); 752 } 753 754 /** @hide */ powerBrickConnectionStatusToString(int powerBrickConnectionStatus)755 public static String powerBrickConnectionStatusToString(int powerBrickConnectionStatus) { 756 switch (powerBrickConnectionStatus) { 757 case POWER_BRICK_STATUS_UNKNOWN: 758 return "unknown"; 759 case POWER_BRICK_STATUS_CONNECTED: 760 return "connected"; 761 case POWER_BRICK_STATUS_DISCONNECTED: 762 return "disconnected"; 763 default: 764 return Integer.toString(powerBrickConnectionStatus); 765 } 766 } 767 768 /** @hide */ roleCombinationsToString(int combo)769 public static String roleCombinationsToString(int combo) { 770 StringBuilder result = new StringBuilder(); 771 result.append("["); 772 773 boolean first = true; 774 while (combo != 0) { 775 final int index = Integer.numberOfTrailingZeros(combo); 776 combo &= ~(1 << index); 777 final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET); 778 final int dataRole = index % NUM_DATA_ROLES; 779 if (first) { 780 first = false; 781 } else { 782 result.append(", "); 783 } 784 result.append(powerRoleToString(powerRole)); 785 result.append(':'); 786 result.append(dataRoleToString(dataRole)); 787 } 788 789 result.append("]"); 790 return result.toString(); 791 } 792 793 /** @hide */ complianceWarningsToString(@onNull int[] complianceWarnings)794 public static String complianceWarningsToString(@NonNull int[] complianceWarnings) { 795 StringBuilder complianceWarningString = new StringBuilder(); 796 complianceWarningString.append("["); 797 798 if (complianceWarnings != null) { 799 for (int warning : complianceWarnings) { 800 switch (warning) { 801 case UsbPortStatus.COMPLIANCE_WARNING_OTHER: 802 complianceWarningString.append("other, "); 803 break; 804 case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY: 805 complianceWarningString.append("debug accessory, "); 806 break; 807 case UsbPortStatus.COMPLIANCE_WARNING_BC_1_2: 808 complianceWarningString.append("bc12, "); 809 break; 810 case UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP: 811 complianceWarningString.append("missing rp, "); 812 break; 813 case UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED: 814 complianceWarningString.append("input power limited, "); 815 break; 816 case UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES: 817 complianceWarningString.append("missing data lines, "); 818 break; 819 case UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL: 820 complianceWarningString.append("enumeration fail, "); 821 break; 822 case UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION: 823 complianceWarningString.append("flaky connection, "); 824 break; 825 case UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO: 826 complianceWarningString.append("unreliable io, "); 827 break; 828 default: 829 complianceWarningString.append(String.format("Unknown(%d), ", warning)); 830 break; 831 } 832 } 833 } 834 835 complianceWarningString.append("]"); 836 return complianceWarningString.toString().replaceAll(", ]$", "]"); 837 } 838 839 /** @hide */ dpAltModeStatusToString(int dpAltModeStatus)840 public static String dpAltModeStatusToString(int dpAltModeStatus) { 841 switch (dpAltModeStatus) { 842 case DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN: 843 return "Unknown"; 844 case DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE: 845 return "Not Capable"; 846 case DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED: 847 return "Capable-Disabled"; 848 case DISPLAYPORT_ALT_MODE_STATUS_ENABLED: 849 return "Enabled"; 850 default: 851 return Integer.toString(dpAltModeStatus); 852 } 853 } 854 855 /** @hide */ checkMode(int powerRole)856 public static void checkMode(int powerRole) { 857 Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE, 858 Constants.PortMode.NUM_MODES - 1, "portMode"); 859 } 860 861 /** @hide */ checkPowerRole(int dataRole)862 public static void checkPowerRole(int dataRole) { 863 Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE, 864 Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole"); 865 } 866 867 /** @hide */ checkDataRole(int mode)868 public static void checkDataRole(int mode) { 869 Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE, 870 Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole"); 871 } 872 873 /** @hide */ checkRoles(int powerRole, int dataRole)874 public static void checkRoles(int powerRole, int dataRole) { 875 Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK, 876 "powerRole"); 877 Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole"); 878 } 879 880 /** @hide */ isModeSupported(int mode)881 public boolean isModeSupported(int mode) { 882 if ((mSupportedModes & mode) == mode) return true; 883 return false; 884 } 885 886 @NonNull 887 @Override toString()888 public String toString() { 889 return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) 890 + ", supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes 891 + ", supportsEnableContaminantPresenceProtection=" 892 + mSupportsEnableContaminantPresenceProtection 893 + ", supportsEnableContaminantPresenceDetection=" 894 + mSupportsEnableContaminantPresenceDetection 895 + ", supportsComplianceWarnings=" 896 + mSupportsComplianceWarnings; 897 } 898 } 899