Camera: Add Hal version 1 video recording test cases
Tests involving Hal version 1 video recording APIs are
required. Several cases will be available:
- 'startStopRecording' - Verifies basic video recording
functionality. Metadata support will be tested if available.
- 'startRecordingFail' - Checks that recording can be enabled
only after preview starts.
Bug: 32022758
Test: compile and run the gtest binary on device
Change-Id: Id9dd8d3a554a1aa3bbbae9b836e4d14da5c4446b
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index fc9d3e5..70b0a3b 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -545,6 +545,9 @@
std::vector<StreamBuffer> mResultBuffers; // Holds stream buffers from capture result
std::vector<ErrorMsg> mErrors; // Holds incoming error notifications
DataCallbackMsg mDataMessageTypeReceived; // Most recent message type received through data callbacks
+ uint32_t mVideoBufferIndex; // Buffer index of the most recent video buffer
+ uint32_t mVideoData; // Buffer data of the most recent video buffer
+ hidl_handle mVideoNativeHandle; // Most recent video buffer native handle
std::mutex mTorchLock; // Synchronize access to torch status
std::condition_variable mTorchCond; // Condition variable for torch status
@@ -581,8 +584,7 @@
return pool->getHeapID();
}
-Return<void> CameraHidlTest::Camera1DeviceCb::unregisterMemory(
- uint32_t memId __unused) {
+Return<void> CameraHidlTest::Camera1DeviceCb::unregisterMemory(uint32_t memId) {
if (mParent->mMemoryPool.count(memId) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, memId);
return Void();
@@ -604,15 +606,36 @@
}
Return<void> CameraHidlTest::Camera1DeviceCb::dataCallbackTimestamp(
- DataCallbackMsg msgType __unused, uint32_t data __unused,
- uint32_t bufferIndex __unused, int64_t timestamp __unused) {
+ DataCallbackMsg msgType, uint32_t data,
+ uint32_t bufferIndex, int64_t timestamp __unused) {
+ std::unique_lock<std::mutex> l(mParent->mLock);
+ mParent->mDataMessageTypeReceived = msgType;
+ mParent->mVideoBufferIndex = bufferIndex;
+ if (mParent->mMemoryPool.count(data) == 0) {
+ ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
+ ADD_FAILURE();
+ }
+ mParent->mVideoData = data;
+ mParent->mResultCondition.notify_one();
+
return Void();
}
Return<void> CameraHidlTest::Camera1DeviceCb::handleCallbackTimestamp(
- DataCallbackMsg msgType __unused, const hidl_handle& frameData __unused,
- uint32_t data __unused, uint32_t bufferIndex __unused,
+ DataCallbackMsg msgType, const hidl_handle& frameData,
+ uint32_t data __unused, uint32_t bufferIndex,
int64_t timestamp __unused) {
+ std::unique_lock<std::mutex> l(mParent->mLock);
+ mParent->mDataMessageTypeReceived = msgType;
+ mParent->mVideoBufferIndex = bufferIndex;
+ if (mParent->mMemoryPool.count(data) == 0) {
+ ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
+ ADD_FAILURE();
+ }
+ mParent->mVideoData = data;
+ mParent->mVideoNativeHandle = frameData;
+ mParent->mResultCondition.notify_one();
+
return Void();
}
@@ -1161,6 +1184,116 @@
}
}
+// Test basic video recording.
+TEST_F(CameraHidlTest, startStopRecording) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_1_0) {
+ sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+ openCameraDevice(name, env, &device1 /*out*/);
+ ASSERT_NE(nullptr, device1.get());
+ sp<BufferItemConsumer> bufferItemConsumer;
+ sp<BufferItemHander> bufferHandler;
+ setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
+ &bufferHandler /*out*/);
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+ }
+
+ device1->enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME);
+ ASSERT_TRUE(device1->msgTypeEnabled(
+ (unsigned int)DataCallbackMsg::PREVIEW_FRAME));
+ ASSERT_EQ(Status::OK, device1->startPreview());
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ while (DataCallbackMsg::PREVIEW_FRAME != mDataMessageTypeReceived) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kStreamBufferTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout,
+ mResultCondition.wait_until(l, timeout));
+ }
+ mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+ mVideoBufferIndex = UINT32_MAX;
+ }
+
+ device1->disableMsgType(
+ (unsigned int)DataCallbackMsg::PREVIEW_FRAME);
+ ASSERT_FALSE(device1->msgTypeEnabled(
+ (unsigned int)DataCallbackMsg::PREVIEW_FRAME));
+
+ bool videoMetaEnabled = false;
+ auto rc = device1->storeMetaDataInBuffers(true);
+ // It is allowed for devices to not support this feature
+ ASSERT_TRUE((Status::OK == rc) ||
+ (Status::OPERATION_NOT_SUPPORTED == rc));
+ if (Status::OK == rc) {
+ videoMetaEnabled = true;
+ }
+
+ device1->enableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME);
+ ASSERT_TRUE(device1->msgTypeEnabled(
+ (unsigned int)DataCallbackMsg::VIDEO_FRAME));
+ ASSERT_FALSE(device1->recordingEnabled());
+
+ ASSERT_EQ(Status::OK, device1->startRecording());
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ while (DataCallbackMsg::VIDEO_FRAME !=
+ mDataMessageTypeReceived) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kStreamBufferTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout,
+ mResultCondition.wait_until(l, timeout));
+ }
+ ASSERT_NE(UINT32_MAX, mVideoBufferIndex);
+
+ device1->disableMsgType(
+ (unsigned int)DataCallbackMsg::VIDEO_FRAME);
+ ASSERT_FALSE(device1->msgTypeEnabled(
+ (unsigned int)DataCallbackMsg::VIDEO_FRAME));
+ }
+
+ ASSERT_TRUE(device1->recordingEnabled());
+ if (videoMetaEnabled) {
+ device1->releaseRecordingFrameHandle(mVideoData,
+ mVideoBufferIndex, mVideoNativeHandle);
+ } else {
+ device1->releaseRecordingFrame(mVideoData, mVideoBufferIndex);
+ }
+
+ device1->stopRecording();
+ device1->stopPreview();
+
+ device1->close();
+ }
+ }
+}
+
+// It shouldn't be possible to start recording without enabling preview first.
+TEST_F(CameraHidlTest, startRecordingFail) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_1_0) {
+ sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+ openCameraDevice(name, env, &device1 /*out*/);
+ ASSERT_NE(nullptr, device1.get());
+
+ ASSERT_FALSE(device1->recordingEnabled());
+ ASSERT_NE(Status::OK, device1->startRecording());
+
+ device1->close();
+ }
+ }
+}
+
// Verify that the static camera characteristics can be retrieved
// successfully.
TEST_F(CameraHidlTest, getCameraCharacteristics) {