Merge "Usb non-compliant port partner frameworks api"

This commit is contained in:
RD Babiera
2022-11-30 01:39:19 +00:00
committed by Android (Google) Code Review
14 changed files with 459 additions and 39 deletions

View File

@@ -5534,6 +5534,7 @@ package android.hardware.usb {
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_ACCESSORY_HANDSHAKE = "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE";
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_COMPLIANCE_CHANGED = "android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED";
field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
field public static final String EXTRA_ACCESSORY_HANDSHAKE_END = "android.hardware.usb.extra.ACCESSORY_HANDSHAKE_END";
field public static final String EXTRA_ACCESSORY_START = "android.hardware.usb.extra.ACCESSORY_START";
@@ -5561,6 +5562,7 @@ package android.hardware.usb {
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbPort(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean supportsComplianceWarnings();
field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1; // 0x1
field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2; // 0x2
field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4; // 0x4
@@ -5586,6 +5588,7 @@ package android.hardware.usb {
public final class UsbPortStatus implements android.os.Parcelable {
method public int describeContents();
method @CheckResult @NonNull public int[] getComplianceWarnings();
method public int getCurrentDataRole();
method public int getCurrentMode();
method public int getCurrentPowerRole();
@@ -5596,6 +5599,10 @@ package android.hardware.usb {
method public boolean isPowerTransferLimited();
method public boolean isRoleCombinationSupported(int, int);
method public void writeToParcel(android.os.Parcel, int);
field public static final int COMPLIANCE_WARNING_BC_1_2 = 3; // 0x3
field public static final int COMPLIANCE_WARNING_DEBUG_ACCESSORY = 2; // 0x2
field public static final int COMPLIANCE_WARNING_MISSING_RP = 4; // 0x4
field public static final int COMPLIANCE_WARNING_OTHER = 1; // 0x1
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.usb.UsbPortStatus> CREATOR;
field public static final int DATA_ROLE_DEVICE = 2; // 0x2
field public static final int DATA_ROLE_HOST = 1; // 0x1

View File

@@ -34,11 +34,13 @@ public final class ParcelableUsbPort implements Parcelable {
private final int mSupportedContaminantProtectionModes;
private final boolean mSupportsEnableContaminantPresenceProtection;
private final boolean mSupportsEnableContaminantPresenceDetection;
private final boolean mSupportsComplianceWarnings;
private ParcelableUsbPort(@NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection) {
boolean supportsEnableContaminantPresenceDetection,
boolean supportsComplianceWarnings) {
mId = id;
mSupportedModes = supportedModes;
mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
@@ -46,6 +48,8 @@ public final class ParcelableUsbPort implements Parcelable {
supportsEnableContaminantPresenceProtection;
mSupportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
mSupportsComplianceWarnings =
supportsComplianceWarnings;
}
/**
@@ -59,7 +63,8 @@ public final class ParcelableUsbPort implements Parcelable {
return new ParcelableUsbPort(port.getId(), port.getSupportedModes(),
port.getSupportedContaminantProtectionModes(),
port.supportsEnableContaminantPresenceProtection(),
port.supportsEnableContaminantPresenceDetection());
port.supportsEnableContaminantPresenceDetection(),
port.supportsComplianceWarnings());
}
/**
@@ -72,7 +77,8 @@ public final class ParcelableUsbPort implements Parcelable {
public @NonNull UsbPort getUsbPort(@NonNull UsbManager usbManager) {
return new UsbPort(usbManager, mId, mSupportedModes, mSupportedContaminantProtectionModes,
mSupportsEnableContaminantPresenceProtection,
mSupportsEnableContaminantPresenceDetection);
mSupportsEnableContaminantPresenceDetection,
mSupportsComplianceWarnings);
}
@Override
@@ -87,6 +93,7 @@ public final class ParcelableUsbPort implements Parcelable {
dest.writeInt(mSupportedContaminantProtectionModes);
dest.writeBoolean(mSupportsEnableContaminantPresenceProtection);
dest.writeBoolean(mSupportsEnableContaminantPresenceDetection);
dest.writeBoolean(mSupportsComplianceWarnings);
}
public static final @android.annotation.NonNull Creator<ParcelableUsbPort> CREATOR =
@@ -98,11 +105,13 @@ public final class ParcelableUsbPort implements Parcelable {
int supportedContaminantProtectionModes = in.readInt();
boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
boolean supportsComplianceWarnings = in.readBoolean();
return new ParcelableUsbPort(id, supportedModes,
supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection);
supportsEnableContaminantPresenceDetection,
supportsComplianceWarnings);
}
@Override

View File

@@ -113,6 +113,19 @@ public class UsbManager {
public static final String ACTION_USB_PORT_CHANGED =
"android.hardware.usb.action.USB_PORT_CHANGED";
/**
* Broadcast Action: A broadcast for USB compliance warning changes.
*
* This intent is sent when a port partner's
* (USB power source/cable/accessory) compliance warnings change state.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.MANAGE_USB)
public static final String ACTION_USB_PORT_COMPLIANCE_CHANGED =
"android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED";
/**
* Activity intent sent when user attaches a USB device.
*

View File

@@ -46,6 +46,10 @@ import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_CONTAMINAN
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.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 android.Manifest;
import android.annotation.CallbackExecutor;
@@ -83,6 +87,7 @@ public final class UsbPort {
private final int mSupportedContaminantProtectionModes;
private final boolean mSupportsEnableContaminantPresenceProtection;
private final boolean mSupportsEnableContaminantPresenceDetection;
private final boolean mSupportsComplianceWarnings;
private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES;
/**
@@ -250,6 +255,18 @@ public final class UsbPort {
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection) {
this(usbManager, id, supportedModes, supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection,
false);
}
/** @hide */
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection,
boolean supportsComplianceWarnings) {
Objects.requireNonNull(id);
Preconditions.checkFlagsArgument(supportedModes,
MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);
@@ -262,6 +279,7 @@ public final class UsbPort {
supportsEnableContaminantPresenceProtection;
mSupportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
mSupportsComplianceWarnings = supportsComplianceWarnings;
}
/**
@@ -330,6 +348,21 @@ public final class UsbPort {
return mUsbManager.getPortStatus(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;
}
/**
* Sets the desired role combination of the port.
* <p>
@@ -685,6 +718,37 @@ public final class UsbPort {
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;
default:
complianceWarningString.append(String.format("Unknown(%d), ", warning));
break;
}
}
}
complianceWarningString.append("]");
return complianceWarningString.toString().replaceAll(", ]$", "]");
}
/** @hide */
public static void checkMode(int powerRole) {
Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE,
@@ -720,10 +784,12 @@ public final class UsbPort {
@Override
public String toString() {
return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes)
+ "supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes
+ "supportsEnableContaminantPresenceProtection="
+ ", supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes
+ ", supportsEnableContaminantPresenceProtection="
+ mSupportsEnableContaminantPresenceProtection
+ "supportsEnableContaminantPresenceDetection="
+ mSupportsEnableContaminantPresenceDetection;
+ ", supportsEnableContaminantPresenceDetection="
+ mSupportsEnableContaminantPresenceDetection
+ ", supportsComplianceWarnings="
+ mSupportsComplianceWarnings;
}
}

View File

@@ -16,9 +16,11 @@
package android.hardware.usb;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -46,6 +48,7 @@ public final class UsbPortStatus implements Parcelable {
private final boolean mPowerTransferLimited;
private final @UsbDataStatus int mUsbDataStatus;
private final @PowerBrickConnectionStatus int mPowerBrickConnectionStatus;
private final @NonNull @ComplianceWarning int[] mComplianceWarnings;
/**
* Power role: This USB port does not have a power role.
@@ -246,6 +249,41 @@ public final class UsbPortStatus implements Parcelable {
*/
public static final int POWER_BRICK_STATUS_DISCONNECTED = 2;
/**
* Used to indicate attached sources/cables/accessories/ports
* that do not match the other warnings below and do not meet the
* requirements of specifications including but not limited to
* USB Type-C Cable and Connector, Universal Serial Bus
* Power Delivery, and Universal Serial Bus 1.x/2.0/3.x/4.0.
* In addition, constants introduced after the target sdk will be
* remapped into COMPLIANCE_WARNING_OTHER.
*/
public static final int COMPLIANCE_WARNING_OTHER = 1;
/**
* Used to indicate Type-C port partner
* (cable/accessory/source) that identifies itself as debug
* accessory source as defined in USB Type-C Cable and
* Connector Specification. However, the specification states
* that this is meant for debug only and shall not be used for
* with commercial products.
*/
public static final int COMPLIANCE_WARNING_DEBUG_ACCESSORY = 2;
/**
* Used to indicate USB ports that does not
* identify itself as one of the charging port types (SDP/CDP
* DCP etc) as defined by Battery Charging v1.2 Specification.
*/
public static final int COMPLIANCE_WARNING_BC_1_2 = 3;
/**
* Used to indicate Type-C sources/cables that are missing pull
* up resistors on the CC pins as required by USB Type-C Cable
* and Connector Specification.
*/
public static final int COMPLIANCE_WARNING_MISSING_RP = 4;
@IntDef(prefix = { "CONTAMINANT_DETECTION_" }, value = {
CONTAMINANT_DETECTION_NOT_SUPPORTED,
CONTAMINANT_DETECTION_DISABLED,
@@ -275,6 +313,15 @@ public final class UsbPortStatus implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
@interface UsbPortMode{}
@IntDef(prefix = { "COMPLIANCE_WARNING_" }, value = {
COMPLIANCE_WARNING_OTHER,
COMPLIANCE_WARNING_DEBUG_ACCESSORY,
COMPLIANCE_WARNING_BC_1_2,
COMPLIANCE_WARNING_MISSING_RP,
})
@Retention(RetentionPolicy.SOURCE)
@interface ComplianceWarning{}
/** @hide */
@IntDef(prefix = { "DATA_STATUS_" }, flag = true, value = {
DATA_STATUS_UNKNOWN,
@@ -302,7 +349,8 @@ public final class UsbPortStatus implements Parcelable {
int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus, @UsbDataStatus int usbDataStatus,
boolean powerTransferLimited,
@PowerBrickConnectionStatus int powerBrickConnectionStatus) {
@PowerBrickConnectionStatus int powerBrickConnectionStatus,
@NonNull @ComplianceWarning int[] complianceWarnings) {
mCurrentMode = currentMode;
mCurrentPowerRole = currentPowerRole;
mCurrentDataRole = currentDataRole;
@@ -312,21 +360,29 @@ public final class UsbPortStatus implements Parcelable {
mUsbDataStatus = usbDataStatus;
mPowerTransferLimited = powerTransferLimited;
mPowerBrickConnectionStatus = powerBrickConnectionStatus;
mComplianceWarnings = complianceWarnings;
}
/** @hide */
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus, @UsbDataStatus int usbDataStatus,
boolean powerTransferLimited,
@PowerBrickConnectionStatus int powerBrickConnectionStatus) {
this(currentMode, currentPowerRole, currentDataRole, supportedRoleCombinations,
contaminantProtectionStatus, contaminantDetectionStatus,
usbDataStatus, powerTransferLimited, powerBrickConnectionStatus,
new int[] {});
}
/** @hide */
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus) {
mCurrentMode = currentMode;
mCurrentPowerRole = currentPowerRole;
mCurrentDataRole = currentDataRole;
mSupportedRoleCombinations = supportedRoleCombinations;
mContaminantProtectionStatus = contaminantProtectionStatus;
mContaminantDetectionStatus = contaminantDetectionStatus;
mUsbDataStatus = DATA_STATUS_UNKNOWN;
mPowerBrickConnectionStatus = POWER_BRICK_STATUS_UNKNOWN;
mPowerTransferLimited = false;
this(currentMode, currentPowerRole, currentDataRole, supportedRoleCombinations,
contaminantProtectionStatus, contaminantDetectionStatus,
DATA_STATUS_UNKNOWN, false, POWER_BRICK_STATUS_UNKNOWN,
new int[] {});
}
/**
@@ -443,6 +499,21 @@ public final class UsbPortStatus implements Parcelable {
return mPowerBrickConnectionStatus;
}
/**
* Returns non compliant reasons, if any, for the connected
* charger/cable/accessory/USB port.
*
* @return array including {@link #NON_COMPLIANT_REASON_DEBUG_ACCESSORY},
* {@link #NON_COMPLIANT_REASON_BC12},
* {@link #NON_COMPLIANT_REASON_MISSING_RP},
* or {@link #NON_COMPLIANT_REASON_TYPEC}
*/
@CheckResult
@NonNull
public @ComplianceWarning int[] getComplianceWarnings() {
return mComplianceWarnings;
}
@NonNull
@Override
public String toString() {
@@ -460,9 +531,11 @@ public final class UsbPortStatus implements Parcelable {
+ UsbPort.usbDataStatusToString(getUsbDataStatus())
+ ", isPowerTransferLimited="
+ isPowerTransferLimited()
+", powerBrickConnectionStatus="
+ ", powerBrickConnectionStatus="
+ UsbPort
.powerBrickConnectionStatusToString(getPowerBrickConnectionStatus())
+ ", complianceWarnings="
+ UsbPort.complianceWarningsToString(getComplianceWarnings())
+ "}";
}
@@ -482,6 +555,7 @@ public final class UsbPortStatus implements Parcelable {
dest.writeInt(mUsbDataStatus);
dest.writeBoolean(mPowerTransferLimited);
dest.writeInt(mPowerBrickConnectionStatus);
dest.writeIntArray(mComplianceWarnings);
}
public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
@@ -497,10 +571,12 @@ public final class UsbPortStatus implements Parcelable {
int usbDataStatus = in.readInt();
boolean powerTransferLimited = in.readBoolean();
int powerBrickConnectionStatus = in.readInt();
@ComplianceWarning int[] complianceWarnings = in.createIntArray();
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus, powerTransferLimited,
powerBrickConnectionStatus);
powerBrickConnectionStatus,
complianceWarnings);
}
@Override
@@ -524,6 +600,7 @@ public final class UsbPortStatus implements Parcelable {
private boolean mPowerTransferLimited;
private @UsbDataStatus int mUsbDataStatus;
private @PowerBrickConnectionStatus int mPowerBrickConnectionStatus;
private @ComplianceWarning int[] mComplianceWarnings;
public Builder() {
mCurrentMode = MODE_NONE;
@@ -533,6 +610,7 @@ public final class UsbPortStatus implements Parcelable {
mContaminantDetectionStatus = CONTAMINANT_DETECTION_NOT_SUPPORTED;
mUsbDataStatus = DATA_STATUS_UNKNOWN;
mPowerBrickConnectionStatus = POWER_BRICK_STATUS_UNKNOWN;
mComplianceWarnings = new int[] {};
}
/**
@@ -618,6 +696,20 @@ public final class UsbPortStatus implements Parcelable {
return this;
}
/**
* Sets the non-compliant charger reasons of {@link UsbPortStatus}
*
* @return Instance of {@link Builder}
*/
@NonNull
public Builder setComplianceWarnings(
@NonNull int[] complianceWarnings) {
mComplianceWarnings = complianceWarnings == null ? new int[] {} :
complianceWarnings;
return this;
}
/**
* Creates the {@link UsbPortStatus} object.
*/
@@ -626,7 +718,7 @@ public final class UsbPortStatus implements Parcelable {
UsbPortStatus status = new UsbPortStatus(mCurrentMode, mCurrentPowerRole,
mCurrentDataRole, mSupportedRoleCombinations, mContaminantProtectionStatus,
mContaminantDetectionStatus, mUsbDataStatus, mPowerTransferLimited,
mPowerBrickConnectionStatus);
mPowerBrickConnectionStatus, mComplianceWarnings);
return status;
}
};

View File

@@ -174,6 +174,9 @@ public class DumpUtils {
} else {
dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, UsbPort.modeToString(mode));
}
dump.write("supports_compliance_warnings",
UsbPortProto.SUPPORTS_COMPLIANCE_WARNINGS,
port.supportsComplianceWarnings());
dump.end(token);
}
@@ -250,6 +253,8 @@ public class DumpUtils {
status.isPowerTransferLimited());
dump.write("usb_power_brick_status", UsbPortStatusProto.USB_POWER_BRICK_STATUS,
UsbPort.powerBrickConnectionStatusToString(status.getPowerBrickConnectionStatus()));
dump.write("compliance_warning_status", UsbPortStatusProto.COMPLIANCE_WARNINGS_STRING,
UsbPort.complianceWarningsToString(status.getComplianceWarnings()));
dump.end(token);
}
}

View File

@@ -240,6 +240,7 @@ message UsbPortProto {
// ID of the port. A device (eg: Chromebooks) might have multiple ports.
optional string id = 1;
repeated Mode supported_modes = 2;
optional bool supports_compliance_warnings = 3;
}
message UsbPortStatusProto {
@@ -268,6 +269,7 @@ message UsbPortStatusProto {
optional string usb_data_status = 7;
optional bool is_power_transfer_limited = 8;
optional string usb_power_brick_status = 9;
optional string compliance_warnings_string = 10;
}
message UsbPortStatusRoleCombinationProto {

View File

@@ -293,6 +293,7 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
<protected-broadcast android:name="android.hardware.usb.action.USB_PORT_CHANGED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE" />

View File

@@ -29,7 +29,7 @@ java_library_static {
"android.hardware.usb-V1.1-java",
"android.hardware.usb-V1.2-java",
"android.hardware.usb-V1.3-java",
"android.hardware.usb-V1-java",
"android.hardware.usb-V2-java",
"android.hardware.usb.gadget-V1.0-java",
"android.hardware.usb.gadget-V1.1-java",
"android.hardware.usb.gadget-V1.2-java",

View File

@@ -73,6 +73,7 @@ import android.service.ServiceProtoEnums;
import android.service.usb.UsbPortInfoProto;
import android.service.usb.UsbPortManagerProto;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
@@ -87,6 +88,7 @@ import com.android.server.usb.hal.port.RawPortInfo;
import com.android.server.usb.hal.port.UsbPortHal;
import com.android.server.usb.hal.port.UsbPortHalInstance;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Objects;
@@ -754,6 +756,31 @@ public class UsbPortManager {
}
}
/**
* Sets Compliance Warnings for simulated USB port objects.
*/
public void simulateComplianceWarnings(String portId, String complianceWarningsString,
IndentingPrintWriter pw) {
synchronized (mLock) {
final RawPortInfo portInfo = mSimulatedPorts.get(portId);
if (portInfo == null) {
pw.println("Simulated port not found");
return;
}
IntArray complianceWarnings = new IntArray();
for (String s : complianceWarningsString.split("[, ]")) {
if (s.length() > 0) {
complianceWarnings.add(Integer.parseInt(s));
}
}
pw.println("Simulating Compliance Warnings: portId=" + portId
+ " Warnings=" + complianceWarningsString);
portInfo.complianceWarnings = complianceWarnings.toArray();
updatePortsLocked(pw, null);
}
}
public void disconnectSimulatedPort(String portId, IndentingPrintWriter pw) {
synchronized (mLock) {
final RawPortInfo portInfo = mSimulatedPorts.get(portId);
@@ -842,7 +869,10 @@ public class UsbPortManager {
portInfo.contaminantDetectionStatus,
portInfo.usbDataStatus,
portInfo.powerTransferLimited,
portInfo.powerBrickConnectionStatus, pw);
portInfo.powerBrickConnectionStatus,
portInfo.supportsComplianceWarnings,
portInfo.complianceWarnings,
pw);
}
} else {
for (RawPortInfo currentPortInfo : newPortInfo) {
@@ -857,7 +887,10 @@ public class UsbPortManager {
currentPortInfo.contaminantDetectionStatus,
currentPortInfo.usbDataStatus,
currentPortInfo.powerTransferLimited,
currentPortInfo.powerBrickConnectionStatus, pw);
currentPortInfo.powerBrickConnectionStatus,
currentPortInfo.supportsComplianceWarnings,
currentPortInfo.complianceWarnings,
pw);
}
}
@@ -880,6 +913,9 @@ public class UsbPortManager {
handlePortRemovedLocked(portInfo, pw);
break;
}
if (portInfo.mComplianceWarningChange == portInfo.COMPLIANCE_WARNING_CHANGED) {
handlePortComplianceWarningLocked(portInfo, pw);
}
}
}
@@ -896,6 +932,8 @@ public class UsbPortManager {
int usbDataStatus,
boolean powerTransferLimited,
int powerBrickConnectionStatus,
boolean supportsComplianceWarnings,
@NonNull int[] complianceWarnings,
IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect.
@@ -949,13 +987,15 @@ public class UsbPortManager {
portInfo = new PortInfo(mContext.getSystemService(UsbManager.class),
portId, supportedModes, supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection);
supportsEnableContaminantPresenceDetection,
supportsComplianceWarnings);
portInfo.setStatus(currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus);
powerTransferLimited, powerBrickConnectionStatus,
complianceWarnings);
mPorts.put(portId, portInfo);
} else {
// Validate that ports aren't changing definition out from under us.
@@ -987,13 +1027,13 @@ public class UsbPortManager {
+ ", current=" + supportsEnableContaminantPresenceDetection);
}
if (portInfo.setStatus(currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus)) {
powerTransferLimited, powerBrickConnectionStatus,
complianceWarnings)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@@ -1019,6 +1059,11 @@ public class UsbPortManager {
handlePortLocked(portInfo, pw);
}
private void handlePortComplianceWarningLocked(PortInfo portInfo, IndentingPrintWriter pw) {
logAndPrint(Log.INFO, pw, "USB port compliance warning changed: " + portInfo);
sendComplianceWarningBroadcastLocked(portInfo);
}
private void handlePortRemovedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
logAndPrint(Log.INFO, pw, "USB port removed: " + portInfo);
handlePortLocked(portInfo, pw);
@@ -1056,6 +1101,23 @@ public class UsbPortManager {
Manifest.permission.MANAGE_USB));
}
private void sendComplianceWarningBroadcastLocked(PortInfo portInfo) {
if (portInfo.mComplianceWarningChange == portInfo.COMPLIANCE_WARNING_UNCHANGED) {
return;
}
final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED);
intent.addFlags(
Intent.FLAG_RECEIVER_FOREGROUND |
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(portInfo.mUsbPort));
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
// Guard against possible reentrance by posting the broadcast from the handler
// instead of from within the critical section.
mHandler.post(() -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
Manifest.permission.MANAGE_USB));
}
private void enableContaminantDetectionIfNeeded(PortInfo portInfo, IndentingPrintWriter pw) {
if (!mConnected.containsKey(portInfo.mUsbPort.getId())) {
return;
@@ -1180,6 +1242,9 @@ public class UsbPortManager {
public static final int DISPOSITION_READY = 2;
public static final int DISPOSITION_REMOVED = 3;
public static final int COMPLIANCE_WARNING_UNCHANGED = 0;
public static final int COMPLIANCE_WARNING_CHANGED = 1;
public final UsbPort mUsbPort;
public UsbPortStatus mUsbPortStatus;
public boolean mCanChangeMode;
@@ -1191,15 +1256,29 @@ public class UsbPortManager {
public long mConnectedAtMillis;
// 0 when port is connected. Else reports the last connected duration
public long mLastConnectDurationMillis;
// default initialized to 0 which means no changes reported
public int mComplianceWarningChange;
PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceDetection,
boolean supportsEnableContaminantPresenceProtection) {
boolean supportsEnableContaminantPresenceProtection,
boolean supportsComplianceWarnings) {
mUsbPort = new UsbPort(usbManager, portId, supportedModes,
supportedContaminantProtectionModes,
supportsEnableContaminantPresenceDetection,
supportsEnableContaminantPresenceProtection);
supportsEnableContaminantPresenceProtection,
supportsComplianceWarnings);
mComplianceWarningChange = COMPLIANCE_WARNING_UNCHANGED;
}
public boolean complianceWarningsChanged(@NonNull int[] complianceWarnings) {
if (Arrays.equals(complianceWarnings, mUsbPortStatus.getComplianceWarnings())) {
mComplianceWarningChange = COMPLIANCE_WARNING_UNCHANGED;
return false;
}
mComplianceWarningChange = COMPLIANCE_WARNING_CHANGED;
return true;
}
public boolean setStatus(int currentMode, boolean canChangeMode,
@@ -1221,7 +1300,8 @@ public class UsbPortManager {
supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED,
UsbPortStatus.DATA_STATUS_UNKNOWN, false,
UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN);
UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN,
new int[] {});
dispositionChanged = true;
}
@@ -1266,7 +1346,8 @@ public class UsbPortManager {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus);
powerTransferLimited, powerBrickConnectionStatus,
new int[] {});
dispositionChanged = true;
}
@@ -1281,6 +1362,62 @@ public class UsbPortManager {
return dispositionChanged;
}
public boolean setStatus(int currentMode, boolean canChangeMode,
int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus, int usbDataStatus,
boolean powerTransferLimited, int powerBrickConnectionStatus,
@NonNull int[] complianceWarnings) {
boolean dispositionChanged = false;
mCanChangeMode = canChangeMode;
mCanChangePowerRole = canChangePowerRole;
mCanChangeDataRole = canChangeDataRole;
if (mUsbPortStatus == null
|| mUsbPortStatus.getCurrentMode() != currentMode
|| mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
|| mUsbPortStatus.getCurrentDataRole() != currentDataRole
|| mUsbPortStatus.getSupportedRoleCombinations()
!= supportedRoleCombinations
|| mUsbPortStatus.getContaminantProtectionStatus()
!= contaminantProtectionStatus
|| mUsbPortStatus.getContaminantDetectionStatus()
!= contaminantDetectionStatus
|| mUsbPortStatus.getUsbDataStatus()
!= usbDataStatus
|| mUsbPortStatus.isPowerTransferLimited()
!= powerTransferLimited
|| mUsbPortStatus.getPowerBrickConnectionStatus()
!= powerBrickConnectionStatus) {
if (mUsbPortStatus == null && complianceWarnings.length > 0) {
mComplianceWarningChange = COMPLIANCE_WARNING_CHANGED;
}
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus,
complianceWarnings);
dispositionChanged = true;
} else if (complianceWarningsChanged(complianceWarnings)) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus,
complianceWarnings);
}
if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) {
mConnectedAtMillis = SystemClock.elapsedRealtime();
mLastConnectDurationMillis = 0;
} else if (!mUsbPortStatus.isConnected() && mConnectedAtMillis != 0) {
mLastConnectDurationMillis = SystemClock.elapsedRealtime() - mConnectedAtMillis;
mConnectedAtMillis = 0;
}
return dispositionChanged;
}
void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
long token = dump.start(idName, id);

