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