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