Add Stable AIDL version of EVS HAL
This CL add a new set of EVS APIs written in Stable AIDL with an empty
IEvsEnumerator implementation.
Bug: 170401743
Bug: 195672428
Bug: 202031799
Bug: 202669715
Test: m -j
Change-Id: I28ff4391ba51b72299ebfae801d21a8ab0e37917
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
new file mode 100644
index 0000000..3c0aa13
--- /dev/null
+++ b/automotive/evs/aidl/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2022 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"],
+}
+
+aidl_interface {
+ name: "android.hardware.automotive.evs",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/automotive/evs/*.aidl"
+ ],
+ stability: "vintf",
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.graphics.common-V3",
+ ],
+ backend: {
+ java: {
+ // android.hardware.graphics.common package is not enabled
+ // for Java backend.
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: false,
+ },
+ min_sdk_version: "29"
+ },
+ },
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl
new file mode 100644
index 0000000..31acdb8
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable BufferDesc {
+ android.hardware.graphics.common.HardwareBuffer buffer;
+ int pixelSizeBytes;
+ int bufferId;
+ @utf8InCpp String deviceId;
+ long timestamp;
+ byte[] metadata;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl
new file mode 100644
index 0000000..4dadeb8
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable CameraDesc {
+ @utf8InCpp String id;
+ int vendorFlags;
+ byte[] metadata;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl
new file mode 100644
index 0000000..ae4ce77
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum CameraParam {
+ BRIGHTNESS = 0,
+ CONTRAST = 1,
+ AUTOGAIN = 2,
+ GAIN = 3,
+ AUTO_WHITE_BALANCE = 4,
+ WHITE_BALANCE_TEMPERATURE = 5,
+ SHARPNESS = 6,
+ AUTO_EXPOSURE = 7,
+ ABSOLUTE_EXPOSURE = 8,
+ ABSOLUTE_FOCUS = 9,
+ AUTO_FOCUS = 10,
+ ABSOLUTE_ZOOM = 11,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl
new file mode 100644
index 0000000..cc066ac
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable DeviceStatus {
+ @utf8InCpp String id;
+ android.hardware.automotive.evs.DeviceStatusType status;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl
new file mode 100644
index 0000000..d0f1d8e
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum DeviceStatusType {
+ CAMERA_AVAILABLE = 0,
+ CAMERA_NOT_AVAILABLE = 1,
+ DISPLAY_AVAILABLE = 2,
+ DISPLAY_NOT_AVAILABLE = 3,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl
new file mode 100644
index 0000000..4ac029e
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable DisplayDesc {
+ @utf8InCpp String id;
+ int width;
+ int height;
+ android.hardware.automotive.evs.Rotation orientation;
+ int vendorFlags;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl
new file mode 100644
index 0000000..a5f4309
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum DisplayState {
+ NOT_OPEN = 0,
+ NOT_VISIBLE = 1,
+ VISIBLE_ON_NEXT_FRAME = 2,
+ VISIBLE = 3,
+ DEAD = 4,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl
new file mode 100644
index 0000000..09b2b9d
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable EvsEventDesc {
+ android.hardware.automotive.evs.EvsEventType aType;
+ @utf8InCpp String deviceId;
+ int[] payload;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl
new file mode 100644
index 0000000..052a6b3
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum EvsEventType {
+ STREAM_STARTED = 0,
+ STREAM_STOPPED = 1,
+ FRAME_DROPPED = 2,
+ TIMEOUT = 3,
+ PARAMETER_CHANGED = 4,
+ MASTER_RELEASED = 5,
+ STREAM_ERROR = 6,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl
new file mode 100644
index 0000000..a0418a9
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum EvsResult {
+ OK = 0,
+ INVALID_ARG = 1,
+ STREAM_ALREADY_RUNNING = 2,
+ BUFFER_NOT_AVAILABLE = 3,
+ OWNERSHIP_LOST = 4,
+ UNDERLYING_SERVICE_ERROR = 5,
+ PERMISSION_DENIED = 6,
+ RESOURCE_NOT_AVAILABLE = 7,
+ RESOURCE_BUSY = 8,
+ NOT_IMPLEMENTED = 9,
+ NOT_SUPPORTED = 10,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl
new file mode 100644
index 0000000..ce1b97d
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsCamera {
+ void doneWithFrame(in android.hardware.automotive.evs.BufferDesc[] buffer);
+ void forcePrimaryClient(in android.hardware.automotive.evs.IEvsDisplay display);
+ android.hardware.automotive.evs.CameraDesc getCameraInfo();
+ byte[] getExtendedInfo(in int opaqueIdentifier);
+ int[] getIntParameter(in android.hardware.automotive.evs.CameraParam id);
+ android.hardware.automotive.evs.ParameterRange getIntParameterRange(in android.hardware.automotive.evs.CameraParam id);
+ android.hardware.automotive.evs.CameraParam[] getParameterList();
+ android.hardware.automotive.evs.CameraDesc getPhysicalCameraInfo(in String deviceId);
+ int importExternalBuffers(in android.hardware.automotive.evs.BufferDesc[] buffers);
+ void pauseVideoStream();
+ void resumeVideoStream();
+ void setExtendedInfo(in int opaqueIdentifier, in byte[] opaqueValue);
+ int[] setIntParameter(in android.hardware.automotive.evs.CameraParam id, in int value);
+ void setPrimaryClient();
+ void setMaxFramesInFlight(in int bufferCount);
+ void startVideoStream(in android.hardware.automotive.evs.IEvsCameraStream receiver);
+ void stopVideoStream();
+ void unsetPrimaryClient();
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl
new file mode 100644
index 0000000..6e2e64a
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsCameraStream {
+ oneway void deliverFrame(in android.hardware.automotive.evs.BufferDesc[] buffer);
+ oneway void notify(in android.hardware.automotive.evs.EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl
new file mode 100644
index 0000000..9b538d4
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsDisplay {
+ android.hardware.automotive.evs.DisplayDesc getDisplayInfo();
+ android.hardware.automotive.evs.DisplayState getDisplayState();
+ android.hardware.automotive.evs.BufferDesc getTargetBuffer();
+ void returnTargetBufferForDisplay(in android.hardware.automotive.evs.BufferDesc buffer);
+ void setDisplayState(in android.hardware.automotive.evs.DisplayState state);
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.aidl
new file mode 100644
index 0000000..a79c68d
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsEnumerator {
+ void closeCamera(in android.hardware.automotive.evs.IEvsCamera carCamera);
+ void closeDisplay(in android.hardware.automotive.evs.IEvsDisplay display);
+ void closeUltrasonicsArray(in android.hardware.automotive.evs.IEvsUltrasonicsArray evsUltrasonicsArray);
+ android.hardware.automotive.evs.CameraDesc[] getCameraList();
+ byte[] getDisplayIdList();
+ android.hardware.automotive.evs.DisplayState getDisplayState();
+ android.hardware.automotive.evs.Stream[] getStreamList(in android.hardware.automotive.evs.CameraDesc description);
+ android.hardware.automotive.evs.UltrasonicsArrayDesc[] getUltrasonicsArrayList();
+ boolean isHardware();
+ android.hardware.automotive.evs.IEvsCamera openCamera(in String cameraId, in android.hardware.automotive.evs.Stream streamCfg);
+ android.hardware.automotive.evs.IEvsDisplay openDisplay(in byte id);
+ android.hardware.automotive.evs.IEvsUltrasonicsArray openUltrasonicsArray(in String ultrasonicsArrayId);
+ void registerStatusCallback(in android.hardware.automotive.evs.IEvsEnumeratorStatusCallback callback);
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
new file mode 100644
index 0000000..c39a4e8
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsEnumeratorStatusCallback {
+ oneway void deviceStatusChanged(in android.hardware.automotive.evs.DeviceStatus[] status);
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
new file mode 100644
index 0000000..1183ab3
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsUltrasonicsArray {
+ void doneWithDataFrame(in android.hardware.automotive.evs.UltrasonicsDataFrameDesc dataFrameDesc);
+ android.hardware.automotive.evs.UltrasonicsArrayDesc getUltrasonicArrayInfo();
+ void setMaxFramesInFlight(in int bufferCount);
+ void startStream(in android.hardware.automotive.evs.IEvsUltrasonicsArrayStream stream);
+ void stopStream();
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
new file mode 100644
index 0000000..510b0a4
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+interface IEvsUltrasonicsArrayStream {
+ oneway void deliverDataFrame(in android.hardware.automotive.evs.UltrasonicsDataFrameDesc dataFrameDesc);
+ oneway void notify(in android.hardware.automotive.evs.EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl
new file mode 100644
index 0000000..44e9b59
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable ParameterRange {
+ int min;
+ int max;
+ int step;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl
new file mode 100644
index 0000000..91971fc
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum Rotation {
+ ROTATION_0 = 0,
+ ROTATION_90 = 1,
+ ROTATION_180 = 2,
+ ROTATION_270 = 3,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl
new file mode 100644
index 0000000..d9c8b6e
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable RotationQuaternion {
+ float x;
+ float y;
+ float z;
+ float w;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl
new file mode 100644
index 0000000..4ead9ea
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable SensorPose {
+ android.hardware.automotive.evs.RotationQuaternion rotation;
+ android.hardware.automotive.evs.Translation translation;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl
new file mode 100644
index 0000000..a780412
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable Stream {
+ int id;
+ android.hardware.automotive.evs.StreamType streamType;
+ int width;
+ int height;
+ android.hardware.graphics.common.PixelFormat format;
+ android.hardware.graphics.common.BufferUsage usage;
+ android.hardware.automotive.evs.Rotation rotation;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl
new file mode 100644
index 0000000..9819c89
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@Backing(type="int") @VintfStability
+enum StreamType {
+ OUTPUT = 0,
+ INPUT = 1,
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl
new file mode 100644
index 0000000..488d80f
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable Translation {
+ float x;
+ float y;
+ float z;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl
new file mode 100644
index 0000000..23f81f8
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable UltrasonicSensor {
+ android.hardware.automotive.evs.SensorPose pose;
+ float maxRangeMm;
+ float angleOfMeasurement;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
new file mode 100644
index 0000000..4a98875
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable UltrasonicsArrayDesc {
+ @utf8InCpp String ultrasonicsArrayId;
+ int maxReadingsPerSensorCount;
+ int maxReceiversCount;
+ android.hardware.automotive.evs.UltrasonicSensor[] sensors;
+}
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
new file mode 100644
index 0000000..35ec84b
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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 <name>-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.automotive.evs;
+@VintfStability
+parcelable UltrasonicsDataFrameDesc {
+ long timestampNs;
+ int id;
+ byte[] transmittersIdList;
+ byte[] receiversIdList;
+ int[] receiversReadingsCountList;
+ android.hardware.common.Ashmem waveformsData;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl
new file mode 100644
index 0000000..0604abe
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.graphics.common.HardwareBuffer;
+
+/**
+ * Structure representing an image buffer through our APIs
+ *
+ * In addition to the handle to the graphics memory, we need to retain
+ * the properties of the buffer for easy reference and reconstruction of
+ * an ANativeWindowBuffer object on the remote side of API calls.
+ * (Not least because OpenGL expect an ANativeWindowBuffer* for us as a
+ * texture via eglCreateImageKHR()).
+ */
+@VintfStability
+parcelable BufferDesc {
+ /**
+ * Stable AIDL counter part of AHardwareBuffer. Please see
+ * hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
+ * for more details.
+ */
+ HardwareBuffer buffer;
+ /**
+ * The size of a pixel in the units of bytes.
+ */
+ int pixelSizeBytes;
+ /**
+ * Opaque value from driver
+ */
+ int bufferId;
+ /**
+ * Unique identifier of the physical camera device that produces this buffer.
+ */
+ @utf8InCpp
+ String deviceId;
+ /**
+ * Time that this buffer is being filled in the units of microseconds and must be
+ * obtained from android::elapsedRealtimeNanos() or its equivalents.
+ */
+ long timestamp;
+ /**
+ * Frame metadata. This is opaque to EvsManager.
+ */
+ byte[] metadata;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.aidl
new file mode 100644
index 0000000..2f500a7
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Structure describing the basic properties of an EVS camera.
+ *
+ * The HAL is responsible for filling out this structure for each
+ * EVS camera in the system.
+ */
+@VintfStability
+parcelable CameraDesc {
+ /**
+ * Unique identifier for camera devices. This may be a path to detected
+ * camera device; for example, "/dev/video0".
+ */
+ @utf8InCpp
+ String id;
+ /**
+ * Opaque value from driver. Vendor may use this field to store additional
+ * information; for example, sensor and bridge chip id.
+ */
+ int vendorFlags;
+ /**
+ * Store camera metadata such as lens characteristics.
+ */
+ byte[] metadata;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl
new file mode 100644
index 0000000..15500b2
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * EVS camera parameter
+ */
+@VintfStability
+@Backing(type="int")
+enum CameraParam {
+ /**
+ * The brightness of image frames
+ */
+ BRIGHTNESS,
+ /**
+ * The contrast of image frames
+ */
+ CONTRAST,
+ /**
+ * Automatic gain/exposure control
+ */
+ AUTOGAIN,
+ /**
+ * Gain control
+ */
+ GAIN,
+ /**
+ * Automatic Whitebalance
+ */
+ AUTO_WHITE_BALANCE,
+ /**
+ * Manual white balance setting as a color temperature in Kelvin.
+ */
+ WHITE_BALANCE_TEMPERATURE,
+ /**
+ * Image sharpness adjustment
+ */
+ SHARPNESS,
+ /**
+ * Auto Exposure Control modes; auto, manual, shutter priority, or
+ * aperture priority.
+ */
+ AUTO_EXPOSURE,
+ /**
+ * Manual exposure time of the camera
+ */
+ ABSOLUTE_EXPOSURE,
+ /**
+ * Sets the focal point of the camera to the specified position. This
+ * parameter may not be effective when auto focus is enabled.
+ */
+ ABSOLUTE_FOCUS,
+ /**
+ * Enables continuous automatic focus adjustments.
+ */
+ AUTO_FOCUS,
+ /**
+ * Specifies the objective lens focal length as an absolute value.
+ */
+ ABSOLUTE_ZOOM,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl
new file mode 100644
index 0000000..535ace3
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.DeviceStatusType;
+
+/**
+ * The status of the devices, as sent by EVS HAL through the
+ * IEvsEnumeratorCallback::deviceStatusChanged() call.
+ */
+@VintfStability
+parcelable DeviceStatus {
+ /**
+ * The identifier of a device that has transitioned to a new status.
+ */
+ @utf8InCpp
+ String id;
+ /**
+ * A new status of this device
+ */
+ DeviceStatusType status;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.aidl
new file mode 100644
index 0000000..902b31b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * The status of the devices available through the EVS
+ */
+@VintfStability
+@Backing(type="int")
+enum DeviceStatusType {
+ /**
+ * A camera device is available and ready to be used.
+ */
+ CAMERA_AVAILABLE,
+ /**
+ * A camera device is not available; e.g. disconnected from the system.
+ */
+ CAMERA_NOT_AVAILABLE,
+ /**
+ * A display device is available and ready to be used.
+ */
+ DISPLAY_AVAILABLE,
+ /**
+ * A display device is not available; e.g. disconnected from the
+ * system.
+ */
+ DISPLAY_NOT_AVAILABLE,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl
new file mode 100644
index 0000000..0b4243b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.Rotation;
+
+/**
+ * Structure describing the basic properties of an EVS display
+ *
+ * The HAL is responsible for filling out this structure to describe
+ * the EVS display. As an implementation detail, this may be a physical
+ * display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+@VintfStability
+parcelable DisplayDesc {
+ /**
+ * Unique identifier for the display
+ */
+ @utf8InCpp
+ String id;
+ /**
+ * The width of the display
+ */
+ int width;
+ /**
+ * The height of the display
+ */
+ int height;
+ /**
+ * Counterclock-wise orientation of the display
+ */
+ Rotation orientation;
+ /**
+ * Opaque value from driver. Vendor may use this field to store additional
+ * information; for example, sensor and bridge chip id.
+ */
+ int vendorFlags;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl
new file mode 100644
index 0000000..c242d2f
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * States for control of the EVS display
+ *
+ * The DisplayInfo structure describes the basic properties of an EVS display. Any EVS
+ * implementation is required to have one. The HAL is responsible for filling out this
+ * structure to describe the EVS display. As an implementation detail, this may be a
+ * physical display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+@VintfStability
+@Backing(type="int")
+enum DisplayState {
+ /*
+ * Display has not been requested by any application yet
+ */
+ NOT_OPEN = 0,
+ /*
+ * Display is inhibited
+ */
+ NOT_VISIBLE,
+ /*
+ * Will become visible with next frame
+ */
+ VISIBLE_ON_NEXT_FRAME,
+ /*
+ * Display is currently active
+ */
+ VISIBLE,
+ /*
+ * Driver is in an undefined state. Interface should be closed.
+ */
+ DEAD,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
new file mode 100644
index 0000000..ebff98f
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.EvsEventType;
+
+/**
+ * Structure that describes informative events occurred during EVS is streaming
+ */
+@VintfStability
+parcelable EvsEventDesc {
+ /**
+ * Type of an informative event
+ */
+ EvsEventType aType;
+ /**
+ * Device identifier
+ */
+ @utf8InCpp
+ String deviceId;
+ /**
+ * Possible additional vendor information that is opaque to the EvsManager
+ */
+ int[] payload;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl
new file mode 100644
index 0000000..3a493af
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Types of informative streaming events
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsEventType {
+ /**
+ * Video stream is started
+ */
+ STREAM_STARTED = 0,
+ /**
+ * Video stream is stopped
+ */
+ STREAM_STOPPED,
+ /**
+ * Video frame is dropped
+ */
+ FRAME_DROPPED,
+ /**
+ * Timeout happens
+ */
+ TIMEOUT,
+ /**
+ * Camera parameter is changed; payload contains a changed parameter ID and
+ * its value
+ */
+ PARAMETER_CHANGED,
+ /**
+ * Master role has become available
+ */
+ MASTER_RELEASED,
+ /**
+ * Any other erroneous streaming events
+ */
+ STREAM_ERROR,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl
new file mode 100644
index 0000000..c355be3
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Error codes used in EVS HAL interface.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsResult {
+ OK = 0,
+ /**
+ * Given arguments are invalid
+ */
+ INVALID_ARG,
+ /**
+ * Requested stream is already running
+ */
+ STREAM_ALREADY_RUNNING,
+ /**
+ * Buffer is not available; e.g. failed to allocate
+ */
+ BUFFER_NOT_AVAILABLE,
+ /**
+ * Ownership has been expired or stolen by other clients
+ */
+ OWNERSHIP_LOST,
+ /**
+ * A dependent service fails to handle a request
+ */
+ UNDERLYING_SERVICE_ERROR,
+ /**
+ * Permission denied
+ */
+ PERMISSION_DENIED,
+ /**
+ * Either the camera or the display is not available
+ */
+ RESOURCE_NOT_AVAILABLE,
+ /**
+ * Device or resource busy
+ */
+ RESOURCE_BUSY,
+ /**
+ * A method is not implemented yet
+ */
+ NOT_IMPLEMENTED,
+ /**
+ * Requested functionality is not supported
+ */
+ NOT_SUPPORTED,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl
new file mode 100644
index 0000000..080dd75
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.CameraDesc;
+import android.hardware.automotive.evs.CameraParam;
+import android.hardware.automotive.evs.IEvsCameraStream;
+import android.hardware.automotive.evs.IEvsDisplay;
+import android.hardware.automotive.evs.ParameterRange;
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+@VintfStability
+interface IEvsCamera {
+ /**
+ * Returns frames that were delivered to the IEvsCameraStream.
+ *
+ * When done consuming a frame delivered to the IEvsCameraStream
+ * interface, it must be returned to the IEvsCamera for reuse.
+ * A small, finite number of buffers are available (possibly as small
+ * as one), and if the supply is exhausted, no further frames may be
+ * delivered until a buffer is returned.
+ *
+ * @param in buffer Buffers to be returned.
+ */
+ void doneWithFrame(in BufferDesc[] buffer);
+
+ /**
+ * Sets to be the primary client forcibly.
+ *
+ * The client, which owns the display, has a high priority and can take over
+ * a primary client role from other clients without the display.
+ *
+ * @param in display IEvsDisplay handle. If a given display is in either
+ * NOT_VISIBLE, VISIBLE_ON_NEXT_FRAME, or VISIBLE state, the
+ * calling client is considered as the high priority client
+ * and therefore allowed to take over a primary client role from
+ * existing primary client.
+ * @throws EvsResult::INVALID_ARG if a given display handle is null or invalid states.
+ */
+ void forcePrimaryClient(in IEvsDisplay display);
+
+ /**
+ * Returns the description of this camera.
+ *
+ * @return The description of this camera. This must be the same value as
+ * reported by IEvsEnumerator::getCameraList().
+ */
+ CameraDesc getCameraInfo();
+
+ /**
+ * Request driver specific information from the HAL implementation.
+ *
+ * The values allowed for opaqueIdentifier are driver specific,
+ * but no value passed in may crash the driver.
+ *
+ * @param in opaqueIdentifier An unique identifier of the information to
+ * request.
+ * @return Requested information. Zero-size vector is returned if the driver does
+ * not recognize a given identifier.
+ * @throws EvsResult::INVALID_ARG for any unrecognized opaqueIdentifier.
+ */
+ byte[] getExtendedInfo(in int opaqueIdentifier);
+
+ /**
+ * Retrieves values of given camera parameter. The driver must report
+ * EvsResult::INVALID_ARG if a request parameter is not supported.
+ *
+ * @param in id The identifier of camera parameter, CameraParam enum.
+ * @return Values of requested camera parameter, the same number of values as
+ * backing camera devices.
+ * @throws EvsResult::INVALID_ARG for any unrecognized parameter.
+ * EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+ */
+ int[] getIntParameter(in CameraParam id);
+
+ /**
+ * Requests a valid value range of a camera parameter
+ *
+ * @param in id The identifier of camera parameter, CameraParam enum.
+ * @return ParameterRange of a requested CameraParam
+ */
+ ParameterRange getIntParameterRange(in CameraParam id);
+
+ /**
+ * Retrieves a list of parameters this camera supports.
+ *
+ * @return A list of CameraParam that this camera supports.
+ */
+ CameraParam[] getParameterList();
+
+ /**
+ * Returns the description of the physical camera device that backs this
+ * logical camera.
+ *
+ * If a requested device does not either exist or back this logical device,
+ * this method returns a null camera descriptor. And, if this is called on
+ * a physical camera device, this method is the same as getCameraInfo()
+ * method if a given device ID is matched. Otherwise, this will return a
+ * null camera descriptor.
+ *
+ * @param in deviceId Physical camera device identifier string.
+ * @return The description of a member physical camera device.
+ * This must be the same value as reported by IEvsEnumerator::getCameraList().
+ */
+ CameraDesc getPhysicalCameraInfo(in String deviceId);
+
+ /**
+ * Import external buffers to capture frames
+ *
+ * This API must be called with a physical camera device identifier.
+ *
+ * @param in buffers A list of buffers allocated by the caller. EvsCamera
+ * will use these buffers to capture frames, in addition to
+ * other buffers already in its buffer pool.
+ * @return The amount of buffer pool size changes after importing given buffers.
+ */
+ int importExternalBuffers(in BufferDesc[] buffers);
+
+ /**
+ * Requests to pause EVS camera stream events.
+ *
+ * Like stopVideoStream(), events may continue to arrive for some time
+ * after this call returns. Delivered frame buffers must be returned.
+ */
+ void pauseVideoStream();
+
+ /**
+ * Requests to resume EVS camera stream.
+ */
+ void resumeVideoStream();
+
+ /**
+ * Send a driver specific value to the HAL implementation.
+ *
+ * This extension is provided to facilitate car specific
+ * extensions, but no HAL implementation may require this call
+ * in order to function in a default state.
+ * INVALID_ARG is returned if the opaqueValue is not meaningful to
+ * the driver implementation.
+ *
+ * @param in opaqueIdentifier An unique identifier of the information to
+ * program.
+ * in opaqueValue A value to program.
+ * @throws EvsResult::INVALID_ARG if this call fails to set a parameter.
+ */
+ void setExtendedInfo(in int opaqueIdentifier, in byte[] opaqueValue);
+
+ /**
+ * Requests to set a camera parameter.
+ *
+ * Only a request from the primary client will be processed successfully.
+ * When this method is called on a logical camera device, it will be forwarded
+ * to each physical device and, if it fails to program any physical device,
+ * it will return an error code with the same number of effective values as
+ * the number of backing camera devices.
+ *
+ * @param in id The identifier of camera parameter, CameraParam enum.
+ * @param in value A desired parameter value.
+ * @return Programmed parameter values. This may differ from what the client
+ * gives if, for example, the driver does not support a target parameter.
+ * @throws EvsResult::INVALID_ARG if either the request is not made by the primary
+ * client, or a requested parameter is not supported.
+ * EvsResult::UNDERLYING_SERVICE_ERROR if it fails to program a value by any
+ * other reason.
+ */
+ int[] setIntParameter(in CameraParam id, in int value);
+
+ /**
+ * Requests to be the primary client.
+ *
+ * When multiple clients subscribe to a single camera hardware and one of
+ * them adjusts a camera parameter such as the contrast, it may disturb
+ * other clients' operations. Therefore, the client must call this method
+ * to be a primary client. Once it becomes a primary client, it will be able to
+ * change camera parameters until either it dies or explicitly gives up the
+ * role.
+ *
+ * @throws EvsResult::OWNERSHIP_LOST if there is already the primary client.
+ */
+ void setPrimaryClient();
+
+ /**
+ * Specifies the depth of the buffer chain the camera is asked to support.
+ *
+ * Up to this many frames may be held concurrently by the client of IEvsCamera.
+ * If this many frames have been delivered to the receiver without being returned
+ * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+ * It is legal for this call to come at any time, even while streams are already running,
+ * in which case buffers should be added or removed from the chain as appropriate.
+ * If no call is made to this entry point, the IEvsCamera must support at least one
+ * frame by default. More is acceptable.
+ *
+ * @param in bufferCount Number of buffers the client of IEvsCamera may hold concurrently.
+ * @throws EvsResult::BUFFER_NOT_AVAILABLE if the client cannot increase the max frames.
+ * EvsResult::INVALID_ARG if the client cannot decrease the max frames.
+ * EvsResult::OWNERSHIP_LOST if we lost an ownership of a target camera.
+ */
+ void setMaxFramesInFlight(in int bufferCount);
+
+ /**
+ * Request to start EVS camera stream from this camera.
+ *
+ * The IEvsCameraStream must begin receiving calls with various events
+ * including new image frame ready until stopVideoStream() is called.
+ *
+ * @param in receiver IEvsCameraStream implementation.
+ * @throws EvsResult::OWNERSHIP_LOST if we lost an ownership of a target camera.
+ * EvsResult::STREAM_ALREADY_RUNNING if a video stream has been started already.
+ * EvsResult::BUFFER_NOT_AVAILABLE if it fails to secure a minimum number of
+ * buffers to run a video stream.
+ * EvsResult::UNDERLYING_SERVICE_ERROR for all other failures.
+ */
+ void startVideoStream(in IEvsCameraStream receiver);
+
+ /**
+ * Stop the delivery of EVS camera frames.
+ *
+ * Because delivery is asynchronous, frames may continue to arrive for
+ * some time after this call returns. Each must be returned until the
+ * closure of the stream is signaled to the IEvsCameraStream.
+ * This function cannot fail and is simply ignored if the stream isn't running.
+ */
+ void stopVideoStream();
+
+ /**
+ * Retires from the primary client role.
+ *
+ * @throws EvsResult::INVALID_ARG if the caller client is not a primary client.
+ */
+ void unsetPrimaryClient();
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
new file mode 100644
index 0000000..2c2b44c
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.EvsEventDesc;
+import android.hardware.graphics.common.HardwareBuffer;
+
+/**
+ * Implemented on client side to receive asynchronous streaming event deliveries.
+ */
+@VintfStability
+oneway interface IEvsCameraStream {
+ /**
+ * Receives calls from the HAL each time video frames is ready for inspection.
+ * Buffer handles received by this method must be returned via calls to
+ * IEvsCamera::doneWithFrame(). When the video stream is stopped via a call
+ * to IEvsCamera::stopVideoStream(), this callback may continue to happen for
+ * some time as the pipeline drains. Each frame must still be returned.
+ * When the last frame in the stream has been delivered, STREAM_STOPPED
+ * event must be delivered. No further frame deliveries may happen
+ * thereafter.
+ *
+ * A camera device will deliver the same number of frames as number of
+ * backing physical camera devices; it means, a physical camera device
+ * sends always a single frame and a logical camera device sends multiple
+ * frames as many as number of backing physical camera devices.
+ *
+ * @param in buffer Buffer descriptors of delivered image frames.
+ */
+ void deliverFrame(in BufferDesc[] buffer);
+
+ /**
+ * Receives calls from the HAL each time an event happens.
+ *
+ * @param in event EVS event with possible event information.
+ */
+ void notify(in EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl
new file mode 100644
index 0000000..8d57014
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.DisplayDesc;
+import android.hardware.automotive.evs.DisplayState;
+
+/**
+ * Represents a single display.
+ */
+@VintfStability
+interface IEvsDisplay {
+ /**
+ * Returns the description of this display.
+ *
+ * @return The information of this display including id, current mode, current state,
+ * and additional vendor-specific information.
+ * @throws EvsResult::UNDERLYING_SERVICE_ERROR if it fails to read a display information.
+ */
+ DisplayDesc getDisplayInfo();
+
+ /**
+ * This call requests the current state of the display
+ *
+ * The HAL implementation should report the actual current state, which might
+ * transiently differ from the most recently requested state. Note, however, that
+ * the logic responsible for changing display states should generally live above
+ * the device layer, making it undesirable for the HAL implementation to spontaneously
+ * change display states.
+ *
+ * @return Current DisplayState of this Display.
+ */
+ DisplayState getDisplayState();
+
+ /**
+ * This call returns a handle to a frame buffer associated with the display.
+ *
+ * @return A handle to a frame buffer. The returned buffer may be locked and
+ * written to by software and/or GL. This buffer must be returned via
+ * a call to returnTargetBufferForDisplay() even if the display is no
+ * longer visible.
+ * @throws EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+ * EvsResult::BUFFER_NOT_AVAILABLE if no buffer is available.
+ * EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+ */
+ BufferDesc getTargetBuffer();
+
+ /**
+ * This call tells the display that the buffer is ready for display.
+ *
+ * The buffer is no longer valid for use by the client after this call.
+ * There is no maximum time the caller may hold onto the buffer before making this
+ * call. The buffer may be returned at any time and in any DisplayState, but all
+ * buffers are expected to be returned before the IEvsDisplay interface is destroyed.
+ *
+ * @param in buffer A buffer handle to the frame that is ready for display.
+ * @throws EvsResult::INVALID_ARG if a given buffer is unknown or invalid.
+ * EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+ * EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+ */
+ void returnTargetBufferForDisplay(in BufferDesc buffer);
+
+ /**
+ * Clients may set the display state to express their desired state.
+ *
+ * The HAL implementation must gracefully accept a request for any state while in
+ * any other state, although the response may be to defer or ignore the request. The display
+ * is defined to start in the NOT_VISIBLE state upon initialization. The client is
+ * then expected to request the VISIBLE_ON_NEXT_FRAME state, and then begin providing
+ * video. When the display is no longer required, the client is expected to request
+ * the NOT_VISIBLE state after passing the last video frame.
+ * Returns INVALID_ARG if the requested state is not a recognized value.
+ *
+ * @param in state Desired new DisplayState.
+ * @throws EvsResult::INVALID_ARG if a given state is invalid.
+ * EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+ */
+ void setDisplayState(in DisplayState state);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl
new file mode 100644
index 0000000..8e380e0
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.CameraDesc;
+import android.hardware.automotive.evs.DisplayState;
+import android.hardware.automotive.evs.IEvsCamera;
+import android.hardware.automotive.evs.IEvsDisplay;
+import android.hardware.automotive.evs.IEvsEnumeratorStatusCallback;
+import android.hardware.automotive.evs.IEvsUltrasonicsArray;
+import android.hardware.automotive.evs.Stream;
+import android.hardware.automotive.evs.UltrasonicsArrayDesc;
+
+/**
+ * Provides the mechanism for EVS camera and ultrasonics array discovery
+ */
+@VintfStability
+interface IEvsEnumerator {
+ /**
+ * Return the specified IEvsCamera interface as no longer in use
+ *
+ * When the IEvsCamera object is no longer required, it must be released.
+ * NOTE: Video streaming must be cleanly stopped before making this call.
+ *
+ * @param in carCamera EvsCamera object to be closed.
+ * @throws EvsResult::INVALID_ARG if a given camera object is invalid.
+ */
+ void closeCamera(in IEvsCamera carCamera);
+
+ /**
+ * Return the specified IEvsDisplay interface as no longer in use
+ *
+ * When the IEvsDisplay object is no longer required, it must be released.
+ * NOTE: All buffers must have been returned to the display before making this call.
+ *
+ * @param in display EvsDisplay object to be closed.
+ */
+ void closeDisplay(in IEvsDisplay display);
+
+ /**
+ * Return the specified IEvsUltrasonicsArray interface as no longer in use
+ *
+ * When the IEvsUltrasonicsArray object is no longer required, it must be released.
+ * NOTE: Data streaming must be cleanly stopped before making this call.
+ *
+ * @param in evsUltrasonicsArray EvsUltrasonics array object to be closed.
+ */
+ void closeUltrasonicsArray(in IEvsUltrasonicsArray evsUltrasonicsArray);
+
+ /**
+ * Returns a list of all EVS cameras available to the system
+ *
+ * @return A list of cameras availale for EVS service.
+ * @throws EvsResult::PERMISSION_DENIED if the process is not permitted to enumerate
+ * camera devices.
+ */
+ CameraDesc[] getCameraList();
+
+ /**
+ * Returns a list of all EVS displays available to the system
+ *
+ * @return Identifiers of available displays.
+ */
+ byte[] getDisplayIdList();
+
+ /**
+ * This call requests the current state of the display
+ *
+ * If there is no open display, this returns DisplayState::NOT_OPEN. otherwise, it returns
+ * the actual state of the active display. This call is replicated on the IEvsEnumerator
+ * interface in order to allow secondary clients to monitor the state of the EVS display
+ * without acquiring exclusive ownership of the display.
+ *
+ * @return Current DisplayState of this Display.
+ * @throws EvsResult::OWNERSHIP_LOST if current display is inactive
+ * EvsResult::PERMISSION_DENIED if the process is not permitted to do this operation.
+ */
+ DisplayState getDisplayState();
+
+ /**
+ * Return a list of the stream configurations a target camera device supports
+ *
+ * @param in description A target camera descriptor
+ * @return A list of stream configurations supported by a given camera device
+ */
+ Stream[] getStreamList(in CameraDesc description);
+
+ /**
+ * Returns a list of all ultrasonics array available to the system.
+ * Will return an empty vector if ultrasonics is not supported.
+ *
+ * @return A list of ultrasonics available for EVS service.
+ */
+ UltrasonicsArrayDesc[] getUltrasonicsArrayList();
+
+ /**
+ * Tells whether this is EvsManager or HAL implementation.
+ *
+ * @return False for EvsManager implementations and true for all others.
+ */
+ boolean isHardware();
+
+ /**
+ * Gets the IEvsCamera associated with a cameraId from a CameraDesc
+ *
+ * Given a camera's unique cameraId from CameraDesc, returns the
+ * IEvsCamera interface associated with the specified camera. When
+ * done using the camera, the caller may release it by calling closeCamera().
+ *
+ * @param in cameraId A unique identifier of the camera.
+ * @param in streamCfg A stream configuration the client wants to use.
+ * @return EvsCamera object associated with a given cameraId.
+ * Returned object would be null if a camera device does not support a
+ * given stream configuration or is already configured differently by
+ * another client.
+ * @throws EvsResult::PERMISSION_DENIED if the process is not permitted to use camera
+ * devices.
+ * EveResult::INVALID_ARG if it fails to open a camera with a given id.
+ */
+ IEvsCamera openCamera(in String cameraId, in Stream streamCfg);
+
+ /**
+ * Get exclusive access to IEvsDisplay for the system
+ *
+ * There can be more than one EVS display objects for the system and this function
+ * requests access to the display identified by a given ID. If the target EVS display
+ * is not available or is already in use the old instance shall be closed and give
+ * the new caller exclusive access.
+ * When done using the display, the caller may release it by calling closeDisplay().
+ *
+ * @param in id Target display identifier.
+ * @return EvsDisplay object to be used.
+ * @throws EvsResult::INVALID_ARG if no display with a given id exists
+ */
+ IEvsDisplay openDisplay(in byte id);
+
+ /**
+ * Gets the IEvsUltrasonicsArray associated with a ultrasonicsArrayId from a
+ * UltrasonicsDataDesc
+ *
+ * @param in ultrasonicsArrayId A unique identifier of the ultrasonic array.
+ * @return IEvsUltrasonicsArray object associated with a given ultrasonicsArrayId.
+ */
+ IEvsUltrasonicsArray openUltrasonicsArray(in String ultrasonicsArrayId);
+
+ /**
+ * Registers a callback to listen to devices' status changes
+ *
+ * @param in callback IEvsEnumeratorStatusCallback implementation
+ */
+ void registerStatusCallback(in IEvsEnumeratorStatusCallback callback);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
new file mode 100644
index 0000000..26ccf72
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.DeviceStatus;
+
+/**
+ * Implemented on client side to receive asynchronous notifications from
+ * IEvsEnumreator.
+ */
+@VintfStability
+oneway interface IEvsEnumeratorStatusCallback {
+ /**
+ * Receives calls from the HAL each time a status of camera devices is
+ * changed.
+ *
+ * @param in status A list of newly updated device status
+ */
+ void deviceStatusChanged(in DeviceStatus[] status);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
new file mode 100644
index 0000000..40de313
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.IEvsUltrasonicsArrayStream;
+import android.hardware.automotive.evs.UltrasonicsArrayDesc;
+import android.hardware.automotive.evs.UltrasonicsDataFrameDesc;
+
+/**
+ * HAL interface for ultrasonics sensor array.
+ */
+@VintfStability
+interface IEvsUltrasonicsArray {
+ /**
+ * Notifies the UltrasonicsDataDesc is consumed that was received from
+ * IEvsUltrasonicsArrayStream
+ *
+ * @param in dataFrameDesc Ultrasonics data descriptor
+ */
+ void doneWithDataFrame(in UltrasonicsDataFrameDesc dataFrameDesc);
+
+ /**
+ * Returns the ultrasonic sensor array information
+ *
+ * @throws The description of this ultrasonic array. This must be the same
+ * value as reported by IEvsEnumerator::getUltrasonicsArrayList().
+ */
+ UltrasonicsArrayDesc getUltrasonicArrayInfo();
+
+ /**
+ * Specifies the depth of the buffer chain the ultrasonic sensors is
+ * asked to support
+ *
+ * Up to this many data frames may be held concurrently by the client of IEvsUltrasonicsArray.
+ * If this many frames have been delivered to the receiver without being returned
+ * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+ * It is legal for this call to come at any time, even while streams are already running,
+ * in which case buffers should be added or removed from the chain as appropriate.
+ * If no call is made to this entry point, the IEvsUltrasonicsArray must support at least one
+ * data frame by default. More is acceptable.
+ *
+ * @param in bufferCount Number of buffers the client of IEvsUltrasonicsArray may hold
+ * concurrently.
+ * @throws EvsResult::INVALID_ARG on invalid bufferCount.
+ */
+ void setMaxFramesInFlight(in int bufferCount);
+
+ /**
+ * Requests to start the stream
+ *
+ * @param in stream Implementation of IEvsUltrasonicsArrayStream.
+ * @throws EvsResult::STREAM_ALREADY_RUNNING if stream is already running
+ */
+ void startStream(in IEvsUltrasonicsArrayStream stream);
+
+ /**
+ * Requests to stop the delivery of the ultrasonic array data frames
+ *
+ * Because delivery is asynchronous, frames may continue to arrive for
+ * some time after this call returns. Each must be returned until the
+ * closure of the stream is signaled to the IEvsCameraStream.
+ * This function cannot fail and is ignored if the stream isn't running.
+ */
+ void stopStream();
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
new file mode 100644
index 0000000..bc31a6b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.EvsEventDesc;
+import android.hardware.automotive.evs.UltrasonicsDataFrameDesc;
+
+/**
+ * Implemented on client side to receive asynchronous ultrasonic data
+ * deliveries.
+ */
+@VintfStability
+interface IEvsUltrasonicsArrayStream {
+ /**
+ * Receives calls from the HAL each time a data frame is ready
+ *
+ * @param in dataFrameDesc Ultrasonic array data frame descriptor
+ */
+ oneway void deliverDataFrame(in UltrasonicsDataFrameDesc dataFrameDesc);
+
+ /**
+ * Receives calls from the HAL each time an event happens
+ *
+ * @param in event Event EVS event with possible event information
+ */
+ oneway void notify(in EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl
new file mode 100644
index 0000000..b08fcbd
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Represent a valid range of CameraParam
+ */
+@VintfStability
+parcelable ParameterRange {
+ /**
+ * Lower bound of a valid value range
+ */
+ int min;
+ /**
+ * Upper bound of a valid value range
+ */
+ int max;
+ /**
+ * A value of unit increment
+ */
+ int step;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl
new file mode 100644
index 0000000..dede39e
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Rotation:
+ *
+ * The required counterclockwise rotation of EVS camera stream and display.
+ */
+@VintfStability
+@Backing(type="int")
+enum Rotation {
+ /** No rotation */
+ ROTATION_0 = 0,
+ /** Rotate by 90 degree counterclockwise */
+ ROTATION_90 = 1,
+ /** Rotate by 180 degree counterclockwise */
+ ROTATION_180 = 2,
+ /** Rotate by 270 degree counterclockwise */
+ ROTATION_270 = 3
+
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl
new file mode 100644
index 0000000..b80343b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Structure for rotation expressed as quaternions.
+ * Convention used: Unit quaternion with hamilton convention.
+ */
+@VintfStability
+parcelable RotationQuaternion {
+ float x;
+ float y;
+ float z;
+ float w;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl
new file mode 100644
index 0000000..26c3339
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.RotationQuaternion;
+import android.hardware.automotive.evs.Translation;
+
+/**
+ * Provides the orientation and location of a car sensor relative to the android automotive
+ * coordinate system:
+ * https://source.android.com/devices/sensors/sensor-types#auto_axes
+ * The sensor pose defines the transformation to be applied to the android automotive axes to
+ * obtain the sensor local axes.
+ * The pose consists of rotation, (specified as a quaternions) and translation
+ * (vector with x, y, z).
+ * This rotation and translation applied to the sensor data in the sensor's local coordinate
+ * system transform the data to the automotive coordinate system.
+ * i.e. loc = ( Rot * Psensor ) + Trans
+ * Here loc is a point in automotive coordinate system and Psensor is a point in the sensor's
+ * coordinate system.
+ * Example:
+ * For a sensor on the front bumper and on the left corner of the car with its X axis pointing to
+ * the front, the sensor is located at (-2, 4, 0) meters w.r.t android automotive axes and the
+ * sensor local axes has a rotation of 90 degrees counter-clockwise w.r.t android automotive axes
+ * when viewing the car from top on the +Z axis side:
+ *
+ * ↑X sensor
+ * Y←∘______
+ * | | front
+ * | car |
+ * | ↑Y |
+ * | ∘→X | rear
+ * |______|
+ *
+ * For this example the rotation and translation will be:
+ * Rotation = + 90 degrees around Z axis = (0.7071, 0, 0, 0.7071) as a unit quaternion.
+ * Translation = (-2, 4, 0) in meters = (-2000, 4000, 0) in milli-meters.
+ * Note: Every sensor type must specify its own pose.
+ */
+@VintfStability
+parcelable SensorPose {
+ /**
+ * Rotation part of the sensor pose, expressed as a unit quaternion.
+ */
+ RotationQuaternion rotation;
+ /**
+ * Translation part of the sensor pose, in (x, y, z) format with milli-meter units.
+ */
+ Translation translation;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl
new file mode 100644
index 0000000..ae5c7f0
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.Rotation;
+import android.hardware.automotive.evs.StreamType;
+import android.hardware.graphics.common.BufferUsage;
+import android.hardware.graphics.common.PixelFormat;
+
+/**
+ * Stream:
+ *
+ * Structure that describes a EVS Camera stream
+ */
+@VintfStability
+parcelable Stream {
+ /**
+ * Stream ID - a non-negative integer identifier for a stream.
+ *
+ * The identical stream ID must reference the same stream, with the same
+ * width/height/format, across consecutive calls to configureStreams.
+ *
+ * If previously-used stream ID is not used in a new call to
+ * configureStreams, then that stream is no longer active. Such a stream ID
+ * may be reused in a future configureStreams with a new
+ * width/height/format.
+ *
+ */
+ int id;
+ /**
+ * The type of the stream (input vs output, etc).
+ */
+ StreamType streamType;
+ /**
+ * The width in pixels of the buffers in this stream.
+ */
+ int width;
+ /**
+ * The height in pixels of the buffers in this stream.
+ */
+ int height;
+ /**
+ * The frame rate of this stream in frames-per-second
+ /
+ int framerate;
+ /**
+ * The pixel format form the buffers in this stream.
+ */
+ PixelFormat format;
+ /**
+ * The gralloc usage flags for this stream, as needed by the consumer of
+ * the stream.
+ */
+ BufferUsage usage;
+ /**
+ * The required output rotation of the stream.
+ *
+ * This must be inspected by HAL along with stream with and height.
+ */
+ Rotation rotation;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl
new file mode 100644
index 0000000..c028a5c
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * StreamType:
+ *
+ * The type of the camera stream, which defines whether the EVS client device is
+ * the producer or the consumer for that stream, and how the buffers of the
+ * stream relate to the other streams.
+ */
+@VintfStability
+@Backing(type="int")
+enum StreamType {
+ /**
+ * This stream is an output stream; the EVS HAL device must fill buffers
+ * from this stream with newly captured or reprocessed image data.
+ */
+ OUTPUT = 0,
+
+ /**
+ * This stream is an input stream; the EVS HAL device must read buffers
+ * from this stream and send them through the camera processing pipeline,
+ * as if the buffer was a newly captured image from the imager.
+ */
+ INPUT = 1
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl
new file mode 100644
index 0000000..14b14db
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+/**
+ * Structure for translation with x, y and z units.
+ */
+@VintfStability
+parcelable Translation {
+ float x;
+ float y;
+ float z;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl
new file mode 100644
index 0000000..712411b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.SensorPose;
+
+/**
+ * Structure that contains all information of an ultrasonic sensor.
+ */
+@VintfStability
+parcelable UltrasonicSensor {
+ /**
+ * Pose provides the orientation and location of the ultrasonic sensor within the car.
+ * The +Y axis points along the center of the beam spread the X axis to the right and the Z
+ * axis in the up direction.
+ */
+ SensorPose pose;
+ /**
+ * Maximum range of the sensor in milli-metres.
+ */
+ float maxRangeMm;
+ /**
+ * Half-angle of the angle of measurement of the sensor, relative to the
+ * sensor’s x axis, in radians.
+ */
+ float angleOfMeasurement;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
new file mode 100644
index 0000000..d4f0663
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.automotive.evs.UltrasonicSensor;
+
+/**
+ * Structure identifies and describes an ultrasonics array in the car.
+ *
+ * A ultrasonics array represents a group of ultrasonic sensors within the
+ * car. These may be sensors that are physically connected to the same hardware
+ * control unit or represent a logical group of sensors like front and back.
+ * The HAL is responsible for filling out this structure for each Ultrasonics
+ * Array.
+ */
+@VintfStability
+parcelable UltrasonicsArrayDesc {
+ /**
+ * Unique identifier for the ultrasonic array. This may be a path or name of the
+ * physical control device or a string identifying a logical group of sensors forming an array
+ * such as "front_array" and "back_array".
+ */
+ @utf8InCpp
+ String ultrasonicsArrayId;
+ /**
+ * Maximum number of readings (points on waveform) provided per sensor in
+ * each data frame. Used by client to pre-allocate required memory buffer for
+ * incoming data.
+ */
+ int maxReadingsPerSensorCount;
+ /**
+ * Maximum number of receiver sensors in a data frame. Must be between 1
+ * and sensorCount. Used by client to pre-allocate required memory buffer for
+ * incoming data.
+ */
+ int maxReceiversCount;
+ /**
+ * The order of sensors specified must be in clockwise order around the car, starting
+ * from front left-most sensor.
+ */
+ UltrasonicSensor[] sensors;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
new file mode 100644
index 0000000..e546db9
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 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.automotive.evs;
+
+import android.hardware.common.Ashmem;
+
+/**
+ * Structure that describes the data frame received from an ultrasonics array.
+ *
+ * Each data frame returned consists of received waveform signals from a subset
+ * of sensors in an array as indicated by the receiversIdList. The signal is
+ * transmitted at a particular time instant indicated by timestampNs from a
+ * subset of sensors in the array as provided in the transmittersIdList.
+ */
+@VintfStability
+parcelable UltrasonicsDataFrameDesc {
+ /**
+ * Timestamp of the start of the transmit signal for this data frame.
+ * Timestamp unit is nanoseconds and is obtained from android::elapsedRealtimeNanos().
+ * timeOfFlight readings are future-deltas to this timestamp.
+ */
+ long timestampNs;
+ /**
+ * Identifier of data frame. Used by implementation for managing multiple frames in flight.
+ */
+ int id;
+ /**
+ * List of indexes of sensors in range [0, sensorCount - 1] that
+ * transmitted the signal for this data frame.
+ */
+ byte[] transmittersIdList;
+ /**
+ * List of indexes of sensors in range [0, sensorCount - 1] that received
+ * the signal. The order of ids must match the order of the waveforms in the
+ * waveformsData.
+ * Size of list is upper bound by maxReceiversCount.
+ */
+ byte[] receiversIdList;
+ /**
+ * List of the number of readings corresponding to each ultrasonics sensor in
+ * the receiversIdList. Order of the readings count must match the order in
+ * receiversIdList.
+ * Size of list is upper bound by maxReadingsPerSensorCount.
+ */
+ int[] receiversReadingsCountList;
+ /**
+ * Shared memory object containing the waveforms data. Contains one waveform
+ * for each sensor specified in receiversIdList, in order.
+ * Each waveform is represented by a number of readings, which are sample
+ * points on the waveform. The number of readings for each waveform is as
+ * specified in the receiversReadingsCountList.
+ * Each reading is a pair of time Of flight and resonance.
+ * Time of flight (float): Time between transmit and receive signal in nanoseconds.
+ * Resonance (float): Resonance at time on waveform in range [0.0, 1.0].
+ *
+ * The structure of shared memory (example with 2 waveforms, each with 2 readings):
+ *
+ * Byte: | 0 | 1-4 | 5-8 | 9-12 | 13-16 || 17 | 18-21 | 22-25 | 26-29 | 30-33 |
+ * Data: | RecId1 | TOF1 | RES1 | TOF2 | RES2 || RecId2 | TOF1 | RES1 | TOF2 | RES2 |
+ * | Waveform1 || Waveform2 |
+ * Here:
+ * RecId : Receiver's Id. Order matches the receiversIdList, type uint8_t
+ * TOF : Time of flight, type float (4 bytes)
+ * RES : Resonance, type float (4 bytes)
+ * Note: All readings and waveforms are contigious with no padding.
+ */
+ Ashmem waveformsData;
+}
diff --git a/automotive/evs/aidl/impl/Android.bp b/automotive/evs/aidl/impl/Android.bp
new file mode 100644
index 0000000..7eb0116
--- /dev/null
+++ b/automotive/evs/aidl/impl/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+ name: "EvsHalDefaults",
+ static_libs: [
+ "android.hardware.automotive.evs-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.graphics.common-V3-ndk",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+}
diff --git a/automotive/evs/aidl/impl/default/Android.bp b/automotive/evs/aidl/impl/default/Android.bp
new file mode 100644
index 0000000..dbe0314
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2022 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_binary {
+ name: "android.hardware.automotive.evs-aidl-default-service",
+ defaults: ["EvsHalDefaults"],
+ local_include_dirs: ["include"],
+ vintf_fragments: ["evs-default-service.xml"],
+ init_rc: ["evs-default-service.rc"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["src/*.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+}
diff --git a/automotive/evs/aidl/impl/default/evs-default-service.rc b/automotive/evs/aidl/impl/default/evs-default-service.rc
new file mode 100644
index 0000000..ea8e689
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/evs-default-service.rc
@@ -0,0 +1,5 @@
+service vendor.evs-hal-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-default-service
+ class early_hal
+ user automotive_evs
+ group automotive_evs
+ disabled
diff --git a/automotive/evs/aidl/impl/default/evs-default-service.xml b/automotive/evs/aidl/impl/default/evs-default-service.xml
new file mode 100644
index 0000000..96ff9f6
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/evs-default-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.evs</name>
+ <transport>hwbinder</transport>
+ <version>1</version>
+ <interface>
+ <name>IEvsEnumerator</name>
+ <instance>hw/0</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h
new file mode 100644
index 0000000..8bcd867
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
+#define android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
+
+#include <aidl/android/hardware/automotive/evs/BnEvsEnumerator.h>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+class DefaultEvsEnumerator final
+ : public ::aidl::android::hardware::automotive::evs::BnEvsEnumerator {
+ ::ndk::ScopedAStatus isHardware(bool* flag) override;
+ ::ndk::ScopedAStatus openCamera(
+ const std::string& cameraId,
+ const ::aidl::android::hardware::automotive::evs::Stream& streamConfig,
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>* obj) override;
+ ::ndk::ScopedAStatus closeCamera(
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>& obj)
+ override;
+ ::ndk::ScopedAStatus getCameraList(
+ std::vector<::aidl::android::hardware::automotive::evs::CameraDesc>* list) override;
+ ::ndk::ScopedAStatus getStreamList(
+ const ::aidl::android::hardware::automotive::evs::CameraDesc& desc,
+ std::vector<::aidl::android::hardware::automotive::evs::Stream>* _aidl_return) override;
+ ::ndk::ScopedAStatus openDisplay(
+ int8_t displayId,
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>* obj) override;
+ ::ndk::ScopedAStatus closeDisplay(
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& obj)
+ override;
+ ::ndk::ScopedAStatus getDisplayIdList(std::vector<uint8_t>* list) override;
+ ::ndk::ScopedAStatus getDisplayState(
+ ::aidl::android::hardware::automotive::evs::DisplayState* state) override;
+ ::ndk::ScopedAStatus registerStatusCallback(
+ const std::shared_ptr<
+ ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback>&
+ callback) override;
+ ::ndk::ScopedAStatus openUltrasonicsArray(
+ const std::string& id,
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>* obj)
+ override;
+ ::ndk::ScopedAStatus closeUltrasonicsArray(
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>&
+ arr) override;
+ ::ndk::ScopedAStatus getUltrasonicsArrayList(
+ std::vector<::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc>* list)
+ override;
+};
+
+} // namespace aidl::android::hardware::automotive::evs::implementation
+
+#endif // android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
diff --git a/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp
new file mode 100644
index 0000000..2ff6d59
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+// TODO(b/203661081): Remove below lines to disable compiler warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+#define LOG_TAG "DefaultEvsEnumerator"
+
+#include <DefaultEvsEnumerator.h>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+using ::ndk::ScopedAStatus;
+
+ScopedAStatus DefaultEvsEnumerator::isHardware(bool* flag) {
+ // This returns true always.
+ *flag = true;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openCamera(const std::string& cameraId,
+ const Stream& streamConfig,
+ std::shared_ptr<IEvsCamera>* obj) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeCamera(const std::shared_ptr<IEvsCamera>& obj) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getCameraList(std::vector<CameraDesc>* list) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getStreamList(const CameraDesc& desc,
+ std::vector<Stream>* _aidl_return) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openDisplay(int8_t displayId,
+ std::shared_ptr<IEvsDisplay>* obj) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeDisplay(const std::shared_ptr<IEvsDisplay>& state) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getDisplayIdList(std::vector<uint8_t>* list) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getDisplayState(DisplayState* state) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::registerStatusCallback(
+ const std::shared_ptr<IEvsEnumeratorStatusCallback>& callback) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openUltrasonicsArray(
+ const std::string& id, std::shared_ptr<IEvsUltrasonicsArray>* obj) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeUltrasonicsArray(
+ const std::shared_ptr<IEvsUltrasonicsArray>& obj) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getUltrasonicsArrayList(
+ std::vector<UltrasonicsArrayDesc>* list) {
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::automotive::evs::implementation
+
+#pragma clang diagnostic pop
diff --git a/automotive/evs/aidl/impl/default/src/service.cpp b/automotive/evs/aidl/impl/default/src/service.cpp
new file mode 100644
index 0000000..0a0913f
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/src/service.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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 "EvsService"
+
+#include <DefaultEvsEnumerator.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+using ::aidl::android::hardware::automotive::evs::implementation::DefaultEvsEnumerator;
+
+int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
+ std::shared_ptr<DefaultEvsEnumerator> vhal = ndk::SharedRefBase::make<DefaultEvsEnumerator>();
+
+ ALOGI("Registering as service...");
+ binder_exception_t err =
+ AServiceManager_addService(vhal->asBinder().get(), "android.hardware.automotive.evs");
+ if (err != EX_NONE) {
+ ALOGE("failed to register android.hardware.automotive.evs service, exception: %d", err);
+ return 1;
+ }
+
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+ ALOGE("%s", "failed to set thread pool max thread count");
+ return 1;
+ }
+ ABinderProcess_startThreadPool();
+
+ ALOGI("Evs Service Ready");
+
+ ABinderProcess_joinThreadPool();
+
+ ALOGI("Evs Service Exiting");
+
+ return 0;
+}
diff --git a/automotive/evs/aidl/vts/Android.bp b/automotive/evs/aidl/vts/Android.bp
new file mode 100644
index 0000000..980c6d5
--- /dev/null
+++ b/automotive/evs/aidl/vts/Android.bp
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2022 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:
+ "VtsHalEvsTargetTest",
+ srcs: [
+ "*.cpp",
+ ],
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcamera_metadata",
+ "libui",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.automotive.evs@common-default-lib",
+ "android.hardware.automotive.evs-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.graphics.common-V3-ndk",
+ "libaidlcommonsupport",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/automotive/evs/aidl/vts/FrameHandler.cpp b/automotive/evs/aidl/vts/FrameHandler.cpp
new file mode 100644
index 0000000..bab832b
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandler.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2022 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 "VtsHalEvsTest"
+
+#include "FrameHandler.h"
+#include "FormatConvert.h"
+
+#include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+
+using ::aidl::android::hardware::automotive::evs::BufferDesc;
+using ::aidl::android::hardware::automotive::evs::CameraDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::IEvsCamera;
+using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
+using ::aidl::android::hardware::graphics::common::HardwareBufferDescription;
+using ::ndk::ScopedAStatus;
+using std::chrono_literals::operator""s;
+
+FrameHandler::FrameHandler(const std::shared_ptr<IEvsCamera>& pCamera, const CameraDesc& cameraInfo,
+ const std::shared_ptr<IEvsDisplay>& pDisplay, BufferControlFlag mode)
+ : mCamera(pCamera), mCameraInfo(cameraInfo), mDisplay(pDisplay), mReturnMode(mode) {
+ // Nothing but member initialization here.
+}
+
+void FrameHandler::shutdown() {
+ // Make sure we're not still streaming
+ blockingStopStream();
+
+ // At this point, the receiver thread is no longer running, so we can safely drop
+ // our remote object references so they can be freed
+ mCamera = nullptr;
+ mDisplay = nullptr;
+}
+
+bool FrameHandler::startStream() {
+ // Tell the camera to start streaming
+ auto status = mCamera->startVideoStream(ref<FrameHandler>());
+ if (!status.isOk()) {
+ return false;
+ }
+
+ // Mark ourselves as running
+ mLock.lock();
+ mRunning = true;
+ mLock.unlock();
+
+ return true;
+}
+
+void FrameHandler::asyncStopStream() {
+ // Tell the camera to stop streaming.
+ // This will result in a null frame being delivered when the stream actually stops.
+ mCamera->stopVideoStream();
+}
+
+void FrameHandler::blockingStopStream() {
+ // Tell the stream to stop
+ asyncStopStream();
+
+ // Wait until the stream has actually stopped
+ std::unique_lock<std::mutex> lock(mEventLock);
+ if (mRunning) {
+ mEventSignal.wait(lock, [this]() { return !mRunning; });
+ }
+}
+
+bool FrameHandler::returnHeldBuffer() {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ // Return the oldest buffer we're holding
+ if (mHeldBuffers.empty()) {
+ // No buffers are currently held
+ return false;
+ }
+
+ std::vector<BufferDesc> buffers = std::move(mHeldBuffers.front());
+ mHeldBuffers.pop();
+ mCamera->doneWithFrame(buffers);
+
+ return true;
+}
+
+bool FrameHandler::isRunning() {
+ std::lock_guard<std::mutex> lock(mLock);
+ return mRunning;
+}
+
+void FrameHandler::waitForFrameCount(unsigned frameCount) {
+ // Wait until we've seen at least the requested number of frames (could be more)
+ std::unique_lock<std::mutex> lock(mLock);
+ mFrameSignal.wait(lock, [this, frameCount]() { return mFramesReceived >= frameCount; });
+}
+
+void FrameHandler::getFramesCounters(unsigned* received, unsigned* displayed) {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ if (received) {
+ *received = mFramesReceived;
+ }
+ if (displayed) {
+ *displayed = mFramesDisplayed;
+ }
+}
+
+ScopedAStatus FrameHandler::deliverFrame(const std::vector<BufferDesc>& buffers) {
+ mLock.lock();
+ // For VTS tests, FrameHandler uses a single frame among delivered frames.
+ auto bufferIdx = mFramesDisplayed % buffers.size();
+ auto& buffer = buffers[bufferIdx];
+ mLock.unlock();
+
+ // Store a dimension of a received frame.
+ mFrameWidth = buffer.buffer.description.width;
+ mFrameHeight = buffer.buffer.description.height;
+
+ // If we were given an opened display at construction time, then send the received
+ // image back down the camera.
+ bool displayed = false;
+ if (mDisplay) {
+ // Get the output buffer we'll use to display the imagery
+ BufferDesc tgtBuffer;
+ auto status = mDisplay->getTargetBuffer(&tgtBuffer);
+ if (!status.isOk()) {
+ printf("Didn't get target buffer - frame lost\n");
+ LOG(ERROR) << "Didn't get requested output buffer -- skipping this frame.";
+ } else {
+ // Copy the contents of the of buffer.memHandle into tgtBuffer
+ copyBufferContents(tgtBuffer, buffer);
+
+ // Send the target buffer back for display
+ auto status = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
+ if (!status.isOk()) {
+ printf("AIDL error on display buffer (%d)- frame lost\n",
+ status.getServiceSpecificError());
+ LOG(ERROR) << "Error making the remote function call. AIDL said "
+ << status.getServiceSpecificError();
+ } else {
+ // Everything looks good!
+ // Keep track so tests or watch dogs can monitor progress
+ displayed = true;
+ }
+ }
+ }
+
+ mLock.lock();
+ // increases counters
+ ++mFramesReceived;
+ mFramesDisplayed += (int)displayed;
+ mLock.unlock();
+ mFrameSignal.notify_all();
+
+ switch (mReturnMode) {
+ case eAutoReturn:
+ // Send the camera buffer back now that the client has seen it
+ LOG(DEBUG) << "Calling doneWithFrame";
+ mCamera->doneWithFrame(buffers);
+ break;
+ case eNoAutoReturn:
+ // Hang onto the buffer handles for now -- the client will return it explicitly later
+ // mHeldBuffers.push(buffers);
+ break;
+ }
+
+ LOG(DEBUG) << "Frame handling complete";
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus FrameHandler::notify(const EvsEventDesc& event) {
+ // Local flag we use to keep track of when the stream is stopping
+ std::unique_lock<std::mutex> lock(mEventLock);
+ mLatestEventDesc.aType = event.aType;
+ mLatestEventDesc.payload[0] = event.payload[0];
+ mLatestEventDesc.payload[1] = event.payload[1];
+ if (mLatestEventDesc.aType == EvsEventType::STREAM_STOPPED) {
+ // Signal that the last frame has been received and the stream is stopped
+ mRunning = false;
+ } else if (mLatestEventDesc.aType == EvsEventType::PARAMETER_CHANGED) {
+ LOG(DEBUG) << "Camera parameter " << mLatestEventDesc.payload[0] << " is changed to "
+ << mLatestEventDesc.payload[1];
+ } else {
+ LOG(DEBUG) << "Received an event " << eventToString(mLatestEventDesc.aType);
+ }
+ lock.unlock();
+ mEventSignal.notify_one();
+
+ return ScopedAStatus::ok();
+}
+
+bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer) {
+ bool success = true;
+ const HardwareBufferDescription* pSrcDesc =
+ reinterpret_cast<const HardwareBufferDescription*>(&srcBuffer.buffer.description);
+ const HardwareBufferDescription* pTgtDesc =
+ reinterpret_cast<const HardwareBufferDescription*>(&tgtBuffer.buffer.description);
+
+ // Make sure we don't run off the end of either buffer
+ const unsigned width = std::min(pTgtDesc->width, pSrcDesc->width);
+ const unsigned height = std::min(pTgtDesc->height, pSrcDesc->height);
+
+ // FIXME: We duplicate file descriptors twice below; consider using TAKE_HANDLE
+ // instead of CLONE_HANDLE.
+ buffer_handle_t target = ::android::dupFromAidl(tgtBuffer.buffer.handle);
+ ::android::sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
+ target, android::GraphicBuffer::CLONE_HANDLE, pTgtDesc->width, pTgtDesc->height,
+ static_cast<android::PixelFormat>(pTgtDesc->format), pTgtDesc->layers,
+ static_cast<uint64_t>(pTgtDesc->usage), pTgtDesc->stride);
+
+ buffer_handle_t source = ::android::dupFromAidl(srcBuffer.buffer.handle);
+ ::android::sp<android::GraphicBuffer> src = new android::GraphicBuffer(
+ source, android::GraphicBuffer::CLONE_HANDLE, pSrcDesc->width, pSrcDesc->height,
+ static_cast<android::PixelFormat>(pSrcDesc->format), pSrcDesc->layers,
+ static_cast<uint64_t>(pSrcDesc->usage), pSrcDesc->stride);
+
+ // Lock our source buffer for reading (current expectation are for this to be NV21 format)
+ uint8_t* srcPixels = nullptr;
+ src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
+
+ // Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format)
+ uint32_t* tgtPixels = nullptr;
+ tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
+
+ if (srcPixels && tgtPixels) {
+ using namespace ::android::hardware::automotive::evs::common;
+ if (static_cast<android_pixel_format_t>(pTgtDesc->format) == HAL_PIXEL_FORMAT_RGBA_8888) {
+ if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
+ Utils::copyNV21toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+ } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
+ Utils::copyYV12toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+ } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
+ Utils::copyYUYVtoRGB32(width, height, srcPixels, pSrcDesc->stride, tgtPixels,
+ pTgtDesc->stride);
+ } else if (pSrcDesc->format == pTgtDesc->format) { // 32bit RGBA
+ Utils::copyMatchedInterleavedFormats(width, height, srcPixels, pSrcDesc->stride,
+ tgtPixels, pTgtDesc->stride,
+ tgtBuffer.pixelSizeBytes);
+ } else {
+ LOG(ERROR) << "Camera buffer format is not supported";
+ success = false;
+ }
+ } else if (static_cast<android_pixel_format_t>(pTgtDesc->format) ==
+ HAL_PIXEL_FORMAT_BGRA_8888) {
+ if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
+ Utils::copyNV21toBGR32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+ } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
+ Utils::copyYV12toBGR32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+ } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+ HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
+ Utils::copyYUYVtoBGR32(width, height, srcPixels, pSrcDesc->stride, tgtPixels,
+ pTgtDesc->stride);
+ } else if (pSrcDesc->format == pTgtDesc->format) { // 32bit RGBA
+ Utils::copyMatchedInterleavedFormats(width, height, srcPixels, pSrcDesc->stride,
+ tgtPixels, pTgtDesc->stride,
+ tgtBuffer.pixelSizeBytes);
+ } else {
+ LOG(ERROR) << "Camera buffer format is not supported";
+ success = false;
+ }
+ } else {
+ // We always expect 32 bit RGB for the display output for now. Is there a need for 565?
+ LOG(ERROR) << "Diplay buffer is always expected to be 32bit RGBA";
+ success = false;
+ }
+ } else {
+ LOG(ERROR) << "Failed to lock buffer contents for contents transfer";
+ success = false;
+ }
+
+ if (srcPixels) {
+ src->unlock();
+ }
+ if (tgtPixels) {
+ tgt->unlock();
+ }
+
+ return success;
+}
+
+void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
+ if (width) {
+ *width = mFrameWidth;
+ }
+
+ if (height) {
+ *height = mFrameHeight;
+ }
+}
+
+bool FrameHandler::waitForEvent(const EvsEventDesc& aTargetEvent, EvsEventDesc& aReceivedEvent,
+ bool ignorePayload) {
+ // Wait until we get an expected parameter change event.
+ std::unique_lock<std::mutex> lock(mEventLock);
+ auto now = std::chrono::system_clock::now();
+ bool found = false;
+ while (!found) {
+ bool result = mEventSignal.wait_until(
+ lock, now + 5s, [this, aTargetEvent, ignorePayload, &aReceivedEvent, &found]() {
+ found = (mLatestEventDesc.aType == aTargetEvent.aType) &&
+ (ignorePayload ||
+ (mLatestEventDesc.payload[0] == aTargetEvent.payload[0] &&
+ mLatestEventDesc.payload[1] == aTargetEvent.payload[1]));
+
+ aReceivedEvent.aType = mLatestEventDesc.aType;
+ aReceivedEvent.payload[0] = mLatestEventDesc.payload[0];
+ aReceivedEvent.payload[1] = mLatestEventDesc.payload[1];
+ return found;
+ });
+
+ if (!result) {
+ LOG(WARNING) << "A timer is expired before a target event has happened.";
+ break;
+ }
+ }
+
+ return found;
+}
+
+const char* FrameHandler::eventToString(const EvsEventType aType) {
+ switch (aType) {
+ case EvsEventType::STREAM_STARTED:
+ return "STREAM_STARTED";
+ case EvsEventType::STREAM_STOPPED:
+ return "STREAM_STOPPED";
+ case EvsEventType::FRAME_DROPPED:
+ return "FRAME_DROPPED";
+ case EvsEventType::TIMEOUT:
+ return "TIMEOUT";
+ case EvsEventType::PARAMETER_CHANGED:
+ return "PARAMETER_CHANGED";
+ case EvsEventType::MASTER_RELEASED:
+ return "MASTER_RELEASED";
+ default:
+ return "Unknown";
+ }
+}
diff --git a/automotive/evs/aidl/vts/FrameHandler.h b/automotive/evs/aidl/vts/FrameHandler.h
new file mode 100644
index 0000000..0b959ab
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandler.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
+#define AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
+
+#include <aidl/android/hardware/automotive/evs/BnEvsCameraStream.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
+#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
+
+#include <mutex>
+#include <queue>
+
+/*
+ * FrameHandler:
+ * This class can be used to receive camera imagery from an IEvsCamera implementation. Given an
+ * IEvsDisplay instance at startup, it will forward the received imagery to the display,
+ * providing a trivial implementation of a rear vew camera type application.
+ * Note that the video frames are delivered on a background thread, while the control interface
+ * is actuated from the applications foreground thread.
+ */
+class FrameHandler : public ::aidl::android::hardware::automotive::evs::BnEvsCameraStream {
+ public:
+ enum BufferControlFlag {
+ eAutoReturn,
+ eNoAutoReturn,
+ };
+
+ FrameHandler(
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>& pCamera,
+ const ::aidl::android::hardware::automotive::evs::CameraDesc& cameraInfo,
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>&
+ pDisplay,
+ BufferControlFlag mode = eAutoReturn);
+ virtual ~FrameHandler() {
+ if (mCamera != nullptr) {
+ /* shutdown a camera explicitly */
+ shutdown();
+ }
+ }
+
+ void shutdown();
+ bool startStream();
+ void asyncStopStream();
+ void blockingStopStream();
+ bool returnHeldBuffer();
+ bool isRunning();
+ void waitForFrameCount(unsigned frameCount);
+ bool waitForEvent(const ::aidl::android::hardware::automotive::evs::EvsEventDesc& aTargetEvent,
+ ::aidl::android::hardware::automotive::evs::EvsEventDesc& aReceivedEvent,
+ bool ignorePayload = false);
+ void getFramesCounters(unsigned* received, unsigned* displayed);
+ void getFrameDimension(unsigned* width, unsigned* height);
+
+ private:
+ // Methods from ::aidl::android::hardware::automotive::evs::IEvsCameraStream follow.
+ ::ndk::ScopedAStatus deliverFrame(
+ const std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>& buffer)
+ override;
+ ::ndk::ScopedAStatus notify(
+ const ::aidl::android::hardware::automotive::evs::EvsEventDesc& event) override;
+
+ // Local implementation details
+ bool copyBufferContents(
+ const ::aidl::android::hardware::automotive::evs::BufferDesc& tgtBuffer,
+ const ::aidl::android::hardware::automotive::evs::BufferDesc& srcBuffer);
+ const char* eventToString(const ::aidl::android::hardware::automotive::evs::EvsEventType aType);
+
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera> mCamera;
+ ::aidl::android::hardware::automotive::evs::CameraDesc mCameraInfo;
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay> mDisplay;
+ BufferControlFlag mReturnMode;
+
+ // Since we get frames delivered to us asynchronously via the IEvsCameraStream interface,
+ // we need to protect all member variables that may be modified while we're streaming
+ // (ie: those below)
+ std::mutex mLock;
+ std::mutex mEventLock;
+ std::condition_variable mEventSignal;
+ std::condition_variable mFrameSignal;
+ std::queue<std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>> mHeldBuffers;
+
+ bool mRunning = false;
+ unsigned mFramesReceived = 0; // Simple counter -- rolls over eventually!
+ unsigned mFramesDisplayed = 0; // Simple counter -- rolls over eventually!
+ unsigned mFrameWidth = 0;
+ unsigned mFrameHeight = 0;
+ ::aidl::android::hardware::automotive::evs::EvsEventDesc mLatestEventDesc;
+};
+
+#endif // AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
diff --git a/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp
new file mode 100644
index 0000000..650f0ed
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2022 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 "FrameHandlerUltrasonics.h"
+
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventType.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+#include <aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.h>
+#include <android-base/logging.h>
+
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
+using ::aidl::android::hardware::automotive::evs::UltrasonicsDataFrameDesc;
+using ::ndk::ScopedAStatus;
+
+namespace {
+
+// Struct used by SerializeWaveformData().
+struct WaveformData {
+ uint8_t receiverId;
+ std::vector<std::pair<float, float>> readings;
+};
+
+} // namespace
+
+FrameHandlerUltrasonics::FrameHandlerUltrasonics(
+ const std::shared_ptr<IEvsUltrasonicsArray>& pArray)
+ : mEvsUltrasonicsArray(pArray), mReceiveFramesCount(0) {
+ // Nothing but member initialization
+}
+
+ScopedAStatus FrameHandlerUltrasonics::notify(const EvsEventDesc& evsEvent) {
+ switch (evsEvent.aType) {
+ case EvsEventType::STREAM_STARTED:
+ case EvsEventType::STREAM_STOPPED:
+ case EvsEventType::FRAME_DROPPED:
+ case EvsEventType::TIMEOUT:
+ mReceivedEvents.emplace_back(evsEvent);
+ break;
+ default:
+ LOG(ERROR) << "Received unexpected event";
+ }
+
+ return ScopedAStatus::ok();
+}
+
+// De-serializes shared memory to vector of WaveformData.
+// TODO(b/149950362): Add a common library for serializing and deserializing waveform data.
+std::vector<WaveformData> DeSerializeWaveformData(std::vector<uint32_t> recvReadingsCountList,
+ uint8_t* pData) {
+ std::vector<WaveformData> waveformDataList(recvReadingsCountList.size());
+
+ for (int i = 0; i < waveformDataList.size(); i++) {
+ // Set Id
+ memcpy(&waveformDataList[i].receiverId, pData, sizeof(uint8_t));
+ pData += sizeof(uint8_t);
+
+ waveformDataList[i].readings.resize(recvReadingsCountList[i]);
+
+ for (auto& reading : waveformDataList[i].readings) {
+ // Set the time of flight.
+ memcpy(&reading.first, pData, sizeof(float));
+ pData += sizeof(float);
+
+ // Set the resonance.
+ memcpy(&reading.second, pData, sizeof(float));
+ pData += sizeof(float);
+ }
+ }
+ return waveformDataList;
+}
+
+bool DataFrameValidator(const UltrasonicsDataFrameDesc& /*dataFrameDesc*/) {
+ // TODO(b/214026378): implement a method to validate an ultrasonics data frame
+ (void)DeSerializeWaveformData;
+ return true;
+}
+
+ScopedAStatus FrameHandlerUltrasonics::deliverDataFrame(
+ const UltrasonicsDataFrameDesc& dataFrameDesc) {
+ LOG(DEBUG) << "FrameHandlerUltrasonics::receiveFrames";
+
+ mReceiveFramesCount++;
+
+ if (!DataFrameValidator(dataFrameDesc)) {
+ mAllFramesValid = false;
+ }
+
+ // Send done with data frame.
+ mEvsUltrasonicsArray->doneWithDataFrame(dataFrameDesc);
+ return ScopedAStatus::ok();
+}
+
+bool FrameHandlerUltrasonics::checkEventReceived(const EvsEventDesc& evsEvent) {
+ LOG(DEBUG) << "FrameHandlerUltrasonics::checkEventReceived";
+ int size = mReceivedEvents.size(); // work around
+ LOG(DEBUG) << "Received event number: " << size;
+ auto iter = find(mReceivedEvents.begin(), mReceivedEvents.end(), evsEvent);
+ return iter != mReceivedEvents.end();
+}
+
+int FrameHandlerUltrasonics::getReceiveFramesCount() {
+ return mReceiveFramesCount;
+}
+
+bool FrameHandlerUltrasonics::areAllFramesValid() {
+ return mAllFramesValid;
+}
diff --git a/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h
new file mode 100644
index 0000000..f853a00
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#ifndef AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
+#define AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
+
+#include <aidl/android/hardware/automotive/evs/BnEvsUltrasonicsArrayStream.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+
+#include <vector>
+
+class FrameHandlerUltrasonics
+ : public ::aidl::android::hardware::automotive::evs::BnEvsUltrasonicsArrayStream {
+ public:
+ FrameHandlerUltrasonics(
+ const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>&
+ pArray);
+
+ // Implementation for ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArrayStream
+ ::ndk::ScopedAStatus notify(
+ const ::aidl::android::hardware::automotive::evs::EvsEventDesc& event) override;
+ ::ndk::ScopedAStatus deliverDataFrame(
+ const ::aidl::android::hardware::automotive::evs::UltrasonicsDataFrameDesc& desc)
+ override;
+
+ bool checkEventReceived(
+ const ::aidl::android::hardware::automotive::evs::EvsEventDesc& evsEvent);
+ int getReceiveFramesCount();
+ bool areAllFramesValid();
+
+ private:
+ std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>
+ mEvsUltrasonicsArray;
+ std::vector<::aidl::android::hardware::automotive::evs::EvsEventDesc> mReceivedEvents;
+ int mReceiveFramesCount;
+ bool mAllFramesValid = true;
+};
+
+#endif // AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
diff --git a/automotive/evs/aidl/vts/OWNERS b/automotive/evs/aidl/vts/OWNERS
new file mode 100644
index 0000000..a104f50
--- /dev/null
+++ b/automotive/evs/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+#Bug component : 853002
+ankitarora@google.com
+changyeon@google.com
diff --git a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
new file mode 100644
index 0000000..c709d40
--- /dev/null
+++ b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
@@ -0,0 +1,2170 @@
+/*
+ * Copyright (C) 2022 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 "FrameHandler.h"
+#include "FrameHandlerUltrasonics.h"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraParam.h>
+#include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
+#include <aidl/android/hardware/automotive/evs/DisplayState.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventType.h>
+#include <aidl/android/hardware/automotive/evs/EvsResult.h>
+#include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
+#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
+#include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+#include <aidl/android/hardware/automotive/evs/ParameterRange.h>
+#include <aidl/android/hardware/automotive/evs/Stream.h>
+#include <aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.h>
+#include <aidl/android/hardware/common/NativeHandle.h>
+#include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <system/camera_metadata.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <utils/Timers.h>
+
+#include <deque>
+#include <thread>
+#include <unordered_set>
+
+namespace {
+
+// These values are called out in the EVS design doc (as of Mar 8, 2017)
+constexpr int kMaxStreamStartMilliseconds = 500;
+constexpr int kMinimumFramesPerSecond = 10;
+constexpr int kSecondsToMilliseconds = 1000;
+constexpr int kMillisecondsToMicroseconds = 1000;
+constexpr float kNanoToMilliseconds = 0.000001f;
+constexpr float kNanoToSeconds = 0.000000001f;
+
+/*
+ * Please note that this is different from what is defined in
+ * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
+ * field to store a framerate.
+ */
+typedef struct {
+ int32_t id;
+ int32_t width;
+ int32_t height;
+ int32_t format;
+ int32_t direction;
+ int32_t framerate;
+} RawStreamConfig;
+constexpr size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+} // namespace
+
+using ::aidl::android::hardware::automotive::evs::BufferDesc;
+using ::aidl::android::hardware::automotive::evs::CameraDesc;
+using ::aidl::android::hardware::automotive::evs::CameraParam;
+using ::aidl::android::hardware::automotive::evs::DisplayDesc;
+using ::aidl::android::hardware::automotive::evs::DisplayState;
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::EvsResult;
+using ::aidl::android::hardware::automotive::evs::IEvsCamera;
+using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
+using ::aidl::android::hardware::automotive::evs::IEvsEnumerator;
+using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
+using ::aidl::android::hardware::automotive::evs::ParameterRange;
+using ::aidl::android::hardware::automotive::evs::Stream;
+using ::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc;
+using ::aidl::android::hardware::graphics::common::BufferUsage;
+using ::aidl::android::hardware::graphics::common::HardwareBufferDescription;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
+using std::chrono_literals::operator""s;
+
+// The main test class for EVS
+class EvsAidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ // Make sure we can connect to the enumerator
+ std::string service_name = GetParam();
+ AIBinder* binder = AServiceManager_waitForService(service_name.data());
+ ASSERT_NE(binder, nullptr);
+ mEnumerator = IEvsEnumerator::fromBinder(::ndk::SpAIBinder(binder));
+ LOG(INFO) << "Test target service: " << service_name;
+
+ ASSERT_TRUE(mEnumerator->isHardware(&mIsHwModule).isOk());
+ }
+
+ virtual void TearDown() override {
+ // Attempt to close any active camera
+ for (auto&& cam : mActiveCameras) {
+ if (cam != nullptr) {
+ mEnumerator->closeCamera(cam);
+ }
+ }
+ mActiveCameras.clear();
+ }
+
+ protected:
+ void loadCameraList() {
+ // SetUp() must run first!
+ ASSERT_NE(mEnumerator, nullptr);
+
+ // Get the camera list
+ ASSERT_TRUE(mEnumerator->getCameraList(&mCameraInfo).isOk())
+ << "Failed to get a list of available cameras";
+ LOG(INFO) << "We have " << mCameraInfo.size() << " cameras.";
+ }
+
+ void loadUltrasonicsArrayList() {
+ // SetUp() must run first!
+ ASSERT_NE(mEnumerator, nullptr);
+
+ // Get the ultrasonics array list
+ ASSERT_TRUE(mEnumerator->getUltrasonicsArrayList(&mUltrasonicsArraysInfo).isOk())
+ << "Failed to get a list of available ultrasonics arrays";
+ LOG(INFO) << "We have " << mCameraInfo.size() << " ultrasonics arrays.";
+ }
+
+ bool isLogicalCamera(const camera_metadata_t* metadata) {
+ if (metadata == nullptr) {
+ // A logical camera device must have a valid camera metadata.
+ return false;
+ }
+
+ // Looking for LOGICAL_MULTI_CAMERA capability from metadata.
+ camera_metadata_ro_entry_t entry;
+ int rc = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ &entry);
+ if (rc != 0) {
+ // No capabilities are found.
+ return false;
+ }
+
+ for (size_t i = 0; i < entry.count; ++i) {
+ uint8_t cap = entry.data.u8[i];
+ if (cap == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ std::unordered_set<std::string> getPhysicalCameraIds(const std::string& id, bool& flag) {
+ std::unordered_set<std::string> physicalCameras;
+ const auto it = std::find_if(mCameraInfo.begin(), mCameraInfo.end(),
+ [&id](const CameraDesc& desc) { return id == desc.id; });
+ if (it == mCameraInfo.end()) {
+ // Unknown camera is requested. Return an empty list.
+ return physicalCameras;
+ }
+
+ const camera_metadata_t* metadata = reinterpret_cast<camera_metadata_t*>(&it->metadata[0]);
+ flag = isLogicalCamera(metadata);
+ if (!flag) {
+ // EVS assumes that the device w/o a valid metadata is a physical
+ // device.
+ LOG(INFO) << id << " is not a logical camera device.";
+ physicalCameras.insert(id);
+ return physicalCameras;
+ }
+
+ // Look for physical camera identifiers
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(metadata, ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
+ &entry);
+ if (rc != 0) {
+ LOG(ERROR) << "No physical camera ID is found for a logical camera device";
+ }
+
+ const uint8_t* ids = entry.data.u8;
+ size_t start = 0;
+ for (size_t i = 0; i < entry.count; ++i) {
+ if (ids[i] == '\0') {
+ if (start != i) {
+ std::string id(reinterpret_cast<const char*>(ids + start));
+ physicalCameras.insert(id);
+ }
+ start = i + 1;
+ }
+ }
+
+ LOG(INFO) << id << " consists of " << physicalCameras.size() << " physical camera devices";
+ return physicalCameras;
+ }
+
+ Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+ Stream targetCfg = {};
+ camera_metadata_entry_t streamCfgs;
+ if (!find_camera_metadata_entry(metadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ &streamCfgs)) {
+ // Stream configurations are found in metadata
+ RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+ if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ targetCfg.width = ptr->width;
+ targetCfg.height = ptr->height;
+ targetCfg.format = static_cast<PixelFormat>(ptr->format);
+ break;
+ }
+ ++ptr;
+ }
+ }
+
+ return targetCfg;
+ }
+
+ // Every test needs access to the service
+ std::shared_ptr<IEvsEnumerator> mEnumerator;
+ // Empty unless/util loadCameraList() is called
+ std::vector<CameraDesc> mCameraInfo;
+ // boolean to tell current module under testing is HW module implementation
+ // or not
+ bool mIsHwModule;
+ // A list of active camera handles that are need to be cleaned up
+ std::deque<std::shared_ptr<IEvsCamera>> mActiveCameras;
+ // Empty unless/util loadUltrasonicsArrayList() is called
+ std::vector<UltrasonicsArrayDesc> mUltrasonicsArraysInfo;
+ // A list of active ultrasonics array handles that are to be cleaned up
+ std::deque<std::weak_ptr<IEvsUltrasonicsArray>> mActiveUltrasonicsArrays;
+};
+
+// Test cases, their implementations, and corresponding requirements are
+// documented at go/aae-evs-public-api-test.
+
+/*
+ * CameraOpenClean:
+ * Opens each camera reported by the enumerator and then explicitly closes it via a
+ * call to closeCamera. Then repeats the test to ensure all cameras can be reopened.
+ */
+TEST_P(EvsAidlTest, CameraOpenClean) {
+ LOG(INFO) << "Starting CameraOpenClean test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Open and close each camera twice
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (mIsHwModule && isLogicalCam) {
+ LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ for (int pass = 0; pass < 2; pass++) {
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ ASSERT_NE(pCam, nullptr);
+
+ CameraDesc cameraInfo;
+ for (auto&& devName : devices) {
+ ASSERT_TRUE(pCam->getPhysicalCameraInfo(devName, &cameraInfo).isOk());
+ EXPECT_EQ(devName, cameraInfo.id);
+ }
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Verify that this camera self-identifies correctly
+ ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
+ EXPECT_EQ(cam.id, cameraInfo.id);
+
+ // Verify methods for extended info
+ const auto id = 0xFFFFFFFF; // meaningless id
+ std::vector<uint8_t> values;
+ auto status = pCam->setExtendedInfo(id, values);
+ if (isLogicalCam) {
+ EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+ static_cast<int>(EvsResult::NOT_SUPPORTED));
+ } else {
+ EXPECT_TRUE(status.isOk());
+ }
+
+ status = pCam->getExtendedInfo(id, &values);
+ if (isLogicalCam) {
+ EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+ static_cast<int>(EvsResult::NOT_SUPPORTED));
+ } else {
+ EXPECT_TRUE(status.isOk());
+ }
+
+ // Explicitly close the camera so resources are released right away
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+ }
+}
+
+/*
+ * CameraOpenAggressive:
+ * Opens each camera reported by the enumerator twice in a row without an intervening closeCamera
+ * call. This ensures that the intended "aggressive open" behavior works. This is necessary for
+ * the system to be tolerant of shutdown/restart race conditions.
+ */
+TEST_P(EvsAidlTest, CameraOpenAggressive) {
+ LOG(INFO) << "Starting CameraOpenAggressive test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Open and close each camera twice
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (mIsHwModule && isLogicalCam) {
+ LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ mActiveCameras.clear();
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Verify that this camera self-identifies correctly
+ CameraDesc cameraInfo;
+ ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
+ EXPECT_EQ(cam.id, cameraInfo.id);
+
+ std::shared_ptr<IEvsCamera> pCam2;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam2).isOk());
+ EXPECT_NE(pCam2, nullptr);
+ EXPECT_NE(pCam, pCam2);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam2);
+
+ auto status = pCam->setMaxFramesInFlight(2);
+ if (mIsHwModule) {
+ // Verify that the old camera rejects calls via HW module.
+ EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+ static_cast<int>(EvsResult::OWNERSHIP_LOST));
+ } else {
+ // default implementation supports multiple clients.
+ EXPECT_TRUE(status.isOk());
+ }
+
+ // Close the superseded camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.pop_front();
+
+ // Verify that the second camera instance self-identifies correctly
+ ASSERT_TRUE(pCam2->getCameraInfo(&cameraInfo).isOk());
+ EXPECT_EQ(cam.id, cameraInfo.id);
+
+ // Close the second camera instance
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam2).isOk());
+ mActiveCameras.pop_front();
+ }
+
+ // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
+ sleep(1); // I hate that this is an arbitrary time to wait. :( b/36122635
+}
+
+/*
+ * CameraStreamPerformance:
+ * Measure and qualify the stream start up time and streaming frame rate of each reported camera
+ */
+TEST_P(EvsAidlTest, CameraStreamPerformance) {
+ LOG(INFO) << "Starting CameraStreamPerformance test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (mIsHwModule && isLogicalCam) {
+ LOG(INFO) << "Skip a logical device " << cam.id;
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Set up a frame receiver object which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start the camera's video stream
+ nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Ensure the first frame arrived within the expected time
+ frameHandler->waitForFrameCount(1);
+ nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t timeToFirstFrame = systemTime(SYSTEM_TIME_MONOTONIC) - start;
+
+ // Extra delays are expected when we attempt to start a video stream on
+ // the logical camera device. The amount of delay is expected the
+ // number of physical camera devices multiplied by
+ // kMaxStreamStartMilliseconds at most.
+ EXPECT_LE(nanoseconds_to_milliseconds(timeToFirstFrame),
+ kMaxStreamStartMilliseconds * devices.size());
+ printf("%s: Measured time to first frame %0.2f ms\n", cam.id.data(),
+ timeToFirstFrame * kNanoToMilliseconds);
+ LOG(INFO) << cam.id << ": Measured time to first frame " << std::scientific
+ << timeToFirstFrame * kNanoToMilliseconds << " ms.";
+
+ // Check aspect ratio
+ unsigned width = 0, height = 0;
+ frameHandler->getFrameDimension(&width, &height);
+ EXPECT_GE(width, height);
+
+ // Wait a bit, then ensure we get at least the required minimum number of frames
+ sleep(5);
+ nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ // Even when the camera pointer goes out of scope, the FrameHandler object will
+ // keep the stream alive unless we tell it to shutdown.
+ // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+ // we have to break that cycle in order for either of them to get cleaned up.
+ frameHandler->shutdown();
+
+ unsigned framesReceived = 0;
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ framesReceived = framesReceived - 1; // Back out the first frame we already waited for
+ nsecs_t runTime = end - firstFrame;
+ float framesPerSecond = framesReceived / (runTime * kNanoToSeconds);
+ printf("Measured camera rate %3.2f fps\n", framesPerSecond);
+ LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond << " fps.";
+ EXPECT_GE(framesPerSecond, kMinimumFramesPerSecond);
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * CameraStreamBuffering:
+ * Ensure the camera implementation behaves properly when the client holds onto buffers for more
+ * than one frame time. The camera must cleanly skip frames until the client is ready again.
+ */
+TEST_P(EvsAidlTest, CameraStreamBuffering) {
+ LOG(INFO) << "Starting CameraStreamBuffering test";
+
+ // Arbitrary constant (should be > 1 and not too big)
+ static const unsigned int kBuffersToHold = 6;
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (mIsHwModule && isLogicalCam) {
+ LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Ask for a very large number of buffers in flight to ensure it errors correctly
+ auto badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF);
+ EXPECT_TRUE(!badResult.isOk() && badResult.getServiceSpecificError() ==
+ static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
+
+ // Now ask for exactly two buffers in flight as we'll test behavior in that case
+ ASSERT_TRUE(pCam->setMaxFramesInFlight(kBuffersToHold).isOk());
+
+ // Set up a frame receiver object which will fire up its own thread.
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Check that the video stream stalls once we've gotten exactly the number of buffers
+ // we requested since we told the frameHandler not to return them.
+ sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
+ unsigned framesReceived = 0;
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+
+ // Give back one buffer
+ ASSERT_TRUE(frameHandler->returnHeldBuffer());
+
+ // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+ // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+ usleep(110 * kMillisecondsToMicroseconds);
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ EXPECT_EQ(kBuffersToHold + 1, framesReceived) << "Stream should've resumed";
+
+ // Even when the camera pointer goes out of scope, the FrameHandler object will
+ // keep the stream alive unless we tell it to shutdown.
+ // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+ // we have to break that cycle in order for either of them to get cleaned up.
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * CameraToDisplayRoundTrip:
+ * End to end test of data flowing from the camera to the display. Each delivered frame of camera
+ * imagery is simply copied to the display buffer and presented on screen. This is the one test
+ * which a human could observe to see the operation of the system on the physical display.
+ */
+TEST_P(EvsAidlTest, CameraToDisplayRoundTrip) {
+ LOG(INFO) << "Starting CameraToDisplayRoundTrip test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Request available display IDs
+ uint8_t targetDisplayId = 0;
+ std::vector<uint8_t> displayIds;
+ ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+ EXPECT_GT(displayIds.size(), 0);
+ targetDisplayId = displayIds[0];
+
+ // Request exclusive access to the first EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+ LOG(INFO) << "Display " << targetDisplayId << " is in use.";
+
+ // Get the display descriptor
+ DisplayDesc displayDesc;
+ ASSERT_TRUE(pDisplay->getDisplayInfo(&displayDesc).isOk());
+ LOG(INFO) << " Resolution: " << displayDesc.width << "x" << displayDesc.height;
+ ASSERT_GT(displayDesc.width, 0);
+ ASSERT_GT(displayDesc.height, 0);
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (mIsHwModule && isLogicalCam) {
+ LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Set up a frame receiver object which will fire up its own thread.
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, pDisplay, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Activate the display
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Wait a while to let the data flow
+ static const int kSecondsToWait = 5;
+ const int streamTimeMs =
+ kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
+ const unsigned minimumFramesExpected =
+ streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
+ sleep(kSecondsToWait);
+ unsigned framesReceived = 0;
+ unsigned framesDisplayed = 0;
+ frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
+ EXPECT_EQ(framesReceived, framesDisplayed);
+ EXPECT_GE(framesDisplayed, minimumFramesExpected);
+
+ // Turn off the display (yes, before the stream stops -- it should be handled)
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+ // Shut down the streamer
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * MultiCameraStream:
+ * Verify that each client can start and stop video streams on the same
+ * underlying camera.
+ */
+TEST_P(EvsAidlTest, MultiCameraStream) {
+ LOG(INFO) << "Starting MultiCameraStream test";
+
+ if (mIsHwModule) {
+ // This test is not for HW module implementation.
+ return;
+ }
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Create two camera clients.
+ std::shared_ptr<IEvsCamera> pCam0;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+ EXPECT_NE(pCam0, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam0);
+
+ std::shared_ptr<IEvsCamera> pCam1;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+ EXPECT_NE(pCam1, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam1);
+
+ // Set up per-client frame receiver objects which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandler0 =
+ std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+ std::shared_ptr<FrameHandler> frameHandler1 =
+ std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler0, nullptr);
+ EXPECT_NE(frameHandler1, nullptr);
+
+ // Start the camera's video stream via client 0
+ ASSERT_TRUE(frameHandler0->startStream());
+ ASSERT_TRUE(frameHandler1->startStream());
+
+ // Ensure the stream starts
+ frameHandler0->waitForFrameCount(1);
+ frameHandler1->waitForFrameCount(1);
+
+ nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ // Wait a bit, then ensure both clients get at least the required minimum number of frames
+ sleep(5);
+ nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+ unsigned framesReceived0 = 0, framesReceived1 = 0;
+ frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+ framesReceived0 = framesReceived0 - 1; // Back out the first frame we already waited for
+ framesReceived1 = framesReceived1 - 1; // Back out the first frame we already waited for
+ nsecs_t runTime = end - firstFrame;
+ float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
+ float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
+ LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
+ << framesPerSecond1 << " fps";
+ EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
+ EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
+
+ // Shutdown one client
+ frameHandler0->shutdown();
+
+ // Read frame counters again
+ frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+
+ // Wait a bit again
+ sleep(5);
+ unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
+ frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
+ EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
+ EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
+
+ // Shutdown another
+ frameHandler1->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+ mActiveCameras.clear();
+
+ // TODO(b/145459970, b/145457727): below sleep() is added to ensure the
+ // destruction of active camera objects; this may be related with two
+ // issues.
+ sleep(1);
+ }
+}
+
+/*
+ * CameraParameter:
+ * Verify that a client can adjust a camera parameter.
+ */
+TEST_P(EvsAidlTest, CameraParameter) {
+ LOG(INFO) << "Starting CameraParameter test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (isLogicalCam) {
+ // TODO(b/145465724): Support camera parameter programming on
+ // logical devices.
+ LOG(INFO) << "Skip a logical device " << cam.id;
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Create a camera client
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera
+ mActiveCameras.push_back(pCam);
+
+ // Get the parameter list
+ std::vector<CameraParam> cmds;
+ ASSERT_TRUE(pCam->getParameterList(&cmds).isOk());
+ if (cmds.size() < 1) {
+ continue;
+ }
+
+ // Set up per-client frame receiver objects which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Ensure the stream starts
+ frameHandler->waitForFrameCount(1);
+
+ // Set current client is the primary client
+ ASSERT_TRUE(pCam->setPrimaryClient().isOk());
+ for (auto& cmd : cmds) {
+ // Get a valid parameter value range
+ ParameterRange range;
+ ASSERT_TRUE(pCam->getIntParameterRange(cmd, &range).isOk());
+
+ std::vector<int32_t> values;
+ if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+ // Try to turn off auto-focus
+ ASSERT_TRUE(pCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(v, 0);
+ }
+ }
+
+ // Try to program a parameter with a random value [minVal, maxVal]
+ int32_t val0 = range.min + (std::rand() % (range.max - range.min));
+
+ // Rounding down
+ val0 = val0 - (val0 % range.step);
+ values.clear();
+ ASSERT_TRUE(pCam->setIntParameter(cmd, val0, &values).isOk());
+
+ values.clear();
+ ASSERT_TRUE(pCam->getIntParameter(cmd, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(val0, v) << "Values are not matched.";
+ }
+ }
+ ASSERT_TRUE(pCam->unsetPrimaryClient().isOk());
+
+ // Shutdown
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * CameraPrimaryClientRelease
+ * Verify that non-primary client gets notified when the primary client either
+ * terminates or releases a role.
+ */
+TEST_P(EvsAidlTest, CameraPrimaryClientRelease) {
+ LOG(INFO) << "Starting CameraPrimaryClientRelease test";
+
+ if (mIsHwModule) {
+ // This test is not for HW module implementation.
+ return;
+ }
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (isLogicalCam) {
+ // TODO(b/145465724): Support camera parameter programming on
+ // logical devices.
+ LOG(INFO) << "Skip a logical device " << cam.id;
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Create two camera clients.
+ std::shared_ptr<IEvsCamera> pPrimaryCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
+ EXPECT_NE(pPrimaryCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pPrimaryCam);
+
+ std::shared_ptr<IEvsCamera> pSecondaryCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
+ EXPECT_NE(pSecondaryCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pSecondaryCam);
+
+ // Set up per-client frame receiver objects which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandlerPrimary = std::make_shared<FrameHandler>(
+ pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+ std::shared_ptr<FrameHandler> frameHandlerSecondary = std::make_shared<FrameHandler>(
+ pSecondaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandlerPrimary, nullptr);
+ EXPECT_NE(frameHandlerSecondary, nullptr);
+
+ // Set one client as the primary client
+ ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
+
+ // Try to set another client as the primary client.
+ ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+ // Start the camera's video stream via a primary client client.
+ ASSERT_TRUE(frameHandlerPrimary->startStream());
+
+ // Ensure the stream starts
+ frameHandlerPrimary->waitForFrameCount(1);
+
+ // Start the camera's video stream via another client
+ ASSERT_TRUE(frameHandlerSecondary->startStream());
+
+ // Ensure the stream starts
+ frameHandlerSecondary->waitForFrameCount(1);
+
+ // Non-primary client expects to receive a primary client role relesed
+ // notification.
+ EvsEventDesc aTargetEvent = {};
+ EvsEventDesc aNotification = {};
+
+ bool listening = false;
+ std::mutex eventLock;
+ std::condition_variable eventCond;
+ std::thread listener =
+ std::thread([&aNotification, &frameHandlerSecondary, &listening, &eventCond]() {
+ // Notify that a listening thread is running.
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification, true)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a listening thread starts.
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening) {
+ timer += 1s;
+ eventCond.wait_until(lock, timer);
+ }
+ lock.unlock();
+
+ // Release a primary client role.
+ ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
+
+ // Join a listening thread.
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ // Verify change notifications.
+ ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
+
+ // Non-primary becomes a primary client.
+ ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
+
+ // Previous primary client fails to become a primary client.
+ ASSERT_FALSE(pPrimaryCam->setPrimaryClient().isOk());
+
+ listening = false;
+ listener = std::thread([&aNotification, &frameHandlerPrimary, &listening, &eventCond]() {
+ // Notify that a listening thread is running.
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification, true)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a listening thread starts.
+ timer = std::chrono::system_clock::now();
+ lock.lock();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Closing current primary client.
+ frameHandlerSecondary->shutdown();
+
+ // Join a listening thread.
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ // Verify change notifications.
+ ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
+
+ // Closing streams.
+ frameHandlerPrimary->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
+ ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * MultiCameraParameter:
+ * Verify that primary and non-primary clients behave as expected when they try to adjust
+ * camera parameters.
+ */
+TEST_P(EvsAidlTest, MultiCameraParameter) {
+ LOG(INFO) << "Starting MultiCameraParameter test";
+
+ if (mIsHwModule) {
+ // This test is not for HW module implementation.
+ return;
+ }
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (isLogicalCam) {
+ // TODO(b/145465724): Support camera parameter programming on
+ // logical devices.
+ LOG(INFO) << "Skip a logical device " << cam.id;
+ continue;
+ }
+
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Create two camera clients.
+ std::shared_ptr<IEvsCamera> pPrimaryCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
+ EXPECT_NE(pPrimaryCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pPrimaryCam);
+
+ std::shared_ptr<IEvsCamera> pSecondaryCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
+ EXPECT_NE(pSecondaryCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pSecondaryCam);
+
+ // Get the parameter list
+ std::vector<CameraParam> camPrimaryCmds, camSecondaryCmds;
+ ASSERT_TRUE(pPrimaryCam->getParameterList(&camPrimaryCmds).isOk());
+ ASSERT_TRUE(pSecondaryCam->getParameterList(&camSecondaryCmds).isOk());
+ if (camPrimaryCmds.size() < 1 || camSecondaryCmds.size() < 1) {
+ // Skip a camera device if it does not support any parameter.
+ continue;
+ }
+
+ // Set up per-client frame receiver objects which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandlerPrimary = std::make_shared<FrameHandler>(
+ pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+ std::shared_ptr<FrameHandler> frameHandlerSecondary = std::make_shared<FrameHandler>(
+ pSecondaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandlerPrimary, nullptr);
+ EXPECT_NE(frameHandlerSecondary, nullptr);
+
+ // Set one client as the primary client.
+ ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
+
+ // Try to set another client as the primary client.
+ ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+ // Start the camera's video stream via a primary client client.
+ ASSERT_TRUE(frameHandlerPrimary->startStream());
+
+ // Ensure the stream starts
+ frameHandlerPrimary->waitForFrameCount(1);
+
+ // Start the camera's video stream via another client
+ ASSERT_TRUE(frameHandlerSecondary->startStream());
+
+ // Ensure the stream starts
+ frameHandlerSecondary->waitForFrameCount(1);
+
+ int32_t val0 = 0;
+ std::vector<int32_t> values;
+ EvsEventDesc aNotification0 = {};
+ EvsEventDesc aNotification1 = {};
+ for (auto& cmd : camPrimaryCmds) {
+ // Get a valid parameter value range
+ ParameterRange range;
+ ASSERT_TRUE(pPrimaryCam->getIntParameterRange(cmd, &range).isOk());
+ if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+ // Try to turn off auto-focus
+ values.clear();
+ ASSERT_TRUE(
+ pPrimaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(v, 0);
+ }
+ }
+
+ // Calculate a parameter value to program.
+ val0 = range.min + (std::rand() % (range.max - range.min));
+ val0 = val0 - (val0 % range.step);
+
+ // Prepare and start event listeners.
+ bool listening0 = false;
+ bool listening1 = false;
+ std::condition_variable eventCond;
+ std::thread listener0 = std::thread([cmd, val0, &aNotification0, &frameHandlerPrimary,
+ &listening0, &listening1, &eventCond]() {
+ listening0 = true;
+ if (listening1) {
+ eventCond.notify_all();
+ }
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+ std::thread listener1 = std::thread([cmd, val0, &aNotification1, &frameHandlerSecondary,
+ &listening0, &listening1, &eventCond]() {
+ listening1 = true;
+ if (listening0) {
+ eventCond.notify_all();
+ }
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a listening thread starts.
+ std::mutex eventLock;
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening0 || !listening1) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Try to program a parameter
+ values.clear();
+ ASSERT_TRUE(pPrimaryCam->setIntParameter(cmd, val0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(val0, v) << "Values are not matched.";
+ }
+
+ // Join a listening thread.
+ if (listener0.joinable()) {
+ listener0.join();
+ }
+ if (listener1.joinable()) {
+ listener1.join();
+ }
+
+ // Verify a change notification
+ ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+ static_cast<EvsEventType>(aNotification0.aType));
+ ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+ static_cast<EvsEventType>(aNotification1.aType));
+ ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
+ ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
+ for (auto&& v : values) {
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification0.payload[1]));
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification1.payload[1]));
+ }
+
+ // Clients expects to receive a parameter change notification
+ // whenever a primary client client adjusts it.
+ values.clear();
+ ASSERT_TRUE(pPrimaryCam->getIntParameter(cmd, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(val0, v) << "Values are not matched.";
+ }
+ }
+
+ // Try to adjust a parameter via non-primary client
+ values.clear();
+ ASSERT_FALSE(pSecondaryCam->setIntParameter(camSecondaryCmds[0], val0, &values).isOk());
+
+ // Non-primary client attempts to be a primary client
+ ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+ // Primary client retires from a primary client role
+ bool listening = false;
+ std::condition_variable eventCond;
+ std::thread listener =
+ std::thread([&aNotification0, &frameHandlerSecondary, &listening, &eventCond]() {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification0, true)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ std::mutex eventLock;
+ auto timer = std::chrono::system_clock::now();
+ std::unique_lock<std::mutex> lock(eventLock);
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
+
+ if (listener.joinable()) {
+ listener.join();
+ }
+ ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification0.aType));
+
+ // Try to adjust a parameter after being retired
+ values.clear();
+ ASSERT_FALSE(pPrimaryCam->setIntParameter(camPrimaryCmds[0], val0, &values).isOk());
+
+ // Non-primary client becomes a primary client
+ ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
+
+ // Try to adjust a parameter via new primary client
+ for (auto& cmd : camSecondaryCmds) {
+ // Get a valid parameter value range
+ ParameterRange range;
+ ASSERT_TRUE(pSecondaryCam->getIntParameterRange(cmd, &range).isOk());
+
+ values.clear();
+ if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+ // Try to turn off auto-focus
+ values.clear();
+ ASSERT_TRUE(
+ pSecondaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(v, 0);
+ }
+ }
+
+ // Calculate a parameter value to program. This is being rounding down.
+ val0 = range.min + (std::rand() % (range.max - range.min));
+ val0 = val0 - (val0 % range.step);
+
+ // Prepare and start event listeners.
+ bool listening0 = false;
+ bool listening1 = false;
+ std::condition_variable eventCond;
+ std::thread listener0 = std::thread([&]() {
+ listening0 = true;
+ if (listening1) {
+ eventCond.notify_all();
+ }
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+ std::thread listener1 = std::thread([&]() {
+ listening1 = true;
+ if (listening0) {
+ eventCond.notify_all();
+ }
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a listening thread starts.
+ std::mutex eventLock;
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening0 || !listening1) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Try to program a parameter
+ values.clear();
+ ASSERT_TRUE(pSecondaryCam->setIntParameter(cmd, val0, &values).isOk());
+
+ // Clients expects to receive a parameter change notification
+ // whenever a primary client client adjusts it.
+ values.clear();
+ ASSERT_TRUE(pSecondaryCam->getIntParameter(cmd, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(val0, v) << "Values are not matched.";
+ }
+
+ // Join a listening thread.
+ if (listener0.joinable()) {
+ listener0.join();
+ }
+ if (listener1.joinable()) {
+ listener1.join();
+ }
+
+ // Verify a change notification
+ ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+ static_cast<EvsEventType>(aNotification0.aType));
+ ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+ static_cast<EvsEventType>(aNotification1.aType));
+ ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
+ ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
+ for (auto&& v : values) {
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification0.payload[1]));
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification1.payload[1]));
+ }
+ }
+
+ // New primary client retires from the role
+ ASSERT_TRUE(pSecondaryCam->unsetPrimaryClient().isOk());
+
+ // Shutdown
+ frameHandlerPrimary->shutdown();
+ frameHandlerSecondary->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
+ ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * HighPriorityCameraClient:
+ * EVS client, which owns the display, is priortized and therefore can take over
+ * a primary client role from other EVS clients without the display.
+ */
+TEST_P(EvsAidlTest, HighPriorityCameraClient) {
+ LOG(INFO) << "Starting HighPriorityCameraClient test";
+
+ if (mIsHwModule) {
+ // This test is not for HW module implementation.
+ return;
+ }
+
+ // Get the camera list
+ loadCameraList();
+
+ // Request available display IDs
+ uint8_t targetDisplayId = 0;
+ std::vector<uint8_t> displayIds;
+ ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+ EXPECT_GT(displayIds.size(), 0);
+ targetDisplayId = displayIds[0];
+
+ // Request exclusive access to the EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Create two clients
+ std::shared_ptr<IEvsCamera> pCam0;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+ EXPECT_NE(pCam0, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam0);
+
+ std::shared_ptr<IEvsCamera> pCam1;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+ EXPECT_NE(pCam1, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam1);
+
+ // Get the parameter list; this test will use the first command in both
+ // lists.
+ std::vector<CameraParam> cam0Cmds, cam1Cmds;
+ ASSERT_TRUE(pCam0->getParameterList(&cam0Cmds).isOk());
+ ASSERT_TRUE(pCam1->getParameterList(&cam1Cmds).isOk());
+ if (cam0Cmds.size() < 1 || cam1Cmds.size() < 1) {
+ // Cannot execute this test.
+ return;
+ }
+
+ // Set up a frame receiver object which will fire up its own thread.
+ std::shared_ptr<FrameHandler> frameHandler0 =
+ std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+ std::shared_ptr<FrameHandler> frameHandler1 =
+ std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler0, nullptr);
+ EXPECT_NE(frameHandler1, nullptr);
+
+ // Activate the display
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler0->startStream());
+ ASSERT_TRUE(frameHandler1->startStream());
+
+ // Ensure the stream starts
+ frameHandler0->waitForFrameCount(1);
+ frameHandler1->waitForFrameCount(1);
+
+ // Client 1 becomes a primary client and programs a parameter.
+
+ // Get a valid parameter value range
+ ParameterRange range;
+ ASSERT_TRUE(pCam1->getIntParameterRange(cam1Cmds[0], &range).isOk());
+
+ // Client1 becomes a primary client
+ ASSERT_TRUE(pCam1->setPrimaryClient().isOk());
+
+ std::vector<int32_t> values;
+ EvsEventDesc aTargetEvent = {};
+ EvsEventDesc aNotification = {};
+ bool listening = false;
+ std::mutex eventLock;
+ std::condition_variable eventCond;
+ if (cam1Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
+ std::thread listener =
+ std::thread([&frameHandler0, &aNotification, &listening, &eventCond] {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
+ aTargetEvent.payload[1] = 0;
+ if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a lister starts.
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Try to turn off auto-focus
+ ASSERT_TRUE(pCam1->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(v, 0);
+ }
+
+ // Join a listener
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ // Make sure AUTO_FOCUS is off.
+ ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
+ EvsEventType::PARAMETER_CHANGED);
+ }
+
+ // Try to program a parameter with a random value [minVal, maxVal] after
+ // rounding it down.
+ int32_t val0 = range.min + (std::rand() % (range.max - range.min));
+ val0 = val0 - (val0 % range.step);
+
+ std::thread listener = std::thread(
+ [&frameHandler1, &aNotification, &listening, &eventCond, &cam1Cmds, val0] {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cam1Cmds[0]);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a lister starts.
+ listening = false;
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ values.clear();
+ ASSERT_TRUE(pCam1->setIntParameter(cam1Cmds[0], val0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(val0, v);
+ }
+
+ // Join a listener
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ // Verify a change notification
+ ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
+ ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam1Cmds[0]);
+ for (auto&& v : values) {
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification.payload[1]));
+ }
+
+ listener = std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+ if (!frameHandler1->waitForEvent(aTargetEvent, aNotification, true)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a lister starts.
+ listening = false;
+ lock.lock();
+ timer = std::chrono::system_clock::now();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Client 0 steals a primary client role
+ ASSERT_TRUE(pCam0->forcePrimaryClient(pDisplay).isOk());
+
+ // Join a listener
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::MASTER_RELEASED);
+
+ // Client 0 programs a parameter
+ val0 = range.min + (std::rand() % (range.max - range.min));
+
+ // Rounding down
+ val0 = val0 - (val0 % range.step);
+
+ if (cam0Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
+ std::thread listener =
+ std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
+ aTargetEvent.payload[1] = 0;
+ if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a lister starts.
+ std::unique_lock<std::mutex> lock(eventLock);
+ auto timer = std::chrono::system_clock::now();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ // Try to turn off auto-focus
+ values.clear();
+ ASSERT_TRUE(pCam0->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+ for (auto&& v : values) {
+ EXPECT_EQ(v, 0);
+ }
+
+ // Join a listener
+ if (listener.joinable()) {
+ listener.join();
+ }
+
+ // Make sure AUTO_FOCUS is off.
+ ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
+ EvsEventType::PARAMETER_CHANGED);
+ }
+
+ listener = std::thread(
+ [&frameHandler0, &aNotification, &listening, &eventCond, &cam0Cmds, val0] {
+ listening = true;
+ eventCond.notify_all();
+
+ EvsEventDesc aTargetEvent;
+ aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+ aTargetEvent.payload[0] = static_cast<uint32_t>(cam0Cmds[0]);
+ aTargetEvent.payload[1] = val0;
+ if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
+ }
+ });
+
+ // Wait until a lister starts.
+ listening = false;
+ timer = std::chrono::system_clock::now();
+ lock.lock();
+ while (!listening) {
+ eventCond.wait_until(lock, timer + 1s);
+ }
+ lock.unlock();
+
+ values.clear();
+ ASSERT_TRUE(pCam0->setIntParameter(cam0Cmds[0], val0, &values).isOk());
+
+ // Join a listener
+ if (listener.joinable()) {
+ listener.join();
+ }
+ // Verify a change notification
+ ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
+ ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam0Cmds[0]);
+ for (auto&& v : values) {
+ ASSERT_EQ(v, static_cast<int32_t>(aNotification.payload[1]));
+ }
+
+ // Turn off the display (yes, before the stream stops -- it should be handled)
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+ // Shut down the streamer
+ frameHandler0->shutdown();
+ frameHandler1->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+ mActiveCameras.clear();
+ }
+
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * CameraUseStreamConfigToDisplay:
+ * End to end test of data flowing from the camera to the display. Similar to
+ * CameraToDisplayRoundTrip test case but this case retrieves available stream
+ * configurations from EVS and uses one of them to start a video stream.
+ */
+TEST_P(EvsAidlTest, CameraUseStreamConfigToDisplay) {
+ LOG(INFO) << "Starting CameraUseStreamConfigToDisplay test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Request available display IDs
+ uint8_t targetDisplayId = 0;
+ std::vector<uint8_t> displayIds;
+ ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+ EXPECT_GT(displayIds.size(), 0);
+ targetDisplayId = displayIds[0];
+
+ // Request exclusive access to the EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ // choose a configuration that has a frame rate faster than minReqFps.
+ Stream targetCfg = {};
+ const int32_t minReqFps = 15;
+ int32_t maxArea = 0;
+ camera_metadata_entry_t streamCfgs;
+ bool foundCfg = false;
+ if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ &streamCfgs)) {
+ // Stream configurations are found in metadata
+ RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+ if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
+ targetCfg.width = ptr->width;
+ targetCfg.height = ptr->height;
+
+ maxArea = ptr->width * ptr->height;
+ foundCfg = true;
+ }
+ }
+ ++ptr;
+ }
+ }
+ targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
+
+ if (!foundCfg) {
+ // Current EVS camera does not provide stream configurations in the
+ // metadata.
+ continue;
+ }
+
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Set up a frame receiver object which will fire up its own thread.
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, pDisplay, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Activate the display
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Wait a while to let the data flow
+ static const int kSecondsToWait = 5;
+ const int streamTimeMs =
+ kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
+ const unsigned minimumFramesExpected =
+ streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
+ sleep(kSecondsToWait);
+ unsigned framesReceived = 0;
+ unsigned framesDisplayed = 0;
+ frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
+ EXPECT_EQ(framesReceived, framesDisplayed);
+ EXPECT_GE(framesDisplayed, minimumFramesExpected);
+
+ // Turn off the display (yes, before the stream stops -- it should be handled)
+ ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+ // Shut down the streamer
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ }
+
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * MultiCameraStreamUseConfig:
+ * Verify that each client can start and stop video streams on the same
+ * underlying camera with same configuration.
+ */
+TEST_P(EvsAidlTest, MultiCameraStreamUseConfig) {
+ LOG(INFO) << "Starting MultiCameraStream test";
+
+ if (mIsHwModule) {
+ // This test is not for HW module implementation.
+ return;
+ }
+
+ // Get the camera list
+ loadCameraList();
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ // choose a configuration that has a frame rate faster than minReqFps.
+ Stream targetCfg = {};
+ const int32_t minReqFps = 15;
+ int32_t maxArea = 0;
+ camera_metadata_entry_t streamCfgs;
+ bool foundCfg = false;
+ if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ &streamCfgs)) {
+ // Stream configurations are found in metadata
+ RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+ if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
+ targetCfg.width = ptr->width;
+ targetCfg.height = ptr->height;
+
+ maxArea = ptr->width * ptr->height;
+ foundCfg = true;
+ }
+ }
+ ++ptr;
+ }
+ }
+ targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
+
+ if (!foundCfg) {
+ LOG(INFO) << "Device " << cam.id
+ << " does not provide a list of supported stream configurations, skipped";
+ continue;
+ }
+
+ // Create the first camera client with a selected stream configuration.
+ std::shared_ptr<IEvsCamera> pCam0;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+ EXPECT_NE(pCam0, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam0);
+
+ // Try to create the second camera client with different stream
+ // configuration.
+ int32_t id = targetCfg.id;
+ targetCfg.id += 1; // EVS manager sees only the stream id.
+ std::shared_ptr<IEvsCamera> pCam1;
+ ASSERT_FALSE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+
+ // Try again with same stream configuration.
+ targetCfg.id = id;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+ EXPECT_NE(pCam1, nullptr);
+
+ // Set up per-client frame receiver objects which will fire up its own thread
+ std::shared_ptr<FrameHandler> frameHandler0 =
+ std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+ std::shared_ptr<FrameHandler> frameHandler1 =
+ std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+ EXPECT_NE(frameHandler0, nullptr);
+ EXPECT_NE(frameHandler1, nullptr);
+
+ // Start the camera's video stream via client 0
+ ASSERT_TRUE(frameHandler0->startStream());
+ ASSERT_TRUE(frameHandler1->startStream());
+
+ // Ensure the stream starts
+ frameHandler0->waitForFrameCount(1);
+ frameHandler1->waitForFrameCount(1);
+
+ nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ // Wait a bit, then ensure both clients get at least the required minimum number of frames
+ sleep(5);
+ nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+ unsigned framesReceived0 = 0, framesReceived1 = 0;
+ frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+ framesReceived0 = framesReceived0 - 1; // Back out the first frame we already waited for
+ framesReceived1 = framesReceived1 - 1; // Back out the first frame we already waited for
+ nsecs_t runTime = end - firstFrame;
+ float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
+ float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
+ LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
+ << framesPerSecond1 << " fps";
+ EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
+ EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
+
+ // Shutdown one client
+ frameHandler0->shutdown();
+
+ // Read frame counters again
+ frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+
+ // Wait a bit again
+ sleep(5);
+ unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
+ frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
+ frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
+ EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
+ EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
+
+ // Shutdown another
+ frameHandler1->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+ mActiveCameras.clear();
+ }
+}
+
+/*
+ * LogicalCameraMetadata:
+ * Opens logical camera reported by the enumerator and validate its metadata by
+ * checking its capability and locating supporting physical camera device
+ * identifiers.
+ */
+TEST_P(EvsAidlTest, LogicalCameraMetadata) {
+ LOG(INFO) << "Starting LogicalCameraMetadata test";
+
+ // Get the camera list
+ loadCameraList();
+
+ // Open and close each camera twice
+ for (auto&& cam : mCameraInfo) {
+ bool isLogicalCam = false;
+ auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+ if (isLogicalCam) {
+ ASSERT_GE(devices.size(), 1) << "Logical camera device must have at least one physical "
+ "camera device ID in its metadata.";
+ }
+ }
+}
+
+/*
+ * CameraStreamExternalBuffering:
+ * This is same with CameraStreamBuffering except frame buffers are allocated by
+ * the test client and then imported by EVS framework.
+ */
+TEST_P(EvsAidlTest, CameraStreamExternalBuffering) {
+ LOG(INFO) << "Starting CameraStreamExternalBuffering test";
+
+ // Arbitrary constant (should be > 1 and not too big)
+ static const unsigned int kBuffersToHold = 3;
+
+ // Get the camera list
+ loadCameraList();
+
+ // Acquire the graphics buffer allocator
+ android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
+ const auto usage =
+ GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+ // Test each reported camera
+ for (auto&& cam : mCameraInfo) {
+ // Read a target resolution from the metadata
+ Stream targetCfg = getFirstStreamConfiguration(
+ reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ // Allocate buffers to use
+ std::vector<BufferDesc> buffers;
+ buffers.resize(kBuffersToHold);
+ for (auto i = 0; i < kBuffersToHold; ++i) {
+ unsigned pixelsPerLine;
+ buffer_handle_t memHandle = nullptr;
+ android::status_t result =
+ alloc.allocate(targetCfg.width, targetCfg.height,
+ static_cast<android::PixelFormat>(targetCfg.format),
+ /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+ /* graphicBufferId = */ 0,
+ /* requestorName = */ "CameraStreamExternalBufferingTest");
+ if (result != android::NO_ERROR) {
+ LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
+ // Release previous allocated buffers
+ for (auto j = 0; j < i; j++) {
+ alloc.free(::android::dupFromAidl(buffers[i].buffer.handle));
+ }
+ return;
+ } else {
+ BufferDesc buf;
+ HardwareBufferDescription* pDesc =
+ reinterpret_cast<HardwareBufferDescription*>(&buf.buffer.description);
+ pDesc->width = targetCfg.width;
+ pDesc->height = targetCfg.height;
+ pDesc->layers = 1;
+ pDesc->format = targetCfg.format;
+ pDesc->usage = static_cast<BufferUsage>(usage);
+ pDesc->stride = pixelsPerLine;
+ buf.buffer.handle = ::android::dupToAidl(memHandle);
+ buf.bufferId = i; // Unique number to identify this buffer
+ buffers[i] = std::move(buf);
+ }
+ }
+
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.id, isLogicalCam);
+
+ std::shared_ptr<IEvsCamera> pCam;
+ ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+ EXPECT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ mActiveCameras.push_back(pCam);
+
+ // Request to import buffers
+ int delta = 0;
+ auto status = pCam->importExternalBuffers(buffers, &delta);
+ if (isLogicalCam) {
+ ASSERT_FALSE(status.isOk());
+ continue;
+ }
+
+ ASSERT_TRUE(status.isOk());
+ EXPECT_GE(delta, kBuffersToHold);
+
+ // Set up a frame receiver object which will fire up its own thread.
+ std::shared_ptr<FrameHandler> frameHandler =
+ std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start the camera's video stream
+ ASSERT_TRUE(frameHandler->startStream());
+
+ // Check that the video stream stalls once we've gotten exactly the number of buffers
+ // we requested since we told the frameHandler not to return them.
+ sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
+ unsigned framesReceived = 0;
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+
+ // Give back one buffer
+ EXPECT_TRUE(frameHandler->returnHeldBuffer());
+
+ // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+ // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+ unsigned framesReceivedAfter = 0;
+ usleep(110 * kMillisecondsToMicroseconds);
+ frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+ EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
+
+ // Even when the camera pointer goes out of scope, the FrameHandler object will
+ // keep the stream alive unless we tell it to shutdown.
+ // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+ // we have to break that cycle in order for either of them to get cleaned up.
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+ mActiveCameras.clear();
+ // Release buffers
+ for (auto& b : buffers) {
+ alloc.free(::android::dupFromAidl(b.buffer.handle));
+ }
+ buffers.resize(0);
+ }
+}
+
+/*
+ * UltrasonicsArrayOpenClean:
+ * Opens each ultrasonics arrays reported by the enumerator and then explicitly closes it via a
+ * call to closeUltrasonicsArray. Then repeats the test to ensure all ultrasonics arrays
+ * can be reopened.
+ */
+TEST_P(EvsAidlTest, UltrasonicsArrayOpenClean) {
+ LOG(INFO) << "Starting UltrasonicsArrayOpenClean test";
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // Open and close each ultrasonics array twice
+ for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+ for (int pass = 0; pass < 2; pass++) {
+ std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+ ASSERT_TRUE(
+ mEnumerator
+ ->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+ .isOk());
+ EXPECT_NE(pUltrasonicsArray, nullptr);
+
+ // Verify that this ultrasonics array self-identifies correctly
+ UltrasonicsArrayDesc desc;
+ ASSERT_TRUE(pUltrasonicsArray->getUltrasonicArrayInfo(&desc).isOk());
+ EXPECT_EQ(ultraInfo.ultrasonicsArrayId, desc.ultrasonicsArrayId);
+ LOG(DEBUG) << "Found ultrasonics array " << ultraInfo.ultrasonicsArrayId;
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+ }
+ }
+}
+
+// Starts a stream and verifies all data received is valid.
+TEST_P(EvsAidlTest, UltrasonicsVerifyStreamData) {
+ LOG(INFO) << "Starting UltrasonicsVerifyStreamData";
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // For each ultrasonics array.
+ for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+ LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
+
+ std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+ ASSERT_TRUE(
+ mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+ .isOk());
+ EXPECT_NE(pUltrasonicsArray, nullptr);
+
+ std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
+ std::make_shared<FrameHandlerUltrasonics>(pUltrasonicsArray);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start stream.
+ ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
+
+ // Wait 5 seconds to receive frames.
+ sleep(5);
+
+ // Stop stream.
+ ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
+
+ EXPECT_GT(frameHandler->getReceiveFramesCount(), 0);
+ EXPECT_TRUE(frameHandler->areAllFramesValid());
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+ }
+}
+
+// Sets frames in flight before and after start of stream and verfies success.
+TEST_P(EvsAidlTest, UltrasonicsSetFramesInFlight) {
+ LOG(INFO) << "Starting UltrasonicsSetFramesInFlight";
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // For each ultrasonics array.
+ for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+ LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
+
+ std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+ ASSERT_TRUE(
+ mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+ .isOk());
+ EXPECT_NE(pUltrasonicsArray, nullptr);
+
+ ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(10).isOk());
+
+ std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
+ std::make_shared<FrameHandlerUltrasonics>(pUltrasonicsArray);
+ EXPECT_NE(frameHandler, nullptr);
+
+ // Start stream.
+ ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
+ ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(5).isOk());
+
+ // Stop stream.
+ ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EvsAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, EvsAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IEvsEnumerator::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b142d0c..3d346c0 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -60,6 +60,14 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.automotive.evs</name>
+ <interface>
+ <name>IEvsEnumerator</name>
+ <instance>default</instance>
+ <regex-instance>[a-z]+/[0-9]+</regex-instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.automotive.evs</name>
<version>1.0-1</version>