Loading automotive/evs/aidl/impl/default/Android.bp +17 −0 Original line number Diff line number Diff line Loading @@ -105,4 +105,21 @@ cc_test { "android.hardware.automotive.evs-aidl-default-service-lib", "libgmock", ], test_suites: [ "general-tests", ], } cc_test { name: "android.hardware.automotive.evs-aidl-default-service_cam_state_test", defaults: ["android.hardware.automotive.evs-aidl-default-service-default"], vendor: true, srcs: ["tests/EvsCameraStateTest.cpp"], static_libs: [ "android.hardware.automotive.evs-aidl-default-service-lib", "libgmock", ], test_suites: [ "general-tests", ], } automotive/evs/aidl/impl/default/include/EvsCamera.h +40 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include "EvsCameraBase.h" #include <aidl/android/hardware/automotive/evs/IEvsCameraStream.h> #include <cutils/native_handle.h> #include <cstddef> Loading Loading @@ -45,11 +46,41 @@ class EvsCamera : public EvsCameraBase { ndk::ScopedAStatus setMaxFramesInFlight(int32_t bufferCount) override; ndk::ScopedAStatus startVideoStream( const std::shared_ptr<evs::IEvsCameraStream>& receiver) override; ndk::ScopedAStatus stopVideoStream() override; ndk::ScopedAStatus pauseVideoStream() override; ndk::ScopedAStatus resumeVideoStream() override; protected: virtual ::android::status_t allocateOneFrame(buffer_handle_t* handle) = 0; virtual void freeOneFrame(const buffer_handle_t handle); virtual bool preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) = 0; virtual bool postVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) = 0; virtual bool postVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); void shutdown() override; void closeAllBuffers_unsafe(); Loading Loading @@ -81,6 +112,15 @@ class EvsCamera : public EvsCameraBase { bool inUse{false}; }; enum class StreamState { STOPPED = 0, RUNNING = 1, STOPPING = 2, DEAD = 3, }; StreamState mStreamState{StreamState::STOPPED}; std::mutex mMutex; // Graphics buffers to transfer images, always in the order of: Loading automotive/evs/aidl/impl/default/src/EvsCamera.cpp +112 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ namespace aidl::android::hardware::automotive::evs::implementation { // Safeguards against unreasonable resource consumption and provides a testable limit constexpr std::size_t kMaxBuffersInFlight = 100; // Minimum number of buffers to run a video stream constexpr int kMinimumBuffersInFlight = 1; EvsCamera::~EvsCamera() { shutdown(); } Loading Loading @@ -108,6 +111,113 @@ void EvsCamera::freeOneFrame(const buffer_handle_t handle) { alloc.free(handle); } bool EvsCamera::preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& /* lck */) { if (!receiver) { LOG(ERROR) << __func__ << ": Null receiver."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::INVALID_ARG)); return false; } // If we've been displaced by another owner of the camera, then we can't do anything else if (mStreamState == StreamState::DEAD) { LOG(ERROR) << __func__ << ": Ignoring when camera has been lost."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::OWNERSHIP_LOST)); return false; } if (mStreamState != StreamState::STOPPED) { LOG(ERROR) << __func__ << ": Ignoring when a stream is already running."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::STREAM_ALREADY_RUNNING)); return false; } // If the client never indicated otherwise, configure ourselves for a single streaming buffer if (mAvailableFrames < kMinimumBuffersInFlight && !setAvailableFrames_unsafe(kMinimumBuffersInFlight)) { LOG(ERROR) << __func__ << "Failed to because we could not get a graphics buffer."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE)); return false; } mStreamState = StreamState::RUNNING; return true; } bool EvsCamera::postVideoStreamStart_locked( const std::shared_ptr<evs::IEvsCameraStream>& /* receiver */, ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) { return true; } bool EvsCamera::preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& /* lck */) { if (mStreamState != StreamState::RUNNING) { // Terminate the stop process because a stream is not running. status = ndk::ScopedAStatus::ok(); return false; } mStreamState = StreamState::STOPPING; return true; } bool EvsCamera::postVideoStreamStop_locked(ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) { mStreamState = StreamState::STOPPED; return true; } ndk::ScopedAStatus EvsCamera::startVideoStream( const std::shared_ptr<evs::IEvsCameraStream>& receiver) { bool needShutdown = false; auto status = ndk::ScopedAStatus::ok(); { std::unique_lock lck(mMutex); if (!preVideoStreamStart_locked(receiver, status, lck)) { return status; } if ((!startVideoStreamImpl_locked(receiver, status, lck) || !postVideoStreamStart_locked(receiver, status, lck)) && !status.isOk()) { needShutdown = true; } } if (needShutdown) { shutdown(); } return status; } ndk::ScopedAStatus EvsCamera::stopVideoStream() { bool needShutdown = false; auto status = ndk::ScopedAStatus::ok(); { std::unique_lock lck(mMutex); if ((!preVideoStreamStop_locked(status, lck) || !stopVideoStreamImpl_locked(status, lck) || !postVideoStreamStop_locked(status, lck)) && !status.isOk()) { needShutdown = true; } } if (needShutdown) { shutdown(); } return status; } ndk::ScopedAStatus EvsCamera::pauseVideoStream() { return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED)); } ndk::ScopedAStatus EvsCamera::resumeVideoStream() { return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED)); } bool EvsCamera::setAvailableFrames_unsafe(const std::size_t bufferCount) { if (bufferCount < 1) { LOG(ERROR) << "Ignoring request to set buffer count to zero."; Loading Loading @@ -159,8 +269,10 @@ bool EvsCamera::setAvailableFrames_unsafe(const std::size_t bufferCount) { } void EvsCamera::shutdown() { stopVideoStream(); std::lock_guard lck(mMutex); closeAllBuffers_unsafe(); mStreamState = StreamState::DEAD; } void EvsCamera::closeAllBuffers_unsafe() { Loading automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -77,8 +77,6 @@ class EvsCameraForTest : public EvsCamera { (const std::string& in_deviceId, ::aidl::android::hardware::automotive::evs::CameraDesc* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, pauseVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, resumeVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setExtendedInfo, (int32_t in_opaqueIdentifier, const std::vector<uint8_t>& in_opaqueValue), (override)); Loading @@ -87,12 +85,13 @@ class EvsCameraForTest : public EvsCamera { std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, startVideoStream, (const std::shared_ptr< ::aidl::android::hardware::automotive::evs::IEvsCameraStream>& in_receiver), (override)); MOCK_METHOD(::ndk::ScopedAStatus, stopVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); MOCK_METHOD(bool, startVideoStreamImpl_locked, (const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck), (override)); MOCK_METHOD(bool, stopVideoStreamImpl_locked, (ndk::ScopedAStatus & status, std::unique_lock<std::mutex>& lck), (override)); }; TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { Loading @@ -118,7 +117,7 @@ TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { evsCam->checkBufferOrder(); } TEST(EvsCameraForTest, UseAndReturn) { TEST(EvsCameraBufferTest, UseAndReturn) { constexpr std::size_t kNumOfHandles = 20; auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); Loading automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp 0 → 100644 +202 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 "EvsCamera.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <cstdint> #include <unordered_set> #include <vector> namespace aidl::android::hardware::automotive::evs::implementation { class EvsCameraForTest : public EvsCamera { private: using Base = EvsCamera; public: using EvsCamera::mStreamState; using EvsCamera::shutdown; using EvsCamera::StreamState; ~EvsCameraForTest() override { shutdown(); } ::android::status_t allocateOneFrame(buffer_handle_t* handle) override { static std::intptr_t handle_cnt = 0; *handle = reinterpret_cast<buffer_handle_t>(++handle_cnt); return ::android::OK; } void freeOneFrame(const buffer_handle_t /* handle */) override { // Nothing to free because the handles are fake. } bool preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPreStartCalled = true; EXPECT_EQ(mStreamState, StreamState::STOPPED); EXPECT_FALSE(mStreamStarted); EXPECT_FALSE(mStreamStopped); return Base::preVideoStreamStart_locked(receiver, status, lck); } bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& /* receiver */, ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) override { EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_FALSE(mStreamStarted); EXPECT_FALSE(mStreamStopped); mStreamStarted = true; return true; } bool postVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPostStartCalled = true; EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); return Base::postVideoStreamStart_locked(receiver, status, lck); } bool preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { // Skip the check if stop was called before. if (!mPreStopCalled) { mPreStopCalled = true; EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); } return Base::preVideoStreamStop_locked(status, lck); } bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) override { EXPECT_EQ(mStreamState, StreamState::STOPPING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); mStreamStopped = true; return true; } bool postVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPostStopCalled = true; const auto ret = Base::postVideoStreamStop_locked(status, lck); EXPECT_EQ(mStreamState, StreamState::STOPPED); EXPECT_TRUE(mStreamStarted); EXPECT_TRUE(mStreamStopped); return ret; } MOCK_METHOD(::ndk::ScopedAStatus, forcePrimaryClient, (const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& in_display), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getCameraInfo, (::aidl::android::hardware::automotive::evs::CameraDesc * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getExtendedInfo, (int32_t in_opaqueIdentifier, std::vector<uint8_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getIntParameter, (::aidl::android::hardware::automotive::evs::CameraParam in_id, std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getIntParameterRange, (::aidl::android::hardware::automotive::evs::CameraParam in_id, ::aidl::android::hardware::automotive::evs::ParameterRange* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getParameterList, (std::vector<::aidl::android::hardware::automotive::evs::CameraParam> * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getPhysicalCameraInfo, (const std::string& in_deviceId, ::aidl::android::hardware::automotive::evs::CameraDesc* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setExtendedInfo, (int32_t in_opaqueIdentifier, const std::vector<uint8_t>& in_opaqueValue), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setIntParameter, (::aidl::android::hardware::automotive::evs::CameraParam in_id, int32_t in_value, std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); bool mStreamStarted = false; bool mStreamStopped = false; bool mPreStartCalled = false; bool mPostStartCalled = false; bool mPreStopCalled = false; bool mPostStopCalled = false; }; class MockEvsCameraStream : public evs::IEvsCameraStream { MOCK_METHOD(::ndk::SpAIBinder, asBinder, (), (override)); MOCK_METHOD(bool, isRemote, (), (override)); MOCK_METHOD( ::ndk::ScopedAStatus, deliverFrame, (const std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>& in_buffer), (override)); MOCK_METHOD(::ndk::ScopedAStatus, notify, (const ::aidl::android::hardware::automotive::evs::EvsEventDesc& in_event), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override)); }; using StreamState = EvsCameraForTest::StreamState; TEST(EvsCameraStateTest, StateChangeHooks) { auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); auto mockStream = ndk::SharedRefBase::make<MockEvsCameraStream>(); EXPECT_FALSE(evsCam->mPreStartCalled); EXPECT_FALSE(evsCam->mPostStartCalled); EXPECT_FALSE(evsCam->mPreStopCalled); EXPECT_FALSE(evsCam->mPostStopCalled); EXPECT_FALSE(evsCam->mStreamStarted); EXPECT_FALSE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::STOPPED); evsCam->startVideoStream(mockStream); EXPECT_TRUE(evsCam->mPreStartCalled); EXPECT_TRUE(evsCam->mPostStartCalled); EXPECT_FALSE(evsCam->mPreStopCalled); EXPECT_FALSE(evsCam->mPostStopCalled); EXPECT_TRUE(evsCam->mStreamStarted); EXPECT_FALSE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::RUNNING); evsCam->stopVideoStream(); EXPECT_TRUE(evsCam->mPreStartCalled); EXPECT_TRUE(evsCam->mPostStartCalled); EXPECT_TRUE(evsCam->mPreStopCalled); EXPECT_TRUE(evsCam->mPostStopCalled); EXPECT_TRUE(evsCam->mStreamStarted); EXPECT_TRUE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::STOPPED); evsCam->shutdown(); EXPECT_EQ(evsCam->mStreamState, StreamState::DEAD); } } // namespace aidl::android::hardware::automotive::evs::implementation Loading
automotive/evs/aidl/impl/default/Android.bp +17 −0 Original line number Diff line number Diff line Loading @@ -105,4 +105,21 @@ cc_test { "android.hardware.automotive.evs-aidl-default-service-lib", "libgmock", ], test_suites: [ "general-tests", ], } cc_test { name: "android.hardware.automotive.evs-aidl-default-service_cam_state_test", defaults: ["android.hardware.automotive.evs-aidl-default-service-default"], vendor: true, srcs: ["tests/EvsCameraStateTest.cpp"], static_libs: [ "android.hardware.automotive.evs-aidl-default-service-lib", "libgmock", ], test_suites: [ "general-tests", ], }
automotive/evs/aidl/impl/default/include/EvsCamera.h +40 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include "EvsCameraBase.h" #include <aidl/android/hardware/automotive/evs/IEvsCameraStream.h> #include <cutils/native_handle.h> #include <cstddef> Loading Loading @@ -45,11 +46,41 @@ class EvsCamera : public EvsCameraBase { ndk::ScopedAStatus setMaxFramesInFlight(int32_t bufferCount) override; ndk::ScopedAStatus startVideoStream( const std::shared_ptr<evs::IEvsCameraStream>& receiver) override; ndk::ScopedAStatus stopVideoStream() override; ndk::ScopedAStatus pauseVideoStream() override; ndk::ScopedAStatus resumeVideoStream() override; protected: virtual ::android::status_t allocateOneFrame(buffer_handle_t* handle) = 0; virtual void freeOneFrame(const buffer_handle_t handle); virtual bool preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) = 0; virtual bool postVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); virtual bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) = 0; virtual bool postVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck); void shutdown() override; void closeAllBuffers_unsafe(); Loading Loading @@ -81,6 +112,15 @@ class EvsCamera : public EvsCameraBase { bool inUse{false}; }; enum class StreamState { STOPPED = 0, RUNNING = 1, STOPPING = 2, DEAD = 3, }; StreamState mStreamState{StreamState::STOPPED}; std::mutex mMutex; // Graphics buffers to transfer images, always in the order of: Loading
automotive/evs/aidl/impl/default/src/EvsCamera.cpp +112 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ namespace aidl::android::hardware::automotive::evs::implementation { // Safeguards against unreasonable resource consumption and provides a testable limit constexpr std::size_t kMaxBuffersInFlight = 100; // Minimum number of buffers to run a video stream constexpr int kMinimumBuffersInFlight = 1; EvsCamera::~EvsCamera() { shutdown(); } Loading Loading @@ -108,6 +111,113 @@ void EvsCamera::freeOneFrame(const buffer_handle_t handle) { alloc.free(handle); } bool EvsCamera::preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& /* lck */) { if (!receiver) { LOG(ERROR) << __func__ << ": Null receiver."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::INVALID_ARG)); return false; } // If we've been displaced by another owner of the camera, then we can't do anything else if (mStreamState == StreamState::DEAD) { LOG(ERROR) << __func__ << ": Ignoring when camera has been lost."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::OWNERSHIP_LOST)); return false; } if (mStreamState != StreamState::STOPPED) { LOG(ERROR) << __func__ << ": Ignoring when a stream is already running."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::STREAM_ALREADY_RUNNING)); return false; } // If the client never indicated otherwise, configure ourselves for a single streaming buffer if (mAvailableFrames < kMinimumBuffersInFlight && !setAvailableFrames_unsafe(kMinimumBuffersInFlight)) { LOG(ERROR) << __func__ << "Failed to because we could not get a graphics buffer."; status = ndk::ScopedAStatus::fromServiceSpecificError( static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE)); return false; } mStreamState = StreamState::RUNNING; return true; } bool EvsCamera::postVideoStreamStart_locked( const std::shared_ptr<evs::IEvsCameraStream>& /* receiver */, ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) { return true; } bool EvsCamera::preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& /* lck */) { if (mStreamState != StreamState::RUNNING) { // Terminate the stop process because a stream is not running. status = ndk::ScopedAStatus::ok(); return false; } mStreamState = StreamState::STOPPING; return true; } bool EvsCamera::postVideoStreamStop_locked(ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) { mStreamState = StreamState::STOPPED; return true; } ndk::ScopedAStatus EvsCamera::startVideoStream( const std::shared_ptr<evs::IEvsCameraStream>& receiver) { bool needShutdown = false; auto status = ndk::ScopedAStatus::ok(); { std::unique_lock lck(mMutex); if (!preVideoStreamStart_locked(receiver, status, lck)) { return status; } if ((!startVideoStreamImpl_locked(receiver, status, lck) || !postVideoStreamStart_locked(receiver, status, lck)) && !status.isOk()) { needShutdown = true; } } if (needShutdown) { shutdown(); } return status; } ndk::ScopedAStatus EvsCamera::stopVideoStream() { bool needShutdown = false; auto status = ndk::ScopedAStatus::ok(); { std::unique_lock lck(mMutex); if ((!preVideoStreamStop_locked(status, lck) || !stopVideoStreamImpl_locked(status, lck) || !postVideoStreamStop_locked(status, lck)) && !status.isOk()) { needShutdown = true; } } if (needShutdown) { shutdown(); } return status; } ndk::ScopedAStatus EvsCamera::pauseVideoStream() { return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED)); } ndk::ScopedAStatus EvsCamera::resumeVideoStream() { return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED)); } bool EvsCamera::setAvailableFrames_unsafe(const std::size_t bufferCount) { if (bufferCount < 1) { LOG(ERROR) << "Ignoring request to set buffer count to zero."; Loading Loading @@ -159,8 +269,10 @@ bool EvsCamera::setAvailableFrames_unsafe(const std::size_t bufferCount) { } void EvsCamera::shutdown() { stopVideoStream(); std::lock_guard lck(mMutex); closeAllBuffers_unsafe(); mStreamState = StreamState::DEAD; } void EvsCamera::closeAllBuffers_unsafe() { Loading
automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -77,8 +77,6 @@ class EvsCameraForTest : public EvsCamera { (const std::string& in_deviceId, ::aidl::android::hardware::automotive::evs::CameraDesc* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, pauseVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, resumeVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setExtendedInfo, (int32_t in_opaqueIdentifier, const std::vector<uint8_t>& in_opaqueValue), (override)); Loading @@ -87,12 +85,13 @@ class EvsCameraForTest : public EvsCamera { std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, startVideoStream, (const std::shared_ptr< ::aidl::android::hardware::automotive::evs::IEvsCameraStream>& in_receiver), (override)); MOCK_METHOD(::ndk::ScopedAStatus, stopVideoStream, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); MOCK_METHOD(bool, startVideoStreamImpl_locked, (const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck), (override)); MOCK_METHOD(bool, stopVideoStreamImpl_locked, (ndk::ScopedAStatus & status, std::unique_lock<std::mutex>& lck), (override)); }; TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { Loading @@ -118,7 +117,7 @@ TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { evsCam->checkBufferOrder(); } TEST(EvsCameraForTest, UseAndReturn) { TEST(EvsCameraBufferTest, UseAndReturn) { constexpr std::size_t kNumOfHandles = 20; auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); Loading
automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp 0 → 100644 +202 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 "EvsCamera.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <cstdint> #include <unordered_set> #include <vector> namespace aidl::android::hardware::automotive::evs::implementation { class EvsCameraForTest : public EvsCamera { private: using Base = EvsCamera; public: using EvsCamera::mStreamState; using EvsCamera::shutdown; using EvsCamera::StreamState; ~EvsCameraForTest() override { shutdown(); } ::android::status_t allocateOneFrame(buffer_handle_t* handle) override { static std::intptr_t handle_cnt = 0; *handle = reinterpret_cast<buffer_handle_t>(++handle_cnt); return ::android::OK; } void freeOneFrame(const buffer_handle_t /* handle */) override { // Nothing to free because the handles are fake. } bool preVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPreStartCalled = true; EXPECT_EQ(mStreamState, StreamState::STOPPED); EXPECT_FALSE(mStreamStarted); EXPECT_FALSE(mStreamStopped); return Base::preVideoStreamStart_locked(receiver, status, lck); } bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& /* receiver */, ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) override { EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_FALSE(mStreamStarted); EXPECT_FALSE(mStreamStopped); mStreamStarted = true; return true; } bool postVideoStreamStart_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPostStartCalled = true; EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); return Base::postVideoStreamStart_locked(receiver, status, lck); } bool preVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { // Skip the check if stop was called before. if (!mPreStopCalled) { mPreStopCalled = true; EXPECT_EQ(mStreamState, StreamState::RUNNING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); } return Base::preVideoStreamStop_locked(status, lck); } bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) override { EXPECT_EQ(mStreamState, StreamState::STOPPING); EXPECT_TRUE(mStreamStarted); EXPECT_FALSE(mStreamStopped); mStreamStopped = true; return true; } bool postVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock<std::mutex>& lck) override { mPostStopCalled = true; const auto ret = Base::postVideoStreamStop_locked(status, lck); EXPECT_EQ(mStreamState, StreamState::STOPPED); EXPECT_TRUE(mStreamStarted); EXPECT_TRUE(mStreamStopped); return ret; } MOCK_METHOD(::ndk::ScopedAStatus, forcePrimaryClient, (const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& in_display), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getCameraInfo, (::aidl::android::hardware::automotive::evs::CameraDesc * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getExtendedInfo, (int32_t in_opaqueIdentifier, std::vector<uint8_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getIntParameter, (::aidl::android::hardware::automotive::evs::CameraParam in_id, std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getIntParameterRange, (::aidl::android::hardware::automotive::evs::CameraParam in_id, ::aidl::android::hardware::automotive::evs::ParameterRange* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getParameterList, (std::vector<::aidl::android::hardware::automotive::evs::CameraParam> * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getPhysicalCameraInfo, (const std::string& in_deviceId, ::aidl::android::hardware::automotive::evs::CameraDesc* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setExtendedInfo, (int32_t in_opaqueIdentifier, const std::vector<uint8_t>& in_opaqueValue), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setIntParameter, (::aidl::android::hardware::automotive::evs::CameraParam in_id, int32_t in_value, std::vector<int32_t>* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); bool mStreamStarted = false; bool mStreamStopped = false; bool mPreStartCalled = false; bool mPostStartCalled = false; bool mPreStopCalled = false; bool mPostStopCalled = false; }; class MockEvsCameraStream : public evs::IEvsCameraStream { MOCK_METHOD(::ndk::SpAIBinder, asBinder, (), (override)); MOCK_METHOD(bool, isRemote, (), (override)); MOCK_METHOD( ::ndk::ScopedAStatus, deliverFrame, (const std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>& in_buffer), (override)); MOCK_METHOD(::ndk::ScopedAStatus, notify, (const ::aidl::android::hardware::automotive::evs::EvsEventDesc& in_event), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t * _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override)); }; using StreamState = EvsCameraForTest::StreamState; TEST(EvsCameraStateTest, StateChangeHooks) { auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); auto mockStream = ndk::SharedRefBase::make<MockEvsCameraStream>(); EXPECT_FALSE(evsCam->mPreStartCalled); EXPECT_FALSE(evsCam->mPostStartCalled); EXPECT_FALSE(evsCam->mPreStopCalled); EXPECT_FALSE(evsCam->mPostStopCalled); EXPECT_FALSE(evsCam->mStreamStarted); EXPECT_FALSE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::STOPPED); evsCam->startVideoStream(mockStream); EXPECT_TRUE(evsCam->mPreStartCalled); EXPECT_TRUE(evsCam->mPostStartCalled); EXPECT_FALSE(evsCam->mPreStopCalled); EXPECT_FALSE(evsCam->mPostStopCalled); EXPECT_TRUE(evsCam->mStreamStarted); EXPECT_FALSE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::RUNNING); evsCam->stopVideoStream(); EXPECT_TRUE(evsCam->mPreStartCalled); EXPECT_TRUE(evsCam->mPostStartCalled); EXPECT_TRUE(evsCam->mPreStopCalled); EXPECT_TRUE(evsCam->mPostStopCalled); EXPECT_TRUE(evsCam->mStreamStarted); EXPECT_TRUE(evsCam->mStreamStopped); EXPECT_EQ(evsCam->mStreamState, StreamState::STOPPED); evsCam->shutdown(); EXPECT_EQ(evsCam->mStreamState, StreamState::DEAD); } } // namespace aidl::android::hardware::automotive::evs::implementation