Support USB V1.2 HAL

USB V1.2 HAL supports contaminant detection interface.

Bug: 119642987
Bug: 117330206
Bug: 77606903

Test: Manually tested for notification pop-up
Change-Id: I304fb4933ba8b8eaa08c32c9e8c116cba7aa6380
This commit is contained in:
Badhri Jagan Sridharan 2018-12-09 14:49:38 -08:00
parent 3f7e640844
commit e966a38b67
11 changed files with 535 additions and 53 deletions

View File

@ -749,6 +749,7 @@ java_defaults {
"android.hardware.tv.input-V1.0-java-constants", "android.hardware.tv.input-V1.0-java-constants",
"android.hardware.usb-V1.0-java-constants", "android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants", "android.hardware.usb-V1.1-java-constants",
"android.hardware.usb-V1.2-java-constants",
"android.hardware.vibrator-V1.0-java", "android.hardware.vibrator-V1.0-java",
"android.hardware.vibrator-V1.1-java", "android.hardware.vibrator-V1.1-java",
"android.hardware.vibrator-V1.2-java", "android.hardware.vibrator-V1.2-java",

View File

@ -120,6 +120,9 @@ interface IUsbManager
/* Sets the port's current role. */ /* Sets the port's current role. */
void setPortRoles(in String portId, int powerRole, int dataRole); void setPortRoles(in String portId, int powerRole, int dataRole);
/* Enable/disable contaminant detection */
void enableContaminantDetection(in String portId, boolean enable);
/* Sets USB device connection handler. */ /* Sets USB device connection handler. */
void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler); void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
} }

View File

