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