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.usb-V1.0-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.1-java",
"android.hardware.vibrator-V1.2-java",

View File

@ -120,6 +120,9 @@ interface IUsbManager
/* Sets the port's current role. */
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. */
void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
}

View File

@ -31,10 +31,21 @@ import com.android.internal.annotations.Immutable;
public final class ParcelableUsbPort implements Parcelable {
private final @NonNull String mId;
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;
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
*/
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
*/
public @NonNull UsbPort getUsbPort(@NonNull UsbManager usbManager) {
return new UsbPort(usbManager, mId, mSupportedModes);
return new UsbPort(usbManager, mId, mSupportedModes, mSupportedContaminantProtectionModes,
mSupportsEnableContaminantPresenceProtection,
mSupportsEnableContaminantPresenceDetection);
}
@Override
@ -68,6 +84,9 @@ public final class ParcelableUsbPort implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mId);
dest.writeInt(mSupportedModes);
dest.writeInt(mSupportedContaminantProtectionModes);
dest.writeBoolean(mSupportsEnableContaminantPresenceProtection);
dest.writeBoolean(mSupportsEnableContaminantPresenceDetection);
}
public static final Creator<ParcelableUsbPort> CREATOR =
@ -76,7 +95,14 @@ public final class ParcelableUsbPort implements Parcelable {
public ParcelableUsbPort createFromParcel(Parcel in) {
String id = in.readString();
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

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.
* <p>

View File

@ -16,6 +16,10 @@
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_HOST;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
@ -48,16 +52,21 @@ public final class 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 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;
/** @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.checkFlagsArgument(supportedModes,
MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);
@ -65,6 +74,11 @@ public final class UsbPort {
mUsbManager = usbManager;
mId = id;
mSupportedModes = supportedModes;
mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
mSupportsEnableContaminantPresenceProtection =
supportsEnableContaminantPresenceProtection;
mSupportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
}
/**
@ -93,6 +107,36 @@ public final class UsbPort {
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.
*
@ -130,6 +174,12 @@ public final class UsbPort {
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
* 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 */
public static String roleCombinationsToString(int combo) {
StringBuilder result = new StringBuilder();
@ -264,6 +330,11 @@ public final class UsbPort {
@Override
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 @UsbDataRole int mCurrentDataRole;
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.
@ -131,6 +133,93 @@ public final class UsbPortStatus implements Parcelable {
public static final int MODE_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 = {
MODE_NONE,
MODE_DFP,
@ -142,12 +231,15 @@ public final class UsbPortStatus implements Parcelable {
@interface UsbPortMode{}
/** @hide */
public UsbPortStatus(int currentMode, @UsbPowerRole int currentPowerRole,
@UsbDataRole int currentDataRole, int supportedRoleCombinations) {
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;
}
/**
@ -212,6 +304,24 @@ public final class UsbPortStatus implements Parcelable {
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
public String toString() {
return "UsbPortStatus{connected=" + isConnected()
@ -220,6 +330,10 @@ public final class UsbPortStatus implements Parcelable {
+ ", currentDataRole=" + UsbPort.dataRoleToString(mCurrentDataRole)
+ ", supportedRoleCombinations="
+ UsbPort.roleCombinationsToString(mSupportedRoleCombinations)
+ ", contaminantDetectionStatus="
+ getContaminantDetectionStatus()
+ ", contaminantProtectionStatus="
+ getContaminantProtectionStatus()
+ "}";
}
@ -234,6 +348,8 @@ public final class UsbPortStatus implements Parcelable {
dest.writeInt(mCurrentPowerRole);
dest.writeInt(mCurrentDataRole);
dest.writeInt(mSupportedRoleCombinations);
dest.writeInt(mContaminantProtectionStatus);
dest.writeInt(mContaminantDetectionStatus);
}
public static final Parcelable.Creator<UsbPortStatus> CREATOR =
@ -244,8 +360,11 @@ public final class UsbPortStatus implements Parcelable {
int currentPowerRole = in.readInt();
int currentDataRole = in.readInt();
int supportedRoleCombinations = in.readInt();
int contaminantProtectionStatus = in.readInt();
int contaminantDetectionStatus = in.readInt();
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations);
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus);
}
@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,
long id, @NonNull UsbPortStatus status) {
@ -232,6 +241,10 @@ public class DumpUtils {
dump.end(roleCombinationToken);
}
writeContaminantPresenceStatus(dump, "contaminant_presence_status",
UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
status.getContaminantDetectionStatus());
dump.end(token);
}
}

View File

@ -245,11 +245,20 @@ message UsbPortStatusProto {
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 UsbPortProto.Mode current_mode = 2;
optional PowerRole power_role = 3;
optional DataRole data_role = 4;
repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
optional ContaminantPresenceStatus contaminant_presence_status = 6;
}
message UsbPortStatusRoleCombinationProto {

View File

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

View File

@ -16,6 +16,8 @@
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_HOST;
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.UsbPort;
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.PortRoleType;
import android.hardware.usb.V1_0.PortStatus;
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_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.IServiceNotification;
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,
IndentingPrintWriter pw) {
synchronized (mLock) {
@ -441,7 +480,8 @@ public class UsbPortManager {
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) {
return;
}
@ -453,14 +493,17 @@ public class UsbPortManager {
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
for (PortStatus current : currentPortStatus) {
for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
RawPortInfo temp = new RawPortInfo(current.portName,
current.supportedModes, current.currentMode,
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
current.currentMode,
current.canChangeMode, current.currentPowerRole,
current.canChangePowerRole,
current.currentDataRole, current.canChangeDataRole);
current.currentDataRole, current.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
newPortInfo.add(temp);
logAndPrint(Log.INFO, pw, "ClientCallback: " + current.portName);
logAndPrint(Log.INFO, pw, "ClientCallback V1_0: " + current.portName);
}
Message message = portManager.mHandler.obtainMessage();
@ -485,14 +528,61 @@ public class UsbPortManager {
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,
current.supportedModes, current.currentMode,
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
current.currentMode,
current.status.canChangeMode, current.status.currentPowerRole,
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);
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();
@ -573,16 +663,26 @@ public class UsbPortManager {
for (int i = 0; i < count; i++) {
final RawPortInfo portInfo = mSimulatedPorts.valueAt(i);
addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes,
portInfo.supportedContaminantProtectionModes,
portInfo.currentMode, portInfo.canChangeMode,
portInfo.currentPowerRole, portInfo.canChangePowerRole,
portInfo.currentDataRole, portInfo.canChangeDataRole, pw);
portInfo.currentDataRole, portInfo.canChangeDataRole,
portInfo.supportsEnableContaminantPresenceProtection,
portInfo.contaminantProtectionStatus,
portInfo.supportsEnableContaminantPresenceDetection,
portInfo.contaminantDetectionStatus, pw);
}
} else {
for (RawPortInfo currentPortInfo : newPortInfo) {
addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes,
currentPortInfo.supportedContaminantProtectionModes,
currentPortInfo.currentMode, currentPortInfo.canChangeMode,
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.
private void addOrUpdatePortLocked(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,
IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect.
@ -664,12 +768,15 @@ public class UsbPortManager {
// Update the port data structures.
PortInfo portInfo = mPorts.get(portId);
if (portInfo == null) {
portInfo = new PortInfo(mContext.getSystemService(UsbManager.class), portId,
supportedModes);
portInfo = new PortInfo(mContext.getSystemService(UsbManager.class),
portId, supportedModes, supportedContaminantProtectionModes,
supportsEnableContaminantPresenceProtection,
supportsEnableContaminantPresenceDetection);
portInfo.setStatus(currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations);
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus);
mPorts.put(portId, portInfo);
} else {
// Sanity check that ports aren't changing definition out from under us.
@ -681,10 +788,32 @@ public class UsbPortManager {
+ ", 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,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations)) {
supportedRoleCombinations, contaminantProtectionStatus,
contaminantDetectionStatus)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@ -784,8 +913,14 @@ public class UsbPortManager {
// 0 when port is connected. Else reports the last connected duration
public long mLastConnectDurationMillis;
PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes) {
mUsbPort = new UsbPort(usbManager, portId, supportedModes);
PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes,
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceDetection,
boolean supportsEnableContaminantPresenceProtection) {
mUsbPort = new UsbPort(usbManager, portId, supportedModes,
supportedContaminantProtectionModes,
supportsEnableContaminantPresenceDetection,
supportsEnableContaminantPresenceProtection);
}
public boolean setStatus(int currentMode, boolean canChangeMode,
@ -804,7 +939,45 @@ public class UsbPortManager {
|| mUsbPortStatus.getSupportedRoleCombinations()
!= supportedRoleCombinations) {
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;
}
@ -855,32 +1028,54 @@ public class UsbPortManager {
private static final class RawPortInfo implements Parcelable {
public final String portId;
public final int supportedModes;
public final int supportedContaminantProtectionModes;
public int currentMode;
public boolean canChangeMode;
public int currentPowerRole;
public boolean canChangePowerRole;
public int currentDataRole;
public boolean canChangeDataRole;
public boolean supportsEnableContaminantPresenceProtection;
public int contaminantProtectionStatus;
public boolean supportsEnableContaminantPresenceDetection;
public int contaminantDetectionStatus;
RawPortInfo(String portId, int supportedModes) {
this.portId = portId;
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 currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole) {
int currentDataRole, boolean canChangeDataRole,
boolean supportsEnableContaminantPresenceProtection,
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus) {
this.portId = portId;
this.supportedModes = supportedModes;
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
this.currentMode = currentMode;
this.canChangeMode = canChangeMode;
this.currentPowerRole = currentPowerRole;
this.canChangePowerRole = canChangePowerRole;
this.currentDataRole = currentDataRole;
this.canChangeDataRole = canChangeDataRole;
this.supportsEnableContaminantPresenceProtection =
supportsEnableContaminantPresenceProtection;
this.contaminantProtectionStatus = contaminantProtectionStatus;
this.supportsEnableContaminantPresenceDetection =
supportsEnableContaminantPresenceDetection;
this.contaminantDetectionStatus = contaminantDetectionStatus;
}
@Override
public int describeContents() {
return 0;
@ -890,35 +1085,50 @@ public class UsbPortManager {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(portId);
dest.writeInt(supportedModes);
dest.writeInt(supportedContaminantProtectionModes);
dest.writeInt(currentMode);
dest.writeByte((byte) (canChangeMode ? 1 : 0));
dest.writeInt(currentPowerRole);
dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
dest.writeInt(currentDataRole);
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 =
new Parcelable.Creator<RawPortInfo>() {
@Override
public RawPortInfo createFromParcel(Parcel in) {
String id = in.readString();
int supportedModes = in.readInt();
int currentMode = in.readInt();
boolean canChangeMode = in.readByte() != 0;
int currentPowerRole = in.readInt();
boolean canChangePowerRole = in.readByte() != 0;
int currentDataRole = in.readInt();
boolean canChangeDataRole = in.readByte() != 0;
return new RawPortInfo(id, supportedModes, currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole);
}
@Override
public RawPortInfo createFromParcel(Parcel in) {
String id = in.readString();
int supportedModes = in.readInt();
int supportedContaminantProtectionModes = in.readInt();
int currentMode = in.readInt();
boolean canChangeMode = in.readByte() != 0;
int currentPowerRole = in.readInt();
boolean canChangePowerRole = in.readByte() != 0;
int currentDataRole = in.readInt();
boolean canChangeDataRole = in.readByte() != 0;
boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
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
public RawPortInfo[] newArray(int size) {
return new RawPortInfo[size];
}
};
@Override
public RawPortInfo[] newArray(int 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
public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);