From e966a38b67e23eaea63cab14f7b430e017499085 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Sun, 9 Dec 2018 14:49:38 -0800 Subject: [PATCH] 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 --- Android.bp | 1 + .../android/hardware/usb/IUsbManager.aidl | 3 + .../hardware/usb/ParcelableUsbPort.java | 34 +- .../java/android/hardware/usb/UsbManager.java | 14 + core/java/android/hardware/usb/UsbPort.java | 77 ++++- .../android/hardware/usb/UsbPortStatus.java | 125 +++++++- .../com/android/internal/usb/DumpUtils.java | 13 + core/proto/android/service/usb.proto | 9 + services/usb/Android.bp | 1 + .../android/server/usb/UsbPortManager.java | 296 +++++++++++++++--- .../com/android/server/usb/UsbService.java | 15 + 11 files changed, 535 insertions(+), 53 deletions(-) diff --git a/Android.bp b/Android.bp index b68312b47c46..8f18a46a7f89 100644 --- a/Android.bp +++ b/Android.bp @@ -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", diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index edc3f9466efc..299a00a426d4 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -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); } diff --git a/core/java/android/hardware/usb/ParcelableUsbPort.java b/core/java/android/hardware/usb/ParcelableUsbPort.java index 7f7ba96b40f2..30388afc0d13 100644 --- a/core/java/android/hardware/usb/ParcelableUsbPort.java +++ b/core/java/android/hardware/usb/ParcelableUsbPort.java @@ -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 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 diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 601447814952..eb148b94ac7b 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -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. *

diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java index 37154e4c81b2..c674480c2a75 100644 --- a/core/java/android/hardware/usb/UsbPort.java +++ b/core/java/android/hardware/usb/UsbPort.java @@ -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. + *

+ * The actual mode of the port is decided by the hardware + *

+ * + * @hide + */ + public int getSupportedContaminantProtectionModes() { + return mSupportedContaminantProtectionModes; + } + + /** + * Tells if UsbService can enable/disable contaminant presence protection. + * + * @hide + */ + public boolean supportsEnableContaminantPresenceProtection() { + return mSupportsEnableContaminantPresenceProtection; + } + + /** + * Tells if UsbService can enable/disable contaminant presence detection. + * + * @hide + */ + public boolean supportsEnableContaminantPresenceDetection() { + return mSupportsEnableContaminantPresenceDetection; + } + /** * Gets the status of this USB port. * @@ -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; } } diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java index d30201a597bf..426dba88c399 100644 --- a/core/java/android/hardware/usb/UsbPortStatus.java +++ b/core/java/android/hardware/usb/UsbPortStatus.java @@ -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 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 diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java index 240c2e757faf..32601368f2fb 100644 --- a/core/java/com/android/internal/usb/DumpUtils.java +++ b/core/java/com/android/internal/usb/DumpUtils.java @@ -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); } } diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto index f7dcee282a57..00fae3d83ebc 100644 --- a/core/proto/android/service/usb.proto +++ b/core/proto/android/service/usb.proto @@ -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 { diff --git a/services/usb/Android.bp b/services/usb/Android.bp index feb7b76ae119..20855b70cabc 100644 --- a/services/usb/Android.bp +++ b/services/usb/Android.bp @@ -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", ], } diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index 6f210e37d6d1..3d051d8524de 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -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 currentPortStatus, int retval) { + public void notifyPortStatusChange( + ArrayList currentPortStatus, int retval) { if (!portManager.mSystemReady) { return; } @@ -453,14 +493,17 @@ public class UsbPortManager { ArrayList 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 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 currentPortStatus, int retval) { + if (!portManager.mSystemReady) { + return; + } + + if (retval != Status.SUCCESS) { + logAndPrint(Log.ERROR, pw, "port status enquiry failed"); + return; + } + + ArrayList 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 CREATOR = new Parcelable.Creator() { - @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]; + } + }; } } diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 911547720a8f..9be542fe3d25 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -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);