@ -31,10 +31,21 @@ import com.android.internal.annotations.Immutable;
public final class ParcelableUsbPort implements Parcelable { public final class ParcelableUsbPort implements Parcelable {
private final @NonNull String mId; private final @NonNull String mId;
private final int mSupportedModes; private final int mSupportedModes;
private final int mSupportedContaminantProtectionModes;
private final boolean mSupportsEnableContaminantPresenceProtection;
private final boolean mSupportsEnableContaminantPresenceDetection;
private ParcelableUsbPort(@NonNull String id, int supportedModes) { private ParcelableUsbPort(@NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection) {
mId = id; mId = id;
mSupportedModes = supportedModes; mSupportedModes = supportedModes;
mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
mSupportsEnableContaminantPresenceProtection =
supportsEnableContaminantPresenceProtection;
mSupportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
} }
/** /**
@ -45,7 +56,10 @@ public final class ParcelableUsbPort implements Parcelable {
* @return The parcelable version of the port * @return The parcelable version of the port
*/ */
public static @NonNull ParcelableUsbPort of(@NonNull UsbPort port) { public static @NonNull ParcelableUsbPort of(@NonNull UsbPort port) {
return new ParcelableUsbPort(port.getId(), port.getSupportedModes()); return new ParcelableUsbPort(port.getId(), port.getSupportedModes(),
port.getSupportedContaminantProtectionModes(),
port.supportsEnableContaminantPresenceProtection(),
port.supportsEnableContaminantPresenceDetection());
} }
/** /**
@ -56,7 +70,9 @@ public final class ParcelableUsbPort implements Parcelable {
* @return The UsbPort for this object * @return The UsbPort for this object
*/ */
public @NonNull UsbPort getUsbPort(@NonNull UsbManager usbManager) { public @NonNull UsbPort getUsbPort(@NonNull UsbManager usbManager) {
return new UsbPort(usbManager, mId, mSupportedModes); return new UsbPort(usbManager, mId, mSupportedModes, mSupportedContaminantProtectionModes,
mSupportsEnableContaminantPresenceProtection,
mSupportsEnableContaminantPresenceDetection);
} }
@Override @Override
@ -68,6 +84,9 @@ public final class ParcelableUsbPort implements Parcelable {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mId); dest.writeString(mId);
dest.writeInt(mSupportedModes); dest.writeInt(mSupportedModes);
dest.writeInt(mSupportedContaminantProtectionModes);
dest.writeBoolean(mSupportsEnableContaminantPresenceProtection);
dest.writeBoolean(mSupportsEnableContaminantPresenceDetection);
} }
public static final Creator<ParcelableUsbPort> CREATOR = public static final Creator<ParcelableUsbPort> CREATOR =
@ -76,7 +95,14 @@ public final class ParcelableUsbPort implements Parcelable {
public ParcelableUsbPort createFromParcel(Parcel in) { public ParcelableUsbPort createFromParcel(Parcel in) {
String id = in.readString(); String id = in.readString();
int supportedModes = in.readInt(); int supportedModes = in.readInt();
return new ParcelableUsbPort(id, supportedModes); int supportedContaminantProtectionModes = in.readInt();
boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
return new ParcelableUsbPort(id, supportedModes,
supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection);
} }
@Override @Override

View File

@ -853,6 +853,20 @@ public class UsbManager {
} }
} }
/**
* Enables USB port contaminant detection algorithm.
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_USB)
void enableContaminantDetection(@NonNull UsbPort port, boolean enable) {
try {
mService.enableContaminantDetection(port.getId(), enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** /**
* Sets the component that will handle USB device connection. * Sets the component that will handle USB device connection.
* <p> * <p>

View File

@ -16,6 +16,10 @@
package android.hardware.usb; package android.hardware.usb;
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_DEVICE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST; import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE; import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
@ -48,16 +52,21 @@ public final class UsbPort {
private final String mId; private final String mId;
private final int mSupportedModes; private final int mSupportedModes;
private final UsbManager mUsbManager; private final UsbManager mUsbManager;
private final int mSupportedContaminantProtectionModes;
private final boolean mSupportsEnableContaminantPresenceProtection;
private final boolean mSupportsEnableContaminantPresenceDetection;
private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES;
/** /**
* Points to the first power role in the IUsb HAL. * Points to the first power role in the IUsb HAL.
*/ */
private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE; private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;
/** @hide */ /** @hide */
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes) { public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection) {
Preconditions.checkNotNull(id); Preconditions.checkNotNull(id);
Preconditions.checkFlagsArgument(supportedModes, Preconditions.checkFlagsArgument(supportedModes,
MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY); MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);
@ -65,6 +74,11 @@ public final class UsbPort {
mUsbManager = usbManager; mUsbManager = usbManager;
mId = id; mId = id;
mSupportedModes = supportedModes; mSupportedModes = supportedModes;
mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
mSupportsEnableContaminantPresenceProtection =
supportsEnableContaminantPresenceProtection;
mSupportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
} }
/** /**
@ -93,6 +107,36 @@ public final class UsbPort {
return mSupportedModes; return mSupportedModes;
} }
/**
* Gets the supported port proctection modes when the port is contaminated.
* <p>
* The actual mode of the port is decided by the hardware
* </p>
*
* @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. * Gets the status of this USB port.
* *
@ -130,6 +174,12 @@ public final class UsbPort {
mUsbManager.setPortRoles(this, powerRole, dataRole); mUsbManager.setPortRoles(this, powerRole, dataRole);
} }
/**
* @hide
**/
public void enableContaminantDetection(boolean enable) {
mUsbManager.enableContaminantDetection(this, enable);
}
/** /**
* Combines one power and one data role together into a unique value with * 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 * exactly one bit set. This can be used to efficiently determine whether
@ -205,6 +255,22 @@ public final class UsbPort {
} }
} }
/** @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 */ /** @hide */
public static String roleCombinationsToString(int combo) { public static String roleCombinationsToString(int combo) {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
@ -264,6 +330,11 @@ public final class UsbPort {
@Override @Override
public String toString() { public String toString() {
return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}"; return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes)
+ "supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes
+ "supportsEnableContaminantPresenceProtection="
+ mSupportsEnableContaminantPresenceProtection
+ "supportsEnableContaminantPresenceDetection="
+ mSupportsEnableContaminantPresenceDetection;
} }
} }

View File

