Add VTS for Ultrasonics to EVS 1.1
Bug: 148619310
Test: atest VtsHalEvsV1_1TargetTest
Change-Id: If91bce64cf06fd374b3829b0f01804bdc375197d
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index 4753933..086a199 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -18,12 +18,16 @@
name: "VtsHalEvsV1_1TargetTest",
srcs: [
"FrameHandler.cpp",
+ "FrameHandlerUltrasonics.cpp",
"VtsHalEvsV1_1TargetTest.cpp",
],
defaults: ["VtsHalTargetTestDefaults"],
shared_libs: [
"libui",
"libcamera_metadata",
+ "libhidlmemory",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
],
static_libs: [
"android.hardware.automotive.evs@1.0",
@@ -34,7 +38,7 @@
"android.hardware.graphics.common@1.2",
"android.hardware.camera.device@3.2",
],
- test_suites: ["general-tests"],
+ test_suites: ["vts-core"],
cflags: [
"-O0",
"-g",
diff --git a/automotive/evs/1.1/vts/functional/FrameHandlerUltrasonics.cpp b/automotive/evs/1.1/vts/functional/FrameHandlerUltrasonics.cpp
new file mode 100644
index 0000000..22522ce
--- /dev/null
+++ b/automotive/evs/1.1/vts/functional/FrameHandlerUltrasonics.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2020 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 <android-base/logging.h>
+#include <hidlmemory/mapping.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::hardware::Return;
+using ::android::sp;
+
+using ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArrayStream;
+using ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray;
+using ::android::hardware::automotive::evs::V1_1::UltrasonicsDataFrameDesc;
+using ::android::hardware::automotive::evs::V1_1::EvsEventDesc;
+using ::android::hardware::automotive::evs::V1_1::EvsEventType;
+
+FrameHandlerUltrasonics::FrameHandlerUltrasonics(sp<IEvsUltrasonicsArray> pEvsUltrasonicsArray) :
+ mEvsUltrasonicsArray(pEvsUltrasonicsArray), mReceiveFramesCount(0) {
+ // Nothing but member initialization
+}
+
+Return<void> 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 android::hardware::Void();
+}
+
+// Struct used by SerializeWaveformData().
+struct WaveformData {
+ uint8_t receiverId;
+ std::vector<std::pair<float, float>> readings;
+};
+
+// De-serializes shared memory to vector of WaveformData.
+// TODO(b/149950362): Add a common library for serialiazing 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) {
+
+ if (dataFrameDesc.receiversIdList.size() != dataFrameDesc.receiversReadingsCountList.size()) {
+ LOG(ERROR) << "Size mismatch of receiversIdList and receiversReadingsCountList";
+ return false;
+ }
+
+ if(!dataFrameDesc.waveformsData.valid()) {
+ LOG(ERROR) << "Data frame does not valid hidl memory";
+ return false;
+ }
+
+ // Check total bytes from dataFrameDesc are within the shared memory size.
+ int totalWaveformDataBytesSize = 0;
+ for (int i = 0; i < dataFrameDesc.receiversIdList.size(); i++) {
+ totalWaveformDataBytesSize = 1 + (4 * 2 * dataFrameDesc.receiversReadingsCountList[i]);
+ }
+ if (totalWaveformDataBytesSize > dataFrameDesc.waveformsData.size()) {
+ LOG(ERROR) << "Total waveform data bytes in desc exceed shared memory size";
+ return false;
+ }
+
+ sp<IMemory> pIMemory = mapMemory(dataFrameDesc.waveformsData);
+ if(pIMemory.get() == nullptr) {
+ LOG(ERROR) << "Failed to map hidl memory";
+ return false;
+ }
+
+ uint8_t* pData = (uint8_t*)((void*)pIMemory->getPointer());
+ if(pData == nullptr) {
+ LOG(ERROR) << "Failed getPointer from mapped shared memory";
+ return false;
+ }
+
+ const std::vector<WaveformData> waveformDataList = DeSerializeWaveformData(
+ dataFrameDesc.receiversReadingsCountList, pData);
+
+ // Verify the waveforms data.
+ for(int i = 0; i < waveformDataList.size(); i++) {
+ if (waveformDataList[i].receiverId != dataFrameDesc.receiversIdList[i]) {
+ LOG(ERROR) << "Receiver Id mismatch";
+ return false;
+ }
+ for(auto& reading : waveformDataList[i].readings) {
+ if (reading.second < 0.0f || reading.second > 1.0f) {
+ LOG(ERROR) << "Resonance reading is not in range [0, 1]";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+Return<void> FrameHandlerUltrasonics::deliverDataFrame(
+ const UltrasonicsDataFrameDesc& dataFrameDesc) {
+ LOG(DEBUG) << "FrameHandlerUltrasonics::receiveFrames";
+
+ mReceiveFramesCount++;
+ mLastReceivedFrames = dataFrameDesc;
+
+ if(!DataFrameValidator(dataFrameDesc)) {
+ mAllFramesValid = false;
+ }
+
+ // Send done with data frame.
+ mEvsUltrasonicsArray->doneWithDataFrame(dataFrameDesc);
+
+ return android::hardware::Void();
+}
+
+bool FrameHandlerUltrasonics::checkEventReceived(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/1.1/vts/functional/FrameHandlerUltrasonics.h b/automotive/evs/1.1/vts/functional/FrameHandlerUltrasonics.h
new file mode 100644
index 0000000..1fc2143
--- /dev/null
+++ b/automotive/evs/1.1/vts/functional/FrameHandlerUltrasonics.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2020 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 FRAME_HANDLER_ULTRASONICS_H
+#define FRAME_HANDLER_ULTRASONICS_H
+
+#include <android/hardware/automotive/evs/1.1/types.h>
+#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArrayStream.h>
+#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArray.h>
+
+#include <vector>
+
+class FrameHandlerUltrasonics : public
+ android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArrayStream {
+public:
+ FrameHandlerUltrasonics(
+ android::sp<android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray>
+ pEvsUltrasonicsArray);
+
+ // Implementation for ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArrayStream
+ android::hardware::Return<void> notify(
+ const android::hardware::automotive::evs::V1_1::EvsEventDesc& evsEvent) override;
+ android::hardware::Return<void> deliverDataFrame(
+ const android::hardware::automotive::evs::V1_1::UltrasonicsDataFrameDesc&
+ dataFrameDesc) override;
+
+ bool checkEventReceived(android::hardware::automotive::evs::V1_1::EvsEventDesc evsEvent);
+ int getReceiveFramesCount();
+ bool areAllFramesValid();
+
+private:
+ android::sp<android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray>
+ mEvsUltrasonicsArray;
+ android::hardware::automotive::evs::V1_1::UltrasonicsDataFrameDesc mLastReceivedFrames;
+ std::vector<android::hardware::automotive::evs::V1_1::EvsEventDesc> mReceivedEvents;
+ int mReceiveFramesCount;
+ bool mAllFramesValid = true;
+};
+
+#endif //FRAME_HANDLER_ULTRASONICS_H
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index ce02973..85c3d68 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -37,6 +37,7 @@
#include "FrameHandler.h"
+#include "FrameHandlerUltrasonics.h"
#include <cstdio>
#include <cstring>
@@ -151,9 +152,21 @@
}
}
);
+ }
- // We insist on at least one camera for EVS to pass any camera tests
- ASSERT_GE(cameraInfo.size(), 1u);
+ void loadUltrasonicsArrayList() {
+ // SetUp() must run first!
+ assert(pEnumerator != nullptr);
+
+ // Get the ultrasonics array list
+ pEnumerator->getUltrasonicsArrayList([this](hidl_vec<UltrasonicsArrayDesc> ultraList) {
+ ALOGI("Ultrasonics array list callback received %zu arrays", ultraList.size());
+ ultrasonicsArraysInfo.reserve(ultraList.size());
+ for (auto&& ultraArray : ultraList) {
+ ALOGI("Found ultrasonics array %s", ultraArray.ultrasonicsArrayId.c_str());
+ ultrasonicsArraysInfo.push_back(ultraArray);
+ }
+ });
}
bool isLogicalCamera(const camera_metadata_t *metadata) {
@@ -240,6 +253,11 @@
// is HW module implementation.
std::deque<wp<IEvsCamera_1_1>> activeCameras; // A list of active camera handles that are
// needed to be cleaned up.
+ std::vector<UltrasonicsArrayDesc>
+ ultrasonicsArraysInfo; // Empty unless/until
+ // loadUltrasonicsArrayList() is called
+ std::deque<wp<IEvsCamera_1_1>> activeUltrasonicsArrays; // A list of active ultrasonic array
+ // handles that are to be cleaned up.
};
@@ -2209,6 +2227,110 @@
}
+/*
+ * 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_F(EvsHidlTest, UltrasonicsArrayOpenClean) {
+ ALOGI("Starting UltrasonicsArrayOpenClean test");
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // Open and close each ultrasonics array twice
+ for (auto&& ultraInfo : ultrasonicsArraysInfo) {
+ for (int pass = 0; pass < 2; pass++) {
+ sp<IEvsUltrasonicsArray> pUltrasonicsArray =
+ pEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId);
+ ASSERT_NE(pUltrasonicsArray, nullptr);
+
+ // Verify that this ultrasonics array self-identifies correctly
+ pUltrasonicsArray->getUltrasonicArrayInfo([&ultraInfo](UltrasonicsArrayDesc desc) {
+ ALOGD("Found ultrasonics array %s", ultraInfo.ultrasonicsArrayId.c_str());
+ EXPECT_EQ(ultraInfo.ultrasonicsArrayId, desc.ultrasonicsArrayId);
+ });
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ pEnumerator->closeUltrasonicsArray(pUltrasonicsArray);
+ }
+ }
+}
+
+
+// Starts a stream and verifies all data received is valid.
+TEST_F(EvsHidlTest, UltrasonicsVerifyStreamData) {
+ ALOGI("Starting UltrasonicsVerifyStreamData");
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // For each ultrasonics array.
+ for (auto&& ultraInfo : ultrasonicsArraysInfo) {
+ ALOGD("Testing ultrasonics array: %s", ultraInfo.ultrasonicsArrayId.c_str());
+
+ sp<IEvsUltrasonicsArray> pUltrasonicsArray =
+ pEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId);
+ ASSERT_NE(pUltrasonicsArray, nullptr);
+
+ sp<FrameHandlerUltrasonics> frameHandler = new FrameHandlerUltrasonics(pUltrasonicsArray);
+
+ // Start stream.
+ EvsResult result = pUltrasonicsArray->startStream(frameHandler);
+ ASSERT_EQ(result, EvsResult::OK);
+
+ // Wait 5 seconds to receive frames.
+ sleep(5);
+
+ // Stop stream.
+ pUltrasonicsArray->stopStream();
+
+ EXPECT_GT(frameHandler->getReceiveFramesCount(), 0);
+ EXPECT_TRUE(frameHandler->areAllFramesValid());
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ pEnumerator->closeUltrasonicsArray(pUltrasonicsArray);
+ }
+}
+
+
+// Sets frames in flight before and after start of stream and verfies success.
+TEST_F(EvsHidlTest, UltrasonicsSetFramesInFlight) {
+ ALOGI("Starting UltrasonicsSetFramesInFlight");
+
+ // Get the ultrasonics array list
+ loadUltrasonicsArrayList();
+
+ // For each ultrasonics array.
+ for (auto&& ultraInfo : ultrasonicsArraysInfo) {
+ ALOGD("Testing ultrasonics array: %s", ultraInfo.ultrasonicsArrayId.c_str());
+
+ sp<IEvsUltrasonicsArray> pUltrasonicsArray =
+ pEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId);
+ ASSERT_NE(pUltrasonicsArray, nullptr);
+
+ EvsResult result = pUltrasonicsArray->setMaxFramesInFlight(10);
+ EXPECT_EQ(result, EvsResult::OK);
+
+ sp<FrameHandlerUltrasonics> frameHandler = new FrameHandlerUltrasonics(pUltrasonicsArray);
+
+ // Start stream.
+ result = pUltrasonicsArray->startStream(frameHandler);
+ ASSERT_EQ(result, EvsResult::OK);
+
+ result = pUltrasonicsArray->setMaxFramesInFlight(5);
+ EXPECT_EQ(result, EvsResult::OK);
+
+ // Stop stream.
+ pUltrasonicsArray->stopStream();
+
+ // Explicitly close the ultrasonics array so resources are released right away
+ pEnumerator->closeUltrasonicsArray(pUltrasonicsArray);
+ }
+}
+
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);