/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.usb; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_NOT_SUPPORTED; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_PORT_MISMATCH; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS; import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED; import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED; import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED; import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED; import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE; import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST; import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE; import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY; import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY; import static android.hardware.usb.UsbPortStatus.MODE_DFP; import static android.hardware.usb.UsbPortStatus.MODE_DUAL; import static android.hardware.usb.UsbPortStatus.MODE_NONE; import static android.hardware.usb.UsbPortStatus.MODE_UFP; import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_DISCONNECTED; import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN; import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_CONNECTED; import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE; import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK; import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_UNKNOWN; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_ENABLED; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_OVERHEAT; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_CONTAMINANT; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DEBUG; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK_HOST_MODE; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK_DEVICE_MODE; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_BC_1_2; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_OTHER; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO; import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE; import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED; import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_ENABLED; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.CheckResult; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.hardware.usb.flags.Flags; import android.hardware.usb.UsbOperationInternal; import android.hardware.usb.V1_0.Constants; import android.os.Binder; import android.util.Log; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Represents a physical USB port and describes its characteristics. * * @hide */ @SystemApi public final class UsbPort { private static final String TAG = "UsbPort"; private final String mId; private final int mSupportedModes; private final UsbManager mUsbManager; private final int mSupportedContaminantProtectionModes; private final boolean mSupportsEnableContaminantPresenceProtection; private final boolean mSupportsEnableContaminantPresenceDetection; private final boolean mSupportsComplianceWarnings; private final @AltModeType int mSupportedAltModes; private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; /** * Points to the first power role in the IUsb HAL. */ private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE; /** * Counter for tracking UsbOperation operations. */ private static final AtomicInteger sUsbOperationCount = new AtomicInteger(); /** * The {@link #enableUsbData} request was successfully completed. */ public static final int ENABLE_USB_DATA_SUCCESS = 0; /** * The {@link #enableUsbData} request failed due to internal error. */ public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1; /** * The {@link #enableUsbData} request failed as it's not supported. */ public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2; /** * The {@link #enableUsbData} request failed as port id mismatched. */ public static final int ENABLE_USB_DATA_ERROR_PORT_MISMATCH = 3; /** * The {@link #enableUsbData} request failed due to other reasons. */ public static final int ENABLE_USB_DATA_ERROR_OTHER = 4; /** @hide */ @IntDef(prefix = { "ENABLE_USB_DATA_" }, value = { ENABLE_USB_DATA_SUCCESS, ENABLE_USB_DATA_ERROR_INTERNAL, ENABLE_USB_DATA_ERROR_NOT_SUPPORTED, ENABLE_USB_DATA_ERROR_PORT_MISMATCH, ENABLE_USB_DATA_ERROR_OTHER }) @Retention(RetentionPolicy.SOURCE) @interface EnableUsbDataStatus{} /** * The {@link #enableLimitPowerTransfer} request was successfully completed. */ public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0; /** * The {@link #enableLimitPowerTransfer} request failed due to internal error. */ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1; /** * The {@link #enableLimitPowerTransfer} request failed as it's not supported. */ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2; /** * The {@link #enableLimitPowerTransfer} request failed as port id mismatched. */ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3; /** * The {@link #enableLimitPowerTransfer} request failed due to other reasons. */ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4; /** @hide */ @IntDef(prefix = { "ENABLE_LIMIT_POWER_TRANSFER_" }, value = { ENABLE_LIMIT_POWER_TRANSFER_SUCCESS, ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL, ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED, ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH, ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER }) @Retention(RetentionPolicy.SOURCE) @interface EnableLimitPowerTransferStatus{} /** * The {@link #enableUsbDataWhileDocked} request was successfully completed. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0; /** * The {@link #enableUsbDataWhileDocked} request failed due to internal error. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL = 1; /** * The {@link #enableUsbDataWhileDocked} request failed as it's not supported. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED = 2; /** * The {@link #enableUsbDataWhileDocked} request failed as port id mismatched. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3; /** * The {@link #enableUsbDataWhileDocked} request failed as data is still enabled. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED = 4; /** * The {@link #enableUsbDataWhileDocked} request failed due to other reasons. */ public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; /** * The {@link #resetUsbPort} request was successfully completed. */ public static final int RESET_USB_PORT_SUCCESS = 0; /** * The {@link #resetUsbPort} request failed due to internal error. */ public static final int RESET_USB_PORT_ERROR_INTERNAL = 1; /** * The {@link #resetUsbPort} request failed as it's not supported. */ public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2; /** * The {@link #resetUsbPort} request failed as port id mismatched. */ public static final int RESET_USB_PORT_ERROR_PORT_MISMATCH = 3; /** * The {@link #resetUsbPort} request failed due to other reasons. */ public static final int RESET_USB_PORT_ERROR_OTHER = 4; /** @hide */ @IntDef(prefix = { "RESET_USB_PORT_" }, value = { RESET_USB_PORT_SUCCESS, RESET_USB_PORT_ERROR_INTERNAL, RESET_USB_PORT_ERROR_NOT_SUPPORTED, RESET_USB_PORT_ERROR_PORT_MISMATCH, RESET_USB_PORT_ERROR_OTHER }) @Retention(RetentionPolicy.SOURCE) @interface ResetUsbPortStatus{} /** @hide */ @IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = { ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS, ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL, ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED, ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH, ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED, ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER }) @Retention(RetentionPolicy.SOURCE) @interface EnableUsbDataWhileDockedStatus{} /** * Indicates that the Alt Mode being described is DisplayPort. */ public static final int FLAG_ALT_MODE_TYPE_DISPLAYPORT = 1 << 0; /** @hide */ @IntDef(prefix = { "FLAG_ALT_MODE_TYPE_" }, flag = true, value = { FLAG_ALT_MODE_TYPE_DISPLAYPORT, }) @Retention(RetentionPolicy.SOURCE) public @interface AltModeType {} /** @hide */ public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection) { this(usbManager, id, supportedModes, supportedContaminantProtectionModes, supportsEnableContaminantPresenceProtection, supportsEnableContaminantPresenceDetection, false, 0); } /** @hide */ public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection, boolean supportsComplianceWarnings, int supportedAltModes) { Objects.requireNonNull(id); Preconditions.checkFlagsArgument(supportedModes, MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY); mUsbManager = usbManager; mId = id; mSupportedModes = supportedModes; mSupportedContaminantProtectionModes = supportedContaminantProtectionModes; mSupportsEnableContaminantPresenceProtection = supportsEnableContaminantPresenceProtection; mSupportsEnableContaminantPresenceDetection = supportsEnableContaminantPresenceDetection; mSupportsComplianceWarnings = supportsComplianceWarnings; mSupportedAltModes = supportedAltModes; } /** * Gets the unique id of the port. * * @return The unique id of the port; not intended for display. * * @hide */ public String getId() { return mId; } /** * Gets the supported modes of the port. *
* The actual mode of the port may vary depending on what is plugged into it. *
* * @return The supported modes: one of {@link UsbPortStatus#MODE_DFP}, * {@link UsbPortStatus#MODE_UFP}, or {@link UsbPortStatus#MODE_DUAL}. * * @hide */ public int getSupportedModes() { return mSupportedModes; } /** * Gets the supported port proctection modes when the port is contaminated. ** The actual mode of the port is decided by the hardware *
* * @hide */ public int getSupportedContaminantProtectionModes() { return mSupportedContaminantProtectionModes; } /** * Tells if UsbService can enable/disable contaminant presence protection. * * @hide */ public boolean supportsEnableContaminantPresenceProtection() { return mSupportsEnableContaminantPresenceProtection; } /** * Tells if UsbService can enable/disable contaminant presence detection. * * @hide */ public boolean supportsEnableContaminantPresenceDetection() { return mSupportsEnableContaminantPresenceDetection; } /** * Gets the status of this USB port. * * @return The status of the this port, or {@code null} if port is unknown. */ @RequiresPermission(Manifest.permission.MANAGE_USB) public @Nullable UsbPortStatus getStatus() { return mUsbManager.getPortStatus(this); } /** * Returns whether this USB port supports mode change * * @return true if mode change is supported. * @hide */ @TestApi @RequiresPermission(Manifest.permission.MANAGE_USB) @FlaggedApi(Flags.FLAG_ENABLE_IS_MODE_CHANGE_SUPPORTED_API) public boolean isModeChangeSupported() { return mUsbManager.isModeChangeSupported(this); } /** * Queries USB Port to see if the port is capable of identifying * non compliant USB power source/cable/accessory. * * @return true when the UsbPort is capable of identifying * non compliant USB power * source/cable/accessory. * @return false otherwise. */ @CheckResult @RequiresPermission(Manifest.permission.MANAGE_USB) public boolean supportsComplianceWarnings() { return mSupportsComplianceWarnings; } /** * Returns all Alt Modes supported by the port. * * @hide */ public @AltModeType int getSupportedAltModesMask() { return mSupportedAltModes; } /** * Returns whether all Alt Mode types in a given mask are supported * by the port. * * @return true if all given Alt Modes are supported, false otherwise. * */ public boolean isAltModeSupported(@AltModeType int typeMask) { return (mSupportedAltModes & typeMask) == typeMask; } /** * Sets the desired role combination of the port. ** The supported role combinations depend on what is connected to the port and may be * determined by consulting * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}. *
* Note: This function is asynchronous and may fail silently without applying * the operationed changes. If this function does cause a status change to occur then * a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent. *
* * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} or * {@link UsbPortStatus#POWER_ROLE_SINK}, or * {@link UsbPortStatus#POWER_ROLE_NONE} if no power role. * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} or * {@link UsbPortStatus#DATA_ROLE_DEVICE}, or * {@link UsbPortStatus#DATA_ROLE_NONE} if no data role. */ @RequiresPermission(Manifest.permission.MANAGE_USB) public void setRoles(@UsbPortStatus.UsbPowerRole int powerRole, @UsbPortStatus.UsbDataRole int dataRole) { UsbPort.checkRoles(powerRole, dataRole); mUsbManager.setPortRoles(this, powerRole, dataRole); } /** * Reset Usb data on the port. * * @param executor Executor for the callback. * @param consumer A consumer that consumes the reset result. * {@link #RESET_USB_PORT_SUCCESS} when request completes * successfully or * {@link #RESET_USB_PORT_ERROR_INTERNAL} when request * fails due to internal error or * {@link RESET_USB_PORT_ERROR_NOT_SUPPORTED} when not * supported or * {@link RESET_USB_PORT_ERROR_PORT_MISMATCH} when request * fails due to port id mismatch or * {@link RESET_USB_PORT_ERROR_OTHER} when fails due to * other reasons. */ @CheckResult @RequiresPermission(Manifest.permission.MANAGE_USB) public void resetUsbPort(@NonNull @CallbackExecutor Executor executor, @NonNull @ResetUsbPortStatus Consumer* Disables charging and limits sourcing power(when permitted by the USB spec) until * port disconnect event. *
* @param enable limits power transfer when true. * @return {@link #ENABLE_LIMIT_POWER_TRANSFER_SUCCESS} when request completes successfully or * {@link #ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL} when request fails due to * internal error or * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED} when not supported or * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH} when request fails due to * port id mismatch or * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER} when fails due to other reasons. */ @CheckResult @RequiresPermission(Manifest.permission.MANAGE_USB) public @EnableLimitPowerTransferStatus int enableLimitPowerTransfer(boolean enable) { // UID is added To minimize operationID overlap between two different packages. int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); Log.i(TAG, "enableLimitPowerTransfer opId:" + operationId + " callingUid:" + Binder.getCallingUid()); UsbOperationInternal opCallback = new UsbOperationInternal(operationId, mId); mUsbManager.enableLimitPowerTransfer(this, enable, operationId, opCallback); opCallback.waitForOperationComplete(); int result = opCallback.getStatus(); switch (result) { case USB_OPERATION_SUCCESS: return ENABLE_LIMIT_POWER_TRANSFER_SUCCESS; case USB_OPERATION_ERROR_INTERNAL: return ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL; case USB_OPERATION_ERROR_NOT_SUPPORTED: return ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED; case USB_OPERATION_ERROR_PORT_MISMATCH: return ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH; default: return ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER; } } /** * @hide **/ public void enableContaminantDetection(boolean enable) { mUsbManager.enableContaminantDetection(this, enable); } /** * Combines one power and one data role together into a unique value with * exactly one bit set. This can be used to efficiently determine whether * a combination of roles is supported by testing whether that bit is present * in a bit-field. * * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} * or {@link UsbPortStatus#POWER_ROLE_SINK}, or 0 if no power role. * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} * or {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 0 if no data role. * @hide */ public static int combineRolesAsBit(int powerRole, int dataRole) { checkRoles(powerRole, dataRole); final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole; return 1 << index; } /** @hide */ public static String modeToString(int mode) { StringBuilder modeString = new StringBuilder(); if (mode == MODE_NONE) { return "none"; } if ((mode & MODE_DUAL) == MODE_DUAL) { modeString.append("dual, "); } else { if ((mode & MODE_DFP) == MODE_DFP) { modeString.append("dfp, "); } else if ((mode & MODE_UFP) == MODE_UFP) { modeString.append("ufp, "); } } if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) { modeString.append("audio_acc, "); } if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) { modeString.append("debug_acc, "); } if (modeString.length() == 0) { return Integer.toString(mode); } return modeString.substring(0, modeString.length() - 2); } /** @hide */ public static String powerRoleToString(int role) { switch (role) { case POWER_ROLE_NONE: return "no-power"; case POWER_ROLE_SOURCE: return "source"; case POWER_ROLE_SINK: return "sink"; default: return Integer.toString(role); } } /** @hide */ public static String dataRoleToString(int role) { switch (role) { case DATA_ROLE_NONE: return "no-data"; case DATA_ROLE_HOST: return "host"; case DATA_ROLE_DEVICE: return "device"; default: return Integer.toString(role); } } /** @hide */ public static String contaminantPresenceStatusToString(int contaminantPresenceStatus) { switch (contaminantPresenceStatus) { case CONTAMINANT_DETECTION_NOT_SUPPORTED: return "not-supported"; case CONTAMINANT_DETECTION_DISABLED: return "disabled"; case CONTAMINANT_DETECTION_DETECTED: return "detected"; case CONTAMINANT_DETECTION_NOT_DETECTED: return "not detected"; default: return Integer.toString(contaminantPresenceStatus); } } /** @hide */ public static String usbDataStatusToString(int usbDataStatus) { StringBuilder statusString = new StringBuilder(); if (usbDataStatus == DATA_STATUS_UNKNOWN) { return "unknown"; } if ((usbDataStatus & DATA_STATUS_ENABLED) == DATA_STATUS_ENABLED) { return "enabled"; } if ((usbDataStatus & DATA_STATUS_DISABLED_OVERHEAT) == DATA_STATUS_DISABLED_OVERHEAT) { statusString.append("disabled-overheat, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_CONTAMINANT) == DATA_STATUS_DISABLED_CONTAMINANT) { statusString.append("disabled-contaminant, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK) == DATA_STATUS_DISABLED_DOCK) { statusString.append("disabled-dock, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_FORCE) == DATA_STATUS_DISABLED_FORCE) { statusString.append("disabled-force, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_DEBUG) == DATA_STATUS_DISABLED_DEBUG) { statusString.append("disabled-debug, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK_HOST_MODE) == DATA_STATUS_DISABLED_DOCK_HOST_MODE) { statusString.append("disabled-host-dock, "); } if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK_DEVICE_MODE) == DATA_STATUS_DISABLED_DOCK_DEVICE_MODE) { statusString.append("disabled-device-dock, "); } return statusString.toString().replaceAll(", $", ""); } /** @hide */ public static String powerBrickConnectionStatusToString(int powerBrickConnectionStatus) { switch (powerBrickConnectionStatus) { case POWER_BRICK_STATUS_UNKNOWN: return "unknown"; case POWER_BRICK_STATUS_CONNECTED: return "connected"; case POWER_BRICK_STATUS_DISCONNECTED: return "disconnected"; default: return Integer.toString(powerBrickConnectionStatus); } } /** @hide */ public static String roleCombinationsToString(int combo) { StringBuilder result = new StringBuilder(); result.append("["); boolean first = true; while (combo != 0) { final int index = Integer.numberOfTrailingZeros(combo); combo &= ~(1 << index); final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET); final int dataRole = index % NUM_DATA_ROLES; if (first) { first = false; } else { result.append(", "); } result.append(powerRoleToString(powerRole)); result.append(':'); result.append(dataRoleToString(dataRole)); } result.append("]"); return result.toString(); } /** @hide */ public static String complianceWarningsToString(@NonNull int[] complianceWarnings) { StringBuilder complianceWarningString = new StringBuilder(); complianceWarningString.append("["); if (complianceWarnings != null) { for (int warning : complianceWarnings) { switch (warning) { case UsbPortStatus.COMPLIANCE_WARNING_OTHER: complianceWarningString.append("other, "); break; case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY: complianceWarningString.append("debug accessory, "); break; case UsbPortStatus.COMPLIANCE_WARNING_BC_1_2: complianceWarningString.append("bc12, "); break; case UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP: complianceWarningString.append("missing rp, "); break; case UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED: complianceWarningString.append("input power limited, "); break; case UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES: complianceWarningString.append("missing data lines, "); break; case UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL: complianceWarningString.append("enumeration fail, "); break; case UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION: complianceWarningString.append("flaky connection, "); break; case UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO: complianceWarningString.append("unreliable io, "); break; default: complianceWarningString.append(String.format("Unknown(%d), ", warning)); break; } } } complianceWarningString.append("]"); return complianceWarningString.toString().replaceAll(", ]$", "]"); } /** @hide */ public static String dpAltModeStatusToString(int dpAltModeStatus) { switch (dpAltModeStatus) { case DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN: return "Unknown"; case DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE: return "Not Capable"; case DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED: return "Capable-Disabled"; case DISPLAYPORT_ALT_MODE_STATUS_ENABLED: return "Enabled"; default: return Integer.toString(dpAltModeStatus); } } /** @hide */ public static void checkMode(int powerRole) { Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE, Constants.PortMode.NUM_MODES - 1, "portMode"); } /** @hide */ public static void checkPowerRole(int dataRole) { Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE, Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole"); } /** @hide */ public static void checkDataRole(int mode) { Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE, Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole"); } /** @hide */ public static void checkRoles(int powerRole, int dataRole) { Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK, "powerRole"); Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole"); } /** @hide */ public boolean isModeSupported(int mode) { if ((mSupportedModes & mode) == mode) return true; return false; } @NonNull @Override public String toString() { return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + ", supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes + ", supportsEnableContaminantPresenceProtection=" + mSupportsEnableContaminantPresenceProtection + ", supportsEnableContaminantPresenceDetection=" + mSupportsEnableContaminantPresenceDetection + ", supportsComplianceWarnings=" + mSupportsComplianceWarnings; } }