xref: /aosp_15_r20/hardware/interfaces/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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