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 
ClearResultsAndMessages()209   void ClearResultsAndMessages() {
210     std::lock_guard<std::mutex> lock(callback_lock_);
211     received_results_.clear();
212     received_messages_.clear();
213   }
214 
ContainsTheSameBuffers(std::vector<StreamBuffer> buffers,std::vector<StreamBuffer> other_buffers)215   bool ContainsTheSameBuffers(std::vector<StreamBuffer> buffers,
216                               std::vector<StreamBuffer> other_buffers) {
217     // Set of pairs of stream ID and buffer ID.
218     std::set<std::pair<uint32_t, uint32_t>> stream_buffer_set;
219     std::set<std::pair<uint32_t, uint32_t>> other_stream_buffer_set;
220 
221     for (auto& buffer : buffers) {
222       stream_buffer_set.emplace(buffer.stream_id, buffer.buffer_id);
223     }
224 
225     for (auto& buffer : other_buffers) {
226       other_stream_buffer_set.emplace(buffer.stream_id, buffer.buffer_id);
227     }
228 
229     return stream_buffer_set == other_stream_buffer_set;
230   }
231 
232   // Caller must lock callback_lock_
IsResultReceivedLocked(const CaptureRequest & request)233   bool IsResultReceivedLocked(const CaptureRequest& request) {
234     auto result = received_results_.find(request.frame_number);
235     if (result == received_results_.end()) {
236       return false;
237     }
238 
239     if (result->second->result_metadata == nullptr) {
240       return false;
241     }
242 
243     if (!ContainsTheSameBuffers(result->second->output_buffers,
244                                 request.output_buffers)) {
245       return false;
246     }
247 
248     if (!ContainsTheSameBuffers(result->second->input_buffers,
249                                 request.input_buffers)) {
250       return false;
251     }
252 
253     return true;
254   }
255 
WaitForResult(const CaptureRequest & request,uint32_t timeout_ms)256   status_t WaitForResult(const CaptureRequest& request, uint32_t timeout_ms) {
257     std::unique_lock<std::mutex> lock(callback_lock_);
258     if (IsResultReceivedLocked(request)) {
259       return OK;
260     }
261 
262     bool received = callback_condition_.wait_for(
263         lock, std::chrono::milliseconds(timeout_ms),
264         [&] { return IsResultReceivedLocked(request); });
265 
266     return received ? OK : TIMED_OUT;
267   }
268 
269   // Caller must lock callback_lock_
IsShutterReceivedLocked(uint32_t frame_number)270   bool IsShutterReceivedLocked(uint32_t frame_number) {
271     for (auto& message : received_messages_) {
272       if (message.type == MessageType::kShutter &&
273           message.message.shutter.frame_number == frame_number) {
274         return true;
275       }
276     }
277 
278     return false;
279   }
280 
WaitForShutter(uint32_t frame_number,uint32_t timeout_ms)281   status_t WaitForShutter(uint32_t frame_number, uint32_t timeout_ms) {
282     std::unique_lock<std::mutex> lock(callback_lock_);
283     if (IsShutterReceivedLocked(frame_number)) {
284       return OK;
285     }
286 
287     bool received = callback_condition_.wait_for(
288         lock, std::chrono::milliseconds(timeout_ms),
289         [&] { return IsShutterReceivedLocked(frame_number); });
290 
291     return received ? OK : TIMED_OUT;
292   }
293 
294   std::mutex callback_lock_;
295   std::condition_variable callback_condition_;  // Protected by callback_lock_.
296 
297   // Maps from a frame number to the received result from CameraDeviceSession.
298   // Protected by callback_lock_.
299   std::unordered_map<uint32_t, std::unique_ptr<CaptureResult>> received_results_;
300 
301   // Received messages from CameraDeviceSession. Protected by callback_lock_.
302   std::vector<NotifyMessage> received_messages_;
303 };
304 
TEST_F(CameraDeviceSessionTests,Create)305 TEST_F(CameraDeviceSessionTests, Create) {
306   auto session = CameraDeviceSession::Create(
307       /*device_session_hwl=*/nullptr, external_session_factory_entries_);
308   EXPECT_EQ(session, nullptr);
309 
310   uint32_t num_sessions = 5;
311   for (uint32_t i = 0; i < num_sessions; i++) {
312     std::unique_ptr<MockDeviceSessionHwl> session_hwl;
313     CreateMockSessionHwlAndCheck(&session_hwl);
314     session_hwl->DelegateCallsToFakeSession();
315     CreateSessionAndCheck(std::move(session_hwl), &session);
316     session = nullptr;
317   }
318 }
319 
TEST_F(CameraDeviceSessionTests,ConstructDefaultRequestSettings)320 TEST_F(CameraDeviceSessionTests, ConstructDefaultRequestSettings) {
321   std::vector<RequestTemplate> types = {
322       RequestTemplate::kPreview,        RequestTemplate::kStillCapture,
323       RequestTemplate::kVideoRecord,    RequestTemplate::kVideoSnapshot,
324       RequestTemplate::kZeroShutterLag, RequestTemplate::kManual};
325 
326   for (auto type : types) {
327     TestInvalidDefaultRequestSettingsForType(type);
328     TestDefaultRequestSettingsForType(type);
329   }
330 }
331 
TEST_F(CameraDeviceSessionTests,ConfigurePreviewStream)332 TEST_F(CameraDeviceSessionTests, ConfigurePreviewStream) {
333   std::vector<std::pair<uint32_t, uint32_t>> preview_resolutions = {
334       std::make_pair(640, 480), std::make_pair(1280, 720),
335       std::make_pair(1920, 1080)};
336 
337   std::unique_ptr<MockDeviceSessionHwl> session_hwl;
338   CreateMockSessionHwlAndCheck(&session_hwl);
339   session_hwl->DelegateCallsToFakeSession();
340 
341   // Expect CreatePipeline() calls back to back.
342   EXPECT_CALL(*session_hwl, ConfigurePipeline(/*camera_id=*/_,
343                                               /*hwl_pipeline_callback=*/_,
344                                               /*request_config=*/_,
345                                               /*overall_config=*/_,
346                                               /*pipeline_id=*/_))
347       .Times(AtLeast(preview_resolutions.size()));
348 
349   // Expect BuildPipelines() calls back to back.
350   EXPECT_CALL(*session_hwl, BuildPipelines())
351       .Times(AtLeast(preview_resolutions.size()));
352 
353   // Expect DestroyPipelines() calls back to back except the first
354   // stream configuration.
355   EXPECT_CALL(*session_hwl, DestroyPipelines())
356       .Times(AtLeast(preview_resolutions.size() - 1));
357 
358   std::unique_ptr<CameraDeviceSession> session;
359   CreateSessionAndCheck(std::move(session_hwl), &session);
360 
361   std::vector<HalStream> hal_configured_streams;
362   StreamConfiguration preview_config;
363   status_t res;
364 
365   for (auto& resolution : preview_resolutions) {
366     test_utils::GetPreviewOnlyStreamConfiguration(
367         &preview_config, resolution.first, resolution.second);
368     ConfigureStreamsReturn hal_config;
369     res = session->ConfigureStreams(preview_config, /*interfaceV3*/ false,
370                                     &hal_config);
371     hal_configured_streams = std::move(hal_config.hal_streams);
372     EXPECT_EQ(res, OK);
373   }
374 }
375 
TEST_F(CameraDeviceSessionTests,PreviewRequests)376 TEST_F(CameraDeviceSessionTests, PreviewRequests) {
377   std::unique_ptr<MockDeviceSessionHwl> session_hwl;
378   CreateMockSessionHwlAndCheck(&session_hwl);
379   session_hwl->DelegateCallsToFakeSession();
380 
381   // Set up mocking expections.
382   static constexpr uint32_t kNumPreviewRequests = 5;
383   EXPECT_CALL(*session_hwl, ConfigurePipeline(_, _, _, _, _)).Times(1);
384   EXPECT_CALL(*session_hwl, SubmitRequests(_, _)).Times(kNumPreviewRequests);
385 
386   std::unique_ptr<CameraDeviceSession> session;
387   CreateSessionAndCheck(std::move(session_hwl), &session);
388 
389   // Configure a preview stream.
390   static const uint32_t kPreviewWidth = 640;
391   static const uint32_t kPreviewHeight = 480;
392   StreamConfiguration preview_config;
393   std::vector<HalStream> hal_configured_streams;
394 
395   // Set up session callback.
396   // Needs to capture the test class as the callback function references the
397   // member variables of the class
398   CameraDeviceSessionCallback session_callback = {
399       .process_capture_result =
400           [&](std::unique_ptr<CaptureResult> result) {
401             ProcessCaptureResult(std::move(result));
402           },
403       .process_batch_capture_result =
404           [&](std::vector<std::unique_ptr<CaptureResult>> results) {
405             ProcessBatchCaptureResult(std::move(results));
406           },
407       .notify = [&](const NotifyMessage& message) { Notify(message); },
408   };
409 
410   ThermalCallback thermal_callback = {
411       .register_thermal_changed_callback =
412           google_camera_hal::RegisterThermalChangedCallbackFunc(
413               [](google_camera_hal::NotifyThrottlingFunc /*notify_throttling*/,
414                  bool /*filter_type*/,
415                  google_camera_hal::TemperatureType /*type*/) {
416                 return INVALID_OPERATION;
417               }),
418       .unregister_thermal_changed_callback =
419           google_camera_hal::UnregisterThermalChangedCallbackFunc([]() {}),
420   };
421 
422   session->SetSessionCallback(session_callback, thermal_callback);
423 
424   test_utils::GetPreviewOnlyStreamConfiguration(&preview_config, kPreviewWidth,
425                                                 kPreviewHeight);
426   ConfigureStreamsReturn hal_config;
427   ASSERT_EQ(session->ConfigureStreams(preview_config, /*interfaceV3*/ false,
428                                       &hal_config),
429             OK);
430   hal_configured_streams = std::move(hal_config.hal_streams);
431   ASSERT_EQ(hal_configured_streams.size(), static_cast<uint32_t>(1));
432 
433   // Allocate buffers.
434   auto allocator = GrallocBufferAllocator::Create();
435   ASSERT_NE(allocator, nullptr);
436 
437   HalBufferDescriptor buffer_descriptor = {
438       .width = preview_config.streams[0].width,
439       .height = preview_config.streams[0].height,
440       .format = hal_configured_streams[0].override_format,
441       .producer_flags = hal_configured_streams[0].producer_usage |
442                         preview_config.streams[0].usage,
443       .consumer_flags = hal_configured_streams[0].consumer_usage,
444       .immediate_num_buffers =
445           std::max(hal_configured_streams[0].max_buffers, kNumPreviewRequests),
446       .max_num_buffers =
447           std::max(hal_configured_streams[0].max_buffers, kNumPreviewRequests),
448   };
449 
450   std::vector<buffer_handle_t> preview_buffers;
451   ASSERT_EQ(allocator->AllocateBuffers(buffer_descriptor, &preview_buffers), OK);
452 
453   std::unique_ptr<HalCameraMetadata> preview_settings;
454   ASSERT_EQ(session->ConstructDefaultRequestSettings(RequestTemplate::kPreview,
455                                                      &preview_settings),
456             OK);
457 
458   // Prepare preview requests.
459   std::vector<CaptureRequest> requests;
460   for (uint32_t i = 0; i < kNumPreviewRequests; i++) {
461     StreamBuffer preview_buffer = {
462         .stream_id = preview_config.streams[0].id,
463         .buffer_id = i,
464         .buffer = preview_buffers[i],
465         .status = BufferStatus::kOk,
466         .acquire_fence = nullptr,
467         .release_fence = nullptr,
468     };
469 
470     CaptureRequest request = {
471         .frame_number = i,
472         .settings = HalCameraMetadata::Clone(preview_settings.get()),
473         .output_buffers = {preview_buffer},
474     };
475 
476     requests.push_back(std::move(request));
477   }
478 
479   ClearResultsAndMessages();
480   uint32_t num_processed_requests = 0;
481   ASSERT_EQ(session->ProcessCaptureRequest(requests, &num_processed_requests),
482             OK);
483   ASSERT_EQ(num_processed_requests, requests.size());
484 
485   // Verify shutters and results are received.
486   for (auto& request : requests) {
487     EXPECT_EQ(WaitForShutter(request.frame_number, kCaptureTimeoutMs), OK);
488     EXPECT_EQ(WaitForResult(request, kCaptureTimeoutMs), OK);
489   }
490 
491   allocator->FreeBuffers(&preview_buffers);
492 }
493 
494 }  // namespace
495 }  // namespace google_camera_hal
496 }  // namespace android
497