1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "CameraDeviceSessionTests"
18 #include <dlfcn.h>
19 #include <log/log.h>
20 #include <sys/stat.h>
21
22 #include <gtest/gtest.h>
23 #include "utils.h"
24
25 #include <algorithm>
26
27 #include "gralloc_buffer_allocator.h"
28 #include "hwl_types.h"
29 #include "mock_device_session_hwl.h"
30 #include "test_utils.h"
31
32 namespace android {
33 namespace google_camera_hal {
34
35 using ::testing::_;
36 using ::testing::AtLeast;
37 using ::testing::Return;
38
39 // HAL external capture session library path
40 #if defined(_LP64)
41 constexpr char kExternalCaptureSessionDir[] =
42 "/vendor/lib64/camera/capture_sessions/";
43 #else // defined(_LP64)
44 constexpr char kExternalCaptureSessionDir[] =
45 "/vendor/lib/camera/capture_sessions/";
46 #endif
47
48 class CameraDeviceSessionTests : public ::testing::Test {
49 protected:
50 static constexpr uint32_t kCaptureTimeoutMs = 3000;
51 std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries_;
52 std::vector<void*> external_capture_session_lib_handles_;
53
CameraDeviceSessionTests()54 CameraDeviceSessionTests() {
55 LoadExternalCaptureSession();
56 }
57
~CameraDeviceSessionTests()58 ~CameraDeviceSessionTests() {
59 for (auto lib_handle : external_capture_session_lib_handles_) {
60 dlclose(lib_handle);
61 }
62 }
63
LoadExternalCaptureSession()64 status_t LoadExternalCaptureSession() {
65 if (external_session_factory_entries_.size() > 0) {
66 ALOGI("%s: External capture session libraries already loaded; skip.",
67 __FUNCTION__);
68 return OK;
69 }
70
71 for (const auto& lib_path :
72 utils::FindLibraryPaths(kExternalCaptureSessionDir)) {
73 ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str());
74 void* lib_handle = nullptr;
75 lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
76 if (lib_handle == nullptr) {
77 ALOGW("Failed loading %s.", lib_path.c_str());
78 continue;
79 }
80
81 GetCaptureSessionFactoryFunc external_session_factory_t =
82 reinterpret_cast<GetCaptureSessionFactoryFunc>(
83 dlsym(lib_handle, "GetCaptureSessionFactory"));
84 if (external_session_factory_t == nullptr) {
85 ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__,
86 "GetCaptureSessionFactory", lib_path.c_str());
87 dlclose(lib_handle);
88 lib_handle = nullptr;
89 continue;
90 }
91
92 external_session_factory_entries_.push_back(external_session_factory_t);
93 }
94
95 return OK;
96 }
97
CreateMockSessionHwlAndCheck(std::unique_ptr<MockDeviceSessionHwl> * session_hwl)98 void CreateMockSessionHwlAndCheck(
99 std::unique_ptr<MockDeviceSessionHwl>* session_hwl) {
100 ASSERT_NE(session_hwl, nullptr);
101
102 *session_hwl = std::make_unique<MockDeviceSessionHwl>();
103 ASSERT_NE(*session_hwl, nullptr);
104 }
105
CreateSessionAndCheck(std::unique_ptr<MockDeviceSessionHwl> session_hwl,std::unique_ptr<CameraDeviceSession> * session)106 void CreateSessionAndCheck(std::unique_ptr<MockDeviceSessionHwl> session_hwl,
107 std::unique_ptr<CameraDeviceSession>* session) {
108 ASSERT_NE(session, nullptr);
109
110 *session = CameraDeviceSession::Create(std::move(session_hwl),
111 external_session_factory_entries_);
112 ASSERT_NE(*session, nullptr);
113 }
114
TestInvalidDefaultRequestSettingsForType(RequestTemplate type)115 void TestInvalidDefaultRequestSettingsForType(RequestTemplate type) {
116 std::unique_ptr<MockDeviceSessionHwl> session_hwl;
117 CreateMockSessionHwlAndCheck(&session_hwl);
118 session_hwl->DelegateCallsToFakeSession();
119
120 EXPECT_CALL(*session_hwl, ConstructDefaultRequestSettings(
121 /*type=*/_, /*default_settings=*/nullptr))
122 .WillRepeatedly(Return(BAD_VALUE));
123
124 std::unique_ptr<CameraDeviceSession> session;
125 CreateSessionAndCheck(std::move(session_hwl), &session);
126
127 status_t res =
128 session->ConstructDefaultRequestSettings(type,
129 /*default_settings=*/nullptr);
130 EXPECT_EQ(res, BAD_VALUE);
131 }
132
TestDefaultRequestSettingsForType(RequestTemplate type)133 void TestDefaultRequestSettingsForType(RequestTemplate type) {
134 std::unique_ptr<MockDeviceSessionHwl> session_hwl;
135 CreateMockSessionHwlAndCheck(&session_hwl);
136 session_hwl->DelegateCallsToFakeSession();
137
138 EXPECT_CALL(*session_hwl, ConstructDefaultRequestSettings(
139 /*type=*/_, /*default_settings=*/_))
140 .Times(AtLeast(1))
141 .WillRepeatedly([](RequestTemplate /*type*/,
142 std::unique_ptr<HalCameraMetadata>* default_settings) {
143 uint32_t num_entries = 128;
144 uint32_t data_bytes = 512;
145
146 *default_settings = HalCameraMetadata::Create(num_entries, data_bytes);
147 return OK;
148 });
149
150 std::unique_ptr<CameraDeviceSession> session;
151 CreateSessionAndCheck(std::move(session_hwl), &session);
152
153 std::unique_ptr<HalCameraMetadata> default_settings;
154 status_t res =
155 session->ConstructDefaultRequestSettings(type, &default_settings);
156 EXPECT_EQ(res, OK);
157 ASSERT_NE(default_settings, nullptr);
158 EXPECT_GT(default_settings->GetCameraMetadataSize(), static_cast<size_t>(0));
159 }
160
161 // Invoked when CameraDeviceSession produces a result.
ProcessCaptureResult(std::unique_ptr<CaptureResult> result)162 void ProcessCaptureResult(std::unique_ptr<CaptureResult> result) {
163 EXPECT_NE(result, nullptr);
164 if (result == nullptr) {
165 return;
166 }
167
168 std::lock_guard<std::mutex> lock(callback_lock_);
169 auto pending_result = received_results_.find(result->frame_number);
170 if (pending_result == received_results_.end()) {
171 ALOGE("%s: frame %u result_metadata %p", __FUNCTION__,
172 result->frame_number, result->result_metadata.get());
173 received_results_.emplace(result->frame_number, std::move(result));
174 } else {
175 if (result->result_metadata != nullptr) {
176 // TODO(b/143902331): support partial results.
177 ASSERT_NE(pending_result->second->result_metadata, nullptr);
178 pending_result->second->result_metadata =
179 std::move(result->result_metadata);
180 }
181
182 pending_result->second->input_buffers.insert(
183 pending_result->second->input_buffers.end(),
184 result->input_buffers.begin(), result->input_buffers.end());
185
186 pending_result->second->output_buffers.insert(
187 pending_result->second->output_buffers.end(),
188 result->output_buffers.begin(), result->output_buffers.end());
189
190 pending_result->second->partial_result = result->partial_result;
191 }
192
193 callback_condition_.notify_one();
194 }
195
196 // Invoked when CameraDeviceSession notify a message.
Notify(const NotifyMessage & message)197 void Notify(const NotifyMessage& message) {
198 std::lock_guard<std::mutex> lock(callback_lock_);
199 received_messages_.push_back(message);
200 callback_condition_.notify_one();
201 }
202
ClearResultsAndMessages()203 void ClearResultsAndMessages() {
204 std::lock_guard<std::mutex> lock(callback_lock_);
205 received_results_.clear();
206 received_messages_.clear();
207 }
208
ContainsTheSameBuffers(std::vector<StreamBuffer> buffers,std::vector<StreamBuffer> other_buffers)209 bool ContainsTheSameBuffers(std::vector<StreamBuffer> buffers,
210 std::vector<StreamBuffer> other_buffers) {
211 // Set of pairs of stream ID and buffer ID.
212 std::set<std::pair<uint32_t, uint32_t>> stream_buffer_set;
213 std::set<std::pair<uint32_t, uint32_t>> other_stream_buffer_set;
214
215 for (auto& buffer : buffers) {
216 stream_buffer_set.emplace(buffer.stream_id, buffer.buffer_id);
217 }
218
219 for (auto& buffer : other_buffers) {
220 other_stream_buffer_set.emplace(buffer.stream_id, buffer.buffer_id);
221 }
222
223 return stream_buffer_set == other_stream_buffer_set;
224 }
225
226 // Caller must lock callback_lock_
IsResultReceivedLocked(const CaptureRequest & request)227 bool IsResultReceivedLocked(const CaptureRequest& request) {
228 auto result = received_results_.find(request.frame_number);
229 if (result == received_results_.end()) {
230 return false;
231 }
232
233 if (result->second->result_metadata == nullptr) {
234 return false;
235 }
236
237 if (!ContainsTheSameBuffers(result->second->output_buffers,
238 request.output_buffers)) {
239 return false;
240 }
241
242 if (!ContainsTheSameBuffers(result->second->input_buffers,
243 request.input_buffers)) {
244 return false;
245 }
246
247 return true;
248 }
249
WaitForResult(const CaptureRequest & request,uint32_t timeout_ms)250 status_t WaitForResult(const CaptureRequest& request, uint32_t timeout_ms) {
251 std::unique_lock<std::mutex> lock(callback_lock_);
252 if (IsResultReceivedLocked(request)) {
253 return OK;
254 }
255
256 bool received = callback_condition_.wait_for(
257 lock, std::chrono::milliseconds(timeout_ms),
258 [&] { return IsResultReceivedLocked(request); });
259
260 return received ? OK : TIMED_OUT;
261 }
262
263 // Caller must lock callback_lock_
IsShutterReceivedLocked(uint32_t frame_number)264 bool IsShutterReceivedLocked(uint32_t frame_number) {
265 for (auto& message : received_messages_) {
266 if (message.type == MessageType::kShutter &&
267 message.message.shutter.frame_number == frame_number) {
268 return true;
269 }
270 }
271
272 return false;
273 }
274
WaitForShutter(uint32_t frame_number,uint32_t timeout_ms)275 status_t WaitForShutter(uint32_t frame_number, uint32_t timeout_ms) {
276 std::unique_lock<std::mutex> lock(callback_lock_);
277 if (IsShutterReceivedLocked(frame_number)) {
278 return OK;
279 }
280
281 bool received = callback_condition_.wait_for(
282 lock, std::chrono::milliseconds(timeout_ms),
283 [&] { return IsShutterReceivedLocked(frame_number); });
284
285 return received ? OK : TIMED_OUT;
286 }
287
288 std::mutex callback_lock_;
289 std::condition_variable callback_condition_; // Protected by callback_lock_.
290
291 // Maps from a frame number to the received result from CameraDeviceSession.
292 // Protected by callback_lock_.
293 std::unordered_map<uint32_t, std::unique_ptr<CaptureResult>> received_results_;
294
295 // Received messages from CameraDeviceSession. Protected by callback_lock_.
296 std::vector<NotifyMessage> received_messages_;
297 };
298
TEST_F(CameraDeviceSessionTests,Create)299 TEST_F(CameraDeviceSessionTests, Create) {
300 auto session = CameraDeviceSession::Create(/*device_session_hwl=*/nullptr,
301 external_session_factory_entries_);
302 EXPECT_EQ(session, nullptr);
303
304 uint32_t num_sessions = 5;
305 for (uint32_t i = 0; i < num_sessions; i++) {
306 std::unique_ptr<MockDeviceSessionHwl> session_hwl;
307 CreateMockSessionHwlAndCheck(&session_hwl);
308 session_hwl->DelegateCallsToFakeSession();
309 CreateSessionAndCheck(std::move(session_hwl), &session);
310 session = nullptr;
311 }
312 }
313
TEST_F(CameraDeviceSessionTests,ConstructDefaultRequestSettings)314 TEST_F(CameraDeviceSessionTests, ConstructDefaultRequestSettings) {
315 std::vector<RequestTemplate> types = {
316 RequestTemplate::kPreview, RequestTemplate::kStillCapture,
317 RequestTemplate::kVideoRecord, RequestTemplate::kVideoSnapshot,
318 RequestTemplate::kZeroShutterLag, RequestTemplate::kManual};
319
320 for (auto type : types) {
321 TestInvalidDefaultRequestSettingsForType(type);
322 TestDefaultRequestSettingsForType(type);
323 }
324 }
325
TEST_F(CameraDeviceSessionTests,ConfigurePreviewStream)326 TEST_F(CameraDeviceSessionTests, ConfigurePreviewStream) {
327 std::vector<std::pair<uint32_t, uint32_t>> preview_resolutions = {
328 std::make_pair(640, 480), std::make_pair(1280, 720),
329 std::make_pair(1920, 1080)};
330
331 std::unique_ptr<MockDeviceSessionHwl> session_hwl;
332 CreateMockSessionHwlAndCheck(&session_hwl);
333 session_hwl->DelegateCallsToFakeSession();
334
335 // Expect CreatePipeline() calls back to back.
336 EXPECT_CALL(*session_hwl, ConfigurePipeline(/*camera_id=*/_,
337 /*hwl_pipeline_callback=*/_,
338 /*request_config=*/_,
339 /*overall_config=*/_,
340 /*pipeline_id=*/_))
341 .Times(AtLeast(preview_resolutions.size()));
342
343 // Expect BuildPipelines() calls back to back.
344 EXPECT_CALL(*session_hwl, BuildPipelines())
345 .Times(AtLeast(preview_resolutions.size()));
346
347 // Expect DestroyPipelines() calls back to back except the first
348 // stream configuration.
349 EXPECT_CALL(*session_hwl, DestroyPipelines())
350 .Times(AtLeast(preview_resolutions.size() - 1));
351
352 std::unique_ptr<CameraDeviceSession> session;
353 CreateSessionAndCheck(std::move(session_hwl), &session);
354
355 std::vector<HalStream> hal_configured_streams;
356 StreamConfiguration preview_config;
357 status_t res;
358
359 for (auto& resolution : preview_resolutions) {
360 test_utils::GetPreviewOnlyStreamConfiguration(
361 &preview_config, resolution.first, resolution.second);
362 res = session->ConfigureStreams(preview_config, &hal_configured_streams);
363 EXPECT_EQ(res, OK);
364 }
365 }
366
TEST_F(CameraDeviceSessionTests,PreviewRequests)367 TEST_F(CameraDeviceSessionTests, PreviewRequests) {
368 std::unique_ptr<MockDeviceSessionHwl> session_hwl;
369 CreateMockSessionHwlAndCheck(&session_hwl);
370 session_hwl->DelegateCallsToFakeSession();
371
372 // Set up mocking expections.
373 static constexpr uint32_t kNumPreviewRequests = 5;
374 EXPECT_CALL(*session_hwl, ConfigurePipeline(_, _, _, _, _)).Times(1);
375 EXPECT_CALL(*session_hwl, SubmitRequests(_, _)).Times(kNumPreviewRequests);
376
377 std::unique_ptr<CameraDeviceSession> session;
378 CreateSessionAndCheck(std::move(session_hwl), &session);
379
380 // Configure a preview stream.
381 static const uint32_t kPreviewWidth = 640;
382 static const uint32_t kPreviewHeight = 480;
383 StreamConfiguration preview_config;
384 std::vector<HalStream> hal_configured_streams;
385
386 // Set up session callback.
387 CameraDeviceSessionCallback session_callback = {
388 .process_capture_result =
389 [&](std::unique_ptr<CaptureResult> result) {
390 ProcessCaptureResult(std::move(result));
391 },
392 .notify = [&](const NotifyMessage& message) { Notify(message); },
393 };
394
395 ThermalCallback thermal_callback = {
396 .register_thermal_changed_callback =
397 google_camera_hal::RegisterThermalChangedCallbackFunc(
398 [](google_camera_hal::NotifyThrottlingFunc /*notify_throttling*/,
399 bool /*filter_type*/,
400 google_camera_hal::TemperatureType /*type*/) {
401 return INVALID_OPERATION;
402 }),
403 .unregister_thermal_changed_callback =
404 google_camera_hal::UnregisterThermalChangedCallbackFunc([]() {}),
405 };
406
407 session->SetSessionCallback(session_callback, thermal_callback);
408
409 test_utils::GetPreviewOnlyStreamConfiguration(&preview_config, kPreviewWidth,
410 kPreviewHeight);
411 ASSERT_EQ(session->ConfigureStreams(preview_config, &hal_configured_streams),
412 OK);
413 ASSERT_EQ(hal_configured_streams.size(), static_cast<uint32_t>(1));
414
415 // Allocate buffers.
416 auto allocator = GrallocBufferAllocator::Create();
417 ASSERT_NE(allocator, nullptr);
418
419 HalBufferDescriptor buffer_descriptor = {
420 .width = preview_config.streams[0].width,
421 .height = preview_config.streams[0].height,
422 .format = hal_configured_streams[0].override_format,
423 .producer_flags = hal_configured_streams[0].producer_usage |
424 preview_config.streams[0].usage,
425 .consumer_flags = hal_configured_streams[0].consumer_usage,
426 .immediate_num_buffers =
427 std::max(hal_configured_streams[0].max_buffers, kNumPreviewRequests),
428 .max_num_buffers =
429 std::max(hal_configured_streams[0].max_buffers, kNumPreviewRequests),
430 };
431
432 std::vector<buffer_handle_t> preview_buffers;
433 ASSERT_EQ(allocator->AllocateBuffers(buffer_descriptor, &preview_buffers), OK);
434
435 std::unique_ptr<HalCameraMetadata> preview_settings;
436 ASSERT_EQ(session->ConstructDefaultRequestSettings(RequestTemplate::kPreview,
437 &preview_settings),
438 OK);
439
440 // Prepare preview requests.
441 std::vector<CaptureRequest> requests;
442 for (uint32_t i = 0; i < kNumPreviewRequests; i++) {
443 StreamBuffer preview_buffer = {
444 .stream_id = preview_config.streams[0].id,
445 .buffer_id = i,
446 .buffer = preview_buffers[i],
447 .status = BufferStatus::kOk,
448 .acquire_fence = nullptr,
449 .release_fence = nullptr,
450 };
451
452 CaptureRequest request = {
453 .frame_number = i,
454 .settings = HalCameraMetadata::Clone(preview_settings.get()),
455 .output_buffers = {preview_buffer},
456 };
457
458 requests.push_back(std::move(request));
459 }
460
461 ClearResultsAndMessages();
462 uint32_t num_processed_requests = 0;
463 ASSERT_EQ(session->ProcessCaptureRequest(requests, &num_processed_requests),
464 OK);
465 ASSERT_EQ(num_processed_requests, requests.size());
466
467 // Verify shutters and results are received.
468 for (auto& request : requests) {
469 EXPECT_EQ(WaitForShutter(request.frame_number, kCaptureTimeoutMs), OK);
470 EXPECT_EQ(WaitForResult(request, kCaptureTimeoutMs), OK);
471 }
472
473 allocator->FreeBuffers(&preview_buffers);
474 }
475
476 } // namespace google_camera_hal
477 } // namespace android
478