Improve test coverage for SurroundViewSession
Bug: 159733690
Bug: 162599435
Test: Run "atest -v -w -c sv_session_tests"; and check the logs for
"sv_session_test"
Change-Id: Ic5c4e7268470c2c769a62d600081a0f19c76e667
Merged-In: Ic5c4e7268470c2c769a62d600081a0f19c76e667
(cherry picked from commit d43fd9b527772edba2627c98e6ec064553bc5189)
diff --git a/surround_view/service-impl/SurroundViewSessionTests.cpp b/surround_view/service-impl/SurroundViewSessionTests.cpp
index b694aaf..2ad6d49 100644
--- a/surround_view/service-impl/SurroundViewSessionTests.cpp
+++ b/surround_view/service-impl/SurroundViewSessionTests.cpp
@@ -28,6 +28,7 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <time.h>
namespace android {
namespace hardware {
@@ -39,6 +40,7 @@
const char* kSvConfigFilename = "vendor/etc/automotive/sv/sv_sample_config.xml";
+// TODO(b/159733690): Verify the callbacks using help/mock methods
TEST(SurroundViewSessionTests, startAndStopSurroundView2dSession) {
sp<IEvsEnumerator> fakeEvs = new MockEvsEnumerator();
IOModule* ioModule = new IOModule(kSvConfigFilename);
@@ -57,6 +59,8 @@
EXPECT_EQ(sv2dSession->startStream(sv2dCallback), SvResult::OK);
+ sleep(5);
+
sv2dSession->stopStream();
}
@@ -86,6 +90,8 @@
EXPECT_EQ(sv3dSession->startStream(sv3dCallback), SvResult::OK);
+ sleep(5);
+
sv3dSession->stopStream();
}
diff --git a/surround_view/service-impl/mock-evs/MockEvsCamera.cpp b/surround_view/service-impl/mock-evs/MockEvsCamera.cpp
index f268e5b..dcd7405 100644
--- a/surround_view/service-impl/mock-evs/MockEvsCamera.cpp
+++ b/surround_view/service-impl/mock-evs/MockEvsCamera.cpp
@@ -16,6 +16,8 @@
#include "MockEvsCamera.h"
+#include <stdlib.h>
+
namespace android {
namespace hardware {
namespace automotive {
@@ -23,10 +25,26 @@
namespace V1_0 {
namespace implementation {
-MockEvsCamera::MockEvsCamera() {
- mConfigManager =
- ConfigManager::Create(
- "/vendor/etc/automotive/evs/evs_sample_configuration.xml");
+// TODO(b/159733690): the number should come from xml
+const int kFramesCount = 4;
+const int kFrameGenerationDelayMillis = 30;
+const char kConfigFilePath[] =
+ "/vendor/etc/automotive/evs/evs_sample_configuration.xml";
+
+MockEvsCamera::MockEvsCamera(const string& cameraId, const Stream& streamCfg) {
+ mConfigManager = ConfigManager::Create(kConfigFilePath);
+
+ mStreamCfg.height = streamCfg.height;
+ mStreamCfg.width = streamCfg.width;
+
+ mCameraDesc.v1.cameraId = cameraId;
+ unique_ptr<ConfigManager::CameraGroupInfo>& cameraGroupInfo =
+ mConfigManager->getCameraGroupInfo(mCameraDesc.v1.cameraId);
+ if (cameraGroupInfo != nullptr) {
+ mCameraDesc.metadata.setToExternal(
+ (uint8_t*)cameraGroupInfo->characteristics,
+ get_camera_metadata_size(cameraGroupInfo->characteristics));
+ }
}
Return<void> MockEvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
@@ -46,8 +64,20 @@
Return<EvsResult> MockEvsCamera::startVideoStream(
const ::android::sp<IEvsCameraStream_1_0>& stream) {
LOG(INFO) << __FUNCTION__;
+ scoped_lock<mutex> lock(mAccessLock);
- (void)stream;
+ mStream = IEvsCameraStream_1_1::castFrom(stream).withDefault(nullptr);
+
+ if (mStreamState != STOPPED) {
+ LOG(ERROR) << "Ignoring startVideoStream call when a stream is "
+ << "already running.";
+ return EvsResult::STREAM_ALREADY_RUNNING;
+ }
+
+ // Start the frame generation thread
+ mStreamState = RUNNING;
+ mCaptureThread = thread([this]() { generateFrames(); });
+
return EvsResult::OK;
}
@@ -60,6 +90,22 @@
Return<void> MockEvsCamera::stopVideoStream() {
LOG(INFO) << __FUNCTION__;
+
+ unique_lock<mutex> lock(mAccessLock);
+ if (mStreamState == RUNNING) {
+ // Tell the GenerateFrames loop we want it to stop
+ mStreamState = STOPPING;
+ // Block outside the mutex until the "stop" flag has been acknowledged
+ // We won't send any more frames, but the client might still get some
+ // already in flight
+ LOG(DEBUG) << __FUNCTION__ << ": Waiting for stream thread to end...";
+ lock.unlock();
+ mCaptureThread.join();
+ lock.lock();
+ mStreamState = STOPPED;
+ mStream = nullptr;
+ LOG(DEBUG) << "Stream marked STOPPED.";
+ }
return {};
}
@@ -80,9 +126,7 @@
}
Return<void> MockEvsCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
- // Not implemented.
-
- (void)_hidl_cb;
+ _hidl_cb(mCameraDesc);
return {};
}
@@ -195,6 +239,69 @@
return {};
}
+void MockEvsCamera::initializeFrames(int framesCount) {
+ LOG(INFO) << "StreamCfg width: " << mStreamCfg.width
+ << " height: " << mStreamCfg.height;
+
+ string label = "EmptyBuffer_";
+ mGraphicBuffers.resize(framesCount);
+ mBufferDescs.resize(framesCount);
+ for (int i = 0; i < framesCount; i++) {
+ mGraphicBuffers[i] = new GraphicBuffer(mStreamCfg.width,
+ mStreamCfg.height,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
+ GRALLOC_USAGE_HW_TEXTURE,
+ label + (char)(i + 48));
+ mBufferDescs[i].buffer.nativeHandle =
+ mGraphicBuffers[i]->getNativeBuffer()->handle;
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc*>(
+ &mBufferDescs[i].buffer.description);
+ pDesc->width = mStreamCfg.width;
+ pDesc->height = mStreamCfg.height;
+ pDesc->layers = 1;
+ pDesc->usage = GRALLOC_USAGE_HW_TEXTURE;
+ pDesc->stride = mGraphicBuffers[i]->getStride();
+ pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
+ }
+}
+
+void MockEvsCamera::generateFrames() {
+ initializeFrames(kFramesCount);
+
+ while (true) {
+ {
+ scoped_lock<mutex> lock(mAccessLock);
+ if (mStreamState != RUNNING) {
+ // Break out of our main thread loop
+ LOG(INFO) << "StreamState does not equal to RUNNING. "
+ << "Exiting the loop";
+ break;
+ }
+ }
+
+ mStream->deliverFrame_1_1(mBufferDescs);
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(kFrameGenerationDelayMillis));
+ }
+
+ {
+ scoped_lock<mutex> lock(mAccessLock);
+
+ if (mStream != nullptr) {
+ LOG(DEBUG) << "Notify EvsEventType::STREAM_STOPPED";
+
+ EvsEventDesc evsEventDesc;
+ evsEventDesc.aType = EvsEventType::STREAM_STOPPED;
+ mStream->notify(evsEventDesc);
+ } else {
+ LOG(WARNING) << "EVS stream is not valid any more. "
+ << "The notify call is ignored.";
+ }
+ }
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace sv
diff --git a/surround_view/service-impl/mock-evs/MockEvsCamera.h b/surround_view/service-impl/mock-evs/MockEvsCamera.h
index d393702..e06a474 100644
--- a/surround_view/service-impl/mock-evs/MockEvsCamera.h
+++ b/surround_view/service-impl/mock-evs/MockEvsCamera.h
@@ -17,13 +17,21 @@
#pragma once
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
+#include <android/hardware/automotive/evs/1.1/IEvsCameraStream.h>
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <ConfigManager.h>
+#include <ui/GraphicBuffer.h>
+
+#include <mutex>
+#include <thread>
+
using ::android::hardware::automotive::evs::V1_0::EvsResult;
using ::android::hardware::automotive::evs::V1_1::CameraParam;
+using ::android::hardware::automotive::evs::V1_1::EvsEventDesc;
+using ::android::hardware::automotive::evs::V1_1::EvsEventType;
namespace android {
namespace hardware {
@@ -38,6 +46,7 @@
using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
using IEvsCameraStream_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
+using IEvsCameraStream_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCameraStream;
using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
using IEvsEnumerator_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsEnumerator;
@@ -45,7 +54,7 @@
// implemented.
class MockEvsCamera : public IEvsCamera_1_1 {
public:
- MockEvsCamera();
+ MockEvsCamera(const std::string& cameraId, const Stream& streamCfg);
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
Return<void> getCameraInfo(getCameraInfo_cb _hidl_cb) override;
@@ -79,7 +88,30 @@
importExternalBuffers_cb _hidl_cb) override;
private:
+ void initializeFrames(int framesCount);
+ void generateFrames();
+
std::unique_ptr<ConfigManager> mConfigManager;
+
+ std::mutex mAccessLock;
+
+ enum StreamStateValues {
+ STOPPED,
+ RUNNING,
+ STOPPING,
+ DEAD,
+ };
+ StreamStateValues mStreamState GUARDED_BY(mAccessLock);
+ Stream mStreamCfg;
+
+ std::vector<android::sp<GraphicBuffer>> mGraphicBuffers;
+ std::vector<BufferDesc_1_1> mBufferDescs;
+ CameraDesc_1_1 mCameraDesc;
+
+ std::string mCameraId;
+ std::thread mCaptureThread; // The thread we'll use to synthesize frames
+
+ android::sp<IEvsCameraStream_1_1> mStream;
};
} // namespace implementation
diff --git a/surround_view/service-impl/mock-evs/MockEvsEnumerator.cpp b/surround_view/service-impl/mock-evs/MockEvsEnumerator.cpp
index 946083c..9e3e5e4 100644
--- a/surround_view/service-impl/mock-evs/MockEvsEnumerator.cpp
+++ b/surround_view/service-impl/mock-evs/MockEvsEnumerator.cpp
@@ -109,11 +109,8 @@
Return<sp<IEvsCamera_1_1>> MockEvsEnumerator::openCamera_1_1(
const hidl_string& cameraId, const Stream& streamCfg) {
- // Not implemented.
-
- (void)cameraId;
- (void)streamCfg;
- return new MockEvsCamera();
+ LOG(INFO) << __FUNCTION__ << ": " << streamCfg.width << ", " << streamCfg.height;
+ return new MockEvsCamera(cameraId, streamCfg);
}
Return<void> MockEvsEnumerator::getDisplayIdList(getDisplayIdList_cb _list_cb) {
diff --git a/surround_view/service-impl/mock-evs/MockSurroundViewCallback.cpp b/surround_view/service-impl/mock-evs/MockSurroundViewCallback.cpp
index d059f72..03f9594 100644
--- a/surround_view/service-impl/mock-evs/MockSurroundViewCallback.cpp
+++ b/surround_view/service-impl/mock-evs/MockSurroundViewCallback.cpp
@@ -18,9 +18,13 @@
#include <android-base/logging.h>
+#include <thread>
+
using ::android::sp;
using ::android::hardware::Return;
+using ::std::thread;
+
namespace android {
namespace hardware {
namespace automotive {
@@ -29,9 +33,8 @@
namespace implementation {
MockSurroundViewCallback::MockSurroundViewCallback(
- sp<ISurroundViewSession> pSession) {
- (void)pSession;
-}
+ sp<ISurroundViewSession> pSession) :
+ mSession(pSession) {}
Return<void> MockSurroundViewCallback::notify(SvEvent svEvent) {
LOG(INFO) << __FUNCTION__ << "SvEvent received: " << (int)svEvent;
@@ -42,6 +45,13 @@
const SvFramesDesc& svFramesDesc) {
LOG(INFO) << __FUNCTION__ << svFramesDesc.svBuffers.size()
<< " frames are received";
+
+ // Create a separate thread to return the frames to the session. This
+ // simulates the behavior of oneway HIDL method call.
+ thread mockHidlThread([this, &svFramesDesc]() {
+ mSession->doneWithFrames(svFramesDesc);
+ });
+ mockHidlThread.detach();
return {};
}
diff --git a/surround_view/service-impl/mock-evs/MockSurroundViewCallback.h b/surround_view/service-impl/mock-evs/MockSurroundViewCallback.h
index 7239bf6..eeabc98 100644
--- a/surround_view/service-impl/mock-evs/MockSurroundViewCallback.h
+++ b/surround_view/service-impl/mock-evs/MockSurroundViewCallback.h
@@ -35,6 +35,9 @@
// Methods from ::android::hardware::automotive::sv::V1_0::ISurroundViewStream.
android::hardware::Return<void> notify(SvEvent svEvent) override;
android::hardware::Return<void> receiveFrames(const SvFramesDesc& svFramesDesc) override;
+
+private:
+ android::sp<ISurroundViewSession> mSession;
};
} // namespace implementation