@ -39,6 +39,8 @@ public final class UsbPortStatus implements Parcelable {
private final @UsbPowerRole int mCurrentPowerRole; private final @UsbPowerRole int mCurrentPowerRole;
private final @UsbDataRole int mCurrentDataRole; private final @UsbDataRole int mCurrentDataRole;
private final int mSupportedRoleCombinations; private final int mSupportedRoleCombinations;
private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
/** /**
* Power role: This USB port does not have a power role. * Power role: This USB port does not have a power role.
@ -131,6 +133,93 @@ public final class UsbPortStatus implements Parcelable {
public static final int MODE_DEBUG_ACCESSORY = public static final int MODE_DEBUG_ACCESSORY =
android.hardware.usb.V1_1.Constants.PortMode_1_1.DEBUG_ACCESSORY; android.hardware.usb.V1_1.Constants.PortMode_1_1.DEBUG_ACCESSORY;
/**
* Contaminant presence detection not supported by the device.
* @hide
*/
public static final int CONTAMINANT_DETECTION_NOT_SUPPORTED =
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_SUPPORTED;
/**
* Contaminant presence detection supported but disabled.
* @hide
*/
public static final int CONTAMINANT_DETECTION_DISABLED =
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DISABLED;
/**
* Contaminant presence enabled but not detected.
* @hide
*/
public static final int CONTAMINANT_DETECTION_NOT_DETECTED =
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_DETECTED;
/**
* Contaminant presence enabled and detected.
* @hide
*/
public static final int CONTAMINANT_DETECTION_DETECTED =
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DETECTED;
/**
* Contaminant protection - No action performed upon detection of
* contaminant presence.
* @hide
*/
public static final int CONTAMINANT_PROTECTION_NONE =
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.NONE;
/**
* Contaminant protection - Port is forced to sink upon detection of
* contaminant presence.
* @hide
*/
public static final int CONTAMINANT_PROTECTION_SINK =
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SINK;
/**
* Contaminant protection - Port is forced to source upon detection of
* contaminant presence.
* @hide
*/
public static final int CONTAMINANT_PROTECTION_SOURCE =
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SOURCE;
/**
* Contaminant protection - Port is disabled upon detection of
* contaminant presence.
* @hide
*/
public static final int CONTAMINANT_PROTECTION_FORCE_DISABLE =
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_DISABLE;
/**
* Contaminant protection - Port is disabled upon detection of
* contaminant presence.
* @hide
*/
public static final int CONTAMINANT_PROTECTION_DISABLED =
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.DISABLED;
@IntDef(prefix = { "CONTAMINANT_DETECION_" }, flag = true, value = {
CONTAMINANT_DETECTION_NOT_SUPPORTED,
CONTAMINANT_DETECTION_DISABLED,
CONTAMINANT_DETECTION_NOT_DETECTED,
CONTAMINANT_DETECTION_DETECTED,
})
@Retention(RetentionPolicy.SOURCE)
@interface ContaminantDetectionStatus{}
@IntDef(prefix = { "CONTAMINANT_PROTECTION_" }, flag = true, value = {
CONTAMINANT_PROTECTION_NONE,
CONTAMINANT_PROTECTION_SINK,
CONTAMINANT_PROTECTION_SOURCE,
CONTAMINANT_PROTECTION_FORCE_DISABLE,
CONTAMINANT_PROTECTION_DISABLED,
})
@Retention(RetentionPolicy.SOURCE)
@interface ContaminantProtectionStatus{}
@IntDef(prefix = { "MODE_" }, flag = true, value = { @IntDef(prefix = { "MODE_" }, flag = true, value = {
MODE_NONE, MODE_NONE,
MODE_DFP, MODE_DFP,
@ -142,12 +231,15 @@ public final class UsbPortStatus implements Parcelable {
@interface UsbPortMode{} @interface UsbPortMode{}
/** @hide */ /** @hide */
public UsbPortStatus(int currentMode, @UsbPowerRole int currentPowerRole, public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
@UsbDataRole int currentDataRole, int supportedRoleCombinations) { int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus) {
mCurrentMode = currentMode; mCurrentMode = currentMode;
mCurrentPowerRole = currentPowerRole; mCurrentPowerRole = currentPowerRole;
mCurrentDataRole = currentDataRole; mCurrentDataRole = currentDataRole;
mSupportedRoleCombinations = supportedRoleCombinations; mSupportedRoleCombinations = supportedRoleCombinations;
mContaminantProtectionStatus = contaminantProtectionStatus;
mContaminantDetectionStatus = contaminantDetectionStatus;
} }
/** /**
@ -212,6 +304,24 @@ public final class UsbPortStatus implements Parcelable {
return mSupportedRoleCombinations; return mSupportedRoleCombinations;
} }
/**
* Returns contaminant detection status.
*
* @hide
*/
public @ContaminantDetectionStatus int getContaminantDetectionStatus() {
return mContaminantDetectionStatus;
}
/**
* Returns contamiant protection status.
*
* @hide
*/
public @ContaminantProtectionStatus int getContaminantProtectionStatus() {
return mContaminantProtectionStatus;
}
@Override @Override
public String toString() { public String toString() {
return "UsbPortStatus{connected=" + isConnected() return "UsbPortStatus{connected=" + isConnected()
@ -220,6 +330,10 @@ public final class UsbPortStatus implements Parcelable {
+ ", currentDataRole=" + UsbPort.dataRoleToString(mCurrentDataRole) + ", currentDataRole=" + UsbPort.dataRoleToString(mCurrentDataRole)
+ ", supportedRoleCombinations=" + ", supportedRoleCombinations="
+ UsbPort.roleCombinationsToString(mSupportedRoleCombinations) + UsbPort.roleCombinationsToString(mSupportedRoleCombinations)
+ ", contaminantDetectionStatus="
+ getContaminantDetectionStatus()
+ ", contaminantProtectionStatus="
+ getContaminantProtectionStatus()
+ "}"; + "}";
} }
@ -234,6 +348,8 @@ public final class UsbPortStatus implements Parcelable {
dest.writeInt(mCurrentPowerRole); dest.writeInt(mCurrentPowerRole);
dest.writeInt(mCurrentDataRole); dest.writeInt(mCurrentDataRole);
dest.writeInt(mSupportedRoleCombinations); dest.writeInt(mSupportedRoleCombinations);
dest.writeInt(mContaminantProtectionStatus);
dest.writeInt(mContaminantDetectionStatus);
} }
public static final Parcelable.Creator<UsbPortStatus> CREATOR = public static final Parcelable.Creator<UsbPortStatus> CREATOR =
@ -244,8 +360,11 @@ public final class UsbPortStatus implements Parcelable {
int currentPowerRole = in.readInt(); int currentPowerRole = in.readInt();
int currentDataRole = in.readInt(); int currentDataRole = in.readInt();
int supportedRoleCombinations = in.readInt(); int supportedRoleCombinations = in.readInt();
int contaminantProtectionStatus = in.readInt();
int contaminantDetectionStatus = in.readInt();
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole, return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations); supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus);
} }
@Override @Override

View File

@ -196,6 +196,15 @@ public class DumpUtils {
} }
} }
private static void writeContaminantPresenceStatus(@NonNull DualDumpOutputStream dump,
@NonNull String idName, long id, int contaminantPresenceStatus) {
if (dump.isProto()) {
dump.write(idName, id, contaminantPresenceStatus);
} else {
dump.write(idName, id,
UsbPort.contaminantPresenceStatusToString(contaminantPresenceStatus));
}
}
public static void writePortStatus(@NonNull DualDumpOutputStream dump, @NonNull String idName, public static void writePortStatus(@NonNull DualDumpOutputStream dump, @NonNull String idName,
long id, @NonNull UsbPortStatus status) { long id, @NonNull UsbPortStatus status) {
@ -232,6 +241,10 @@ public class DumpUtils {
dump.end(roleCombinationToken); dump.end(roleCombinationToken);
} }
writeContaminantPresenceStatus(dump, "contaminant_presence_status",
UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
status.getContaminantDetectionStatus());
dump.end(token); dump.end(token);
} }
} }

