From b9f69ea7763fe7e9ce1af933acb9b9aae9bbff8f Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 19 Oct 2021 13:09:44 -0700 Subject: [PATCH 1/4] Migrate IUsb to AIDL This change migrates android.hardware.usb.IUsb to AIDL and adds the default implementation. Compared to the HIDL interface, AIDL based interface adds transactionId argument to each of the interface method which is used while invoking the corresponding callback. Bug: 200993386 Bug: 199357330 Test: Ran new hal implementation on Pixel. Yet to run VTS. Change-Id: Id8aa40682d4c4b435c63b3ae249b176276dbb31d --- .../compatibility_matrix.current.xml | 7 + usb/aidl/Android.bp | 33 + .../usb/ContaminantDetectionStatus.aidl | 41 ++ .../usb/ContaminantProtectionMode.aidl | 41 ++ .../usb/ContaminantProtectionStatus.aidl | 42 ++ .../current/android/hardware/usb/IUsb.aidl | 42 ++ .../android/hardware/usb/IUsbCallback.aidl | 42 ++ .../android/hardware/usb/PortDataRole.aidl | 40 + .../android/hardware/usb/PortMode.aidl | 43 ++ .../android/hardware/usb/PortPowerRole.aidl | 40 + .../android/hardware/usb/PortRole.aidl | 40 + .../android/hardware/usb/PortStatus.aidl | 51 ++ .../current/android/hardware/usb/Status.aidl | 42 ++ .../usb/ContaminantDetectionStatus.aidl | 37 + .../usb/ContaminantProtectionMode.aidl | 43 ++ .../usb/ContaminantProtectionStatus.aidl | 51 ++ usb/aidl/android/hardware/usb/IUsb.aidl | 85 +++ .../android/hardware/usb/IUsbCallback.aidl | 86 +++ .../android/hardware/usb/PortDataRole.aidl | 35 + usb/aidl/android/hardware/usb/PortMode.aidl | 49 ++ .../android/hardware/usb/PortPowerRole.aidl | 35 + usb/aidl/android/hardware/usb/PortRole.aidl | 31 + usb/aidl/android/hardware/usb/PortStatus.aidl | 107 +++ usb/aidl/android/hardware/usb/Status.aidl | 39 + usb/aidl/conversion.log | 11 + usb/aidl/default/Android.bp | 35 + usb/aidl/default/Usb.cpp | 693 ++++++++++++++++++ usb/aidl/default/Usb.h | 76 ++ .../android.hardware.usb-service.example.rc | 4 + .../android.hardware.usb-service.example.xml | 10 + usb/aidl/default/service.cpp | 35 + 31 files changed, 1966 insertions(+) create mode 100644 usb/aidl/Android.bp create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl create mode 100644 usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl create mode 100644 usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl create mode 100644 usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl create mode 100644 usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl create mode 100644 usb/aidl/android/hardware/usb/IUsb.aidl create mode 100644 usb/aidl/android/hardware/usb/IUsbCallback.aidl create mode 100644 usb/aidl/android/hardware/usb/PortDataRole.aidl create mode 100644 usb/aidl/android/hardware/usb/PortMode.aidl create mode 100644 usb/aidl/android/hardware/usb/PortPowerRole.aidl create mode 100644 usb/aidl/android/hardware/usb/PortRole.aidl create mode 100644 usb/aidl/android/hardware/usb/PortStatus.aidl create mode 100644 usb/aidl/android/hardware/usb/Status.aidl create mode 100644 usb/aidl/conversion.log create mode 100644 usb/aidl/default/Android.bp create mode 100644 usb/aidl/default/Usb.cpp create mode 100644 usb/aidl/default/Usb.h create mode 100644 usb/aidl/default/android.hardware.usb-service.example.rc create mode 100644 usb/aidl/default/android.hardware.usb-service.example.xml create mode 100644 usb/aidl/default/service.cpp diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 74d93b39ef..3a5f5eff0f 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -702,6 +702,13 @@ default + + android.hardware.usb + + IUsb + default + + android.hardware.usb.gadget 1.0-2 diff --git a/usb/aidl/Android.bp b/usb/aidl/Android.bp new file mode 100644 index 0000000000..d1e9e680e9 --- /dev/null +++ b/usb/aidl/Android.bp @@ -0,0 +1,33 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +aidl_interface { + name: "android.hardware.usb", + vendor_available: true, + srcs: ["android/hardware/usb/*.aidl"], + stability: "vintf", + backend: { + cpp: { + enabled: false, + }, + java: { + sdk_version: "module_current", + }, + ndk: { + vndk: { + enabled: true, + }, + }, + }, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl new file mode 100644 index 0000000000..24c69664f7 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum ContaminantDetectionStatus { + NOT_SUPPORTED = 0, + DISABLED = 1, + NOT_DETECTED = 2, + DETECTED = 3, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl new file mode 100644 index 0000000000..99798693ff --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum ContaminantProtectionMode { + NONE = 0, + FORCE_SINK = 1, + FORCE_SOURCE = 2, + FORCE_DISABLE = 3, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl new file mode 100644 index 0000000000..9642261444 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum ContaminantProtectionStatus { + NONE = 0, + FORCE_SINK = 1, + FORCE_SOURCE = 2, + FORCE_DISABLE = 3, + DISABLED = 4, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl new file mode 100644 index 0000000000..7513461afb --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +interface IUsb { + oneway void enableContaminantPresenceDetection(in String portName, in boolean enable, long transactionId); + oneway void enableUsbData(in String portName, boolean enable, long transactionId); + oneway void queryPortStatus(long transactionId); + oneway void setCallback(in android.hardware.usb.IUsbCallback callback); + oneway void switchRole(in String portName, in android.hardware.usb.PortRole role, long transactionId); +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl new file mode 100644 index 0000000000..57be590563 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +interface IUsbCallback { + oneway void notifyPortStatusChange(in android.hardware.usb.PortStatus[] currentPortStatus, in android.hardware.usb.Status retval); + oneway void notifyRoleSwitchStatus(in String portName, in android.hardware.usb.PortRole newRole, in android.hardware.usb.Status retval, long transactionId); + oneway void notifyEnableUsbDataStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId); + oneway void notifyContaminantEnabledStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId); + oneway void notifyQueryPortStatus(in String portName, in android.hardware.usb.Status retval, long transactionId); +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl new file mode 100644 index 0000000000..105b316775 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum PortDataRole { + NONE = 0, + HOST = 1, + DEVICE = 2, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl new file mode 100644 index 0000000000..34e43343ad --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum PortMode { + NONE = 0, + UFP = 1, + DFP = 2, + DRP = 3, + AUDIO_ACCESSORY = 4, + DEBUG_ACCESSORY = 5, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl new file mode 100644 index 0000000000..0e6f3fb426 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +enum PortPowerRole { + NONE = 0, + SOURCE = 1, + SINK = 2, +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl new file mode 100644 index 0000000000..c66aeccde9 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +union PortRole { + android.hardware.usb.PortPowerRole powerRole = android.hardware.usb.PortPowerRole.NONE; + android.hardware.usb.PortDataRole dataRole; + android.hardware.usb.PortMode mode; +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl new file mode 100644 index 0000000000..78dcfacef9 --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@VintfStability +parcelable PortStatus { + String portName; + android.hardware.usb.PortDataRole currentDataRole = android.hardware.usb.PortDataRole.NONE; + android.hardware.usb.PortPowerRole currentPowerRole = android.hardware.usb.PortPowerRole.NONE; + android.hardware.usb.PortMode currentMode = android.hardware.usb.PortMode.NONE; + boolean canChangeMode; + boolean canChangeDataRole; + boolean canChangePowerRole; + android.hardware.usb.PortMode[] supportedModes; + android.hardware.usb.ContaminantProtectionMode[] supportedContaminantProtectionModes; + boolean supportsEnableContaminantPresenceProtection; + android.hardware.usb.ContaminantProtectionStatus contaminantProtectionStatus = android.hardware.usb.ContaminantProtectionStatus.NONE; + boolean supportsEnableContaminantPresenceDetection; + android.hardware.usb.ContaminantDetectionStatus contaminantDetectionStatus = android.hardware.usb.ContaminantDetectionStatus.NOT_SUPPORTED; + boolean usbDataEnabled; +} diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl new file mode 100644 index 0000000000..f28fc2a70e --- /dev/null +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.usb; +@Backing(type="int") @VintfStability +enum Status { + SUCCESS = 0, + ERROR = 1, + INVALID_ARGUMENT = 2, + UNRECOGNIZED_ROLE = 3, + NOT_SUPPORTED = 4, +} diff --git a/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl b/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl new file mode 100644 index 0000000000..d9bc576f94 --- /dev/null +++ b/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +@VintfStability +enum ContaminantDetectionStatus { + /** + * Contaminant presence detection is not supported. + */ + NOT_SUPPORTED = 0, + /** + * Contaminant presence detection is supported but disabled. + */ + DISABLED = 1, + /** + * Contaminant presence detection is enabled and contaminant not detected. + */ + NOT_DETECTED = 2, + /** + * Contaminant presence detection is enabled and contaminant detected. + */ + DETECTED = 3, +} diff --git a/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl b/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl new file mode 100644 index 0000000000..47c073dcc4 --- /dev/null +++ b/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +@VintfStability +enum ContaminantProtectionMode { + /** + * No action performed upon detection of contaminant presence. + */ + NONE = 0, + /** + * Upon detection of contaminant presence, Port is forced to sink only + * mode where a port shall only detect chargers until contaminant presence + * is no longer detected. + */ + FORCE_SINK = 1, + /** + * Upon detection of contaminant presence, Port is forced to source only + * mode where a port shall only detect usb accessories such as headsets + * until contaminant presence is no longer detected. + */ + FORCE_SOURCE = 2, + /** + * Upon detection of contaminant presence, port is disabled until contaminant + * presence is no longer detected. In the disabled state port will + * not respond to connection of chargers or usb accessories. + */ + FORCE_DISABLE = 3, +} diff --git a/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl b/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl new file mode 100644 index 0000000000..c4fa979698 --- /dev/null +++ b/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.hardware.usb.ContaminantProtectionMode; + +@VintfStability +enum ContaminantProtectionStatus { + /** + * No action performed upon detection of contaminant presence. + */ + NONE = 0, + /** + * Upon detection of contaminant presence, Port is forced to sink only + * mode where a port shall only detect chargers until contaminant presence + * is no longer detected. + */ + FORCE_SINK = 1, + /** + * Upon detection of contaminant presence, Port is forced to source only + * mode where a port shall only detect usb accessories such as headsets + * until contaminant presence is no longer detected. + */ + FORCE_SOURCE = 2, + /** + * Upon detection of contaminant presence, port is disabled until contaminant + * presence is no longer detected. In the disabled state port will + * not respond to connection of chargers or usb accessories. + */ + FORCE_DISABLE = 3, + /** + * Client disabled cotaminant protection by calling + * enableContaminantPresencePortProtection set to false. Low level drivers should + * not autmomously take any corrective action when contaminant presence is detected. + */ + DISABLED = 4, +} diff --git a/usb/aidl/android/hardware/usb/IUsb.aidl b/usb/aidl/android/hardware/usb/IUsb.aidl new file mode 100644 index 0000000000..9a8f0006ee --- /dev/null +++ b/usb/aidl/android/hardware/usb/IUsb.aidl @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.hardware.usb.IUsbCallback; +import android.hardware.usb.PortRole; + +@VintfStability +oneway interface IUsb { + /** + * When supportsEnableContaminantPresenceDetection is true, + * enableContaminantPresenceDetection enables/disables contaminant + * presence detection algorithm. Calling enableContaminantPresenceDetection + * when supportsEnableContaminantPresenceDetection is false does + * not have any effect. + * Change in contantaminant presence status should be notified to the + * client via notifyPortStatusChange through PortStatus. + * + * @param portName name of the port. + * @param enable true Enable contaminant presence detection algorithm. + * false Disable contaminant presence detection algorithm. + * @param transactionId ID to be used when invoking the callback. + */ + void enableContaminantPresenceDetection(in String portName, in boolean enable, long transactionId); + + /** + * This function is used to enable/disable USB data controller. + * + * @param portName Name of the port. + * @param enable true Enable USB data signaling. + * false Disable USB data signaling. + * @param transactionId ID to be used when invoking the callback. + * + */ + void enableUsbData(in String portName, boolean enable, long transactionId); + + /** + * This functions is used to request the hal for the current status + * status of the Type-C ports. The result of the query would be sent + * through the IUsbCallback object's notifyRoleSwitchStatus + * to the caller. This api would would let the caller know of the number + * of type-c ports that are present and their connection status through the + * PortStatus type. + * @param transactionId ID to be used when invoking the callback. + */ + void queryPortStatus(long transactionId); + + /** + * This function is used to register a callback function which is + * called by the HAL to inform the client of port status updates and + * result of the requested operation. Please refer IUsbCallback for + * complete description of when each of the IUsbCallback's interface + * methods is expected to be called. + * + * @param callback IUsbCallback object used to convey status to the + * userspace. + */ + void setCallback(in IUsbCallback callback); + + /** + * This function is used to change the port role of a specific port. + * For example, when DR_SWAP or PR_SWAP is supported. + * The status of the role switch will be informed through IUsbCallback + * object's notifyPortStatusChange method. + * + * @param portName name of the port for which the role has to be changed + * @param role the new port role. + * @param transactionId ID to be used when invoking the callback. + */ + void switchRole(in String portName, in PortRole role, long transactionId); +} diff --git a/usb/aidl/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/android/hardware/usb/IUsbCallback.aidl new file mode 100644 index 0000000000..232a15babe --- /dev/null +++ b/usb/aidl/android/hardware/usb/IUsbCallback.aidl @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.usb; + +import android.hardware.usb.PortRole; +import android.hardware.usb.PortStatus; +import android.hardware.usb.Status; + +/** + * Callback object used for all the IUsb async methods which expects a result. + * Caller is expected to register the callback object using setCallback method + * to receive updates on the PortStatus. + */ +@VintfStability +oneway interface IUsbCallback { + /** + * Used to convey the current port status to the caller. + * Must be called either when PortState changes due to the port partner or + * when caller requested for the PortStatus update through queryPortStatus. + * + * @param currentPortStatus describes the status of all the USB ports in the + * device. + * @param retval SUCCESS when the required information was enquired form + * kernel and the PortStatus object was built. + * ERROR otherwise. + */ + void notifyPortStatusChange(in PortStatus[] currentPortStatus, in Status retval); + + /** + * Used to notify the result of the switchRole call to the caller. + * + * @param portName name of the port for which the roleswap is requested. + * @param newRole the new role requested by the caller. + * @param retval SUCCESS if the role switch succeeded. FAILURE otherwise. + * @param transactionId transactionId sent during switchRole request. + */ + void notifyRoleSwitchStatus(in String portName, in PortRole newRole, in Status retval, + long transactionId); + + /** + * Used to notify the result of notifyEnableUsbDataStatus call to the caller. + * + * @param portName name of the port for which the enableUsbData is requested. + * @param enable true when usb data is enabled. + * false when usb data is disabled. + * @param retval SUCCESS if current request succeeded. FAILURE otherwise. + * @param transactionId transactionId sent during enableUsbData request. + */ + void notifyEnableUsbDataStatus(in String portName, boolean enable, in Status retval, + long transactionId); + + /** + * Used to notify the result of enableContaminantPresenceDetection. + * + * @param portName name of the port for which contaminant detection is enabled/disabled. + * @param enable true when contaminant detection is enabled. + * false when disabled. + * @param retval SUCCESS if the request for enabling/disabling contamiant detection succeeds. + * FAILURE otherwise. + * @param transactionId transactionId sent during queryPortStatus request + */ + void notifyContaminantEnabledStatus(in String portName, boolean enable, in Status retval, + long transactionId); + + /** + * Used to notify the request to query port status. + * + * @param portName name of the port for which port status is queried. + * @param retval SUCCESS if the port query succeeded. FAILURE otherwise. + * @param transactionId transactionId sent during queryPortStatus request + */ + void notifyQueryPortStatus(in String portName, in Status retval, long transactionId); +} diff --git a/usb/aidl/android/hardware/usb/PortDataRole.aidl b/usb/aidl/android/hardware/usb/PortDataRole.aidl new file mode 100644 index 0000000000..a69f97719e --- /dev/null +++ b/usb/aidl/android/hardware/usb/PortDataRole.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +@VintfStability +enum PortDataRole { + /** + * Indicates that the port does not have a data role. + * In case of DRP, the current data role of the port is only resolved + * when the type-c handshake happens. + */ + NONE = 0, + /** + * Indicates that the port is acting as a host for data. + */ + HOST = 1, + /** + * Indicated that the port is acting as a device for data. + */ + DEVICE = 2, +} diff --git a/usb/aidl/android/hardware/usb/PortMode.aidl b/usb/aidl/android/hardware/usb/PortMode.aidl new file mode 100644 index 0000000000..399f0ebaeb --- /dev/null +++ b/usb/aidl/android/hardware/usb/PortMode.aidl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.hardware.usb.PortMode; + +@VintfStability +enum PortMode { + /** + * Indicates that the port does not have a mode. + * In case of DRP, the current mode of the port is only resolved + * when the type-c handshake happens. + */ + NONE = 0, + /** + * Indicates that port can only act as device for data and sink for power. + */ + UFP = 1, + /** + * Indicates the port can only act as host for data and source for power. + */ + DFP = 2, + /** + * Indicates can either act as UFP or DFP at a given point of time. + */ + DRP = 3, + /* + * Indicates that the port supports Audio Accessory mode. + */ + AUDIO_ACCESSORY = 4, + /* + * Indicates that the port supports Debug Accessory mode. + */ + DEBUG_ACCESSORY = 5, +} diff --git a/usb/aidl/android/hardware/usb/PortPowerRole.aidl b/usb/aidl/android/hardware/usb/PortPowerRole.aidl new file mode 100644 index 0000000000..ae3dc47c45 --- /dev/null +++ b/usb/aidl/android/hardware/usb/PortPowerRole.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +@VintfStability +enum PortPowerRole { + /** + * Indicates that the port does not have a power role. + * In case of DRP, the current power role of the port is only resolved + * when the type-c handshake happens. + */ + NONE = 0, + /** + * Indicates that the port is supplying power to the other port. + */ + SOURCE = 1, + /** + * Indicates that the port is sinking power from the other port. + */ + SINK = 2, +} diff --git a/usb/aidl/android/hardware/usb/PortRole.aidl b/usb/aidl/android/hardware/usb/PortRole.aidl new file mode 100644 index 0000000000..e0429c8b74 --- /dev/null +++ b/usb/aidl/android/hardware/usb/PortRole.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.hardware.usb.PortDataRole; +import android.hardware.usb.PortMode; +import android.hardware.usb.PortPowerRole; + +/** + * Used as a container to send port role information. + */ +@VintfStability +union PortRole { + PortPowerRole powerRole = PortPowerRole.NONE; + PortDataRole dataRole; + PortMode mode; +} diff --git a/usb/aidl/android/hardware/usb/PortStatus.aidl b/usb/aidl/android/hardware/usb/PortStatus.aidl new file mode 100644 index 0000000000..8afe00916c --- /dev/null +++ b/usb/aidl/android/hardware/usb/PortStatus.aidl @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.hardware.usb.ContaminantDetectionStatus; +import android.hardware.usb.ContaminantProtectionMode; +import android.hardware.usb.ContaminantProtectionStatus; +import android.hardware.usb.PortDataRole; +import android.hardware.usb.PortMode; +import android.hardware.usb.PortPowerRole; + +@VintfStability +parcelable PortStatus { + /** + * Name of the port. + * Used as the port's id by the caller. + */ + String portName; + /** + * Data role of the port. + */ + PortDataRole currentDataRole = PortDataRole.NONE; + /** + * Power Role of thte port. + */ + PortPowerRole currentPowerRole = PortPowerRole.NONE; + /** + * Mode in which the port is connected. + * Can be UFP or DFP or AUDIO_ACCESSORY or + * DEBUG_ACCESSORY. + */ + PortMode currentMode = PortMode.NONE; + /** + * True indicates that the port's mode can + * be changed. False otherwise. + */ + boolean canChangeMode; + /** + * True indicates that the port's data role + * can be changed. False otherwise. + * For example, true if Type-C PD PD_SWAP + * is supported. + */ + boolean canChangeDataRole; + /** + * True indicates that the port's power role + * can be changed. False otherwise. + * For example, true if Type-C PD PR_SWAP + * is supported. + */ + boolean canChangePowerRole; + /** + * Identifies the type of the local port. + * + * UFP - Indicates that port can only act as device for + * data and sink for power. + * DFP - Indicates the port can only act as host for data + * and source for power. + * DRP - Indicates can either act as UFP or DFP at a + * given point of time. + * AUDIO_ACCESSORY - Indicates that the port supports + * Audio Accessory mode. + * DEBUG_ACCESSORY - Indicates that the port supports + * Debug Accessory mode. + */ + PortMode[] supportedModes; + /** + * Contaminant presence protection modes supported by the port. + */ + ContaminantProtectionMode[] supportedContaminantProtectionModes; + /** + * Client can enable/disable contaminant presence protection through + * enableContaminantPresenceProtection when true. + */ + boolean supportsEnableContaminantPresenceProtection; + /** + * Contaminant presence protection modes currently active for the port. + */ + ContaminantProtectionStatus contaminantProtectionStatus = ContaminantProtectionStatus.NONE; + /** + * Client can enable/disable contaminant presence detection through + * enableContaminantPresenceDetection when true. + */ + boolean supportsEnableContaminantPresenceDetection; + /** + * Current status of contaminant detection algorithm. + */ + ContaminantDetectionStatus contaminantDetectionStatus = ContaminantDetectionStatus.NOT_SUPPORTED; + /** + * UsbData status of the port. + */ + boolean usbDataEnabled; +} diff --git a/usb/aidl/android/hardware/usb/Status.aidl b/usb/aidl/android/hardware/usb/Status.aidl new file mode 100644 index 0000000000..468ba4a068 --- /dev/null +++ b/usb/aidl/android/hardware/usb/Status.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +@VintfStability +@Backing(type="int") +enum Status { + SUCCESS = 0, + /** + * error value when the HAL operation fails for reasons not listed here. + */ + ERROR = 1, + /** + * error value returned when input argument is invalid. + */ + INVALID_ARGUMENT = 2, + /** + * error value returned when role string is unrecognized. + */ + UNRECOGNIZED_ROLE = 3, + /** + * Error value returned when the operation is not supported. + */ + NOT_SUPPORTED = 4, +} diff --git a/usb/aidl/conversion.log b/usb/aidl/conversion.log new file mode 100644 index 0000000000..c09044689f --- /dev/null +++ b/usb/aidl/conversion.log @@ -0,0 +1,11 @@ +Notes relating to hidl2aidl conversion of android.hardware.usb@1.3 to android.hardware.usb (if any) follow: +Unhandled comments from android.hardware.usb@1.1::types follow. Consider using hidl-lint to locate these and fixup as many as possible. + // NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be + // changed to 'PortMode' which the convention dictates. + // NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be + // changed to 'PortStatus' which the convention dictates. + +An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus +An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus +An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus +END OF LOG diff --git a/usb/aidl/default/Android.bp b/usb/aidl/default/Android.bp new file mode 100644 index 0000000000..da0cff23c3 --- /dev/null +++ b/usb/aidl/default/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_binary { + name: "android.hardware.usb-service.example", + relative_install_path: "hw", + init_rc: ["android.hardware.usb-service.example.rc"], + vintf_fragments: ["android.hardware.usb-service.example.xml"], + vendor: true, + srcs: [ + "service.cpp", + "Usb.cpp", + ], + shared_libs: [ + "android.hardware.usb-V1-ndk", + "libbase", + "libbinder_ndk", + "libcutils", + "liblog", + "libutils", + ], +} diff --git a/usb/aidl/default/Usb.cpp b/usb/aidl/default/Usb.cpp new file mode 100644 index 0000000000..1105376ad9 --- /dev/null +++ b/usb/aidl/default/Usb.cpp @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.usb.aidl-service" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Usb.h" + +using android::base::GetProperty; +using android::base::Trim; + +namespace aidl { +namespace android { +namespace hardware { +namespace usb { + +constexpr char kTypecPath[] = "/sys/class/typec/"; +constexpr char kDataRoleNode[] = "/data_role"; +constexpr char kPowerRoleNode[] = "/power_role"; + +// Set by the signal handler to destroy the thread +volatile bool destroyThread; + +void queryVersionHelper(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus); + +ScopedAStatus Usb::enableUsbData(const string& in_portName, bool in_enable, int64_t in_transactionId) { + std::vector currentPortStatus; + + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyEnableUsbDataStatus( + in_portName, true, in_enable ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("notifyEnableUsbDataStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + queryVersionHelper(this, ¤tPortStatus); + + return ScopedAStatus::ok(); +} + +Status queryMoistureDetectionStatus(std::vector *currentPortStatus) { + string enabled, status, path, DetectedPath; + + for (int i = 0; i < currentPortStatus->size(); i++) { + (*currentPortStatus)[i].supportedContaminantProtectionModes + .push_back(ContaminantProtectionMode::NONE); + (*currentPortStatus)[i].contaminantProtectionStatus + = ContaminantProtectionStatus::NONE; + (*currentPortStatus)[i].contaminantDetectionStatus + = ContaminantDetectionStatus::NOT_SUPPORTED; + (*currentPortStatus)[i].supportsEnableContaminantPresenceDetection = false; + (*currentPortStatus)[i].supportsEnableContaminantPresenceProtection = false; + } + + return Status::SUCCESS; +} + +string appendRoleNodeHelper(const string &portName, PortRole::Tag tag) { + string node(kTypecPath + portName); + + switch (tag) { + case PortRole::dataRole: + return node + kDataRoleNode; + case PortRole::powerRole: + return node + kPowerRoleNode; + case PortRole::mode: + return node + "/port_type"; + default: + return ""; + } +} + +string convertRoletoString(PortRole role) { + if (role.getTag() == PortRole::powerRole) { + if (role.get() == PortPowerRole::SOURCE) + return "source"; + else if (role.get() == PortPowerRole::SINK) + return "sink"; + } else if (role.getTag() == PortRole::dataRole) { + if (role.get() == PortDataRole::HOST) + return "host"; + if (role.get() == PortDataRole::DEVICE) + return "device"; + } else if (role.getTag() == PortRole::mode) { + if (role.get() == PortMode::UFP) + return "sink"; + if (role.get() == PortMode::DFP) + return "source"; + } + return "none"; +} + +void extractRole(string *roleName) { + std::size_t first, last; + + first = roleName->find("["); + last = roleName->find("]"); + + if (first != string::npos && last != string::npos) { + *roleName = roleName->substr(first + 1, last - first - 1); + } +} + +void switchToDrp(const string &portName) { + string filename = appendRoleNodeHelper(string(portName.c_str()), PortRole::mode); + FILE *fp; + + if (filename != "") { + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + int ret = fputs("dual", fp); + fclose(fp); + if (ret == EOF) + ALOGE("Fatal: Error while switching back to drp"); + } else { + ALOGE("Fatal: Cannot open file to switch back to drp"); + } + } else { + ALOGE("Fatal: invalid node type"); + } +} + +bool switchMode(const string &portName, const PortRole &in_role, struct Usb *usb) { + string filename = appendRoleNodeHelper(string(portName.c_str()), in_role.getTag()); + string written; + FILE *fp; + bool roleSwitch = false; + + if (filename == "") { + ALOGE("Fatal: invalid node type"); + return false; + } + + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + // Hold the lock here to prevent loosing connected signals + // as once the file is written the partner added signal + // can arrive anytime. + pthread_mutex_lock(&usb->mPartnerLock); + usb->mPartnerUp = false; + int ret = fputs(convertRoletoString(in_role).c_str(), fp); + fclose(fp); + + if (ret != EOF) { + struct timespec to; + struct timespec now; + + wait_again: + clock_gettime(CLOCK_MONOTONIC, &now); + to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT; + to.tv_nsec = now.tv_nsec; + + int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to); + // There are no uevent signals which implies role swap timed out. + if (err == ETIMEDOUT) { + ALOGI("uevents wait timedout"); + // Validity check. + } else if (!usb->mPartnerUp) { + goto wait_again; + // Role switch succeeded since usb->mPartnerUp is true. + } else { + roleSwitch = true; + } + } else { + ALOGI("Role switch failed while wrting to file"); + } + pthread_mutex_unlock(&usb->mPartnerLock); + } + + if (!roleSwitch) + switchToDrp(string(portName.c_str())); + + return roleSwitch; +} + +Usb::Usb() + : mLock(PTHREAD_MUTEX_INITIALIZER), + mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER), + mPartnerLock(PTHREAD_MUTEX_INITIALIZER), + mPartnerUp(false) +{ + pthread_condattr_t attr; + if (pthread_condattr_init(&attr)) { + ALOGE("pthread_condattr_init failed: %s", strerror(errno)); + abort(); + } + if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) { + ALOGE("pthread_condattr_setclock failed: %s", strerror(errno)); + abort(); + } + if (pthread_cond_init(&mPartnerCV, &attr)) { + ALOGE("pthread_cond_init failed: %s", strerror(errno)); + abort(); + } + if (pthread_condattr_destroy(&attr)) { + ALOGE("pthread_condattr_destroy failed: %s", strerror(errno)); + abort(); + } +} + +ScopedAStatus Usb::switchRole(const string& in_portName, + const PortRole& in_role, int64_t in_transactionId) { + string filename = appendRoleNodeHelper(string(in_portName.c_str()), in_role.getTag()); + string written; + FILE *fp; + bool roleSwitch = false; + + if (filename == "") { + ALOGE("Fatal: invalid node type"); + return ScopedAStatus::ok(); + } + + pthread_mutex_lock(&mRoleSwitchLock); + + ALOGI("filename write: %s role:%s", filename.c_str(), convertRoletoString(in_role).c_str()); + + if (in_role.getTag() == PortRole::mode) { + roleSwitch = switchMode(in_portName, in_role, this); + } else { + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + int ret = fputs(convertRoletoString(in_role).c_str(), fp); + fclose(fp); + if ((ret != EOF) && ReadFileToString(filename, &written)) { + written = Trim(written); + extractRole(&written); + ALOGI("written: %s", written.c_str()); + if (written == convertRoletoString(in_role)) { + roleSwitch = true; + } else { + ALOGE("Role switch failed"); + } + } else { + ALOGE("failed to update the new role"); + } + } else { + ALOGE("fopen failed"); + } + } + + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyRoleSwitchStatus( + in_portName, in_role, roleSwitch ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("RoleSwitchStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + pthread_mutex_unlock(&mRoleSwitchLock); + + return ScopedAStatus::ok(); +} + +Status getAccessoryConnected(const string &portName, string *accessory) { + string filename = kTypecPath + portName + "-partner/accessory_mode"; + + if (!ReadFileToString(filename, accessory)) { + ALOGE("getAccessoryConnected: Failed to open filesystem node: %s", filename.c_str()); + return Status::ERROR; + } + *accessory = Trim(*accessory); + + return Status::SUCCESS; +} + +Status getCurrentRoleHelper(const string &portName, bool connected, PortRole *currentRole) { + string filename; + string roleName; + string accessory; + + // Mode + + if (currentRole->getTag() == PortRole::powerRole) { + filename = kTypecPath + portName + kPowerRoleNode; + currentRole->set(PortPowerRole::NONE); + } else if (currentRole->getTag() == PortRole::dataRole) { + filename = kTypecPath + portName + kDataRoleNode; + currentRole->set(PortDataRole::NONE); + } else if (currentRole->getTag() == PortRole::mode) { + filename = kTypecPath + portName + kDataRoleNode; + currentRole->set(PortMode::NONE); + } else { + return Status::ERROR; + } + + if (!connected) + return Status::SUCCESS; + + if (currentRole->getTag() == PortRole::mode) { + if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) { + return Status::ERROR; + } + if (accessory == "analog_audio") { + currentRole->set(PortMode::AUDIO_ACCESSORY); + return Status::SUCCESS; + } else if (accessory == "debug") { + currentRole->set(PortMode::DEBUG_ACCESSORY); + return Status::SUCCESS; + } + } + + if (!ReadFileToString(filename, &roleName)) { + ALOGE("getCurrentRole: Failed to open filesystem node: %s", filename.c_str()); + return Status::ERROR; + } + + roleName = Trim(roleName); + extractRole(&roleName); + + if (roleName == "source") { + currentRole->set(PortPowerRole::SOURCE); + } else if (roleName == "sink") { + currentRole->set(PortPowerRole::SINK); + } else if (roleName == "host") { + if (currentRole->getTag() == PortRole::dataRole) + currentRole->set(PortDataRole::HOST); + else + currentRole->set(PortMode::DFP); + } else if (roleName == "device") { + if (currentRole->getTag() == PortRole::dataRole) + currentRole->set(PortDataRole::DEVICE); + else + currentRole->set(PortMode::UFP); + } else if (roleName != "none") { + /* case for none has already been addressed. + * so we check if the role isn't none. + */ + return Status::UNRECOGNIZED_ROLE; + } + + return Status::SUCCESS; +} + +Status getTypeCPortNamesHelper(std::unordered_map *names) { + DIR *dp; + + dp = opendir(kTypecPath); + if (dp != NULL) { + struct dirent *ep; + + while ((ep = readdir(dp))) { + if (ep->d_type == DT_LNK) { + if (string::npos == string(ep->d_name).find("-partner")) { + std::unordered_map::const_iterator portName = + names->find(ep->d_name); + if (portName == names->end()) { + names->insert({ep->d_name, false}); + } + } else { + (*names)[std::strtok(ep->d_name, "-")] = true; + } + } + } + closedir(dp); + return Status::SUCCESS; + } + + ALOGE("Failed to open /sys/class/typec"); + return Status::ERROR; +} + +bool canSwitchRoleHelper(const string &portName) { + string filename = kTypecPath + portName + "-partner/supports_usb_power_delivery"; + string supportsPD; + + if (ReadFileToString(filename, &supportsPD)) { + supportsPD = Trim(supportsPD); + if (supportsPD == "yes") { + return true; + } + } + + return false; +} + +Status getPortStatusHelper(std::vector *currentPortStatus) { + std::unordered_map names; + Status result = getTypeCPortNamesHelper(&names); + int i = -1; + + if (result == Status::SUCCESS) { + currentPortStatus->resize(names.size()); + for (std::pair port : names) { + i++; + ALOGI("%s", port.first.c_str()); + (*currentPortStatus)[i].portName = port.first; + + PortRole currentRole; + currentRole.set(PortPowerRole::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS){ + (*currentPortStatus)[i].currentPowerRole = currentRole.get(); + } else { + ALOGE("Error while retrieving portNames"); + goto done; + } + + currentRole.set(PortDataRole::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS) { + (*currentPortStatus)[i].currentDataRole = currentRole.get(); + } else { + ALOGE("Error while retrieving current port role"); + goto done; + } + + currentRole.set(PortMode::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS) { + (*currentPortStatus)[i].currentMode = currentRole.get(); + } else { + ALOGE("Error while retrieving current data role"); + goto done; + } + + (*currentPortStatus)[i].canChangeMode = true; + (*currentPortStatus)[i].canChangeDataRole = + port.second ? canSwitchRoleHelper(port.first) : false; + (*currentPortStatus)[i].canChangePowerRole = + port.second ? canSwitchRoleHelper(port.first) : false; + + (*currentPortStatus)[i].supportedModes.push_back(PortMode::DRP); + (*currentPortStatus)[i].usbDataEnabled = true; + + ALOGI("%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d " + "usbDataEnabled:%d", + i, port.first.c_str(), port.second, + (*currentPortStatus)[i].canChangeMode, + (*currentPortStatus)[i].canChangeDataRole, + (*currentPortStatus)[i].canChangePowerRole, 0); + } + + return Status::SUCCESS; + } +done: + return Status::ERROR; +} + +void queryVersionHelper(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus) { + Status status; + pthread_mutex_lock(&usb->mLock); + status = getPortStatusHelper(currentPortStatus); + queryMoistureDetectionStatus(currentPortStatus); + if (usb->mCallback != NULL) { + ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus, + status); + if (!ret.isOk()) + ALOGE("queryPortStatus error %s", ret.getDescription().c_str()); + } else { + ALOGI("Notifying userspace skipped. Callback is NULL"); + } + pthread_mutex_unlock(&usb->mLock); +} + +ScopedAStatus Usb::queryPortStatus(int64_t in_transactionId) { + std::vector currentPortStatus; + + queryVersionHelper(this, ¤tPortStatus); + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyQueryPortStatus( + "all", Status::SUCCESS, in_transactionId); + if (!ret.isOk()) + ALOGE("notifyQueryPortStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + + return ScopedAStatus::ok(); +} + +ScopedAStatus Usb::enableContaminantPresenceDetection(const string& in_portName, + bool /*in_enable*/, int64_t in_transactionId) { + std::vector currentPortStatus; + + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyContaminantEnabledStatus( + in_portName, false, Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("enableContaminantPresenceDetection error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + + queryVersionHelper(this, ¤tPortStatus); + return ScopedAStatus::ok(); +} + + +struct data { + int uevent_fd; + ::aidl::android::hardware::usb::Usb *usb; +}; + +static void uevent_event(uint32_t /*epevents*/, struct data *payload) { + char msg[UEVENT_MSG_LEN + 2]; + char *cp; + int n; + + n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN); + if (n <= 0) + return; + if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ + return; + + msg[n] = '\0'; + msg[n + 1] = '\0'; + cp = msg; + + while (*cp) { + if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) { + ALOGI("partner added"); + pthread_mutex_lock(&payload->usb->mPartnerLock); + payload->usb->mPartnerUp = true; + pthread_cond_signal(&payload->usb->mPartnerCV); + pthread_mutex_unlock(&payload->usb->mPartnerLock); + } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_"))) { + std::vector currentPortStatus; + queryVersionHelper(payload->usb, ¤tPortStatus); + + // Role switch is not in progress and port is in disconnected state + if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) { + for (unsigned long i = 0; i < currentPortStatus.size(); i++) { + DIR *dp = + opendir(string(kTypecPath + + string(currentPortStatus[i].portName.c_str()) + + "-partner").c_str()); + if (dp == NULL) { + switchToDrp(currentPortStatus[i].portName); + } else { + closedir(dp); + } + } + pthread_mutex_unlock(&payload->usb->mRoleSwitchLock); + } + break; + } /* advance to after the next \0 */ + while (*cp++) { + } + } +} + +void *work(void *param) { + int epoll_fd, uevent_fd; + struct epoll_event ev; + int nevents = 0; + struct data payload; + + uevent_fd = uevent_open_socket(UEVENT_MAX_EVENTS * UEVENT_MSG_LEN, true); + + if (uevent_fd < 0) { + ALOGE("uevent_init: uevent_open_socket failed\n"); + return NULL; + } + + payload.uevent_fd = uevent_fd; + payload.usb = (::aidl::android::hardware::usb::Usb *)param; + + fcntl(uevent_fd, F_SETFL, O_NONBLOCK); + + ev.events = EPOLLIN; + ev.data.ptr = (void *)uevent_event; + + epoll_fd = epoll_create(UEVENT_MAX_EVENTS); + if (epoll_fd == -1) { + ALOGE("epoll_create failed; errno=%d", errno); + goto error; + } + + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) { + ALOGE("epoll_ctl failed; errno=%d", errno); + goto error; + } + + while (!destroyThread) { + struct epoll_event events[UEVENT_MAX_EVENTS]; + + nevents = epoll_wait(epoll_fd, events, UEVENT_MAX_EVENTS, -1); + if (nevents == -1) { + if (errno == EINTR) + continue; + ALOGE("usb epoll_wait failed; errno=%d", errno); + break; + } + + for (int n = 0; n < nevents; ++n) { + if (events[n].data.ptr) + (*(void (*)(int, struct data *payload))events[n].data.ptr)(events[n].events, + &payload); + } + } + + ALOGI("exiting worker thread"); +error: + close(uevent_fd); + + if (epoll_fd >= 0) + close(epoll_fd); + + return NULL; +} + +void sighandler(int sig) { + if (sig == SIGUSR1) { + destroyThread = true; + ALOGI("destroy set"); + return; + } + signal(SIGUSR1, sighandler); +} + +ScopedAStatus Usb::setCallback( + const shared_ptr& in_callback) { + + pthread_mutex_lock(&mLock); + if ((mCallback == NULL && in_callback == NULL) || + (mCallback != NULL && in_callback != NULL)) { + mCallback = in_callback; + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); + } + + mCallback = in_callback; + ALOGI("registering callback"); + + if (mCallback == NULL) { + if (!pthread_kill(mPoll, SIGUSR1)) { + pthread_join(mPoll, NULL); + ALOGI("pthread destroyed"); + } + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); + } + + destroyThread = false; + signal(SIGUSR1, sighandler); + + /* + * Create a background thread if the old callback value is NULL + * and being updated with a new value. + */ + if (pthread_create(&mPoll, NULL, work, this)) { + ALOGE("pthread creation failed %d", errno); + mCallback = NULL; + } + + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); +} + +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/usb/aidl/default/Usb.h b/usb/aidl/default/Usb.h new file mode 100644 index 0000000000..bca86ae06c --- /dev/null +++ b/usb/aidl/default/Usb.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#define UEVENT_MSG_LEN 2048 +#define UEVENT_MAX_EVENTS 64 +// The type-c stack waits for 4.5 - 5.5 secs before declaring a port non-pd. +// The -partner directory would not be created until this is done. +// Having a margin of ~3 secs for the directory and other related bookeeping +// structures created and uvent fired. +#define PORT_TYPE_TIMEOUT 8 + +namespace aidl { +namespace android { +namespace hardware { +namespace usb { + +using ::aidl::android::hardware::usb::IUsbCallback; +using ::aidl::android::hardware::usb::PortRole; +using ::android::base::ReadFileToString; +using ::android::base::WriteStringToFile; +using ::android::sp; +using ::ndk::ScopedAStatus; +using ::std::shared_ptr; +using ::std::string; + +struct Usb : public BnUsb { + Usb(); + + ScopedAStatus enableContaminantPresenceDetection(const std::string& in_portName, + bool in_enable, int64_t in_transactionId) override; + ScopedAStatus queryPortStatus(int64_t in_transactionId) override; + ScopedAStatus setCallback(const shared_ptr& in_callback) override; + ScopedAStatus switchRole(const string& in_portName, const PortRole& in_role, + int64_t in_transactionId) override; + ScopedAStatus enableUsbData(const string& in_portName, bool in_enable, + int64_t in_transactionId) override; + + shared_ptr mCallback; + // Protects mCallback variable + pthread_mutex_t mLock; + // Protects roleSwitch operation + pthread_mutex_t mRoleSwitchLock; + // Threads waiting for the partner to come back wait here + pthread_cond_t mPartnerCV; + // lock protecting mPartnerCV + pthread_mutex_t mPartnerLock; + // Variable to signal partner coming back online after type switch + bool mPartnerUp; + private: + pthread_t mPoll; +}; + +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/usb/aidl/default/android.hardware.usb-service.example.rc b/usb/aidl/default/android.hardware.usb-service.example.rc new file mode 100644 index 0000000000..335bca744d --- /dev/null +++ b/usb/aidl/default/android.hardware.usb-service.example.rc @@ -0,0 +1,4 @@ +service vendor.usb_default /vendor/bin/hw/android.hardware.usb-service.example + class hal + user system + group system diff --git a/usb/aidl/default/android.hardware.usb-service.example.xml b/usb/aidl/default/android.hardware.usb-service.example.xml new file mode 100644 index 0000000000..6088194890 --- /dev/null +++ b/usb/aidl/default/android.hardware.usb-service.example.xml @@ -0,0 +1,10 @@ + + + android.hardware.usb + 1 + + IUsb + default + + + diff --git a/usb/aidl/default/service.cpp b/usb/aidl/default/service.cpp new file mode 100644 index 0000000000..398458aff7 --- /dev/null +++ b/usb/aidl/default/service.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "Usb.h" + +using ::aidl::android::hardware::usb::Usb; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr usb = ndk::SharedRefBase::make(); + + const std::string instance = std::string() + Usb::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(usb->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return -1; // Should never be reached +} From aef9dec7dd394016caf42cd0287430f94b5d31ed Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Mon, 27 Dec 2021 14:02:56 -0800 Subject: [PATCH 2/4] VTS tests for USB AIDL interface Bug: 200993386 Bug: 199357330 Bug: 211677613 Change-Id: I49881d136697cd5f207a61e179779b532d0d8e76 --- usb/aidl/vts/Android.bp | 43 +++ usb/aidl/vts/VtsAidlUsbTargetTest.cpp | 424 ++++++++++++++++++++++++++ 2 files changed, 467 insertions(+) create mode 100644 usb/aidl/vts/Android.bp create mode 100644 usb/aidl/vts/VtsAidlUsbTargetTest.cpp diff --git a/usb/aidl/vts/Android.bp b/usb/aidl/vts/Android.bp new file mode 100644 index 0000000000..00a7c93ec3 --- /dev/null +++ b/usb/aidl/vts/Android.bp @@ -0,0 +1,43 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsAidlUsbTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsAidlUsbTargetTest.cpp"], + shared_libs: [ + "libbinder_ndk", + ], + static_libs: [ + "android.hardware.usb-V1-ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp new file mode 100644 index 0000000000..09cb096702 --- /dev/null +++ b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2021 The Android Open Source Probject + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "UsbAidlTest" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TIMEOUT_PERIOD 10 + +using ::aidl::android::hardware::usb::BnUsbCallback; +using ::aidl::android::hardware::usb::IUsb; +using ::aidl::android::hardware::usb::IUsbCallback; +using ::aidl::android::hardware::usb::PortDataRole; +using ::aidl::android::hardware::usb::PortMode; +using ::aidl::android::hardware::usb::PortPowerRole; +using ::aidl::android::hardware::usb::PortRole; +using ::aidl::android::hardware::usb::PortStatus; +using ::aidl::android::hardware::usb::Status; + +using ::ndk::ScopedAStatus; +using ::ndk::SpAIBinder; +using std::vector; +using std::shared_ptr; +using std::string; + +// The main test class for the USB aidl hal +class UsbAidlTest : public testing::TestWithParam { + public: + // Callback class for the USB aidl hal. + // Usb Hal will call this object upon role switch or port query. + class UsbCallback : public BnUsbCallback { + UsbAidlTest& parent_; + int cookie; + + public: + UsbCallback(UsbAidlTest& parent, int cookie) + : parent_(parent), cookie(cookie){}; + + virtual ~UsbCallback() = default; + + // Callback method for the port status. + ScopedAStatus notifyPortStatusChange(const vector& currentPortStatus, + Status retval) override { + if (retval == Status::SUCCESS && currentPortStatus.size() > 0) { + parent_.usb_last_port_status.portName = + currentPortStatus[0].portName.c_str(); + parent_.usb_last_port_status.currentDataRole = + currentPortStatus[0].currentDataRole; + parent_.usb_last_port_status.currentPowerRole = + currentPortStatus[0].currentPowerRole; + parent_.usb_last_port_status.currentMode = + currentPortStatus[0].currentMode; + } + parent_.usb_last_cookie = cookie; + return ScopedAStatus::ok(); + } + + // Callback method for the status of role switch operation. + ScopedAStatus notifyRoleSwitchStatus(const string& /*portName*/, const PortRole& newRole, + Status retval, int64_t transactionId) override { + parent_.usb_last_status = retval; + parent_.usb_last_cookie = cookie; + parent_.usb_last_port_role = newRole; + parent_.usb_role_switch_done = true; + parent_.last_transactionId = transactionId; + parent_.notify(); + return ScopedAStatus::ok(); + } + + // Callback method for the status of enableUsbData operation + ScopedAStatus notifyEnableUsbDataStatus(const string& /*portName*/, bool /*enable*/, + Status /*retval*/, int64_t transactionId) override { + parent_.last_transactionId = transactionId; + parent_.usb_last_cookie = cookie; + parent_.enable_usb_data_done = true; + parent_.notify(); + return ScopedAStatus::ok(); + } + + // Callback method for the status of enableContaminantPresenceDetection + ScopedAStatus notifyContaminantEnabledStatus(const string& /*portName*/, bool /*enable*/, + Status /*retval*/, int64_t transactionId) override { + parent_.last_transactionId = transactionId; + parent_.usb_last_cookie = cookie; + parent_.enable_contaminant_done = true; + parent_.notify(); + return ScopedAStatus::ok(); + } + + // Callback method for the status of queryPortStatus operation + ScopedAStatus notifyQueryPortStatus(const string& /*portName*/, Status /*retval*/, + int64_t transactionId) override { + parent_.last_transactionId = transactionId; + parent_.notify(); + return ScopedAStatus::ok(); + } + }; + + virtual void SetUp() override { + ALOGI("Setup"); + usb = IUsb::fromBinder( + SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); + ASSERT_NE(usb, nullptr); + + usb_cb_2 = ::ndk::SharedRefBase::make(*this, 2); + ASSERT_NE(usb_cb_2, nullptr); + const auto& ret = usb->setCallback(usb_cb_2); + ASSERT_TRUE(ret.isOk()); + } + + virtual void TearDown() override { ALOGI("Teardown"); } + + // Used as a mechanism to inform the test about data/event callback. + inline void notify() { + std::unique_lock lock(usb_mtx); + usb_count++; + usb_cv.notify_one(); + } + + // Test code calls this function to wait for data/event callback. + inline std::cv_status wait() { + std::unique_lock lock(usb_mtx); + + std::cv_status status = std::cv_status::no_timeout; + auto now = std::chrono::system_clock::now(); + while (usb_count == 0) { + status = + usb_cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD)); + if (status == std::cv_status::timeout) { + ALOGI("timeout"); + return status; + } + } + usb_count--; + return status; + } + + // USB aidl hal Proxy + shared_ptr usb; + + // Callback objects for usb aidl + // Methods of these objects are called to notify port status updates. + shared_ptr usb_cb_1, usb_cb_2; + + // The last conveyed status of the USB ports. + // Stores information of currentt_data_role, power_role for all the USB ports + PortStatus usb_last_port_status; + + // Status of the last role switch operation. + Status usb_last_status; + + // Port role information of the last role switch operation. + PortRole usb_last_port_role; + + // Flag to indicate the invocation of role switch callback. + bool usb_role_switch_done; + + // Flag to indicate the invocation of notifyContaminantEnabledStatus callback. + bool enable_contaminant_done; + + // Flag to indicate the invocation of notifyEnableUsbDataStatus callback. + bool enable_usb_data_done; + + // Stores the cookie of the last invoked usb callback object. + int usb_last_cookie; + + // Last transaction ID that was recorded. + int64_t last_transactionId; + // synchronization primitives to coordinate between main test thread + // and the callback thread. + std::mutex usb_mtx; + std::condition_variable usb_cv; + int usb_count = 0; +}; + +/* + * Test to see if setCallback succeeds. + * Callback object is created and registered. + */ +TEST_P(UsbAidlTest, setCallback) { + ALOGI("UsbAidlTest setCallback start"); + usb_cb_1 = ::ndk::SharedRefBase::make(*this, 1); + ASSERT_NE(usb_cb_1, nullptr); + const auto& ret = usb->setCallback(usb_cb_1); + ASSERT_TRUE(ret.isOk()); + ALOGI("UsbAidlTest setCallback end"); +} + +/* + * Check to see if querying type-c + * port status succeeds. + * The callback parameters are checked to see if the transaction id + * matches. + */ +TEST_P(UsbAidlTest, queryPortStatus) { + ALOGI("UsbAidlTest queryPortStatus start"); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + ALOGI("UsbAidlTest queryPortStatus end: %s", usb_last_port_status.portName.c_str()); +} + +/* + * Trying to switch a non-existent port should fail. + * This test case tried to switch the port with empty + * name which is expected to fail. + * The callback parameters are checked to see if the transaction id + * matches. + */ +TEST_P(UsbAidlTest, switchEmptyPort) { + ALOGI("UsbAidlTest switchEmptyPort start"); + PortRole role; + role.set(PortPowerRole::SOURCE); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->switchRole("", role, transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(Status::ERROR, usb_last_status); + EXPECT_EQ(transactionId, last_transactionId); + EXPECT_EQ(2, usb_last_cookie); + ALOGI("UsbAidlTest switchEmptyPort end"); +} + +/* + * Test switching the power role of usb port. + * Test case queries the usb ports present in device. + * If there is at least one usb port, a power role switch + * to SOURCE is attempted for the port. + * The callback parameters are checked to see if the transaction id + * matches. + */ +TEST_P(UsbAidlTest, switchPowerRole) { + ALOGI("UsbAidlTest switchPowerRole start"); + PortRole role; + role.set(PortPowerRole::SOURCE); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + + if (!usb_last_port_status.portName.empty()) { + string portBeingSwitched = usb_last_port_status.portName; + ALOGI("switchPower role portname:%s", portBeingSwitched.c_str()); + usb_role_switch_done = false; + transactionId = rand() % 10000; + const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId); + ASSERT_TRUE(ret.isOk()); + + std::cv_status waitStatus = wait(); + while (waitStatus == std::cv_status::no_timeout && + usb_role_switch_done == false) + waitStatus = wait(); + + EXPECT_EQ(std::cv_status::no_timeout, waitStatus); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + } + ALOGI("UsbAidlTest switchPowerRole end"); +} + +/* + * Test switching the data role of usb port. + * Test case queries the usb ports present in device. + * If there is at least one usb port, a data role switch + * to device is attempted for the port. + * The callback parameters are checked to see if transaction id + * matches. + */ +TEST_P(UsbAidlTest, switchDataRole) { + ALOGI("UsbAidlTest switchDataRole start"); + PortRole role; + role.set(PortDataRole::DEVICE); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + + if (!usb_last_port_status.portName.empty()) { + string portBeingSwitched = usb_last_port_status.portName; + ALOGI("portname:%s", portBeingSwitched.c_str()); + usb_role_switch_done = false; + transactionId = rand() % 10000; + const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId); + ASSERT_TRUE(ret.isOk()); + + std::cv_status waitStatus = wait(); + while (waitStatus == std::cv_status::no_timeout && + usb_role_switch_done == false) + waitStatus = wait(); + + EXPECT_EQ(std::cv_status::no_timeout, waitStatus); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + } + ALOGI("UsbAidlTest switchDataRole end"); +} + +/* + * Test enabling contaminant presence detection of the port. + * Test case queries the usb ports present in device. + * If there is at least one usb port, enabling contaminant detection + * is attempted for the port. + * The callback parameters are checked to see if transaction id + * matches. + */ +TEST_P(UsbAidlTest, enableContaminantPresenceDetection) { + ALOGI("UsbAidlTest enableContaminantPresenceDetection start"); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + + if (!usb_last_port_status.portName.empty()) { + ALOGI("portname:%s", usb_last_port_status.portName.c_str()); + enable_contaminant_done = false; + transactionId = rand() % 10000; + const auto& ret = usb->enableContaminantPresenceDetection(usb_last_port_status.portName, + true, transactionId); + ASSERT_TRUE(ret.isOk()); + + std::cv_status waitStatus = wait(); + while (waitStatus == std::cv_status::no_timeout && + enable_contaminant_done == false) + waitStatus = wait(); + + EXPECT_EQ(std::cv_status::no_timeout, waitStatus); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + } + ALOGI("UsbAidlTest enableContaminantPresenceDetection end"); +} + +/* + * Test enabling Usb data of the port. + * Test case queries the usb ports present in device. + * If there is at least one usb port, enabling Usb data is attempted + * for the port. + * The callback parameters are checked to see if transaction id + * matches. + */ +TEST_P(UsbAidlTest, enableUsbData) { + ALOGI("UsbAidlTest enableUsbData start"); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + + if (!usb_last_port_status.portName.empty()) { + ALOGI("portname:%s", usb_last_port_status.portName.c_str()); + enable_usb_data_done = false; + transactionId = rand() % 10000; + const auto& ret = usb->enableUsbData(usb_last_port_status.portName, true, transactionId); + ASSERT_TRUE(ret.isOk()); + + std::cv_status waitStatus = wait(); + while (waitStatus == std::cv_status::no_timeout && + enable_usb_data_done == false) + waitStatus = wait(); + + EXPECT_EQ(std::cv_status::no_timeout, waitStatus); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + } + ALOGI("UsbAidlTest enableUsbData end"); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, UsbAidlTest, + testing::ValuesIn(::android::getAidlHalInstanceNames(IUsb::descriptor)), + ::android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} From 623f13385f0e839c2c1d41e61f149a61f2e10e31 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Thu, 25 Nov 2021 09:35:21 -0800 Subject: [PATCH 3/4] Add limitPowerTransfer API to IUsb limitPowerTransfer is invoked to limit power transfer in and out of the Usb port. Bug: 199357330 Signed-off-by: Badhri Jagan Sridharan Change-Id: I5f4991d024ad827ae8148fc143a44cc05bafdcb4 --- .../current/android/hardware/usb/IUsb.aidl | 1 + .../android/hardware/usb/IUsbCallback.aidl | 1 + .../android/hardware/usb/PortStatus.aidl | 1 + usb/aidl/android/hardware/usb/IUsb.aidl | 13 +++++++++++++ .../android/hardware/usb/IUsbCallback.aidl | 12 ++++++++++++ usb/aidl/android/hardware/usb/PortStatus.aidl | 4 ++++ usb/aidl/default/Usb.cpp | 18 ++++++++++++++++++ usb/aidl/default/Usb.h | 2 ++ 8 files changed, 52 insertions(+) diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl index 7513461afb..73c7b825e2 100644 --- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl @@ -39,4 +39,5 @@ interface IUsb { oneway void queryPortStatus(long transactionId); oneway void setCallback(in android.hardware.usb.IUsbCallback callback); oneway void switchRole(in String portName, in android.hardware.usb.PortRole role, long transactionId); + oneway void limitPowerTransfer(in String portName, boolean limit, long transactionId); } diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl index 57be590563..85861e9d41 100644 --- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl @@ -39,4 +39,5 @@ interface IUsbCallback { oneway void notifyEnableUsbDataStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId); oneway void notifyContaminantEnabledStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId); oneway void notifyQueryPortStatus(in String portName, in android.hardware.usb.Status retval, long transactionId); + oneway void notifyLimitPowerTransferStatus(in String portName, boolean limit, in android.hardware.usb.Status retval, long transactionId); } diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl index 78dcfacef9..14bb90fd15 100644 --- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl +++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl @@ -48,4 +48,5 @@ parcelable PortStatus { boolean supportsEnableContaminantPresenceDetection; android.hardware.usb.ContaminantDetectionStatus contaminantDetectionStatus = android.hardware.usb.ContaminantDetectionStatus.NOT_SUPPORTED; boolean usbDataEnabled; + boolean powerTransferLimited; } diff --git a/usb/aidl/android/hardware/usb/IUsb.aidl b/usb/aidl/android/hardware/usb/IUsb.aidl index 9a8f0006ee..1596d9ada5 100644 --- a/usb/aidl/android/hardware/usb/IUsb.aidl +++ b/usb/aidl/android/hardware/usb/IUsb.aidl @@ -82,4 +82,17 @@ oneway interface IUsb { * @param transactionId ID to be used when invoking the callback. */ void switchRole(in String portName, in PortRole role, long transactionId); + + /** + * This function is used to limit power transfer in and out of the port. + * When limited, the port does not charge from the partner port. + * Also, the port limits sourcing power to the partner port when the USB + * specification allows it to do so. + * + * @param portName name of the port for which power transfer is being limited. + * @param limit true limit power transfer. + * false relax limiting power transfer. + * @param transactionId ID to be used when invoking the callback. + */ + void limitPowerTransfer(in String portName, boolean limit, long transactionId); } diff --git a/usb/aidl/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/android/hardware/usb/IUsbCallback.aidl index 232a15babe..b733fede3b 100644 --- a/usb/aidl/android/hardware/usb/IUsbCallback.aidl +++ b/usb/aidl/android/hardware/usb/IUsbCallback.aidl @@ -83,4 +83,16 @@ oneway interface IUsbCallback { * @param transactionId transactionId sent during queryPortStatus request */ void notifyQueryPortStatus(in String portName, in Status retval, long transactionId); + + /** + * Used to notify the result of requesting limitPowerTransfer. + * + * @param portName name of the port for which power transfer is being limited. + * @param limit true limit power transfer. + * false relax limiting power transfer. + * @param retval SUCCESS if the request to enable/disable limitPowerTransfer succeeds. + * FAILURE otherwise. + * @param transactionId ID sent during limitPowerTransfer request. + */ + void notifyLimitPowerTransferStatus(in String portName, boolean limit, in Status retval, long transactionId); } diff --git a/usb/aidl/android/hardware/usb/PortStatus.aidl b/usb/aidl/android/hardware/usb/PortStatus.aidl index 8afe00916c..fb979e5f62 100644 --- a/usb/aidl/android/hardware/usb/PortStatus.aidl +++ b/usb/aidl/android/hardware/usb/PortStatus.aidl @@ -104,4 +104,8 @@ parcelable PortStatus { * UsbData status of the port. */ boolean usbDataEnabled; + /** + * Denoted whether power transfer is limited in the port. + */ + boolean powerTransferLimited; } diff --git a/usb/aidl/default/Usb.cpp b/usb/aidl/default/Usb.cpp index 1105376ad9..0624963883 100644 --- a/usb/aidl/default/Usb.cpp +++ b/usb/aidl/default/Usb.cpp @@ -289,6 +289,24 @@ ScopedAStatus Usb::switchRole(const string& in_portName, return ScopedAStatus::ok(); } +ScopedAStatus Usb::limitPowerTransfer(const string& in_portName, bool /*in_limit*/, + int64_t in_transactionId) { + std::vector currentPortStatus; + + pthread_mutex_lock(&mLock); + if (mCallback != NULL && in_transactionId >= 0) { + ScopedAStatus ret = mCallback->notifyLimitPowerTransferStatus( + in_portName, false, Status::NOT_SUPPORTED, in_transactionId); + if (!ret.isOk()) + ALOGE("limitPowerTransfer error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + + return ScopedAStatus::ok(); +} + Status getAccessoryConnected(const string &portName, string *accessory) { string filename = kTypecPath + portName + "-partner/accessory_mode"; diff --git a/usb/aidl/default/Usb.h b/usb/aidl/default/Usb.h index bca86ae06c..71ec938a56 100644 --- a/usb/aidl/default/Usb.h +++ b/usb/aidl/default/Usb.h @@ -54,6 +54,8 @@ struct Usb : public BnUsb { int64_t in_transactionId) override; ScopedAStatus enableUsbData(const string& in_portName, bool in_enable, int64_t in_transactionId) override; + ScopedAStatus limitPowerTransfer(const std::string& in_portName, bool in_limit, + int64_t in_transactionId)override; shared_ptr mCallback; // Protects mCallback variable From 6f67c56a65257844d04fb82684cf9db687f484ee Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Mon, 17 Jan 2022 19:13:08 -0800 Subject: [PATCH 4/4] Add Vts test for limitPowerTransfer interface Bug: 199357330 Change-Id: I018e3ebf1b8a6d7e5b1ad2592695ab2541439a59 --- usb/aidl/vts/VtsAidlUsbTargetTest.cpp | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp index 09cb096702..bab5a3af59 100644 --- a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp +++ b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp @@ -129,6 +129,16 @@ class UsbAidlTest : public testing::TestWithParam { parent_.notify(); return ScopedAStatus::ok(); } + + // Callback method for the status of limitPowerTransfer operation + ScopedAStatus notifyLimitPowerTransferStatus(const string& /*portName*/, bool /*limit*/, + Status /*retval*/, int64_t transactionId) override { + parent_.last_transactionId = transactionId; + parent_.usb_last_cookie = cookie; + parent_.limit_power_transfer_done = true; + parent_.notify(); + return ScopedAStatus::ok(); + } }; virtual void SetUp() override { @@ -196,6 +206,9 @@ class UsbAidlTest : public testing::TestWithParam { // Flag to indicate the invocation of notifyEnableUsbDataStatus callback. bool enable_usb_data_done; + // Flag to indicate the invocation of notifyLimitPowerTransferStatus callback. + bool limit_power_transfer_done; + // Stores the cookie of the last invoked usb callback object. int usb_last_cookie; @@ -410,6 +423,42 @@ TEST_P(UsbAidlTest, enableUsbData) { ALOGI("UsbAidlTest enableUsbData end"); } +/* + * Test enabling Usb data of the port. + * Test case queries the usb ports present in device. + * If there is at least one usb port, relaxing limit power transfer + * is attempted for the port. + * The callback parameters are checked to see if transaction id + * matches. + */ +TEST_P(UsbAidlTest, limitPowerTransfer) { + ALOGI("UsbAidlTest limitPowerTransfer start"); + int64_t transactionId = rand() % 10000; + const auto& ret = usb->queryPortStatus(transactionId); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + + if (!usb_last_port_status.portName.empty()) { + ALOGI("portname:%s", usb_last_port_status.portName.c_str()); + limit_power_transfer_done = false; + transactionId = rand() % 10000; + const auto& ret = usb->limitPowerTransfer(usb_last_port_status.portName, false, transactionId); + ASSERT_TRUE(ret.isOk()); + + std::cv_status waitStatus = wait(); + while (waitStatus == std::cv_status::no_timeout && + limit_power_transfer_done == false) + waitStatus = wait(); + + EXPECT_EQ(std::cv_status::no_timeout, waitStatus); + EXPECT_EQ(2, usb_last_cookie); + EXPECT_EQ(transactionId, last_transactionId); + } + ALOGI("UsbAidlTest limitPowerTransfer end"); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, UsbAidlTest,