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