View File

@ -245,11 +245,20 @@ message UsbPortStatusProto {
DATA_ROLE_DEVICE = 2; DATA_ROLE_DEVICE = 2;
} }
/* Same as android.hardware.usb.V1_2.Constants.ContaminantPresenceStatus */
enum ContaminantPresenceStatus {
CONTAMINANT_STATUS_NOT_SUPPORTED = 0;
CONTAMINANT_STATUS_DISABLED = 1;
CONTAMINANT_STATUS_NOT_DETECTED = 2;
CONTAMINANT_STATUS_DETECTED = 3;
}
optional bool connected = 1; optional bool connected = 1;
optional UsbPortProto.Mode current_mode = 2; optional UsbPortProto.Mode current_mode = 2;
optional PowerRole power_role = 3; optional PowerRole power_role = 3;
optional DataRole data_role = 4; optional DataRole data_role = 4;
repeated UsbPortStatusRoleCombinationProto role_combinations = 5; repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
optional ContaminantPresenceStatus contaminant_presence_status = 6;
} }
message UsbPortStatusRoleCombinationProto { message UsbPortStatusRoleCombinationProto {

View File

@ -10,6 +10,7 @@ java_library_static {
static_libs: [ static_libs: [
"android.hardware.usb-V1.0-java", "android.hardware.usb-V1.0-java",
"android.hardware.usb-V1.1-java", "android.hardware.usb-V1.1-java",
"android.hardware.usb-V1.2-java",
"android.hardware.usb.gadget-V1.0-java", "android.hardware.usb.gadget-V1.0-java",
], ],
} }

View File

@ -16,6 +16,8 @@
package com.android.server.usb; package com.android.server.usb;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE; 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_HOST;
import static android.hardware.usb.UsbPortStatus.MODE_DFP; import static android.hardware.usb.UsbPortStatus.MODE_DFP;
@ -35,13 +37,13 @@ import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus; import android.hardware.usb.UsbPortStatus;
import android.hardware.usb.V1_0.IUsb;
import android.hardware.usb.V1_0.PortRole; import android.hardware.usb.V1_0.PortRole;
import android.hardware.usb.V1_0.PortRoleType; import android.hardware.usb.V1_0.PortRoleType;
import android.hardware.usb.V1_0.PortStatus;
import android.hardware.usb.V1_0.Status; import android.hardware.usb.V1_0.Status;
import android.hardware.usb.V1_1.IUsbCallback;
import android.hardware.usb.V1_1.PortStatus_1_1; import android.hardware.usb.V1_1.PortStatus_1_1;
import android.hardware.usb.V1_2.IUsb;
import android.hardware.usb.V1_2.IUsbCallback;
import android.hardware.usb.V1_2.PortStatus;
import android.hidl.manager.V1_0.IServiceManager; import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification; import android.hidl.manager.V1_0.IServiceNotification;
import android.os.Bundle; import android.os.Bundle;
@ -184,6 +186,43 @@ public class UsbPortManager {
} }
} }
/**
* Enables/disables contaminant detection.
*
* @param portId port identifier.
* @param enable enable contaminant detection when set to true.
*/
public void enableContaminantDetection(@NonNull String portId, boolean enable,
@NonNull IndentingPrintWriter pw) {
final PortInfo portInfo = mPorts.get(portId);
if (portInfo == null) {
if (pw != null) {
pw.println("No such USB port: " + portId);
}
return;
}
if (!portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()) {
return;
}
if ((enable && portInfo.mUsbPortStatus.getContaminantDetectionStatus()
!= UsbPortStatus.CONTAMINANT_DETECTION_DISABLED) || (!enable
&& portInfo.mUsbPortStatus.getContaminantDetectionStatus()
== UsbPortStatus.CONTAMINANT_DETECTION_DISABLED)
|| (portInfo.mUsbPortStatus.getContaminantDetectionStatus()
== UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED)) {
return;
}
try {
// Oneway call into the hal
mProxy.enableContaminantPresenceDetection(portId, enable);
} catch (RemoteException e) {
logAndPrintException(null, "Failed to set contaminant detection", e);
}
}
public void setPortRoles(String portId, int newPowerRole, int newDataRole, public void setPortRoles(String portId, int newPowerRole, int newDataRole,
IndentingPrintWriter pw) { IndentingPrintWriter pw) {
synchronized (mLock) { synchronized (mLock) {
@ -441,7 +480,8 @@ public class UsbPortManager {
this.portManager = portManager; this.portManager = portManager;
} }
public void notifyPortStatusChange(ArrayList<PortStatus> currentPortStatus, int retval) { public void notifyPortStatusChange(
ArrayList<android.hardware.usb.V1_0.PortStatus> currentPortStatus, int retval) {
if (!portManager.mSystemReady) { if (!portManager.mSystemReady) {
return; return;
} }
@ -453,14 +493,17 @@ public class UsbPortManager {
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>(); ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
for (PortStatus current : currentPortStatus) { for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
RawPortInfo temp = new RawPortInfo(current.portName, RawPortInfo temp = new RawPortInfo(current.portName,
current.supportedModes, current.currentMode, current.supportedModes, CONTAMINANT_PROTECTION_NONE,
current.currentMode,
current.canChangeMode, current.currentPowerRole, current.canChangeMode, current.currentPowerRole,
current.canChangePowerRole, current.canChangePowerRole,
current.currentDataRole, current.canChangeDataRole); current.currentDataRole, current.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
newPortInfo.add(temp); newPortInfo.add(temp);
logAndPrint(Log.INFO, pw, "ClientCallback: " + current.portName); logAndPrint(Log.INFO, pw, "ClientCallback V1_0: " + current.portName);
} }
Message message = portManager.mHandler.obtainMessage(); Message message = portManager.mHandler.obtainMessage();
@ -485,14 +528,61 @@ public class UsbPortManager {
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>(); ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
for (PortStatus_1_1 current : currentPortStatus) { int numStatus = currentPortStatus.size();
for (int i = 0; i < numStatus; i++) {
PortStatus_1_1 current = currentPortStatus.get(i);
RawPortInfo temp = new RawPortInfo(current.status.portName, RawPortInfo temp = new RawPortInfo(current.status.portName,
current.supportedModes, current.currentMode, current.supportedModes, CONTAMINANT_PROTECTION_NONE,
current.currentMode,
current.status.canChangeMode, current.status.currentPowerRole, current.status.canChangeMode, current.status.currentPowerRole,
current.status.canChangePowerRole, current.status.canChangePowerRole,
current.status.currentDataRole, current.status.canChangeDataRole); current.status.currentDataRole, current.status.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
newPortInfo.add(temp); newPortInfo.add(temp);
logAndPrint(Log.INFO, pw, "ClientCallback: " + current.status.portName); logAndPrint(Log.INFO, pw, "ClientCallback V1_1: " + current.status.portName);
}
Message message = portManager.mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
message.what = MSG_UPDATE_PORTS;
message.setData(bundle);
portManager.mHandler.sendMessage(message);
}
public void notifyPortStatusChange_1_2(
ArrayList<PortStatus> currentPortStatus, int retval) {
if (!portManager.mSystemReady) {
return;
}
if (retval != Status.SUCCESS) {
logAndPrint(Log.ERROR, pw, "port status enquiry failed");
return;
}
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
int numStatus = currentPortStatus.size();
for (int i = 0; i < numStatus; i++) {
PortStatus current = currentPortStatus.get(i);
RawPortInfo temp = new RawPortInfo(current.status_1_1.status.portName,
current.status_1_1.supportedModes,
current.supportedContaminantProtectionModes,
current.status_1_1.currentMode,
current.status_1_1.status.canChangeMode,
current.status_1_1.status.currentPowerRole,
current.status_1_1.status.canChangePowerRole,
current.status_1_1.status.currentDataRole,
current.status_1_1.status.canChangeDataRole,
current.supportsEnableContaminantPresenceProtection,
current.contaminantProtectionStatus,
current.supportsEnableContaminantPresenceDetection,
current.contaminantDetectionStatus);
newPortInfo.add(temp);
logAndPrint(Log.INFO, pw, "ClientCallback V1_2: "
+ current.status_1_1.status.portName);
} }
Message message = portManager.mHandler.obtainMessage(); Message message = portManager.mHandler.obtainMessage();
@ -573,16 +663,26 @@ public class UsbPortManager {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final RawPortInfo portInfo = mSimulatedPorts.valueAt(i); final RawPortInfo portInfo = mSimulatedPorts.valueAt(i);
addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes, addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes,
portInfo.supportedContaminantProtectionModes,
portInfo.currentMode, portInfo.canChangeMode, portInfo.currentMode, portInfo.canChangeMode,
portInfo.currentPowerRole, portInfo.canChangePowerRole, portInfo.currentPowerRole, portInfo.canChangePowerRole,
portInfo.currentDataRole, portInfo.canChangeDataRole, pw); portInfo.currentDataRole, portInfo.canChangeDataRole,
portInfo.supportsEnableContaminantPresenceProtection,
portInfo.contaminantProtectionStatus,
portInfo.supportsEnableContaminantPresenceDetection,
portInfo.contaminantDetectionStatus, pw);
} }
} else { } else {
for (RawPortInfo currentPortInfo : newPortInfo) { for (RawPortInfo currentPortInfo : newPortInfo) {
addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes, addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes,
currentPortInfo.supportedContaminantProtectionModes,
currentPortInfo.currentMode, currentPortInfo.canChangeMode, currentPortInfo.currentMode, currentPortInfo.canChangeMode,
currentPortInfo.currentPowerRole, currentPortInfo.canChangePowerRole, currentPortInfo.currentPowerRole, currentPortInfo.canChangePowerRole,
currentPortInfo.currentDataRole, currentPortInfo.canChangeDataRole, pw); currentPortInfo.currentDataRole, currentPortInfo.canChangeDataRole,
currentPortInfo.supportsEnableContaminantPresenceProtection,
currentPortInfo.contaminantProtectionStatus,
currentPortInfo.supportsEnableContaminantPresenceDetection,
currentPortInfo.contaminantDetectionStatus, pw);
} }
} }
@ -608,12 +708,16 @@ public class UsbPortManager {
} }
} }
// Must only be called by updatePortsLocked. // Must only be called by updatePortsLocked.
private void addOrUpdatePortLocked(String portId, int supportedModes, private void addOrUpdatePortLocked(String portId, int supportedModes,
int supportedContaminantProtectionModes,
int currentMode, boolean canChangeMode, int currentMode, boolean canChangeMode,
int currentPowerRole, boolean canChangePowerRole, int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole, int currentDataRole, boolean canChangeDataRole,
boolean supportsEnableContaminantPresenceProtection,
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus,
IndentingPrintWriter pw) { IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports. // Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect. // Validate that the current mode matches the supported modes we expect.
@ -664,12 +768,15 @@ public class UsbPortManager {
// Update the port data structures. // Update the port data structures.
PortInfo portInfo = mPorts.get(portId); PortInfo portInfo = mPorts.get(portId);
if (portInfo == null) { if (portInfo == null) {
portInfo = new PortInfo(mContext.getSystemService(UsbManager.class), portId, portInfo = new PortInfo(mContext.getSystemService(UsbManager.class),
supportedModes); portId, supportedModes, supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection);
portInfo.setStatus(currentMode, canChangeMode, portInfo.setStatus(currentMode, canChangeMode,
currentPowerRole, canChangePowerRole, currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole, currentDataRole, canChangeDataRole,
supportedRoleCombinations); supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus);
mPorts.put(portId, portInfo); mPorts.put(portId, portInfo);
} else { } else {
// Sanity check that ports aren't changing definition out from under us. // Sanity check that ports aren't changing definition out from under us.
@ -681,10 +788,32 @@ public class UsbPortManager {
+ ", current=" + UsbPort.modeToString(supportedModes)); + ", current=" + UsbPort.modeToString(supportedModes));
} }
if (supportsEnableContaminantPresenceProtection
!= portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()) {
logAndPrint(Log.WARN, pw,
"Ignoring inconsistent supportsEnableContaminantPresenceProtection"
+ "USB port driver (should be immutable): "
+ "previous="
+ portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()
+ ", current=" + supportsEnableContaminantPresenceProtection);
}
if (supportsEnableContaminantPresenceDetection
!= portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()) {
logAndPrint(Log.WARN, pw,
"Ignoring inconsistent supportsEnableContaminantPresenceDetection "
+ "USB port driver (should be immutable): "
+ "previous="
+ portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()
+ ", current=" + supportsEnableContaminantPresenceDetection);
}
if (portInfo.setStatus(currentMode, canChangeMode, if (portInfo.setStatus(currentMode, canChangeMode,
currentPowerRole, canChangePowerRole, currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole, currentDataRole, canChangeDataRole,
supportedRoleCombinations)) { supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED; portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else { } else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY; portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@ -784,8 +913,14 @@ public class UsbPortManager {
// 0 when port is connected. Else reports the last connected duration // 0 when port is connected. Else reports the last connected duration
public long mLastConnectDurationMillis; public long mLastConnectDurationMillis;
PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes) { PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes,
mUsbPort = new UsbPort(usbManager, portId, supportedModes); int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceDetection,
boolean supportsEnableContaminantPresenceProtection) {
mUsbPort = new UsbPort(usbManager, portId, supportedModes,
supportedContaminantProtectionModes,
supportsEnableContaminantPresenceDetection,
supportsEnableContaminantPresenceProtection);
} }
public boolean setStatus(int currentMode, boolean canChangeMode, public boolean setStatus(int currentMode, boolean canChangeMode,
@ -804,7 +939,45 @@ public class UsbPortManager {
|| mUsbPortStatus.getSupportedRoleCombinations() || mUsbPortStatus.getSupportedRoleCombinations()
!= supportedRoleCombinations) { != supportedRoleCombinations) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole, mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations); supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED);
dispositionChanged = true;
}
if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) {
mConnectedAtMillis = SystemClock.elapsedRealtime();
mLastConnectDurationMillis = 0;
} else if (!mUsbPortStatus.isConnected() && mConnectedAtMillis != 0) {
mLastConnectDurationMillis = SystemClock.elapsedRealtime() - mConnectedAtMillis;
mConnectedAtMillis = 0;
}
return dispositionChanged;
}
public boolean setStatus(int currentMode, boolean canChangeMode,
int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus) {
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 = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus);
dispositionChanged = true; dispositionChanged = true;
} }
@ -855,32 +1028,54 @@ public class UsbPortManager {
private static final class RawPortInfo implements Parcelable { private static final class RawPortInfo implements Parcelable {
public final String portId; public final String portId;
public final int supportedModes; public final int supportedModes;
public final int supportedContaminantProtectionModes;
public int currentMode; public int currentMode;
public boolean canChangeMode; public boolean canChangeMode;
public int currentPowerRole; public int currentPowerRole;
public boolean canChangePowerRole; public boolean canChangePowerRole;
public int currentDataRole; public int currentDataRole;
public boolean canChangeDataRole; public boolean canChangeDataRole;
public boolean supportsEnableContaminantPresenceProtection;
public int contaminantProtectionStatus;
public boolean supportsEnableContaminantPresenceDetection;
public int contaminantDetectionStatus;
RawPortInfo(String portId, int supportedModes) { RawPortInfo(String portId, int supportedModes) {
this.portId = portId; this.portId = portId;
this.supportedModes = supportedModes; this.supportedModes = supportedModes;
this.supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
this.supportsEnableContaminantPresenceProtection = false;
this.contaminantProtectionStatus = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
this.supportsEnableContaminantPresenceDetection = false;
this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
} }
RawPortInfo(String portId, int supportedModes, RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
int currentMode, boolean canChangeMode, int currentMode, boolean canChangeMode,
int currentPowerRole, boolean canChangePowerRole, int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole) { int currentDataRole, boolean canChangeDataRole,
boolean supportsEnableContaminantPresenceProtection,
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus) {
this.portId = portId; this.portId = portId;
this.supportedModes = supportedModes; this.supportedModes = supportedModes;
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
this.currentMode = currentMode; this.currentMode = currentMode;
this.canChangeMode = canChangeMode; this.canChangeMode = canChangeMode;
this.currentPowerRole = currentPowerRole; this.currentPowerRole = currentPowerRole;
this.canChangePowerRole = canChangePowerRole; this.canChangePowerRole = canChangePowerRole;
this.currentDataRole = currentDataRole; this.currentDataRole = currentDataRole;
this.canChangeDataRole = canChangeDataRole; this.canChangeDataRole = canChangeDataRole;
this.supportsEnableContaminantPresenceProtection =
supportsEnableContaminantPresenceProtection;
this.contaminantProtectionStatus = contaminantProtectionStatus;
this.supportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
this.contaminantDetectionStatus = contaminantDetectionStatus;
} }
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@ -890,35 +1085,50 @@ public class UsbPortManager {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(portId); dest.writeString(portId);
dest.writeInt(supportedModes); dest.writeInt(supportedModes);
dest.writeInt(supportedContaminantProtectionModes);
dest.writeInt(currentMode); dest.writeInt(currentMode);
dest.writeByte((byte) (canChangeMode ? 1 : 0)); dest.writeByte((byte) (canChangeMode ? 1 : 0));
dest.writeInt(currentPowerRole); dest.writeInt(currentPowerRole);
dest.writeByte((byte) (canChangePowerRole ? 1 : 0)); dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
dest.writeInt(currentDataRole); dest.writeInt(currentDataRole);
dest.writeByte((byte) (canChangeDataRole ? 1 : 0)); dest.writeByte((byte) (canChangeDataRole ? 1 : 0));
dest.writeBoolean(supportsEnableContaminantPresenceProtection);
dest.writeInt(contaminantProtectionStatus);
dest.writeBoolean(supportsEnableContaminantPresenceDetection);
dest.writeInt(contaminantDetectionStatus);
} }
public static final Parcelable.Creator<RawPortInfo> CREATOR = public static final Parcelable.Creator<RawPortInfo> CREATOR =
new Parcelable.Creator<RawPortInfo>() { new Parcelable.Creator<RawPortInfo>() {
@Override @Override
public RawPortInfo createFromParcel(Parcel in) { public RawPortInfo createFromParcel(Parcel in) {
String id = in.readString(); String id = in.readString();
int supportedModes = in.readInt(); int supportedModes = in.readInt();
int currentMode = in.readInt(); int supportedContaminantProtectionModes = in.readInt();
boolean canChangeMode = in.readByte() != 0; int currentMode = in.readInt();
int currentPowerRole = in.readInt(); boolean canChangeMode = in.readByte() != 0;
boolean canChangePowerRole = in.readByte() != 0; int currentPowerRole = in.readInt();
int currentDataRole = in.readInt(); boolean canChangePowerRole = in.readByte() != 0;
boolean canChangeDataRole = in.readByte() != 0; int currentDataRole = in.readInt();
return new RawPortInfo(id, supportedModes, currentMode, canChangeMode, boolean canChangeDataRole = in.readByte() != 0;
currentPowerRole, canChangePowerRole, boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
currentDataRole, canChangeDataRole); int contaminantProtectionStatus = in.readInt();
} boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
int contaminantDetectionStatus = in.readInt();
return new RawPortInfo(id, supportedModes,
supportedContaminantProtectionModes, currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportsEnableContaminantPresenceProtection,
contaminantProtectionStatus,
supportsEnableContaminantPresenceDetection,
contaminantDetectionStatus);
}
@Override @Override
public RawPortInfo[] newArray(int size) { public RawPortInfo[] newArray(int size) {
return new RawPortInfo[size]; return new RawPortInfo[size];
} }
}; };
} }
} }

View File

@ -553,6 +553,21 @@ public class UsbService extends IUsbManager.Stub {
} }
} }
@Override
public void enableContaminantDetection(String portId, boolean enable) {
Preconditions.checkNotNull(portId, "portId must not be null");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
final long ident = Binder.clearCallingIdentity();
try {
if (mPortManager != null) {
mPortManager.enableContaminantDetection(portId, enable, null);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override @Override
public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) { public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);