• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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