View File

@@ -1093,6 +1093,23 @@ public class UsbService extends IUsbManager.Stub {
mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")),
"", 0);
}
} else if ("set-compliance-reasons".equals(args[0]) && args.length == 3) {
final String portId = args[1];
final String complianceWarnings = args[2];
if (mPortManager != null) {
mPortManager.simulateComplianceWarnings(portId, complianceWarnings, pw);
pw.println();
mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")),
"", 0);
}
} else if ("clear-compliance-reasons".equals(args[0]) && args.length == 2) {
final String portId = args[1];
if (mPortManager != null) {
mPortManager.simulateComplianceWarnings(portId, "", pw);
pw.println();
mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")),
"", 0);
}
} else if ("ports".equals(args[0]) && args.length == 1) {
if (mPortManager != null) {
mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")),
@@ -1142,6 +1159,17 @@ public class UsbService extends IUsbManager.Stub {
pw.println(" dumpsys usb set-contaminant-status \"matrix\" true");
pw.println(" dumpsys usb set-contaminant-status \"matrix\" false");
pw.println();
pw.println("Example simulate compliance warnings:");
pw.println(" dumpsys usb add-port \"matrix\" dual");
pw.println(" dumpsys usb set-compliance-reasons \"matrix\" <reason-list>");
pw.println(" dumpsys usb clear-compliance-reasons \"matrix\"");
pw.println("<reason-list> is expected to be formatted as \"1, ..., 4\"");
pw.println("with reasons that need to be simulated.");
pw.println(" 1: debug accessory");
pw.println(" 2: bc12");
pw.println(" 3: missing rp");
pw.println(" 4: type c");
pw.println();
pw.println("Example USB device descriptors:");
pw.println(" dumpsys usb dump-descriptors -dump-short");
pw.println(" dumpsys usb dump-descriptors -dump-tree");

View File

@@ -40,6 +40,8 @@ public final class RawPortInfo implements Parcelable {
public int usbDataStatus;
public boolean powerTransferLimited;
public int powerBrickConnectionStatus;
public final boolean supportsComplianceWarnings;
public int[] complianceWarnings;
public RawPortInfo(String portId, int supportedModes) {
this.portId = portId;
@@ -50,9 +52,10 @@ public final class RawPortInfo implements Parcelable {
this.supportsEnableContaminantPresenceDetection = false;
this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
this.usbDataStatus = UsbPortStatus.DATA_STATUS_UNKNOWN;
this.powerTransferLimited = false;
this.powerBrickConnectionStatus = UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN;
this.supportsComplianceWarnings = false;
this.complianceWarnings = new int[] {};
}
public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
@@ -66,6 +69,29 @@ public final class RawPortInfo implements Parcelable {
int usbDataStatus,
boolean powerTransferLimited,
int powerBrickConnectionStatus) {
this(portId, supportedModes, supportedContaminantProtectionModes,
currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportsEnableContaminantPresenceProtection, contaminantProtectionStatus,
supportsEnableContaminantPresenceDetection, contaminantDetectionStatus,
usbDataStatus, powerTransferLimited, powerBrickConnectionStatus,
false, new int[] {});
}
public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
int currentMode, boolean canChangeMode,
int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole,
boolean supportsEnableContaminantPresenceProtection,
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus,
int usbDataStatus,
boolean powerTransferLimited,
int powerBrickConnectionStatus,
boolean supportsComplianceWarnings,
int[] complianceWarnings) {
this.portId = portId;
this.supportedModes = supportedModes;
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
@@ -84,6 +110,8 @@ public final class RawPortInfo implements Parcelable {
this.usbDataStatus = usbDataStatus;
this.powerTransferLimited = powerTransferLimited;
this.powerBrickConnectionStatus = powerBrickConnectionStatus;
this.supportsComplianceWarnings = supportsComplianceWarnings;
this.complianceWarnings = complianceWarnings;
}
@Override
@@ -109,6 +137,8 @@ public final class RawPortInfo implements Parcelable {
dest.writeInt(usbDataStatus);
dest.writeBoolean(powerTransferLimited);
dest.writeInt(powerBrickConnectionStatus);
dest.writeBoolean(supportsComplianceWarnings);
dest.writeIntArray(complianceWarnings);
}
public static final Parcelable.Creator<RawPortInfo> CREATOR =
@@ -131,6 +161,8 @@ public final class RawPortInfo implements Parcelable {
int usbDataStatus = in.readInt();
boolean powerTransferLimited = in.readBoolean();
int powerBrickConnectionStatus = in.readInt();
boolean supportsComplianceWarnings = in.readBoolean();
int[] complianceWarnings = in.createIntArray();
return new RawPortInfo(id, supportedModes,
supportedContaminantProtectionModes, currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
@@ -139,7 +171,8 @@ public final class RawPortInfo implements Parcelable {
contaminantProtectionStatus,
supportsEnableContaminantPresenceDetection,
contaminantDetectionStatus, usbDataStatus,
powerTransferLimited, powerBrickConnectionStatus);
powerTransferLimited, powerBrickConnectionStatus,
supportsComplianceWarnings, complianceWarnings);
}
@Override

View File

@@ -34,9 +34,12 @@ import android.hardware.usb.Status;
import android.hardware.usb.IUsbCallback;
import android.hardware.usb.PortRole;
import android.hardware.usb.PortStatus;
import android.hardware.usb.ComplianceWarning;
import android.os.Build;
import android.os.ServiceManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.IntArray;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
@@ -46,6 +49,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.usb.UsbPortManager;
import com.android.server.usb.hal.port.RawPortInfo;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
import java.util.NoSuchElementException;
@@ -551,6 +555,24 @@ public final class UsbPortAidl implements UsbPortHal {
return usbDataStatus;
}
private int[] formatComplianceWarnings(int[] complianceWarnings) {
Objects.requireNonNull(complianceWarnings);
IntArray newComplianceWarnings = new IntArray();
Arrays.sort(complianceWarnings);
for (int warning : complianceWarnings) {
if (newComplianceWarnings.indexOf(warning) == -1
&& warning >= UsbPortStatus.COMPLIANCE_WARNING_OTHER) {
// ComplianceWarnings range from [1, 4] in Android U
if (warning > UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP) {
newComplianceWarnings.add(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
} else {
newComplianceWarnings.add(warning);
}
}
}
return newComplianceWarnings.toArray();
}
@Override
public void notifyPortStatusChange(
android.hardware.usb.PortStatus[] currentPortStatus, int retval) {
@@ -584,7 +606,9 @@ public final class UsbPortAidl implements UsbPortHal {
current.contaminantDetectionStatus,
toUsbDataStatusInt(current.usbDataStatus),
current.powerTransferLimited,
current.powerBrickStatus);
current.powerBrickStatus,
current.supportsComplianceWarnings,
formatComplianceWarnings(current.complianceWarnings));
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback AIDL V1: "
+ current.portName);

View File

@@ -421,7 +421,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.currentDataRole, current.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataStatus,
false, POWER_BRICK_STATUS_UNKNOWN);
false, POWER_BRICK_STATUS_UNKNOWN,
false, new int[] {});
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_0: "
+ current.portName);
@@ -455,7 +456,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.status.currentDataRole, current.status.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataStatus,
false, POWER_BRICK_STATUS_UNKNOWN);
false, POWER_BRICK_STATUS_UNKNOWN,
false, new int[] {});
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_1: "
+ current.status.portName);
@@ -493,7 +495,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.supportsEnableContaminantPresenceDetection,
current.contaminantDetectionStatus,
sUsbDataStatus,
false, POWER_BRICK_STATUS_UNKNOWN);
false, POWER_BRICK_STATUS_UNKNOWN,
false, new int[] {});
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_2: "
+ current.status_1_1.status.portName);