diff options
70 files changed, 6085 insertions, 0 deletions
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp new file mode 100644 index 0000000000..3c0aa13f49 --- /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 0000000000..31acdb8e27 --- /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 0000000000..4dadeb88b2 --- /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 0000000000..ae4ce77192 --- /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 0000000000..cc066ac6db --- /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 0000000000..d0f1d8e1d6 --- /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 0000000000..4ac029e479 --- /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 0000000000..a5f43095c8 --- /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 0000000000..09b2b9db13 --- /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 0000000000..052a6b3969 --- /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 0000000000..a0418a94ef --- /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 0000000000..ce1b97d16c --- /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 0000000000..6e2e64a3c4 --- /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 0000000000..9b538d43a2 --- /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 0000000000..a79c68d898 --- /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 0000000000..c39a4e855e --- /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 0000000000..1183ab392c --- /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 0000000000..510b0a4692 --- /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 0000000000..44e9b59276 --- /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 0000000000..91971fc5e7 --- /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 0000000000..d9c8b6e247 --- /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 0000000000..4ead9eaf2e --- /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 0000000000..a7804121b3 --- /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 0000000000..9819c8910b --- /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 0000000000..488d80f479 --- /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 0000000000..23f81f8093 --- /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 0000000000..4a988759fd --- /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 0000000000..35ec84bdcc --- /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 0000000000..0604abe1dc --- /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 0000000000..2f500a73c5 --- /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 0000000000..15500b2def --- /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 0000000000..535ace30ac --- /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 0000000000..902b31b15e --- /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 0000000000..0b4243b8d9 --- /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 0000000000..c242d2fb7d --- /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 0000000000..ebff98f077 --- /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 0000000000..3a493af61b --- /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 0000000000..c355be35c2 --- /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 0000000000..080dd75247 --- /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 0000000000..2c2b44caf5 --- /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 0000000000..8d57014df5 --- /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 0000000000..8e380e0bd4 --- /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 0000000000..26ccf72f08 --- /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 0000000000..40de313abf --- /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 0000000000..bc31a6ba95 --- /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 0000000000..b08fcbd975 --- /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 0000000000..dede39e15e --- /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 0000000000..b80343bf7c --- /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 0000000000..26c33399b8 --- /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 0000000000..ae5c7f0748 --- /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 0000000000..c028a5c43f --- /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 0000000000..14b14db0c9 --- /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 0000000000..712411bd6d --- /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 0000000000..d4f0663b27 --- /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 0000000000..e546db92c2 --- /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 0000000000..7eb01166c3 --- /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 0000000000..dbe0314118 --- /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 0000000000..ea8e6892dc --- /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 0000000000..96ff9f6576 --- /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 0000000000..8bcd867d48 --- /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 0000000000..2ff6d59af2 --- /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 0000000000..0a0913fd3c --- /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 0000000000..980c6d5a5c --- /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 0000000000..bab832b09c --- /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 0000000000..0b959ab48d --- /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 0000000000..650f0ed501 --- /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 0000000000..f853a00a25 --- /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 0000000000..a104f509b2 --- /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 0000000000..c709d40690 --- /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 761a962a23..594f07bd59 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> |