1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "EvsCamera.h" 18 19 #include <gmock/gmock.h> 20 #include <gtest/gtest.h> 21 22 #include <cstdint> 23 #include <unordered_set> 24 #include <vector> 25 26 namespace aidl::android::hardware::automotive::evs::implementation { 27 28 class EvsCameraForTest : public EvsCamera { 29 public: 30 using EvsCamera::increaseAvailableFrames_unsafe; 31 using EvsCamera::returnBuffer_unsafe; 32 using EvsCamera::useBuffer_unsafe; 33 ~EvsCameraForTest()34 ~EvsCameraForTest() override { shutdown(); } 35 allocateOneFrame(buffer_handle_t * handle)36 ::android::status_t allocateOneFrame(buffer_handle_t* handle) override { 37 static std::intptr_t handle_cnt = 0; 38 *handle = reinterpret_cast<buffer_handle_t>(++handle_cnt); 39 return ::android::OK; 40 } 41 freeOneFrame(const buffer_handle_t)42 void freeOneFrame(const buffer_handle_t /* handle */) override { 43 // Nothing to free because the handles are fake. 44 } 45 checkBufferOrder()46 void checkBufferOrder() { 47 for (std::size_t idx = 0; idx < mBuffers.size(); ++idx) { 48 const auto& buffer = mBuffers[idx]; 49 EXPECT_EQ(idx < mFramesInUse, buffer.inUse); 50 EXPECT_EQ(idx < mAvailableFrames, buffer.handle != nullptr); 51 EXPECT_LE(mFramesInUse, mAvailableFrames); 52 } 53 } 54 55 MOCK_METHOD(::ndk::ScopedAStatus, forcePrimaryClient, 56 (const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& 57 in_display), 58 (override)); 59 MOCK_METHOD(::ndk::ScopedAStatus, getCameraInfo, 60 (::aidl::android::hardware::automotive::evs::CameraDesc * _aidl_return), 61 (override)); 62 MOCK_METHOD(::ndk::ScopedAStatus, getExtendedInfo, 63 (int32_t in_opaqueIdentifier, std::vector<uint8_t>* _aidl_return), (override)); 64 MOCK_METHOD(::ndk::ScopedAStatus, getIntParameter, 65 (::aidl::android::hardware::automotive::evs::CameraParam in_id, 66 std::vector<int32_t>* _aidl_return), 67 (override)); 68 MOCK_METHOD(::ndk::ScopedAStatus, getIntParameterRange, 69 (::aidl::android::hardware::automotive::evs::CameraParam in_id, 70 ::aidl::android::hardware::automotive::evs::ParameterRange* _aidl_return), 71 (override)); 72 MOCK_METHOD(::ndk::ScopedAStatus, getParameterList, 73 (std::vector<::aidl::android::hardware::automotive::evs::CameraParam> * 74 _aidl_return), 75 (override)); 76 MOCK_METHOD(::ndk::ScopedAStatus, getPhysicalCameraInfo, 77 (const std::string& in_deviceId, 78 ::aidl::android::hardware::automotive::evs::CameraDesc* _aidl_return), 79 (override)); 80 MOCK_METHOD(::ndk::ScopedAStatus, setExtendedInfo, 81 (int32_t in_opaqueIdentifier, const std::vector<uint8_t>& in_opaqueValue), 82 (override)); 83 MOCK_METHOD(::ndk::ScopedAStatus, setIntParameter, 84 (::aidl::android::hardware::automotive::evs::CameraParam in_id, int32_t in_value, 85 std::vector<int32_t>* _aidl_return), 86 (override)); 87 MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); 88 MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); 89 MOCK_METHOD(bool, startVideoStreamImpl_locked, 90 (const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& status, 91 std::unique_lock<std::mutex>& lck), 92 (override)); 93 MOCK_METHOD(bool, stopVideoStreamImpl_locked, 94 (ndk::ScopedAStatus & status, std::unique_lock<std::mutex>& lck), (override)); 95 MOCK_METHOD(std::string, getId, (), (override)); 96 }; 97 TEST(EvsCameraBufferTest,ChangeBufferPoolSize)98 TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { 99 auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); 100 EXPECT_TRUE(evsCam->setMaxFramesInFlight(100).isOk()); 101 evsCam->checkBufferOrder(); 102 EXPECT_TRUE(evsCam->setMaxFramesInFlight(50).isOk()); 103 evsCam->checkBufferOrder(); 104 105 // 2 buffers in use. 106 const auto [id1, handle1] = evsCam->useBuffer_unsafe(); 107 const auto [id2, handle2] = evsCam->useBuffer_unsafe(); 108 std::ignore = evsCam->useBuffer_unsafe(); 109 110 // It allows you to set the buffer pool size to 1, but it will keep the space for the in use 111 // buffers. 112 EXPECT_TRUE(evsCam->setMaxFramesInFlight(1).isOk()); 113 evsCam->checkBufferOrder(); 114 115 evsCam->returnBuffer_unsafe(id1); 116 evsCam->checkBufferOrder(); 117 evsCam->returnBuffer_unsafe(id2); 118 evsCam->checkBufferOrder(); 119 } 120 TEST(EvsCameraBufferTest,UseAndReturn)121 TEST(EvsCameraBufferTest, UseAndReturn) { 122 constexpr std::size_t kNumOfHandles = 20; 123 auto evsCam = ndk::SharedRefBase::make<EvsCameraForTest>(); 124 125 // Our "fake handles" of this test case is 1 to kNumOfHandles. 126 for (std::size_t i = 1; i <= kNumOfHandles; ++i) { 127 evsCam->increaseAvailableFrames_unsafe(reinterpret_cast<buffer_handle_t>(i)); 128 } 129 evsCam->checkBufferOrder(); 130 131 { 132 std::vector<std::pair<std::size_t, std::intptr_t>> inUseIDHandlePairs; 133 std::unordered_set<std::size_t> inUseIDs; 134 std::unordered_set<std::intptr_t> inUseHandles; 135 for (std::size_t i = 0; i < kNumOfHandles; ++i) { 136 const auto [id, handle] = evsCam->useBuffer_unsafe(); 137 const std::size_t handleInt = reinterpret_cast<std::size_t>(handle); 138 EXPECT_TRUE(EvsCamera::IsBufferIDValid(id)); 139 EXPECT_NE(handle, nullptr); 140 EXPECT_LT(id, kNumOfHandles); 141 142 // handleInt must be between [1, kNumOfHandles] as we "allocated" above. 143 EXPECT_LT(0u, handleInt); 144 EXPECT_LE(handleInt, kNumOfHandles); 145 146 inUseIDHandlePairs.push_back({id, handleInt}); 147 EXPECT_TRUE(inUseIDs.insert(id).second); 148 EXPECT_TRUE(inUseHandles.insert(handleInt).second); 149 evsCam->checkBufferOrder(); 150 } 151 // Return buffers in the order of acquiring. 152 for (const auto [id, handleInt] : inUseIDHandlePairs) { 153 evsCam->returnBuffer_unsafe(id); 154 evsCam->checkBufferOrder(); 155 } 156 } 157 158 { 159 std::vector<std::pair<std::size_t, std::intptr_t>> inUseIDHandlePairs; 160 std::unordered_set<std::size_t> inUseIDs; 161 std::unordered_set<std::intptr_t> inUseHandles; 162 for (std::size_t i = 0; i < kNumOfHandles; ++i) { 163 const auto [id, handle] = evsCam->useBuffer_unsafe(); 164 const std::size_t handleInt = reinterpret_cast<std::size_t>(handle); 165 EXPECT_TRUE(EvsCamera::IsBufferIDValid(id)); 166 EXPECT_NE(handle, nullptr); 167 EXPECT_LT(id, kNumOfHandles); 168 169 // handleInt must be between [1, kNumOfHandles] as we "allocated" above. 170 EXPECT_LT(0u, handleInt); 171 EXPECT_LE(handleInt, kNumOfHandles); 172 173 inUseIDHandlePairs.push_back({id, handleInt}); 174 EXPECT_TRUE(inUseIDs.insert(id).second); 175 EXPECT_TRUE(inUseHandles.insert(handleInt).second); 176 evsCam->checkBufferOrder(); 177 } 178 // Return buffers in the reverse order of acquiring. 179 std::reverse(inUseIDHandlePairs.begin(), inUseIDHandlePairs.end()); 180 for (const auto [id, handleInt] : inUseIDHandlePairs) { 181 evsCam->returnBuffer_unsafe(id); 182 evsCam->checkBufferOrder(); 183 } 184 } 185 186 { 187 // Making sure the handles are still in [1, kNumOfHandles] and IDs are still [0, 188 // kNumOfHandles). The mapping may be different, though. 189 std::vector<std::pair<std::size_t, std::intptr_t>> inUseIDHandlePairs; 190 std::unordered_set<std::size_t> inUseIDs; 191 std::unordered_set<std::intptr_t> inUseHandles; 192 for (std::size_t i = 0; i < kNumOfHandles; ++i) { 193 const auto [id, handle] = evsCam->useBuffer_unsafe(); 194 const std::size_t handleInt = reinterpret_cast<std::size_t>(handle); 195 EXPECT_TRUE(EvsCamera::IsBufferIDValid(id)); 196 EXPECT_NE(handle, nullptr); 197 EXPECT_LT(id, kNumOfHandles); 198 199 // handleInt must be between [1, kNumOfHandles] as we "allocated" above. 200 EXPECT_LT(0u, handleInt); 201 EXPECT_LE(handleInt, kNumOfHandles); 202 203 inUseIDHandlePairs.push_back({id, handleInt}); 204 EXPECT_TRUE(inUseIDs.insert(id).second); 205 EXPECT_TRUE(inUseHandles.insert(handleInt).second); 206 evsCam->checkBufferOrder(); 207 } 208 } 209 } 210 211 } // namespace aidl::android::hardware::automotive::evs::implementation 212